vfs: check userland buffers before reading them.
[haiku.git] / src / tests / kits / net / sock / sockopts.c
blob7574a54a8784f9d141298367ab6f61baca0bd5cf
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.
9 */
12 #include <stdio.h>
13 #include <netdb.h>
14 #include <sys/types.h>
15 #include <netinet/in.h>
16 #include <arpa/inet.h>
17 #include <sys/time.h>
18 #include <unistd.h>
19 #include <signal.h>
20 #include "sock.h"
21 #include <fcntl.h>
22 #include <sys/ioctl.h>
24 #ifdef FIOASYNC
25 static void sigio_func(int);
27 static void
28 sigio_func(int signo)
30 fprintf(stderr, "SIGIO\n");
31 /* shouldn't printf from a signal handler ... */
33 #endif
35 void
36 sockopts(int sockfd, int doall)
38 int option;
39 unsigned optlen;
40 struct linger ling;
41 struct timeval timer;
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. */
47 if (debug) {
48 option = 1;
49 if (setsockopt(sockfd, SOL_SOCKET, SO_DEBUG,
50 &option, sizeof(option)) < 0)
51 err_sys("SO_DEBUG setsockopt error");
53 option = 0;
54 optlen = sizeof(option);
55 if (getsockopt(sockfd, SOL_SOCKET, SO_DEBUG,
56 &option, &optlen) < 0)
57 err_sys("SO_DEBUG getsockopt error");
58 if (option == 0)
59 err_quit("SO_DEBUG not set (%d)", option);
61 if (verbose)
62 fprintf(stderr, "SO_DEBUG set\n");
65 if (dontroute) {
66 option = 1;
67 if (setsockopt(sockfd, SOL_SOCKET, SO_DONTROUTE,
68 &option, sizeof(option)) < 0)
69 err_sys("SO_DONTROUTE setsockopt error");
71 option = 0;
72 optlen = sizeof(option);
73 if (getsockopt(sockfd, SOL_SOCKET, SO_DONTROUTE,
74 &option, &optlen) < 0)
75 err_sys("SO_DONTROUTE getsockopt error");
76 if (option == 0)
77 err_quit("SO_DONTROUTE not set (%d)", option);
79 if (verbose)
80 fprintf(stderr, "SO_DONTROUTE set\n");
83 #ifdef IP_TOS
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");
89 option = 0;
90 optlen = sizeof(option);
91 if (getsockopt(sockfd, IPPROTO_IP, IP_TOS,
92 &option, &optlen) < 0)
93 err_sys("IP_TOS getsockopt error");
94 if (option != iptos)
95 err_quit("IP_TOS not set (%d)", option);
97 if (verbose)
98 fprintf(stderr, "IP_TOS set to %d\n", iptos);
100 #endif
102 #ifdef IP_TTL
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");
108 option = 0;
109 optlen = sizeof(option);
110 if (getsockopt(sockfd, IPPROTO_IP, IP_TTL,
111 &option, &optlen) < 0)
112 err_sys("IP_TTL getsockopt error");
113 if (option != ipttl)
114 err_quit("IP_TTL not set (%d)", option);
116 if (verbose)
117 fprintf(stderr, "IP_TTL set to %d\n", ipttl);
119 #endif
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");
129 option = 0;
130 optlen = sizeof(option);
131 if (getsockopt(sockfd, IPPROTO_TCP, TCP_MAXSEG,
132 &option, &optlen) < 0)
133 err_sys("TCP_MAXSEG getsockopt error");
135 if (verbose)
136 fprintf(stderr, "TCP_MAXSEG = %d\n", option);
139 if (sroute_cnt > 0)
140 sroute_set(sockfd);
142 if (broadcast) {
143 option = 1;
144 if (setsockopt(sockfd, SOL_SOCKET, SO_BROADCAST,
145 &option, sizeof(option)) < 0)
146 err_sys("SO_BROADCAST setsockopt error");
148 option = 0;
149 optlen = sizeof(option);
150 if (getsockopt(sockfd, SOL_SOCKET, SO_BROADCAST,
151 &option, &optlen) < 0)
152 err_sys("SO_BROADCAST getsockopt error");
153 if (option == 0)
154 err_quit("SO_BROADCAST not set (%d)", option);
156 if (verbose)
157 fprintf(stderr, "SO_BROADCAST set\n");
159 #ifdef IP_ONESBCAST
160 if (onesbcast) {
161 option = 1;
162 if (setsockopt(sockfd, IPPROTO_IP, IP_ONESBCAST,
163 &option, sizeof(option)) < 0)
164 err_sys("IP_ONESBCAST setsockopt error");
166 option = 0;
167 optlen = sizeof(option);
168 if (getsockopt(sockfd, IPPROTO_IP, IP_ONESBCAST,
169 &option, &optlen) < 0)
170 err_sys("IP_ONESBCAST getsockopt error");
171 if (option == 0)
172 err_quit("IP_ONESBCAST not set (%d)", option);
174 if (verbose)
175 fprintf(stderr, "IP_ONESBCAST set\n");
177 #endif
180 #ifdef IP_ADD_MEMBERSHIP
181 if (joinip[0]) {
182 struct ip_mreq join;
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");
191 if (verbose)
192 fprintf(stderr, "IP_ADD_MEMBERSHIP set\n");
194 #endif
196 #ifdef IP_MULTICAST_TTL
197 if (mcastttl) {
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,
206 &ttl, &optlen) < 0)
207 err_sys("IP_MULTICAST_TTL getsockopt error");
208 if (ttl != mcastttl)
209 err_quit("IP_MULTICAST_TTL not set (%d)", ttl);
211 if (verbose)
212 fprintf(stderr, "IP_MULTICAST_TTL set to %d\n", ttl);
214 #endif
216 if (keepalive && doall && udp == 0) {
217 option = 1;
218 if (setsockopt(sockfd, SOL_SOCKET, SO_KEEPALIVE,
219 &option, sizeof(option)) < 0)
220 err_sys("SO_KEEPALIVE setsockopt error");
222 option = 0;
223 optlen = sizeof(option);
224 if (getsockopt(sockfd, SOL_SOCKET, SO_KEEPALIVE,
225 &option, &optlen) < 0)
226 err_sys("SO_KEEPALIVE getsockopt error");
227 if (option == 0)
228 err_quit("SO_KEEPALIVE not set (%d)", option);
230 if (verbose)
231 fprintf(stderr, "SO_KEEPALIVE set\n");
234 if (nodelay && doall && udp == 0) {
235 option = 1;
236 if (setsockopt(sockfd, IPPROTO_TCP, TCP_NODELAY,
237 &option, sizeof(option)) < 0)
238 err_sys("TCP_NODELAY setsockopt error");
240 option = 0;
241 optlen = sizeof(option);
242 if (getsockopt(sockfd, IPPROTO_TCP, TCP_NODELAY,
243 &option, &optlen) < 0)
244 err_sys("TCP_NODELAY getsockopt error");
245 if (option == 0)
246 err_quit("TCP_NODELAY not set (%d)", option);
248 if (verbose)
249 fprintf(stderr, "TCP_NODELAY set\n");
252 if (doall && verbose && udp == 0) { /* just print MSS if verbose */
253 option = 0;
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) {
263 ling.l_onoff = 1;
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");
269 ling.l_onoff = 0;
270 ling.l_linger = -1;
271 optlen = sizeof(struct linger);
272 if (getsockopt(sockfd, SOL_SOCKET, SO_LINGER,
273 &ling, &optlen) < 0)
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);
278 if (verbose)
279 fprintf(stderr, "linger %s, time = %d\n",
280 ling.l_onoff ? "on" : "off", ling.l_linger);
283 if (doall && rcvtimeo) {
284 #ifdef SO_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");
298 if (verbose)
299 fprintf(stderr, "SO_RCVTIMEO: %ld.%06ld\n",
300 timer.tv_sec, timer.tv_usec);
301 #else
302 fprintf(stderr, "warning: SO_RCVTIMEO not supported by host\n");
303 #endif
306 if (doall && sndtimeo) {
307 #ifdef SO_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");
321 if (verbose)
322 fprintf(stderr, "SO_SNDTIMEO: %ld.%06ld\n",
323 timer.tv_sec, timer.tv_usec);
324 #else
325 fprintf(stderr, "warning: SO_SNDTIMEO not supported by host\n");
326 #endif
329 if (recvdstaddr && udp) {
330 #ifdef IP_RECVDSTADDR
331 option = 1;
332 if (setsockopt(sockfd, IPPROTO_IP, IP_RECVDSTADDR,
333 &option, sizeof(option)) < 0)
334 err_sys("IP_RECVDSTADDR setsockopt error");
336 option = 0;
337 optlen = sizeof(option);
338 if (getsockopt(sockfd, IPPROTO_IP, IP_RECVDSTADDR,
339 &option, &optlen) < 0)
340 err_sys("IP_RECVDSTADDR getsockopt error");
341 if (option == 0)
342 err_quit("IP_RECVDSTADDR not set (%d)", option);
344 if (verbose)
345 fprintf(stderr, "IP_RECVDSTADDR set\n");
346 #else
347 fprintf(stderr, "warning: IP_RECVDSTADDR not supported by host\n");
348 #endif
351 if (sigio) {
352 #ifdef FIOASYNC
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");
364 option = 1;
365 if (ioctl(sockfd, FIOASYNC, (char *) &option) < 0)
366 err_sys("ioctl FIOASYNC error");
368 if (verbose)
369 fprintf(stderr, "FIOASYNC set\n");
370 #else
371 fprintf(stderr, "warning: FIOASYNC not supported by host\n");
372 #endif