I got the following link: SOL_SOCKET in getsockopt()
But it is really confusing for me. One replied that the SOL_SOCKET means the socket layer. What is the socket layer? Are there any other options available for that parameter?
What happens if we pass the SOL_SOCKET parameter and what does the SOL stand for?
I am using UNIX.
"socket layers" refers to the socket abstraction of the operative system. Those options can be set independently of the type of socket you are handling. In practice, you may be only interested in TCP/IP sockets, but there are also UDP/IP sockets, Unix domain sockets, and others. The options related to SOL_SOCKET can be applied to any of them. The list provided in the answer of the other question has some of them; in the manual page of sockets there are even more, under the "Socket options" section.
SOL_SOCKET is a constant for the "protocol number" associated with that level. For other protocols or levels, you can use getprotoent to obtain the protocol number from its name, or check the manual of the protocol - for example, in the manual page of IP are described the constants for the protocol numbers of IP (IPPROTO_IP), TCP (IPPROTO_TCP) and UDP (IPPROTO_UDP), while the manual page of Unix sockets says that, for historial reasons, its protocol options must be set using SOL_SOCKET too. Moreover, you can find the list of supported protocols for your system in /etc/protocols. And, of course, the options supported by each of the protocols is in their manuals: IP, TCP, UDP, Unix sockets...
Related
int s;
struct addrinfo hints, *res;
getaddrinfo("www.example.com", "http", &hints, &res);
s = socket(res->ai_family, res->ai_socktype, res->ai_protocol);
Please explain the last line of code
The notion of socket is a very generic communication means.
It could deal with communication between local processes, communication between your process and some internal aspects of your system's kernel (events...), communication through the network...
Even when it deals with the network, there exists many protocol families and many protocols.
That's why, when we create a socket (with the socket() call on your last line), we have to provide several parameters in order to select the right properties of the required socket.
man 2 socket mainly explains the first parameter (domain or protocol family) but the other parameters are explained in subsequent pages since they depend on the choice made with this first parameter.
Note that once a socket is obtained with the socket() call, you may need to provide many other settings by other system calls, depending on your intention (bind() for a server, connect() for a client... many settings exist).
In your example, it seems that you want to reach an HTTP server named www.example.com.
You could have hardcoded the fact that such a server can be reached with the AF_INET protocol family (for ipv4, or AF_INET6 for ipv6), through a TCP connection (type SOCK_STREAM, protocol 0) but the getaddrinfo() function can help provide all these details and some other to be used in subsequent system calls (IP address and port number to be specified in a subsequent connect() call for example).
All this information stands in the members of the returned struct addrinfo.
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.
As I know, If one creates a raw socket (with type of SOCK_RAW) and binds it to a network interface, he can receive all the IP traffic on that interface only by using the recvfrom function.
But, in many examples for sniffers I saw a call to the winsock's function WSAIoctl with control code SIO_RCVALL to perform.
So, what's the purpose of that control mode in the mission of sniffing?
Read the documentation. SIO_RCVALL is what enables the NIC to be sniffed, and to some extent what level of sniffing is allowed.
My code is passed an open socket. This socket could be either a TCP socket (AF_INET) or a Unix Domain Socket (AF_UNIX).
Depending on the domain of the socket, it will need to be handled differently. In particular if the socket is bound to an address then I might want to accept incoming connections in a diffent way.
What is the best way to determine whether the socket I have been passed is a unix domain socket or a TCP socket? The solution would need to work on OS X and Linux at least.
getsockopt appears to allow getting the type of the socket (e.g. SOCK_STREAM etc) but not the domain.
getsockname will return a zero length for unix domain sockets on OSX, but this is officially a bug and the Linux behaviour is different.
The first member of the struct sockaddr returned by getsockname is sa_family, just test that against the symbolic constants. The bug on OSX lets you assume the unix domain when the returned address structure is zero bytes, for other platforms and domains, just check the returned structure.
getsockname() is the only cross-platform socket API to query a socket for its locally bound address, and thus its address family.
On Windows, at least, you can use getsockopt(SOL_SOCKET, SO_PROTOCOL_INFO) to retrieve a WSAPROTOCOL_INFO struct, which has an iAddressFamily field. Maybe there are similar platform-specific APIs on other OSes.
I am studying a simple web server using c, and came up with some of these questions. How does IPv6 used in TCP? To use IPv6, do we have to use some form of modified version of TCP?? If we have to used the modified version of TCP, what do we have to change?? I think I read about Little Endian, as well as Big Endian, but I am not sure if there should be some special cases for IPv6.
As you'll probably be wanting the more gory details of the API changes, it's here: http://www.faqs.org/rfcs/rfc2553.html
Mostly it's a couple of longer address structures to pass in that can take a longer number and a new Family and Protocol name specified so the API can destiguish which struct you are using. Byte ordering is the same.
The actual TCP SYN, SYN/ACK, ACK stuff and all that is identical, it is literally a different IP layer frame with a longet number and other changes.