UNIX Network Programming Volume 1, Third Edition [Electronic resources] : The Sockets Networking API نسخه متنی

This is a Digital Library

With over 100,000 free electronic resource in Persian, Arabic and English

UNIX Network Programming Volume 1, Third Edition [Electronic resources] : The Sockets Networking API - نسخه متنی

Addison Wesley

| نمايش فراداده ، افزودن یک نقد و بررسی
افزودن به کتابخانه شخصی
ارسال به دوستان
جستجو در متن کتاب
بیشتر
تنظیمات قلم

فونت

اندازه قلم

+ - پیش فرض

حالت نمایش

روز نیمروز شب
جستجو در لغت نامه
بیشتر
لیست موضوعات
توضیحات
افزودن یادداشت جدید










7.3 Checking if an Option Is Supported and Obtaining the Default


We now write a program to check whether most of the options defined in Figures 7.1 and 7.2 are supported, and if so, print their default value. Figure 7.3 contains the declarations for our program.


Declare union of possible values


38 Our union contains one member for each possible return value from getsockopt.


Define function prototypes


912 We define function prototypes for four functions that are called to print the value for a given socket option.


Define structure and initialize array


1352 Our sock_opts structure contains all the information necessary to call getsockopt for each socket option and then print its current value. The final member, opt_val_str, is a pointer to one of our four functions that will print the option value. We allocate and initialize an array of these structures, one element for each socket option.

Not all implementations support all socket options. The way to determine if a given option is supported is to use an #ifdef or a #if defined, as we show for SO_REUSEPORT. For completeness,

every element of the array should be compiled similarly to what we show for SO_REUSEPORT, but we omit these because the #ifdefs just lengthen the code that we show and add nothing to the discussion.


Figure 7.3 Declarations for our program to check the socket options.

sockopt/checkopts.c


1 #include "unp.h"
2 #include <netinet/tcp.h> /* for TCP_xxx defines */
3 union val {
4 int i_val;
5 long l_val;
6 struct linger linger_val;
7 struct timeval timeval_val;
8 } val;
9 static char *sock_str_flag(union val *, int);
10 static char *sock_str_int(union val *, int);
11 static char *sock_str_linger(union val *, int);
12 static char *sock_str_timeval(union val *, int);
13 struct sock_opts {
14 const char *opt_str;
15 int opt_level;
16 int opt_name;
17 char *(*opt_val_str) (union val *, int);
18 } sock_opts[] = {
19 { "SO_BROADCAST", SOL_SOCKET, SO_BROADCAST, sock_str_flag },
20 { "SO_DEBUG", SOL_SOCKET, SO_DEBUG, sock_str_flag },
21 { "SO_DONTROUTE", SOL_SOCKET, SO_DONTROUTE, sock_str_flag },
22 { "SO_ERROR", SOL_SOCKET, SO_ERROR, sock_str_int },
23 { "SO_KEEPALIVE", SOL_SOCKET, SO_KEEPALIVE, sock_str_flag },
24 { "SO_LINGER", SOL_SOCKET, SO_LINGER, sock_str_linger },
25 { "SO_OOBINLINE", SOL_SOCKET, SO_OOBINLINE, sock_str_flag },
26 { "SO_RCVBUF", SOL_SOCKET, SO_RCVBUF, sock_str_int },
27 { "SO_SNDBUF", SOL_SOCKET, SO_SNDBUF, sock_str_int },
28 { "SO_RCVLOWAT", SOL_SOCKET, SO_RCVLOWAT, sock_str_int },
29 { "SO_SNDLOWAT", SOL_SOCKET, SO_SNDLOWAT, sock_str_int },
30 { "SO_RCVTIMEO", SOL_SOCKET, SO_RCVTIMEO, sock_str_timeval },
31 { "SO_SNDTIMEO", SOL_SOCKET, SO_SNDTIMEO, sock_str_timeval },
32 { "SO_REUSEADDR", SOL_SOCKET, SO_REUSEADDR, sock_str_flag },
33 #ifdef SO_REUSEPORT
34 { "SO_REUSEPORT", SOL_SOCKET, SO_REUSEPORT, sock_str_flag },
35 #else
36 { "SO_REUSEPORT", 0, 0, NULL },
37 #endif
38 { "SO_TYPE", SOL_SOCKET, SO_TYPE, sock_str_int },
39 { "SO_USELOOPBACK", SOL_SOCKET, SO_USELOOPBACK, sock_str_flag },
40 { "IP_TOS", IPPROTO_IP, IP_TOS, sock_str_int },
41 { "IP_TTL", IPPROTO_IP, IP_TTL, sock_str_int },
42 { "IPV6_DONTFRAG", IPPROTO_IPV6,IPV6_DONTFRAG, sock_str_flag },
43 { "IPV6_UNICAST_HOPS", IPPROTO_IPV6,IPV6_UNICAST_HOPS,sock_str_int },
44 { "IPV6_V6ONLY", IPPROTO_IPV6,IPV6_V6ONLY, sock_str_flag },
45 { "TCP_MAXSEG", IPPROTO_TCP,TCP_MAXSEG, sock_str_int },
46 { "TCP_NODELAY", IPPROTO_TCP,TCP_NODELAY, sock_str_flag },
47 { "SCTP_AUTOCLOSE", IPPROTO_SCTP,SCTP_AUTOCLOSE,sock_str_int },
48 { "SCTP_MAXBURST", IPPROTO_SCTP,SCTP_MAXBURST, sock_str_int },
49 { "SCTP_MAXSEG", IPPROTO_SCTP,SCTP_MAXSEG, sock_str_int },
50 { "SCTP_NODELAY", IPPROTO_SCTP,SCTP_NODELAY, sock_str_flag },
51 { NULL, 0, 0, NULL }
52 };

