1 /*
2 * Copyright (c) 1997, 1998, 1999, 2001, 2003, 2008, 2009, 2010, 2011, 2012,
3 * 2013, 2014, 2016
4 * Inferno Nettverk A/S, Norway. All rights reserved.
5 *
6 * Redistribution and use in source and binary forms, with or without
7 * modification, are permitted provided that the following conditions
8 * are met:
9 * 1. The above copyright notice, this list of conditions and the following
10 * disclaimer must appear in all copies of the software, derivative works
11 * or modified versions, and any portions thereof, aswell as in all
12 * supporting documentation.
13 * 2. All advertising materials mentioning features or use of this software
14 * must display the following acknowledgement:
15 * This product includes software developed by
16 * Inferno Nettverk A/S, Norway.
17 * 3. The name of the author may not be used to endorse or promote products
18 * derived from this software without specific prior written permission.
19 *
20 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
21 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
22 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
23 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
24 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
25 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
26 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
27 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
28 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
29 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
30 *
31 * Inferno Nettverk A/S requests users of this software to return to
32 *
33 * Software Distribution Coordinator or sdc@inet.no
34 * Inferno Nettverk A/S
35 * Oslo Research Park
36 * Gaustadall�en 21
37 * NO-0349 Oslo
38 * Norway
39 *
40 * any improvements or extensions that they make and grant Inferno Nettverk A/S
41 * the rights to redistribute these changes.
42 *
43 */
44
45 #include "common.h"
46
47 static const char rcsid[] =
48 "$Id: sockd_socket.c,v 1.170.4.1.2.2 2017/01/31 08:17:39 karls Exp $";
49
50 #define MAXSOCKETOPTIONS ( 1 /* TCP_NODELAY || SO_BROADCAST */\
51 + 1 /* SO_TIMESTAMP */\
52 + 1 /* SO_OOBINLINE */\
53 + 1 /* SO_KEEPALIVE */\
54 + 1 /* SO_SNDBUF || SO_SNDBUFFORCE */\
55 + 1 /* SO_RCVBUF || SO_RCVBUFFORCE */\
56 + 1 /* IPV6_V6ONLY */\
57 )
58 #define MAXOPTIONNAME (16) /* max length of any of the option names above. */
59 typedef struct {
60 unsigned char wantprivileges;
61 int level;
62 int optname;
63 int optval;
64 size_t optlen;
65 char textname[MAXOPTIONNAME];
66 } socketoptions_t;
67
68 static size_t
69 getoptions(const sa_family_t family, const int type, const int isclientside,
70 socketoptions_t *optionsv, const size_t optionsc);
71 /*
72 * Fills in "optionsv" with the correct values for a socket of family "family"
73 * and type "type".
74 * "isclientside" indicates if the socket is to be used on the client side
75 * or not.
76 *
77 * Returns the number of options set (always <= MAXSOCKETOPTIONS).
78 */
79
80 int
sockd_unconnect(s,oldpeer)81 sockd_unconnect(s, oldpeer)
82 const int s;
83 const struct sockaddr_storage *oldpeer;
84 {
85 const char *function = "sockd_unconnect()";
86 struct sockaddr_storage local, remote, newlocal;
87 socklen_t addrlen;
88 char buf[MAXSOCKADDRSTRING];
89 int havepeer;
90
91 addrlen = sizeof(local);
92 if (getsockname(s, TOSA(&local), &addrlen) != 0) {
93 swarn("%s: getsockname()", function);
94 return -1;
95 }
96
97 if (getpeername(s, TOSA(&remote), &addrlen) != 0) {
98 #if HAVE_LINUX_BUGS
99 if (oldpeer != NULL && GET_SOCKADDRPORT(oldpeer) == htons(0))
100 /*
101 * Linux bug; accepts udp connect(2) to port 0, but getpeername(2)
102 * on the same socket afterwards fails.
103 */
104 ;
105 else
106 #endif /* HAVE_LINUX_BUGS */
107
108 {
109 swarn("%s: could not unconnect fd %d from %s",
110 function,
111 s,
112 oldpeer == NULL ? "N/A" : sockaddr2string(oldpeer, NULL, 0));
113
114 if (!ERRNOISTMP(errno))
115 SWARN(errno); /* not bound? Should not happen. */
116 }
117
118 havepeer = 0;
119 }
120 else
121 havepeer = 1;
122
123 slog(LOG_DEBUG, "%s: unconnecting fd %d, currently connected from %s to %s",
124 function,
125 s,
126 sockaddr2string(&local, buf, sizeof(buf)),
127 havepeer ? sockaddr2string(&remote, NULL, 0) : "nothing");
128
129 bzero(&remote, sizeof(remote));
130 SET_SOCKADDR(&remote, AF_UNSPEC);
131
132 if (connect(s, TOSA(&remote), salen(remote.ss_family)) != 0)
133 slog(LOG_DEBUG, "%s: connect to %s failed: %s",
134 function, sockaddr2string(&remote, NULL, 0), strerror(errno));
135
136 /*
137 * May need to re-bind the socket after unconnect to make sure we get the
138 * same address as we had before, as some systems only keep the portnumber
139 * if not. :-/ Check first.
140 */
141 addrlen = sizeof(newlocal);
142 if (getsockname(s, TOSA(&newlocal), &addrlen) != 0) {
143 swarn("%s: getsockname() failed the second time", function);
144 return -1;
145 }
146
147 if (sockaddrareeq(&local, &newlocal, 0))
148 return 0; /* ok, no problem on this system. */
149
150 /*
151 * Ack, need to try to rebind the socket. :-/
152 */
153
154 if (socks_bind(s, &local, 1) != 0) {
155 char a[MAXSOCKADDRSTRING], b[MAXSOCKADDRSTRING];
156 int new_s;
157
158 slog(LOG_DEBUG, "%s: re-bind(2) after unconnecting failed: %s. "
159 "Current address is %s (was %s). Trying to create a "
160 "new socket instead, though we might loose some packets "
161 "doing so",
162 function,
163 strerror(errno),
164 sockaddr2string(&newlocal, a, sizeof(a)),
165 sockaddr2string(&local, b, sizeof(b)));
166
167 /*
168 * There is an unfortunate race here, as while we create the new
169 * socket packets could come in on the old socket, and those packets
170 * will be lost.
171 */
172
173 new_s = 1;
174 if (setsockopt(s, SOL_SOCKET, SO_REUSEADDR, &new_s, sizeof(new_s)) != 0)
175 swarn("%s: setsockopt(SO_REUSEADDR)", function);
176
177 if ((new_s = socketoptdup(s, -1)) == -1) {
178 swarn("%s: socketoptdup(%d) failed", function, s);
179 return -1;
180 }
181
182 if (socks_bind(new_s, &local, 1) != 0) {
183 slog(LOG_DEBUG, "%s: bind of new socket also failed: %s",
184 function, strerror(errno));
185
186 close(new_s);
187 return 0;
188 }
189
190 slog(LOG_DEBUG, "%s: bind of new socket to address %s succeeded",
191 function, sockaddr2string(&local, NULL, 0));
192
193 if (dup2(new_s, s) == -1) {
194 swarn("%s: dup2() failed", function);
195
196 close(new_s);
197 return 0;
198 }
199
200 close(new_s);
201 }
202
203 return 0;
204 }
205
206 void
sockd_rstonclose(s)207 sockd_rstonclose(s)
208 const int s;
209 {
210 const char *function = "sockd_rstonclose()";
211 /* try to make the kernel generate a TCP RST for the other end upon close. */
212 const struct linger linger = { 1, 0 };
213
214 if (setsockopt(s,
215 SOL_SOCKET,
216 SO_LINGER,
217 &linger,
218 sizeof(linger)) != 0)
219 slog(LOG_DEBUG,
220 "%s: setsockopt(fd %d, SO_LINGER) failed: %s",
221 function, s, strerror(errno));
222 }
223
224 int
bindinternal(protocol)225 bindinternal(protocol)
226 const int protocol;
227 {
228 const char *function = "bindinternal()";
229 size_t i;
230
231 for (i = 0; i < sockscf.internal.addrc; ++i) {
232 listenaddress_t *l = &sockscf.internal.addrv[i];
233 int val;
234
235 if (l->protocol != protocol)
236 continue;
237
238 if (l->s != -1) {
239 slog(LOG_DEBUG, "%s: address %s should be bound to fd %d already",
240 function,
241 sockaddr2string(&l->addr, NULL, 0),
242 l->s);
243
244 SASSERTX(fdisopen(l->s));
245
246 /*
247 * config-based socket options need to be (re)set though.
248 * XXX missing code to unset any previously set options.
249 */
250 setconfsockoptions(l->s,
251 l->s,
252 SOCKS_TCP,
253 1,
254 0,
255 NULL,
256 0,
257 SOCKETOPT_PRE | SOCKETOPT_ANYTIME);
258
259 continue;
260 }
261
262 if ((l->s = socket(l->addr.ss_family, SOCK_STREAM, 0)) == -1) {
263 swarn("%s: could not create %s socket(2)",
264 function, safamily2string(l->addr.ss_family));
265
266 return -1;
267 }
268
269 setsockoptions(l->s, l->addr.ss_family, SOCK_STREAM, 1);
270
271 /*
272 * This breaks the principle that we should only set socket options
273 * on sockets used for data (rather than sockets used for the control
274 * messages), but some options can only be set at pre-connect time,
275 * so if we do not set them here, we will never be able to set them.
276 * Possibly we should limit the settings here to the options that
277 * can _only_ be set at pre-connect time, so that at least other
278 * options are not set unnecessarily.
279 */
280
281 /* XXX missing code to unset any previously set options. */
282 setconfsockoptions(l->s,
283 l->s,
284 SOCKS_TCP,
285 1,
286 0,
287 NULL,
288 0,
289 SOCKETOPT_PRE | SOCKETOPT_ANYTIME);
290
291 val = 1;
292 if (setsockopt(l->s, SOL_SOCKET, SO_REUSEADDR, &val, sizeof(val)) != 0)
293 swarn("%s: setsockopt(SO_REUSEADDR)", function);
294
295 #if !HAVE_PRIVILEGES
296 {
297 /*
298 * Specialcase this so that if we are started as root we do bind
299 * the listen port requested, regardless of whether user.privileged is
300 * set to root or not. Allows a user who does not want Dante to
301 * run as root, ever, but does want Dante to bind a privileged port
302 * when initially starting, get what he wants.
303 */
304 socklen_t len;
305 uid_t old_euid;
306 int changed_euid = 0;
307
308 len = salen(l->addr.ss_family);
309
310 if (PORTISRESERVED(GET_SOCKADDRPORT(&l->addr))) {
311 old_euid = geteuid();
312
313 if (old_euid != 0) {
314 if (seteuid(0) == 0) {
315 sockscf.state.euid = 0;
316 changed_euid = 1;
317 }
318 }
319 }
320
321 if ((val = bind(l->s, TOSA(&l->addr), len)) == -1 && errno == EADDRINUSE)
322 /* retry once. */
323 val = bind(l->s, TOSA(&l->addr), len);
324
325 if (changed_euid) {
326 if (seteuid(old_euid) == 0)
327 sockscf.state.euid = old_euid;
328 }
329 }
330 #else /* HAVE_PRIVILEGES */
331
332 val = socks_bind(l->s, &l->addr, 1);
333
334 #endif /* HAVE_PRIVILEGES */
335
336 if (val != 0) {
337 swarn("%s: bind of address %s (address #%lu/%lu) for server to "
338 "listen on failed",
339 function,
340 sockaddr2string(&l->addr, NULL, 0),
341 (unsigned long)i + 1,
342 (unsigned long)sockscf.internal.addrc);
343
344 return -1;
345 }
346
347 val = 1;
348 if (setsockopt(l->s, SOL_SOCKET, SO_REUSEADDR, &val, sizeof(val)) != 0)
349 swarn("%s: setsockopt(SO_REUSEADDR)", function);
350
351 if (listen(l->s, SOCKD_MAXCLIENTQUEUE) == -1) {
352 swarn("%s: listen(%d) failed", function, SOCKD_MAXCLIENTQUEUE);
353 return -1;
354 }
355
356 /*
357 * We want to accept(2) the client on a non-blocking descriptor.
358 */
359 if (setnonblocking(l->s, "accepting new clients") == -1)
360 return -1;
361 }
362
363 return 0;
364 }
365
366 void
setsockoptions(s,family,type,isclientside)367 setsockoptions(s, family, type, isclientside)
368 const int s;
369 const sa_family_t family;
370 const int type;
371 const int isclientside;
372 {
373 const char *function = "setsockoptions()";
374 socketoptions_t optionsv[MAXSOCKETOPTIONS];
375 size_t optc, i;
376
377 slog(LOG_DEBUG, "%s: fd %d, type = %d, isclientside = %d",
378 function, s, type, isclientside);
379
380 /*
381 * Our default builtin options.
382 */
383 optc = getoptions(family, type, isclientside, optionsv, ELEMENTS(optionsv));
384 slog(LOG_DEBUG, "%s: %lu options to set", function, (unsigned long)optc);
385
386 for (i = 0; i < optc; ++i) {
387 int rc;
388
389 SASSERTX(*optionsv[i].textname != NUL);
390
391 if (optionsv[i].wantprivileges)
392 sockd_priv(SOCKD_PRIV_PRIVILEGED, PRIV_ON);
393
394 rc = setsockopt(s,
395 optionsv[i].level,
396 optionsv[i].optname,
397 &optionsv[i].optval,
398 optionsv[i].optlen);
399
400 if (optionsv[i].wantprivileges)
401 sockd_priv(SOCKD_PRIV_PRIVILEGED, PRIV_OFF);
402
403 if (rc != 0) {
404 if (optionsv[i].optname == SO_BROADCAST
405 && type == SOCK_DGRAM
406 && errno == EPROTO)
407 ; /* SO_BROADCAST is not always supported. */
408 else
409 swarn("%s: setsockopt(%s) to value %d on fd %d failed",
410 function, optionsv[i].textname, optionsv[i].optval, s);
411 }
412 }
413
414 (void)setnonblocking(s, function);
415
416 if (sockscf.option.debug) {
417 socklen_t len;
418 int sndbuf, rcvbuf;
419
420 len = sizeof(sndbuf);
421 if (getsockopt(s, SOL_SOCKET, SO_SNDBUF, &sndbuf, &len) != 0) {
422 swarn("%s: could not get the size of SO_SNDBUF for fd %d",
423 function, s);
424
425 sndbuf = -1;
426 }
427
428 len = sizeof(rcvbuf);
429 if (getsockopt(s, SOL_SOCKET, SO_RCVBUF, &rcvbuf, &len) != 0) {
430 swarn("%s: could not get the size of SO_RCVBUF for fd %d",
431 function, s);
432
433 rcvbuf = -1;
434 }
435
436 slog(LOG_DEBUG,
437 "%s: buffer sizes for fd %d are: SO_SNDBUF: %d, SO_RCVBUF: %d",
438 function, s, sndbuf, rcvbuf);
439 }
440
441 #if DIAGNOSTIC
442 checksockoptions(s, family, type, isclientside);
443 #endif /* DIAGNOSTIC */
444 }
445
446 #if DIAGNOSTIC
447 void
checksockoptions(s,family,type,isclientside)448 checksockoptions(s, family, type, isclientside)
449 const int s;
450 const sa_family_t family;
451 const int type;
452 const int isclientside;
453 {
454 const char *function = "checksockoptions()";
455 socketoptions_t optionsv[MAXSOCKETOPTIONS];
456 size_t optc, i;
457 int val;
458
459 slog(LOG_DEBUG, "%s: fd %d, type = %d, isclientside = %d",
460 function, s, type, isclientside);
461
462 optc = getoptions(family, type, isclientside, optionsv, ELEMENTS(optionsv));
463 for (i = 0; i < optc; ++i) {
464 socklen_t vallen = sizeof(val);
465 int rc;
466
467 #if HAVE_LINUX_BUGS
468 #if defined(SO_SNDBUFFORCE) || defined(SO_RCVBUFFORCE)
469 /*
470 * Crazy Linux ... one name to set it, another one to get it.
471 */
472 if (optionsv[i].optname == SO_SNDBUFFORCE)
473 optionsv[i].optname = SO_SNDBUF;
474 else if (optionsv[i].optname == SO_RCVBUFFORCE)
475 optionsv[i].optname = SO_RCVBUF;
476 #endif /* SO_SNDBUFFORCE || SO_RCVBUFFORCE */
477 #endif /* HAVE_LINUX_BUGS */
478
479 rc = getsockopt(s,
480 optionsv[i].level,
481 optionsv[i].optname,
482 &val,
483 &vallen);
484
485 if (rc != 0) {
486 if (type == SOCK_STREAM && errno == ECONNRESET)
487 continue; /* presumably failed while transferring the descriptor. */
488
489 if (optionsv[i].optname == SO_BROADCAST
490 && type == SOCK_DGRAM
491 && errno == EPROTO)
492 continue; /* SO_BROADCAST is not always supported. */
493
494 swarn("%s: could not get socket option %s on fd %d",
495 function, optionsv[i].textname, s);
496 }
497
498 if (val != optionsv[i].optval) {
499 if ((optionsv[i].optval == 1) && val)
500 ; /* assume it's a boolean; true, but not necessarily 1. */
501 else if (( optionsv[i].optname == SO_SNDBUF
502 || optionsv[i].optname == SO_RCVBUF)) {
503 if (val < optionsv[i].optval)
504 slog(LOG_INFO,
505 "%s: socketoption %s on fd %d should be %d, but is %d",
506 function,
507 optionsv[i].textname,
508 s,
509 optionsv[i].optval,
510 val);
511 }
512 else
513 slog((type == SOCK_DGRAM && optionsv[i].optname == SO_BROADCAST) ?
514 LOG_DEBUG : LOG_WARNING,
515 "%s: socket option %s on fd %d should be %d, but is %d",
516 function,
517 optionsv[i].textname,
518 s,
519 optionsv[i].optval,
520 val);
521 }
522 }
523
524 if ((val = fcntl(s, F_GETFL, 0)) == -1)
525 swarn("%s: fcntl() failed to get descriptor flags of fd %d",
526 function, s);
527 else {
528 if (! (val & O_NONBLOCK))
529 swarn("%s: fd %d is blocking", function, s);
530 }
531 }
532
533 #endif /* DIAGNOSTIC */
534
535 static size_t
getoptions(family,type,isclientside,optionsv,optionsc)536 getoptions(family, type, isclientside, optionsv, optionsc)
537 const sa_family_t family;
538 const int type;
539 const int isclientside;
540 socketoptions_t *optionsv;
541 const size_t optionsc;
542 {
543 size_t optc;
544
545 optc = 0;
546 switch (type) {
547 case SOCK_STREAM:
548 optionsv[optc].wantprivileges = 0;
549 optionsv[optc].level = IPPROTO_TCP;
550 optionsv[optc].optname = TCP_NODELAY;
551 optionsv[optc].optval = 1;
552 optionsv[optc].optlen = sizeof(optionsv[optc].optval);
553 STRCPY_ASSERTSIZE(optionsv[optc].textname, "TCP_NODELAY");
554 ++optc;
555 SASSERTX(optc <= optionsc);
556
557 optionsv[optc].wantprivileges = 0;
558 optionsv[optc].level = SOL_SOCKET;
559 optionsv[optc].optname = SO_OOBINLINE;
560 optionsv[optc].optval = 1;
561 optionsv[optc].optlen = sizeof(optionsv[optc].optval);
562 STRCPY_ASSERTSIZE(optionsv[optc].textname, "SO_OOBINLINE");
563 ++optc;
564 SASSERTX(optc <= optionsc);
565
566 if (sockscf.option.keepalive) {
567 optionsv[optc].wantprivileges = 0;
568 optionsv[optc].level = SOL_SOCKET;
569 optionsv[optc].optname = SO_KEEPALIVE;
570 optionsv[optc].optval = 1;
571 optionsv[optc].optlen = sizeof(optionsv[optc].optval);
572 STRCPY_ASSERTSIZE(optionsv[optc].textname, "SO_KEEPALIVE");
573 ++optc;
574 SASSERTX(optc <= optionsc);
575 }
576
577 break;
578
579 case SOCK_DGRAM:
580 optionsv[optc].wantprivileges = 0;
581 optionsv[optc].level = SOL_SOCKET;
582 optionsv[optc].optname = SO_BROADCAST;
583 optionsv[optc].optval = 1;
584 optionsv[optc].optlen = sizeof(optionsv[optc].optval);
585 STRCPY_ASSERTSIZE(optionsv[optc].textname, "SO_BROADCAST");
586 ++optc;
587 SASSERTX(optc <= optionsc);
588
589 #if HAVE_SO_TIMESTAMP
590 optionsv[optc].wantprivileges = 0;
591 optionsv[optc].level = SOL_SOCKET;
592 optionsv[optc].optname = SO_TIMESTAMP;
593 optionsv[optc].optval = 1;
594 optionsv[optc].optlen = sizeof(optionsv[optc].optval);
595 STRCPY_ASSERTSIZE(optionsv[optc].textname, "SO_TIMESTAMP");
596 ++optc;
597 SASSERTX(optc <= optionsc);
598 #endif /* HAVE_SO_TIMESTAMP */
599
600 break;
601
602 default:
603 SERRX(type);
604 }
605
606 SASSERTX(optc <= optionsc);
607 return optc;
608 }
609