Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Do we need to specify "protocol" when "type" is SOCK_DGRAM or SOCK_STREAM in socket()?

From APUE

#include <sys/socket.h>
int socket(int domain, int type, int protocol);

Where:

  • type can be SOCK_DGRAM, SOCK_RAW, SOCK_SEQPACKET, SOCK_STREAM, and
  • protocol can be IPPROTO_TCP, IPPROTO_UDP, ...

Can SOCK_DGRAM work with IPPROTO_UDP, but not with IPPROTO_TCP?

Can SOCK_STREAM work with IPPROTO_TCP, but not with IPPROTO_UDP?

If answers are yes, does it mean that we don't need to specify protocol when type is SOCK_DGRAM or SOCK_STREAM ?

like image 613
Tim Avatar asked Sep 02 '25 03:09

Tim


2 Answers

From the man page for socket(2):

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; see protocols(5). See getprotoent(3) on how to map protocol name strings to protocol numbers.

So whether the protocol field needs to be specified or not depends both on the domain and type field. Assuming domain is AF_INET, i.e. IPv4, then the protocol field should be set to 0 for both SOCK_DGRAM and SOCK_STREAM. The man page for ip(7) shows this:

SYNOPSIS

   #include <sys/socket.h>
   #include <netinet/in.h>
   #include <netinet/ip.h> /* superset of previous */

   tcp_socket = socket(AF_INET, SOCK_STREAM, 0);
   udp_socket = socket(AF_INET, SOCK_DGRAM, 0);
   raw_socket = socket(AF_INET, SOCK_RAW, protocol);

...

An IP socket is created by calling the socket(2) function as socket(AF_INET, socket_type, protocol). Valid socket types are SOCK_STREAM to open a tcp(7) socket, SOCK_DGRAM to open a udp(7) socket, or SOCK_RAW to open a raw(7) socket to access the IP protocol directly. protocol is the IP protocol in the IP header to be received or sent. The only valid values for protocol are 0 and IPPROTO_TCP for TCP sockets, and 0 and IPPROTO_UDP for UDP sockets. For SOCK_RAW you may specify a valid IANA IP protocol defined in RFC 1700 assigned numbers.

The ipv6(7) man page shows something different:

SYNOPSIS

   #include <sys/socket.h>
   #include <netinet/in.h>

   tcp6_socket = socket(AF_INET6, SOCK_STREAM, 0);
   raw6_socket = socket(AF_INET6, SOCK_RAW, protocol);
   udp6_socket = socket(AF_INET6, SOCK_DGRAM, protocol);

It seems that for IPv6 you can specify the protocol field, although the man page doesn't say anything regarding what values are allowed.

like image 193
dbush Avatar answered Sep 05 '25 00:09

dbush


The answer by dbush is outdated. Here's what current man page for ip(7) states:

protocol is the IP protocol in the IP header to be received or sent.
Valid values for protocol include:


   •  0 and IPPROTO_TCP for tcp(7) stream sockets;

   •  0 and IPPROTO_UDP for udp(7) datagram sockets;

   •  IPPROTO_SCTP for sctp(7) stream sockets; and

   •  IPPROTO_UDPLITE for udplite(7) datagram sockets.

   For SOCK_RAW you may specify a valid IANA IP protocol defined in
   RFC 1700 assigned numbers.

As you can see, currently there are two different protocols for each of the stream and datagram socket types. And the protocol parameter is what specifies which one of them to use for the corresponding socket type.

like image 45
Sgg8 Avatar answered Sep 05 '25 01:09

Sgg8