Figure 7.4 shows our main function.

Figure 7.4 main function to check all socket options.

sockopt/checkopts.c


53 int
54 main(int argc, char **argv)
55 {
56 int fd;
57 socklen_t len;
58 struct sock_opts *ptr;
59 for (ptr = sock_opts; ptr->opt_str != NULL; ptr++) {
60 printf("%s: ", ptr->opt_str);
61 if (ptr->opt_val_str == NULL)
62 printf("(undefined)\n");
63 else {
64 switch (ptr->opt_level) {
65 case SOL_SOCKET:
66 case IPPROTO_IP:
67 case IPPROTO_TCP:
68 fd = Socket(AF_INET, SOCK_STREAM, 0);
69 break;
70 #ifdef IPV6
71 case IPPROTO_IPV6:
72 fd = Socket(AF_INET6, SOCK_STREAM, 0);
73 break;
74 #endif
75 #ifdef IPPROTO_SCTP
76 case IPPROTO_SCTP:
77 fd = Socket(AF_INET, SOCK_SEQPACKET, IPPROTO_SCTP);
78 break;
79 #endif
80 default:
81 err_quit("Can't create fd for level %d\n", ptr->opt_level);
82 }
83 len = sizeof(val);
84 if (getsockopt(fd, ptr->opt_level, ptr->opt_name,
85 &val, &len) == -1) {
86 err_ret("getsockopt error");
87 } else {
88 printf("default = %s\n", (*ptr->opt_val_str) (&val, len));
89 }
90 close(fd);
91 }
92 }
93 exit(0);
94 }


Go through all options


5963 We go through all elements in our array. If the opt_val_str pointer is null, the option is not defined by the implementation (which we showed for SO_REUSEPORT).


Create socket


6382 We create a socket on which to try the option. To try socket, IPv4, and TCP layer socket options, we use an IPv4 TCP socket. To try IPv6 layer socket options, we use an IPv6 TCP socket, and to try SCTP layer socket options, we use an IPv4 SCTP socket.


Call getsockopt


8387 We call getsockopt but do not terminate if an error is returned. Many implementations define some of the socket option names even though they do not support the option. Unsupported options should elicit an error of ENOPROTOOPT.


Print option's default value


8889 If getsockopt returns success, we call our function to convert the option value to a string and print the string.

In Figure 7.3, we showed four function prototypes, one for each type of option value that is returned. Figure 7.5 shows one of these four functions, sock_str_flag, which prints the value of a flag option. The other three functions are similar.

Figure 7.5 sock_str_flag function: convert flag option to a string.

sockopt/checkopts.c


95 static char strres[128];
96 static char *
97 sock_str_flag(union val *ptr, int len)
98 {
99 if (len != sizeof(int))
100 snprintf(strres, sizeof(strres), "size (%d) not sizeof(int)", len);
101 else
102 snprintf(strres, sizeof(strres),
103 "%s", (ptr->i_val == 0) ? "off" : "on");
104 return(strres);
105 }

99104 Recall that the final argument to getsockopt is a value-result argument. The first check we make is that the size of the value returned by getsockopt is the expected size. The string returned is off or on, depending on whether the value of the flag option is zero or nonzero, respectively.

Running this program under FreeBSD 4.8 with KAME SCTP patches gives the following output:



freebsd %

checkopts
SO_BROADCAST: default = off
SO_DEBUG: default = off
SO_DONTROUTE: default = off
SO_ERROR: default = 0
SO_KEEPALIVE: default = off
SO_LINGER: default = l_onoff = 0, l_linger = 0
SO_OOBINLINE: default = off
SO_RCVBUF: default = 57344
SO_SNDBUF: default = 32768
SO_RCVLOWAT: default = 1
SO_SNDLOWAT: default = 2048
SO_RCVTIMEO: default = 0 sec, 0 usec
SO_SNDTIMEO: default = 0 sec, 0 usec
SO_REUSEADDR: default = off
SO_REUSEPORT: default = off
SO_TYPE: default = 1
SO_USELOOPBACK: default = off
IP_TOS: default = 0
IP_TTL: default = 64
IPV6_DONTFRAG: default = off
IPV6_UNICAST_HOPS: default = -1
IPV6_V6ONLY: default = off
TCP_MAXSEG: default = 512
TCP_NODELAY: default = off
SCTP_AUTOCLOSE: default = 0
SCTP_MAXBURST: default = 4
SCTP_MAXSEG: default = 1408
SCTP_NODELAY: default = off



The value of 1 returned for the SO_TYPE option corresponds to SOCK_STREAM for this implementation.


/ 450