What does the parameter protocol stand for in socket() system call? - linux

http://linux.die.net/man/2/socket
The protocol specifies a particular protocol to be used with the
socket. Normally only a single protocol exists to support a particular
socket type within a given protocol family, in which case protocol can
be specified as 0. However, it is possible that many protocols may
exist, in which case a particular protocol must be specified in this
manner. The protocol number to use is specific to the 'communication
domain' in which communication is to take place;
http://linux.die.net/man/5/protocols
The field descriptions are:
protocol the native name for the protocol. For example ip, tcp, or
udp.
When we are already specifying the second parameter either sock dgram or sock stream then why again do we need the protocol parameter?

There are or can be many different datagram or stream protocols.
The typical default for the AF_INET and AF_INET6 domain(when you pass 0) for a streaming protocol is TCP, and for a datagram protocol is UDP.
Another interesting protocol is SCTP, which can operate in both datagram and stream mode, so you can create an SCTP socket in either of these ways:
socket(AF_INET, SOCK_STREAM, IPPROTO_SCTP);
socket(AF_INET, SOCK_DGRAM, IPPROTO_SCTP);
An UDP-lite variant can be created with
socket(AF_INET, SOCK_DGRAM, IPPROTO_UDPLITE);
Note also that socket() is a general call, and can be used to create non-IP based sockets, e.g. for bluetooth, infrared, CANbus protocols which might provide different protocols that you can use.

Related

Receiving and filtering UDP packets with the same destination port from multiple peers

I have two independent network peers sending video data over UDP to a single host both using the same destination port.
e.g.
protocol src_addr src_port dst_addr dst_port
UDP peer1 ephemeral host1 5555
UDP peer2 ephemeral host1 5555
I can have a single socket receive both streams and dispatch the video data to the appropriate decode engine based on src_addr; but what is the best way to achieve the same result without a single receive socket (which is desirable because I would prefer both decodes to be independent applications)?
It feels like it should be possible because each video data stream is uniquely identified in the table above.
The primary issue is that bind() fails when the two sockets, in the two separate receive applications, attempt to bind to the same port.
Options:
1) SO_REUSEADDR and connect()
Can I use SO_REUSEADDR to allow both sockets to bind to the same port? Will a subsequent call to connect() filter the appropriate datagrams to the appropriate application? Or will all datagrams still be delivered to the first socket?
2) SO_REUSEPORT and connect()
SO_REUSEPORT seems to be used to achieve the above for, as an example, load balancing. How is a receiving socket selected? And will it respect connect()?
A quick look at the code in the Linux kernel (net/core/sock_reuseport.c) suggests it is selected randomly unless a Berkeley packet filter is set.
3) Berkeley packet filter
Is this a sensible approach?

What is the purpose of SOCK_DGRAM and SOCK_STREAM in the context AF_UNIX sockets?

I understand that, SOCK_DGRAM and SOCK_STREAM corresponds to Connection-less and connection oriented network communication done using INET Address family.
Now i am trying to learn AF_UNIX sockets to carry out IPC between processes running on same host, and there i see we need to specify the sub_socket_type as SOCK_DGRAM Or SOCK_STREAM. I am not able to understand for AF_UNIX sockets, what is the purpose of specifying the sub socket type.
Can anyone pls help understand the significance of SOCK_DGRAM and SOCK_STREAM in the context of AF_UNIX sockets ?
It happens that TCP is both a stream protocol, and connection oriented, whereas UDP is a datagram protocol, and connectionless. However it is possible to have a connection-oriented datagram protocol. That is what a block special file (or a Windows Mailslot) are.
(You can't have a connectionless stream protocol though, it doesn't make sense, unless /dev/null counts)
The flag SOCK_DGRAM does not mean the socket is connectionless, it means that the socket is datagram oriented.
A stream-oriented socket (and a character special file like /dev/random or /dev/null) provides (or consumes, or both) a continuous sequence of bytes, with no inherent structure. Structure is provided by interpreting the contents of the stream. Generally speaking there is only one process on either end of the stream.
A datagram-oriented socket, provides (or consumes or both) short messages which are limited in size and self-contained. Generally speaking, the server can receive datagrams from multiple clients using recvfrom (which provides the caller with an address to send replies to) and replies to them with sendto specifying that address.
The question also confused me for a while, but as Ben said, with socket type is SOCK_STREAM OR SOCK_DGRAM ,they all means the same way to access inter-process communication between client and server. Under domain AF_UNIX ,it makes not one jot of difference.

Why does socketpair() allow SOCK_DGRAM type?

I've been learning about Linux socket programming recently, mostly from this site.
The site says that using the domain/type combination PF_LOCAL/SOCK_DGRAM...
Provides datagram services within the local host. Note that this
service is connectionless, but reliable, with the possible exception
that packets might be lost if kernel buffers should become exhausted.
My question, then, is why does socketpair(int domain, int type, int protocol, int sv[2]) allow this combination, when according to its man page...
The socketpair() call creates an unnamed pair of connected sockets in
the specified domain, of the specified type...
Isn't there a contradiction here?
I thought SOCK_DGRAM in the PF_LOCAL and PF_INET domains implied UDP, which is a connectionless protocol, so I can't reconcile the seeming conflict with socketpair()'s claim to create connected sockets.
Datagram sockets have "pseudo-connections". The protocol doesn't really have connections, but you can still call connect(). This associates a remote address and port with the socket, and then it only receives packets that come from that source, rather than all packets whose destination is the address/port that the socket is bound to, and you can use send() rather than sendto() to send back to this remote address.
An example where this might be used is the TFTP protocol. The server initially listens for incoming requests on the well-known port. Once a transfer has started, a different port is used, and the sender and receiver can use connect() to associate a socket with that pair of ports. Then they can simply send and receive on that new socket to participate in the transfer.
Similarly, if you use socketpair() with datagram sockets, it creates a pseudo-connection between the two sockets.

How to bind multiple interfaces to a raw socket

I have opened a raw socket to get all the raw packets:
socket(PF_PACKET, SOCK_RAW, htons(ETH_P_ALL)
When a packet is received on an interface which is member of a LAG or bond, the kernel is sending the packets to the user application 2 times. One for the actual physical interface and another one for the bond interface. How can I restrict the kernel to lift the packet only for the interface which I am interested?
We can achieve it by binding the application interested interface to the socket. But I don't want to create multiple sockets (one for each interface) to avoid scalability issue. Is it possible to bind multiple interface to the raw socket dynamically?
Use SO_BINDTODEVICE socket option to bind to specific interface:
char *iface = "eth0";
setsockopt(sock, SOL_SOCKET, SO_BINDTODEVICE, iface, 4);
In this case you'll have to create separate socket for each interface.
Alternative solution would be to use bind(2) with INADDR_ANY.
You do not have a third option.

How reliable are unix domain sockets?

I'm trying to figure out a protocol to use with domain sockets and can't find information on how blindly the domain sockets can be trusted.
Can data be lost? Are messages always received in the same order as sent? Even when using datagram sockets?
Are transfers atomic? When reading the socket, can I trust that I get the whole message on one read or do I have to check it myself?
From 'man AF_UNIX':
Valid types are: SOCK_STREAM, for a stream-oriented socket and
SOCK_DGRAM, for a datagram-oriented socket that preserves message
boundaries (as on most Unix implementations, Unix domain datagram sockets
are always reliable and don’t reorder datagrams);

Resources