Is it possible for a UDP socket (SOCK_DGRAM) to access checksum field from an incoming UDP packet and check for errors? I know that we can do that using raw sockets (SOCK_RAW), but I want to know whether we can do it using datagram sockets. If so, how can we do it in C?
If you create a normal UDP socket you don't have access to the UDP header and thus also not to the checksum. But the kernel will already discard packets where the checksum is incorrect so you would not see these packets anyway.
You can't do it using datagram sockets (SOCK_DGRAM), because the TCP/IP stack removes those UDP header bytes from the received buffer before passing it up to higher layer APIs. You need to use raw sockets (SOCK_RAW) so that these bytes are preserved.
Related
When trying to use TCP/IP socket - "socket(AF_INET, SOCK_STREAM, 0)", tcp in this case, does the call to send and recv do a byte-order conversion automatically ?
At the TCP level, byte ordering only applies to the IPs and ports in the TCP/IP headers, which are established when connect()/accept() are called. When working with instances of sockaddr_in... structs, the user is responsible for handling byte conversions to/from network byte order as needed.
send()/recv() simply deal with a socket handle and a raw byte array, so there are no byte order issues when calling them. However, if the byte array has data that contains multi-byte integers in it, those have to be handled separately by the user as needed.
I'd like to count bytes in/out from a socket. For a regular socket, I can just total the size change of buffer effected by recv() and the return value of send(). How do you do this with IO::Socket::SSL?
IO::Socket::SSL does not provide you with that view to the underlying TCP socket since it let just OpenSSL handle the TCP socket (via Net::SSLeay). In order to get such details you would need to handle read/write on the TCP socket yourself and then interact with the SSL layer using the BIO interface. Of course, this is way more complex than just using the abstraction offered by IO::Socket::SSL.
I started to program a packet sniffer, And I have searched for the correct parameters to pass to socket() function in order to capture packets with their Ethernet header.
I noticed that in this tutorial , In order to recieve the Ethernet header, they changed this line:
s = socket.socket(socket.AF_INET, socket.SOCK_RAW, socket.IPPROTO_TCP)
To this line:
s = socket.socket( socket.AF_PACKET , socket.SOCK_RAW , socket.ntohs(0x0003))
And my questions are:
I understood from this link that AF_INET with raw socket won't give me the Ethernet header. My question is why?
Why he also changed from IPPROTO_TCP to ntohs(0x0003) which I know that this is GGP protocol. As far as I understood, the third parameter states the protocol which the socket will recieve. If the protocol parameter is GGP, then the socket will look for packets who have GGP as their internet layer protocol, isn't? then why they pass GGP and not TCP or IP? After all, almost every PDU has IP and\or TCP\UDP as their data protocols.. Does it matter what's the third parameter for my packet sniffer?
In addition to the second question, I think that I didn't get the objective of the third parameter. If this is IPPROTO_TCP, the socket will capture packets with TCP in the network layer (and not UDP for example)? and if i'll pass IPPROTO_IP, the socket will capture packets with IP as their internet layer protocol, without checking the other layer's protocols (It doesn't matter for the socket what protocol is used for the network layer? It only cares that IP is exists as the internet layer protocol)?
Thanks and sorry for the grammer mistakes (English isn't my first language).
If you check linux/if_ether.h you will see
#define ETH_P_ALL 0x0003 /* Every packet (be careful!!!) */
So the value of ETH_P_ALL is 0x0003. The authors of this tutorial use 0x0003 instead of ETH_P_ALL because in some systems when used in python a "not defined" error occurs.
The raw socket feature can be set up at different layers of the network stack, in order to allow the kernel do perform some of the work for you at lower levels (eg: ethernet crafting).
The change to GGP protocol might make sense on the website you found the example, but it is ugly to do so and getprotoent() should be used rather than using magic numbers.
Yes you can tweak (filter) how the packet capture will happen. If you want to capture all packets then use ETH_P_ALL:
When protocol is set to htons(ETH_P_ALL) then all protocols are
received.
I was brushing up my sockte programming knowledge and came across a doubt.
First let me explain my understanding of sockets.
Socket binding associates the socket with port.
Socket binding helps kernel to identify the process to whom it should forward the incoming packet.
In connection oriented communication socket establishment is as below
At server side
socket()-->bind()-->listen()-->accept().....
client side is
socket()-->connect-->......
My question is why client need not bind to a socket. In client case if it send a request it has to get a response to its socket and kernel has to forward it to its process.For these things to happen isn't binding needed?If not how kernel will understand to whom to send the response packet?
Also in connection less client call bind socket.Why is it needed here?
My question is why client need not bind to a socket.
Because the kernel does the bind automatically when you call connect(), if you haven't bound the socket yourself.
Also in connectionless client call bind socket. Why is it needed here?
Because otherwise the socket isn't bound to an IP address:port, so it can't send or receive anything. It has no path to the outside world.
You always open a socket first. This is the path through the kernel. The connect call for say TCP happens after the socket is made.
Look at TCP versus UDP clients.
TCP
s = socket(options....)
connect(s)
send(s, data)
UDP
s = socket(options....)
send(s, data)
bind("0.0.0.0", 0) (all interfaces, any port) is implicit if you call connect(...) or listen(...) without an explicit bind(...).
All sockets must be bound to a local port even when connectionless so that bi-directional communication is possible (even if you're not going to do so).
I am creating a UDP socket client in C (unicast) and is wondering why recvfrom() has a struct sockaddr * argument in which in the man page says,
A null pointer, or points to a sockaddr structure in which the sending address is to be stored.
Is it possible that I could receive a message from a different server other than the one I sendto? If yes, how to create this scenario?
If no, is it correct to say that this argument is only useful when broadcast mode is used?
Yes, this is perfectly possible. The reason for this is that UDP is not stream-based, but packet-based. Every packet is treated without any history (other packets sent or received).
For this reason you may also open a UDP port and then send packets to different hosts from it. However, I do not remember how well this is supported by the API.
The UDP socket will recvfrom() any host sending to this one with correct port unless you explicitly connect(), in which case you can just write() and read(), and get errors upon received ICMP messages.
Considering you always have two parties in UDP, it seems rather obvious that someone has to recvfrom() first.