1 /* -*- c-basic-offset: 8; -*-
3 * Copyright (c) 1993 W. Richard Stevens. All rights reserved.
4 * Permission to use or modify this software and its documentation only for
5 * educational purposes and without fee is hereby granted, provided that
6 * the above copyright notice appear in all copies. The author makes no
7 * representations about the suitability of this software for any purpose.
8 * It is provided "as is" without express or implied warranty.
14 #include <sys/types.h>
15 #include <netinet/in.h>
16 #include <arpa/inet.h>
22 #include <sys/ioctl.h>
25 static void sigio_func(int);
30 fprintf(stderr
, "SIGIO\n");
31 /* shouldn't printf from a signal handler ... */
36 sockopts(int sockfd
, int doall
)
43 /* "doall" is 0 for a server's listening socket (i.e., before
44 accept() has returned.) Some socket options such as SO_KEEPALIVE
45 don't make sense at this point, while others like SO_DEBUG do. */
49 if (setsockopt(sockfd
, SOL_SOCKET
, SO_DEBUG
,
50 &option
, sizeof(option
)) < 0)
51 err_sys("SO_DEBUG setsockopt error");
54 optlen
= sizeof(option
);
55 if (getsockopt(sockfd
, SOL_SOCKET
, SO_DEBUG
,
56 &option
, &optlen
) < 0)
57 err_sys("SO_DEBUG getsockopt error");
59 err_quit("SO_DEBUG not set (%d)", option
);
62 fprintf(stderr
, "SO_DEBUG set\n");
67 if (setsockopt(sockfd
, SOL_SOCKET
, SO_DONTROUTE
,
68 &option
, sizeof(option
)) < 0)
69 err_sys("SO_DONTROUTE setsockopt error");
72 optlen
= sizeof(option
);
73 if (getsockopt(sockfd
, SOL_SOCKET
, SO_DONTROUTE
,
74 &option
, &optlen
) < 0)
75 err_sys("SO_DONTROUTE getsockopt error");
77 err_quit("SO_DONTROUTE not set (%d)", option
);
80 fprintf(stderr
, "SO_DONTROUTE set\n");
84 if (iptos
!= -1 && doall
== 0) {
85 if (setsockopt(sockfd
, IPPROTO_IP
, IP_TOS
,
86 &iptos
, sizeof(iptos
)) < 0)
87 err_sys("IP_TOS setsockopt error");
90 optlen
= sizeof(option
);
91 if (getsockopt(sockfd
, IPPROTO_IP
, IP_TOS
,
92 &option
, &optlen
) < 0)
93 err_sys("IP_TOS getsockopt error");
95 err_quit("IP_TOS not set (%d)", option
);
98 fprintf(stderr
, "IP_TOS set to %d\n", iptos
);
103 if (ipttl
!= -1 && doall
== 0) {
104 if (setsockopt(sockfd
, IPPROTO_IP
, IP_TTL
,
105 &ipttl
, sizeof(ipttl
)) < 0)
106 err_sys("IP_TTL setsockopt error");
109 optlen
= sizeof(option
);
110 if (getsockopt(sockfd
, IPPROTO_IP
, IP_TTL
,
111 &option
, &optlen
) < 0)
112 err_sys("IP_TTL getsockopt error");
114 err_quit("IP_TTL not set (%d)", option
);
117 fprintf(stderr
, "IP_TTL set to %d\n", ipttl
);
121 if (maxseg
&& udp
== 0) {
122 /* Need to set MSS for server before connection established */
123 /* Beware: some kernels do not let the process set this socket
124 option; others only let it be decreased. */
125 if (setsockopt(sockfd
, IPPROTO_TCP
, TCP_MAXSEG
,
126 &maxseg
, sizeof(maxseg
)) < 0)
127 err_sys("TCP_MAXSEG setsockopt error");
130 optlen
= sizeof(option
);
131 if (getsockopt(sockfd
, IPPROTO_TCP
, TCP_MAXSEG
,
132 &option
, &optlen
) < 0)
133 err_sys("TCP_MAXSEG getsockopt error");
136 fprintf(stderr
, "TCP_MAXSEG = %d\n", option
);
144 if (setsockopt(sockfd
, SOL_SOCKET
, SO_BROADCAST
,
145 &option
, sizeof(option
)) < 0)
146 err_sys("SO_BROADCAST setsockopt error");
149 optlen
= sizeof(option
);
150 if (getsockopt(sockfd
, SOL_SOCKET
, SO_BROADCAST
,
151 &option
, &optlen
) < 0)
152 err_sys("SO_BROADCAST getsockopt error");
154 err_quit("SO_BROADCAST not set (%d)", option
);
157 fprintf(stderr
, "SO_BROADCAST set\n");
162 if (setsockopt(sockfd
, IPPROTO_IP
, IP_ONESBCAST
,
163 &option
, sizeof(option
)) < 0)
164 err_sys("IP_ONESBCAST setsockopt error");
167 optlen
= sizeof(option
);
168 if (getsockopt(sockfd
, IPPROTO_IP
, IP_ONESBCAST
,
169 &option
, &optlen
) < 0)
170 err_sys("IP_ONESBCAST getsockopt error");
172 err_quit("IP_ONESBCAST not set (%d)", option
);
175 fprintf(stderr
, "IP_ONESBCAST set\n");
180 #ifdef IP_ADD_MEMBERSHIP
184 if (inet_aton(joinip
, &join
.imr_multiaddr
) == 0)
185 err_quit("invalid multicast address: %s", joinip
);
186 join
.imr_interface
.s_addr
= htonl(INADDR_ANY
);
187 if (setsockopt(sockfd
, IPPROTO_IP
, IP_ADD_MEMBERSHIP
,
188 &join
, sizeof(join
)) < 0)
189 err_sys("IP_ADD_MEMBERSHIP setsockopt error");
192 fprintf(stderr
, "IP_ADD_MEMBERSHIP set\n");
196 #ifdef IP_MULTICAST_TTL
198 u_char ttl
= mcastttl
;
200 if (setsockopt(sockfd
, IPPROTO_IP
, IP_MULTICAST_TTL
,
201 &ttl
, sizeof(ttl
)) < 0)
202 err_sys("IP_MULTICAST_TTL setsockopt error");
204 optlen
= sizeof(ttl
);
205 if (getsockopt(sockfd
, IPPROTO_IP
, IP_MULTICAST_TTL
,
207 err_sys("IP_MULTICAST_TTL getsockopt error");
209 err_quit("IP_MULTICAST_TTL not set (%d)", ttl
);
212 fprintf(stderr
, "IP_MULTICAST_TTL set to %d\n", ttl
);
216 if (keepalive
&& doall
&& udp
== 0) {
218 if (setsockopt(sockfd
, SOL_SOCKET
, SO_KEEPALIVE
,
219 &option
, sizeof(option
)) < 0)
220 err_sys("SO_KEEPALIVE setsockopt error");
223 optlen
= sizeof(option
);
224 if (getsockopt(sockfd
, SOL_SOCKET
, SO_KEEPALIVE
,
225 &option
, &optlen
) < 0)
226 err_sys("SO_KEEPALIVE getsockopt error");
228 err_quit("SO_KEEPALIVE not set (%d)", option
);
231 fprintf(stderr
, "SO_KEEPALIVE set\n");
234 if (nodelay
&& doall
&& udp
== 0) {
236 if (setsockopt(sockfd
, IPPROTO_TCP
, TCP_NODELAY
,
237 &option
, sizeof(option
)) < 0)
238 err_sys("TCP_NODELAY setsockopt error");
241 optlen
= sizeof(option
);
242 if (getsockopt(sockfd
, IPPROTO_TCP
, TCP_NODELAY
,
243 &option
, &optlen
) < 0)
244 err_sys("TCP_NODELAY getsockopt error");
246 err_quit("TCP_NODELAY not set (%d)", option
);
249 fprintf(stderr
, "TCP_NODELAY set\n");
252 if (doall
&& verbose
&& udp
== 0) { /* just print MSS if verbose */
254 optlen
= sizeof(option
);
255 if (getsockopt(sockfd
, IPPROTO_TCP
, TCP_MAXSEG
,
256 &option
, &optlen
) < 0)
257 err_sys("TCP_MAXSEG getsockopt error");
259 fprintf(stderr
, "TCP_MAXSEG = %d\n", option
);
262 if (linger
>= 0 && doall
&& udp
== 0) {
264 ling
.l_linger
= linger
; /* 0 for abortive disconnect */
265 if (setsockopt(sockfd
, SOL_SOCKET
, SO_LINGER
,
266 &ling
, sizeof(ling
)) < 0)
267 err_sys("SO_LINGER setsockopt error");
271 optlen
= sizeof(struct linger
);
272 if (getsockopt(sockfd
, SOL_SOCKET
, SO_LINGER
,
274 err_sys("SO_LINGER getsockopt error");
275 if (ling
.l_onoff
== 0 || ling
.l_linger
!= linger
)
276 err_quit("SO_LINGER not set (%d, %d)", ling
.l_onoff
, ling
.l_linger
);
279 fprintf(stderr
, "linger %s, time = %d\n",
280 ling
.l_onoff
? "on" : "off", ling
.l_linger
);
283 if (doall
&& rcvtimeo
) {
285 /* User specifies millisec, must convert to sec/usec */
286 timer
.tv_sec
= rcvtimeo
/ 1000;
287 timer
.tv_usec
= (rcvtimeo
% 1000) * 1000;
288 if (setsockopt(sockfd
, SOL_SOCKET
, SO_RCVTIMEO
,
289 &timer
, sizeof(timer
)) < 0)
290 err_sys("SO_RCVTIMEO setsockopt error");
292 timer
.tv_sec
= timer
.tv_usec
= 0;
293 optlen
= sizeof(timer
);
294 if (getsockopt(sockfd
, SOL_SOCKET
, SO_RCVTIMEO
,
295 &timer
, &optlen
) < 0)
296 err_sys("SO_RCVTIMEO getsockopt error");
299 fprintf(stderr
, "SO_RCVTIMEO: %ld.%06ld\n",
300 timer
.tv_sec
, timer
.tv_usec
);
302 fprintf(stderr
, "warning: SO_RCVTIMEO not supported by host\n");
306 if (doall
&& sndtimeo
) {
308 /* User specifies millisec, must convert to sec/usec */
309 timer
.tv_sec
= sndtimeo
/ 1000;
310 timer
.tv_usec
= (sndtimeo
% 1000) * 1000;
311 if (setsockopt(sockfd
, SOL_SOCKET
, SO_SNDTIMEO
,
312 &timer
, sizeof(timer
)) < 0)
313 err_sys("SO_SNDTIMEO setsockopt error");
315 timer
.tv_sec
= timer
.tv_usec
= 0;
316 optlen
= sizeof(timer
);
317 if (getsockopt(sockfd
, SOL_SOCKET
, SO_SNDTIMEO
,
318 &timer
, &optlen
) < 0)
319 err_sys("SO_SNDTIMEO getsockopt error");
322 fprintf(stderr
, "SO_SNDTIMEO: %ld.%06ld\n",
323 timer
.tv_sec
, timer
.tv_usec
);
325 fprintf(stderr
, "warning: SO_SNDTIMEO not supported by host\n");
329 if (recvdstaddr
&& udp
) {
330 #ifdef IP_RECVDSTADDR
332 if (setsockopt(sockfd
, IPPROTO_IP
, IP_RECVDSTADDR
,
333 &option
, sizeof(option
)) < 0)
334 err_sys("IP_RECVDSTADDR setsockopt error");
337 optlen
= sizeof(option
);
338 if (getsockopt(sockfd
, IPPROTO_IP
, IP_RECVDSTADDR
,
339 &option
, &optlen
) < 0)
340 err_sys("IP_RECVDSTADDR getsockopt error");
342 err_quit("IP_RECVDSTADDR not set (%d)", option
);
345 fprintf(stderr
, "IP_RECVDSTADDR set\n");
347 fprintf(stderr
, "warning: IP_RECVDSTADDR not supported by host\n");
354 * Should be able to set this with fcntl(O_ASYNC) or fcntl(FASYNC),
355 * but some systems (AIX?) only do it with ioctl().
357 * Need to set this for listening socket and for connected socket.
359 signal(SIGIO
, sigio_func
);
361 if (fcntl(sockfd
, F_SETOWN
, getpid()) < 0)
362 err_sys("fcntl F_SETOWN error");
365 if (ioctl(sockfd
, FIOASYNC
, (char *) &option
) < 0)
366 err_sys("ioctl FIOASYNC error");
369 fprintf(stderr
, "FIOASYNC set\n");
371 fprintf(stderr
, "warning: FIOASYNC not supported by host\n");