The FreeRADIUS server $Id: 15bac2a4c627c01d1aa2047687b3418955ac7f00 $
Loading...
Searching...
No Matches
socket.c
Go to the documentation of this file.
1/*
2 * This program is is free software; you can redistribute it and/or modify
3 * it under the terms of the GNU General Public License as published by
4 * the Free Software Foundation; either version 2 of the License, or (at
5 * your option) any later version.
6 *
7 * This program is distributed in the hope that it will be useful,
8 * but WITHOUT ANY WARRANTY; without even the implied warranty of
9 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
10 * GNU General Public License for more details.
11 *
12 * You should have received a copy of the GNU General Public License
13 * along with this program; if not, write to the Free Software
14 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
15 */
16
17/** Functions for establishing and managing low level sockets
18 *
19 * @file src/lib/util/socket.c
20 *
21 * @author Arran Cudbard-Bell (a.cudbardb@freeradius.org)
22 * @author Alan DeKok (aland@freeradius.org)
23 *
24 * @copyright 2015 The FreeRADIUS project
25 */
26
27#include <freeradius-devel/util/debug.h>
28#include <freeradius-devel/util/misc.h>
29#include <freeradius-devel/util/socket.h>
30#include <freeradius-devel/util/syserror.h>
31#include <freeradius-devel/util/udpfromto.h>
32#include <freeradius-devel/util/value.h>
33#include <freeradius-devel/util/cap.h>
34
35#include <fcntl.h>
36#include <ifaddrs.h>
37
38/** Resolve a named service to a port
39 *
40 * @param[in] proto The protocol. Either IPPROTO_TCP or IPPROTO_UDP.
41 * @param[in] port_name The service name, i.e. "radius".
42 * @return
43 * - > 0 the port port_name resolves to.
44 * - < 0 on error.
45 */
46static int socket_port_from_service(int proto, char const *port_name)
47{
48 struct servent *service;
49 char const *proto_name;
50
51 if (!port_name) {
52 fr_strerror_const("No port specified");
53 return -1;
54 }
55
56 switch (proto) {
57 case IPPROTO_UDP:
58 proto_name = "udp";
59 break;
60
61 case IPPROTO_TCP:
62 proto_name = "tcp";
63 break;
64
65#ifdef IPPROTO_SCTP
66 case IPPROTO_SCTP:
67 proto_name = "sctp";
68 break;
69#endif
70
71 default:
72 fr_strerror_printf("Unrecognised proto %i", proto);
73 return -1;
74 }
75
76 service = getservbyname(port_name, proto_name);
77 if (!service) {
78 fr_strerror_printf("Unknown service %s", port_name);
79 return -1;
80 }
81
82 return ntohs(service->s_port);
83}
84
85#ifdef FD_CLOEXEC
86static int socket_dont_inherit(int sockfd)
87{
88 int ret;
89
90 /*
91 * We don't want child processes inheriting these
92 * file descriptors.
93 */
94 ret = fcntl(sockfd, F_GETFD);
95 if (ret >= 0) {
96 if (fcntl(sockfd, F_SETFD, ret | FD_CLOEXEC) < 0) {
97 fr_strerror_printf("Failed setting close on exec: %s", fr_syserror(errno));
98 return -1;
99 }
100 }
101
102 return 0;
103}
104#else
106{
107 return 0;
108}
109#endif
110
111#ifdef HAVE_STRUCT_SOCKADDR_IN6
112/** Restrict wildcard sockets to v6 only
113 *
114 * If we don't do this we get v4 and v6 packets coming in on the same
115 * socket, which is weird.
116 *
117 * @param[in] sockfd to modify.
118 * @param[in] ipaddr we will be binding to.
119 * @return
120 * - 0 on success.
121 * - -1 on failure.
122 */
123static int socket_inaddr_any_v6only(int sockfd, fr_ipaddr_t const *ipaddr)
124{
125 /*
126 * Listening on '::' does NOT get you IPv4 to
127 * IPv6 mapping. You've got to listen on an IPv4
128 * address, too. This makes the rest of the server
129 * design a little simpler.
130 */
131 if (ipaddr->af == AF_INET6) {
132# ifdef IPV6_V6ONLY
133 /* unconst for emscripten/musl */
134 if (IN6_IS_ADDR_UNSPECIFIED(UNCONST(struct in6_addr *, &ipaddr->addr.v6))) {
135 int on = 1;
136
137 if (setsockopt(sockfd, IPPROTO_IPV6, IPV6_V6ONLY,
138 (char *)&on, sizeof(on)) < 0) {
139 fr_strerror_printf("Failed setting socket to IPv6 only: %s", fr_syserror(errno));
140 close(sockfd);
141 return -1;
142 }
143 }
144# endif /* IPV6_V6ONLY */
145 }
146 return 0;
147}
148#else
150{
151 return 0;
152}
153#endif
154
155#if (defined(IP_MTU_DISCOVER) && defined(IP_PMTUDISC_DONT)) || defined(IP_DONTFRAG)
156/** Set the don't fragment bit
157 *
158 * @param[in] sockfd to set don't fragment bit for.
159 * @param[in] af of the socket.
160 * @return
161 * - 0 on success.
162 * - -1 on failure.
163 */
164static int socket_dont_fragment(int sockfd, int af)
165{
166 /*
167 * Set the "don't fragment" flag on UDP sockets. Most
168 * routers don't have good support for fragmented UDP
169 * packets.
170 */
171 if (af == AF_INET) {
172 int flag;
173
174# if defined(IP_MTU_DISCOVER) && defined(IP_PMTUDISC_DONT)
175 /*
176 * Disable PMTU discovery. On Linux, this
177 * also makes sure that the "don't fragment"
178 * flag is zero.
179 */
180 flag = IP_PMTUDISC_DONT;
181
182 if (setsockopt(sockfd, IPPROTO_IP, IP_MTU_DISCOVER, &flag, sizeof(flag)) < 0) {
183 fr_strerror_printf("Failed disabling PMTU discovery: %s", fr_syserror(errno));
184 return -1;
185 }
186# endif
187
188# if defined(IP_DONTFRAG)
189 /*
190 * Ensure that the "don't fragment" flag is zero.
191 */
192 flag = 0;
193
194 if (setsockopt(sockfd, IPPROTO_IP, IP_DONTFRAG, &flag, sizeof(flag)) < 0) {
195 fr_strerror_printf("Failed setting don't fragment flag: %s", fr_syserror(errno));
196 return -1;
197 }
198# endif
199 }
200
201 return 0;
202}
203#else
205{
206 return 0;
207}
208#endif /* lots of things */
209
210/** Bind a UDP/TCP v4/v6 socket to a given ipaddr src port, and interface.
211 *
212 * Use one of:
213 * - fr_socket_server_udp - for non-connected socket.
214 * - fr_socket_server_tcp
215 * ...to open a file descriptor, then call this function to bind the socket to an IP address.
216 *
217 * @param[in] sockfd the socket which opened by fr_socket_server_*.
218 * @param[in] ifname to bind to.
219 * @param[in,out] src_ipaddr The IP address to bind to. Will be updated to the IP address
220 * that was actually bound to. Pass NULL to just bind to an interface.
221 * @param[in] src_port the port to bind to. NULL if any port is allowed.
222
223 * @return
224 * - 0 on success
225 * - -1 on failure.
226 */
227int fr_socket_bind(int sockfd, char const *ifname, fr_ipaddr_t *src_ipaddr, uint16_t *src_port)
228{
229 int ret;
230 uint16_t my_port = 0;
232 struct sockaddr_storage salocal;
233 socklen_t salen;
234
235 /*
236 * Clear the thread local error stack as we may
237 * push multiple errors onto the stack, and this
238 * is likely to be the function which returns
239 * the "original" error.
240 */
242
243 if (src_port) my_port = *src_port;
244 if (src_ipaddr) {
245 my_ipaddr = *src_ipaddr;
246 } else {
248 .af = AF_UNSPEC
249 };
250 }
251
252#ifdef HAVE_CAPABILITY_H
253 /*
254 * If we're binding to a special port as non-root, then
255 * check capabilities. If we're root, we already have
256 * equivalent capabilities so we don't need to check.
257 */
258 if (src_port && (*src_port < 1024) && (geteuid() != 0)) {
259 (void)fr_cap_enable(CAP_NET_BIND_SERVICE, CAP_EFFECTIVE); /* Sets error on failure, which will be seen if the bind fails */
260 }
261#endif
262
263 /*
264 * Bind to a device BEFORE touching IP addresses.
265 */
266 if (ifname) {
267#ifdef HAVE_NET_IF_H
268 unsigned int scope_id;
269
270 scope_id = if_nametoindex(ifname);
271 if (!scope_id) {
272 fr_strerror_printf_push("Failed finding interface %s: %s", ifname, fr_syserror(errno));
273 return -1;
274 }
275
276 /*
277 * If the scope ID hasn't already been set, then
278 * set it. This allows us to get the scope from the interface name.
279 */
280 if ((my_ipaddr.scope_id != 0) && (scope_id != my_ipaddr.scope_id)) {
281 fr_strerror_printf_push("Cannot bind to interface %s: Socket is already bound "
282 "to another interface", ifname);
283 return -1;
284 }
285#endif
286
287#ifdef SO_BINDTODEVICE
288 /*
289 * The caller didn't specify a scope_id, but we
290 * have one from above. Call "bind to device",
291 * and set the scope_id.
292 */
293 if (!my_ipaddr.scope_id) {
294 /*
295 * The internet hints that CAP_NET_RAW
296 * is required to use SO_BINDTODEVICE.
297 *
298 * This function also sets fr_strerror()
299 * on failure, which will be seen if the
300 * bind fails. If the bind succeeds,
301 * then we don't really care that the
302 * capability change has failed. We must
303 * already have that capability.
304 */
305#ifdef HAVE_CAPABILITY_H
306 (void)fr_cap_enable(CAP_NET_RAW, CAP_EFFECTIVE);
307#endif
308 ret = setsockopt(sockfd, SOL_SOCKET, SO_BINDTODEVICE, ifname, strlen(ifname));
309 if (ret < 0) {
310 fr_strerror_printf_push("Failed binding socket to interface %s: %s",
311 ifname, fr_syserror(errno));
312 return -1;
313 } /* else it worked. */
314
315 /*
316 * Set the scope ID.
317 */
318 my_ipaddr.scope_id = scope_id;
319 }
320
321 /*
322 * SO_BINDTODEVICE succeeded, so we're always
323 * bound to the socket.
324 */
325
326#elif defined(IP_BOUND_IF) || defined(IPV6_BOUND_IF)
327 {
328 int idx = scope_id;
329
330 if (my_ipaddr.af == AF_INET) {
331 if (unlikely(setsockopt(sockfd, IPPROTO_IP, IP_BOUND_IF, &idx, sizeof(idx)) < 0)) {
332 error:
333 fr_strerror_printf_push("Failed binding socket to interface %s: %s",
334 ifname, fr_syserror(errno));
335 return -1;
336 }
337
338 } else if (my_ipaddr.af == AF_INET6) {
339 if (unlikely(setsockopt(sockfd, IPPROTO_IPV6, IPV6_BOUND_IF, &idx, sizeof(idx)) < 0)) goto error;
340
341 } else {
342 fr_strerror_printf("Invalid address family for 'interface = ...'");
343 return -1;
344 }
345
346 my_ipaddr.scope_id = scope_id;
347 }
348
349#else
350 {
351 struct ifaddrs *list = NULL;
352 bool bound = false;
353
354 /*
355 * Troll through all interfaces to see if there's
356 */
357 if (getifaddrs(&list) == 0) {
358 struct ifaddrs *i;
359
360 for (i = list; i != NULL; i = i->ifa_next) {
361 if (i->ifa_addr && i->ifa_name && (strcmp(i->ifa_name, ifname) == 0)) {
362 /*
363 * IPv4, and there's either no src_ip, OR src_ip is INADDR_ANY,
364 * it's a match.
365 *
366 * We also update my_ipaddr to point to this particular IP,
367 * so that we can later bind() to it. This gets us the same
368 * effect as SO_BINDTODEVICE.
369 */
370 if ((i->ifa_addr->sa_family == AF_INET) &&
371 (!src_ipaddr || fr_ipaddr_is_inaddr_any(src_ipaddr))) {
373 (struct sockaddr_storage *) i->ifa_addr,
374 sizeof(struct sockaddr_in));
375 my_ipaddr.scope_id = scope_id;
376 bound = true;
377 break;
378 }
379
380 /*
381 * The caller specified a source IP, and we find a matching
382 * address family. Allow it.
383 *
384 * Note that we do NOT check for matching IPs here. If we did,
385 * then binding to an interface and the *wrong* IP would get us
386 * a "bind to device is unsupported" message.
387 *
388 * Instead we say "yes, we found a matching interface", and then
389 * allow the bind() call below to run. If that fails, we get a
390 * "Can't assign requested address" error, which is more informative.
391 */
392 if (src_ipaddr && (src_ipaddr->af == i->ifa_addr->sa_family)) {
393 my_ipaddr.scope_id = scope_id;
394 bound = true;
395 break;
396 }
397 }
398 }
399
400 freeifaddrs(list);
401
402 if (!bound) {
403 /*
404 * IPv4: no link local addresses,
405 * and no bind to device.
406 */
407 fr_strerror_printf_push("Bind to interface %s failed: Unable to match "
408 "interface with the given IP address.", ifname);
409 return -1;
410 }
411 } else {
412 fr_strerror_printf_push("Bind to interface %s failed, unable to get list of interfaces: %s",
413 ifname, fr_syserror(errno));
414 return -1;
415 }
416 }
417#endif
418 } /* else no interface was passed in */
419
420 /*
421 * Don't bind to an IP address if there's no src IP address.
422 */
423 if (my_ipaddr.af == AF_UNSPEC) goto done;
424
425 /*
426 * Set up sockaddr stuff.
427 */
428 if (fr_ipaddr_to_sockaddr(&salocal, &salen, &my_ipaddr, my_port) < 0) return -1;
429
430 ret = bind(sockfd, (struct sockaddr *) &salocal, salen);
431 if (ret < 0) {
432 fr_strerror_printf_push("Bind failed with source address %pV:%pV on interface %s: %s",
433 src_ipaddr ? fr_box_ipaddr(*src_ipaddr) : fr_box_strvalue("*"),
434 src_port ? fr_box_int16(*src_port) : fr_box_strvalue("*"),
435 ifname ? ifname : "*",
436 fr_syserror(errno));
437 return ret;
438 }
439
440 if (!src_port) goto done;
441
442 /*
443 * FreeBSD jail issues. We bind to 0.0.0.0, but the
444 * kernel instead binds us to a 1.2.3.4. So once the
445 * socket is bound, ask it what it's IP address is.
446 */
447 salen = sizeof(salocal);
448 memset(&salocal, 0, salen);
449 if (getsockname(sockfd, (struct sockaddr *) &salocal, &salen) < 0) {
450 fr_strerror_printf_push("Failed getting socket name: %s", fr_syserror(errno));
451 return -1;
452 }
453
454 if (fr_ipaddr_from_sockaddr(&my_ipaddr, &my_port, &salocal, salen) < 0) return -1;
455 *src_port = my_port;
456 *src_ipaddr = my_ipaddr;
457
458done:
459#ifdef HAVE_CAPABILITY_H
460 /*
461 * Clear any errors we may have produced in the
462 * capabilities check.
463 */
465#endif
466 return 0;
467}
468
469#ifdef HAVE_SYS_UN_H
470/** Open a Unix socket
471 *
472 * @note If the file doesn't exist then errno will be set to ENOENT.
473 *
474 * The following code demonstrates using this function with a connection timeout:
475 @code {.c}
476 sockfd = fr_socket_client_unix(path, true);
477 if (sockfd < 0) {
478 fr_perror();
479 fr_exit_now(1);
480 }
481 if ((errno == EINPROGRESS) && (fr_socket_wait_for_connect(sockfd, timeout) < 0)) {
482 error:
483 fr_perror();
484 close(sockfd);
485 goto error;
486 }
487 //Optionally, if blocking operation is required
488 if (fr_blocking(sockfd) < 0) goto error;
489 @endcode
490 *
491 * @param path to the file bound to the unix socket.
492 * @param async Whether to set the socket to nonblocking, allowing use of
493 * #fr_socket_wait_for_connect.
494 * @return
495 * - Socket FD on success.
496 * - -1 on failure.
497 */
498int fr_socket_client_unix(char const *path, bool async)
499{
500 int sockfd = -1;
501 size_t len;
502 socklen_t socklen;
503 struct sockaddr_un saremote;
504
505 len = strlen(path);
506 if (len >= sizeof(saremote.sun_path)) {
507 fr_strerror_printf("Path too long, maximum length is %zu", sizeof(saremote.sun_path) - 1);
508 errno = EINVAL;
509 return -1;
510 }
511
512 sockfd = socket(AF_UNIX, SOCK_STREAM, 0);
513 if (sockfd < 0) {
514 fr_strerror_printf("Failed creating UNIX socket: %s", fr_syserror(errno));
515 return -1;
516 }
517
518 if (async && (fr_nonblock(sockfd) < 0)) {
519 close(sockfd);
520 return -1;
521 }
522
523 saremote.sun_family = AF_UNIX;
524 memcpy(saremote.sun_path, path, len + 1); /* SUN_LEN does strlen */
525
526 socklen = SUN_LEN(&saremote);
527
528 /*
529 * Although we ignore SIGPIPE, some operating systems
530 * like BSD and OSX ignore the ignoring.
531 *
532 * Fortunately, those operating systems usually support
533 * SO_NOSIGPIPE, to prevent them raising the signal in
534 * the first place.
535 */
536#ifdef SO_NOSIGPIPE
537 {
538 int set = 1;
539
540 setsockopt(sockfd, SOL_SOCKET, SO_NOSIGPIPE, (void *)&set, sizeof(int));
541 }
542#endif
543
544 if (connect(sockfd, (struct sockaddr *)&saremote, socklen) < 0) {
545 /*
546 * POSIX says the only time we will get this,
547 * is if the socket has been marked as
548 * nonblocking. This is not an error, the caller
549 * must check the state of errno, and wait for
550 * the connection to complete.
551 */
552 if (errno == EINPROGRESS) return sockfd;
553
554 close(sockfd);
555 fr_strerror_printf("Failed connecting to %s: %s", path, fr_syserror(errno));
556
557 return -1;
558 }
559 return sockfd;
560}
561#else
562int fr_socket_client_unix(UNUSED char const *path, UNUSED bool async)
563{
564 fprintf(stderr, "Unix domain sockets not supported on this system");
565 return -1;
566}
567#endif /* WITH_SYS_UN_H */
568
569#if defined SO_BINDTODEVICE || defined IP_BOUND_IF
570static inline CC_HINT(always_inline) int socket_bind_ifname(int sockfd, char const *ifname)
571#else
572static inline CC_HINT(always_inline) int socket_bind_ifname(UNUSED int sockfd, UNUSED char const *ifname)
573#endif
574{
575#if defined(SO_BINDTODEVICE)
576 if (setsockopt(sockfd, SOL_SOCKET, SO_BINDTODEVICE, ifname, strlen(ifname)) < 0) {
577 fr_strerror_printf("Failed binding socket to %s: %s", ifname, fr_syserror(errno));
578 return -1;
579 }
580#elif defined(IP_BOUND_IF)
581 {
582 int idx = if_nametoindex(ifname);
583 if (idx == 0) {
584 error:
585 fr_strerror_printf("Failed binding socket to %s: %s", ifname, fr_syserror(errno));
586 return -1;
587 }
588 if (unlikely(setsockopt(sockfd, IPPROTO_IP, IP_BOUND_IF, &idx, sizeof(idx)) < 0)) goto error;
589 }
590#else
591 fr_strerror_const("Binding sockets to interfaces not supported on this platform");
592 return -1;
593#endif
594
595 return 0;
596}
597
598/** Establish a connected UDP socket
599 *
600 * Connected UDP sockets can be used with write(), unlike unconnected sockets
601 * which must be used with sendto and recvfrom.
602 *
603 * The following code demonstrates using this function with a connection timeout:
604 @code {.c}
605 sockfd = fr_socket_client_udp(NULL, NULL, NULL, ipaddr, port, true);
606 if (sockfd < 0) {
607 fr_perror();
608 fr_exit_now(1);
609 }
610 if ((errno == EINPROGRESS) && (fr_socket_wait_for_connect(sockfd, timeout) < 0)) {
611 error:
612 fr_perror();
613 close(sockfd);
614 goto error;
615 }
616 //Optionally, if blocking operation is required
617 if (fr_blocking(sockfd) < 0) goto error;
618 @endcode
619 *
620 * @param[in] ifname If non-NULL, bind the socket to this interface.
621 * @param[in,out] src_ipaddr to bind socket to, may be NULL if socket is not bound to any specific
622 * address. If non-null, the bound IP is copied here, too.
623 * @param[out] src_port The source port we were bound to, may be NULL.
624 * @param[in] dst_ipaddr Where to send datagrams.
625 * @param[in] dst_port Where to send datagrams.
626 * @param[in] async Whether to set the socket to nonblocking, allowing use of
627 * #fr_socket_wait_for_connect.
628 * @return
629 * - FD on success.
630 * - -1 on failure.
631 */
632int fr_socket_client_udp(char const *ifname, fr_ipaddr_t *src_ipaddr, uint16_t *src_port,
633 fr_ipaddr_t const *dst_ipaddr, uint16_t dst_port, bool async)
634{
635 int sockfd;
636 struct sockaddr_storage salocal;
637 socklen_t salen;
638
639 if (!dst_ipaddr) return -1;
640
641 sockfd = socket(dst_ipaddr->af, SOCK_DGRAM, 0);
642 if (sockfd < 0) {
643 fr_strerror_printf("Error creating UDP socket: %s", fr_syserror(errno));
644 return -1;
645 }
646
647 if (async && (fr_nonblock(sockfd) < 0)) {
648 error:
649 close(sockfd);
650 return -1;
651 }
652
653 /*
654 * Although we ignore SIGPIPE, some operating systems
655 * like BSD and OSX ignore the ignoring.
656 *
657 * Fortunately, those operating systems usually support
658 * SO_NOSIGPIPE, to prevent them raising the signal in
659 * the first place.
660 */
661#ifdef SO_NOSIGPIPE
662 {
663 int set = 1;
664
665 setsockopt(sockfd, SOL_SOCKET, SO_NOSIGPIPE, (void *)&set, sizeof(int));
666 }
667#endif
668
669 if (unlikely(fr_socket_bind(sockfd, ifname, src_ipaddr, src_port) < 0)) goto error;
670
671 /*
672 * And now get our destination
673 */
674 if (fr_ipaddr_to_sockaddr(&salocal, &salen, dst_ipaddr, dst_port) < 0) {
675 close(sockfd);
676 return -1;
677 }
678
679 if (connect(sockfd, (struct sockaddr *) &salocal, salen) < 0) {
680 /*
681 * POSIX says the only time we will get this,
682 * is if the socket has been marked as
683 * nonblocking. This is not an error, the caller
684 * must check the state of errno, and wait for
685 * the connection to complete.
686 */
687 if (errno == EINPROGRESS) return sockfd;
688
689 fr_strerror_printf("Failed connecting socket: %s", fr_syserror(errno));
690 close(sockfd);
691 return -1;
692 }
693
694 return sockfd;
695}
696
697/** Establish a connected TCP socket
698 *
699 * The following code demonstrates using this function with a connection timeout:
700 @code {.c}
701 sockfd = fr_socket_client_tcp(NULL, NULL, ipaddr, port, true);
702 if (sockfd < 0) {
703 fr_perror();
704 fr_exit_now(1);
705 }
706 if ((errno == EINPROGRESS) && (fr_socket_wait_for_connect(sockfd, timeout) < 0)) {
707 error:
708 fr_perror();
709 close(sockfd);
710 goto error;
711 }
712 //Optionally, if blocking operation is required
713 if (fr_blocking(sockfd) < 0) goto error;
714 @endcode
715 *
716 * @param[in] ifname If non-NULL, bind the socket to this interface.
717 * @param src_ipaddr to bind socket to, may be NULL if socket is not bound to any specific
718 * address.
719 * @param dst_ipaddr Where to connect to.
720 * @param dst_port Where to connect to.
721 * @param async Whether to set the socket to nonblocking, allowing use of
722 * #fr_socket_wait_for_connect.
723 * @return
724 * - FD on success
725 * - -1 on failure.
726 */
727int fr_socket_client_tcp(char const *ifname, fr_ipaddr_t *src_ipaddr,
728 fr_ipaddr_t const *dst_ipaddr, uint16_t dst_port, bool async)
729{
730 int sockfd;
731 struct sockaddr_storage salocal;
732 socklen_t salen;
733
734 if (!dst_ipaddr) return -1;
735
736 sockfd = socket(dst_ipaddr->af, SOCK_STREAM, 0);
737 if (sockfd < 0) {
738 fr_strerror_printf("Error creating TCP socket: %s", fr_syserror(errno));
739 return sockfd;
740 }
741
742 if (async && (fr_nonblock(sockfd) < 0)) {
743 error:
744 close(sockfd);
745 return -1;
746 }
747
748 if (unlikely(fr_socket_bind(sockfd, ifname, src_ipaddr, NULL) < 0)) goto error;
749
750 if (fr_ipaddr_to_sockaddr(&salocal, &salen, dst_ipaddr, dst_port) < 0) {
751 close(sockfd);
752 return -1;
753 }
754
755 /*
756 * Although we ignore SIGPIPE, some operating systems
757 * like BSD and OSX ignore the ignoring.
758 *
759 * Fortunately, those operating systems usually support
760 * SO_NOSIGPIPE, to prevent them raising the signal in
761 * the first place.
762 */
763#ifdef SO_NOSIGPIPE
764 {
765 int set = 1;
766
767 setsockopt(sockfd, SOL_SOCKET, SO_NOSIGPIPE, (void *)&set, sizeof(int));
768 }
769#endif
770
771 if (connect(sockfd, (struct sockaddr *) &salocal, salen) < 0) {
772 /*
773 * POSIX says the only time we will get this,
774 * is if the socket has been marked as
775 * nonblocking. This is not an error, the caller
776 * must check the state of errno, and wait for
777 * the connection to complete.
778 */
779 if (errno == EINPROGRESS) return sockfd;
780
781 fr_strerror_printf("Failed connecting socket: %s", fr_syserror(errno));
782 close(sockfd);
783 return -1;
784 }
785
786 return sockfd;
787}
788
789/** Wait for a socket to be connected, with an optional timeout
790 *
791 * @note On error the caller is expected to ``close(sockfd)``.
792 *
793 * @param sockfd the socket to wait on.
794 * @param timeout How long to wait for socket to open.
795 * @return
796 * - 0 on success.
797 * - -1 on connection error.
798 * - -2 on timeout.
799 * - -3 on select error.
800 */
802{
803 int ret;
804 fd_set error_set;
805 fd_set write_set; /* POSIX says sockets are open when they become writable */
806
807 FD_ZERO(&error_set);
808 FD_ZERO(&write_set);
809
810 FD_SET(sockfd, &error_set);
811 FD_SET(sockfd, &write_set);
812
813 /* Don't let signals mess up the select */
814 do {
815 ret = select(sockfd + 1, NULL, &write_set, &error_set, &fr_time_delta_to_timeval(timeout));
816 } while ((ret == -1) && (errno == EINTR));
817
818 switch (ret) {
819 case 1: /* ok (maybe) */
820 {
821 int error;
822 socklen_t socklen = sizeof(error);
823
824 if (getsockopt(sockfd, SOL_SOCKET, SO_ERROR, (void *)&error, &socklen)) {
825 fr_strerror_printf("Failed connecting socket: %s", fr_syserror(errno));
826 return -1;
827 }
828
829 if (FD_ISSET(sockfd, &error_set)) {
830 fr_strerror_const("Failed connecting socket: Unknown error");
831 return -1;
832 }
833 }
834 return 0;
835
836 case 0: /* timeout */
837 if (!fr_cond_assert(fr_time_delta_ispos(timeout))) return -1;
838 fr_strerror_printf("Connection timed out after %pVs", fr_box_time_delta(timeout));
839 return -2;
840
841 case -1: /* select error */
842 fr_strerror_printf("Failed waiting for connection: %s", fr_syserror(errno));
843 return -3;
844
845 default:
846 (void)fr_cond_assert(0);
847 return -1;
848 }
849}
850
851/** Open an IPv4/IPv6 unconnected UDP socket
852 *
853 * Function name is a bit of a misnomer as it can also be used to create client sockets too,
854 * such is the nature of UDP.
855 *
856 * @param[in] src_ipaddr The IP address to listen on
857 * @param[in,out] src_port the port to listen on. If *port == 0, the resolved
858 * service port will be written here.
859 * @param[in] port_name if *port == 0, the name of the port
860 * @param[in] async whether we block or not on reads and writes
861 * @return
862 * - Socket FD on success.
863 * - -1 on failure.
864 */
865int fr_socket_server_udp(fr_ipaddr_t const *src_ipaddr, uint16_t *src_port, char const *port_name, bool async)
866{
867 int sockfd;
868 uint16_t my_port = 0;
869
870 if (src_port) my_port = *src_port;
871
872 /*
873 * Check IP looks OK
874 */
875 if (!src_ipaddr || ((src_ipaddr->af != AF_INET) && (src_ipaddr->af != AF_INET6))) {
876 fr_strerror_const("No address specified");
877 return -1;
878 }
879
880 /*
881 * Check we have a port value or stuff we can resolve to a port
882 */
883 if (!my_port && port_name) {
884 int ret;
885
886 ret = socket_port_from_service(IPPROTO_UDP, port_name);
887 if (ret < 0) return -1;
888
889 my_port = ret;
890 }
891
892 /*
893 * Open the socket
894 */
895 sockfd = socket(src_ipaddr->af, SOCK_DGRAM, IPPROTO_UDP);
896 if (sockfd < 0) {
897 fr_strerror_printf("Failed creating UDP socket: %s", fr_syserror(errno));
898 return -1;
899 }
900
901 /*
902 * Make it non-blocking if asked
903 */
904 if (async && (fr_nonblock(sockfd) < 0)) {
905 error:
906 close(sockfd);
907 return -1;
908 }
909
910 /*
911 * Don't allow child processes to inherit the socket
912 */
913 if (socket_dont_inherit(sockfd) < 0) goto error;
914
915 /*
916 * Initialize udpfromto for UDP sockets.
917 */
918 if (udpfromto_init(sockfd, src_ipaddr->af) != 0) {
919 fr_strerror_printf("Failed initializing udpfromto: %s", fr_syserror(errno));
920 goto error;
921 }
922
923 /*
924 * Make sure we don't get v4 and v6 packets on inaddr_any sockets.
925 */
926 if (socket_inaddr_any_v6only(sockfd, src_ipaddr) < 0) goto error;
927
928 /*
929 * Ensure don't fragment bit is set
930 */
931 if (socket_dont_fragment(sockfd, src_ipaddr->af) < 0) goto error;
932
933#ifdef SO_TIMESTAMP
934 {
935 int on = 1;
936
937 /*
938 * Enable receive timestamps, these should reflect
939 * when the packet was received, not when it was read
940 * from the socket.
941 */
942 if (setsockopt(sockfd, SOL_SOCKET, SO_TIMESTAMP, &on, sizeof(int)) < 0) {
943 close(sockfd);
944 fr_strerror_printf("Failed enabling socket timestamps: %s", fr_syserror(errno));
945 return -1;
946 }
947 }
948#endif
949
950 if (src_port) *src_port = my_port;
951
952 return sockfd;
953}
954
955/** Open an IPv4/IPv6 TCP socket
956 *
957 * @param[in] src_ipaddr The IP address to listen on
958 * @param[in,out] src_port the port to listen on. If *port == 0, the resolved
959 * service port will be written here.
960 * NULL if any port is allowed.
961 * @param[in] port_name if *port == 0, the name of the port
962 * @param[in] async whether we block or not on reads and writes
963 * @return
964 * - Socket FD on success.
965 * - -1 on failure.
966 */
967int fr_socket_server_tcp(fr_ipaddr_t const *src_ipaddr, uint16_t *src_port, char const *port_name, bool async)
968{
969 int sockfd;
970 uint16_t my_port = 0;
971
972 if (src_port) my_port = *src_port;
973
974 /*
975 * Check IP looks OK
976 */
977 if (!src_ipaddr || ((src_ipaddr->af != AF_INET) && (src_ipaddr->af != AF_INET6))) {
978 fr_strerror_const("No address specified");
979 return -1;
980 }
981
982 /*
983 * Check we have a port value or stuff we can resolve to a port
984 */
985 if (!my_port && port_name) {
986 int ret;
987
988 ret = socket_port_from_service(IPPROTO_TCP, port_name);
989 if (ret < 0) return -1;
990
991 my_port = ret;
992 }
993
994 /*
995 * Open the socket
996 */
997 sockfd = socket(src_ipaddr->af, SOCK_STREAM, IPPROTO_TCP);
998 if (sockfd < 0) {
999 fr_strerror_printf("Failed creating TCP socket: %s", fr_syserror(errno));
1000 return -1;
1001 }
1002
1003 /*
1004 * Make it non-blocking if asked
1005 */
1006 if (async && (fr_nonblock(sockfd) < 0)) {
1007 error:
1008 close(sockfd);
1009 return -1;
1010 }
1011
1012 /*
1013 * Don't allow child processes to inherit the socket
1014 */
1015 if (socket_dont_inherit(sockfd) < 0) goto error;
1016
1017 /*
1018 * Make sure we don't get v4 and v6 packets on inaddr_any sockets.
1019 */
1020 if (socket_inaddr_any_v6only(sockfd, src_ipaddr) < 0) goto error;
1021
1022 {
1023 int on = 1;
1024
1025 if (setsockopt(sockfd, SOL_SOCKET, SO_REUSEADDR, &on, sizeof(on)) < 0) {
1026 close(sockfd);
1027 fr_strerror_printf("Failed to reuse address: %s", fr_syserror(errno));
1028 return -1;
1029 }
1030 }
1031
1032 if (src_port) *src_port = my_port;
1033
1034 return sockfd;
1035}
#define UNCONST(_type, _ptr)
Remove const qualification from a pointer.
Definition build.h:167
#define unlikely(_x)
Definition build.h:383
#define UNUSED
Definition build.h:317
#define fr_cond_assert(_x)
Calls panic_action ifndef NDEBUG, else logs error and evaluates to value of _x.
Definition debug.h:139
static int sockfd
Definition dhcpclient.c:56
int fr_ipaddr_from_sockaddr(fr_ipaddr_t *ipaddr, uint16_t *port, struct sockaddr_storage const *sa, socklen_t salen)
Convert sockaddr to our internal ip address representation.
Definition inet.c:1441
int fr_ipaddr_is_inaddr_any(fr_ipaddr_t const *ipaddr)
Determine if an address is the INADDR_ANY address for its address family.
Definition inet.c:62
int fr_ipaddr_to_sockaddr(struct sockaddr_storage *sa, socklen_t *salen, fr_ipaddr_t const *ipaddr, uint16_t port)
Convert our internal ip address representation to a sockaddr.
Definition inet.c:1392
union fr_ipaddr_t::@133 addr
int af
Address family.
Definition inet.h:64
uint32_t scope_id
A host may have multiple link-local interfaces the scope ID allows the application to specify which o...
Definition inet.h:70
IPv4/6 prefix.
unsigned short uint16_t
int fr_nonblock(UNUSED int fd)
Definition misc.c:293
static bool done
Definition radclient.c:81
static uint16_t my_port
static fr_ipaddr_t my_ipaddr
#define FD_CLOEXEC
static socket_dont_inherit(UNUSED int sockfd)
Definition socket.c:105
static int socket_inaddr_any_v6only(UNUSED int sockfd, UNUSED fr_ipaddr_t const *ipaddr)
Definition socket.c:149
static int socket_port_from_service(int proto, char const *port_name)
Resolve a named service to a port.
Definition socket.c:46
static int socket_bind_ifname(UNUSED int sockfd, UNUSED char const *ifname)
Definition socket.c:572
int fr_socket_server_tcp(fr_ipaddr_t const *src_ipaddr, uint16_t *src_port, char const *port_name, bool async)
Open an IPv4/IPv6 TCP socket.
Definition socket.c:967
int fr_socket_client_udp(char const *ifname, fr_ipaddr_t *src_ipaddr, uint16_t *src_port, fr_ipaddr_t const *dst_ipaddr, uint16_t dst_port, bool async)
Establish a connected UDP socket.
Definition socket.c:632
int fr_socket_server_udp(fr_ipaddr_t const *src_ipaddr, uint16_t *src_port, char const *port_name, bool async)
Open an IPv4/IPv6 unconnected UDP socket.
Definition socket.c:865
int fr_socket_client_tcp(char const *ifname, fr_ipaddr_t *src_ipaddr, fr_ipaddr_t const *dst_ipaddr, uint16_t dst_port, bool async)
Establish a connected TCP socket.
Definition socket.c:727
static int socket_dont_fragment(UNUSED int sockfd, UNUSED int af)
Definition socket.c:204
int fr_socket_bind(int sockfd, char const *ifname, fr_ipaddr_t *src_ipaddr, uint16_t *src_port)
Bind a UDP/TCP v4/v6 socket to a given ipaddr src port, and interface.
Definition socket.c:227
int fr_socket_wait_for_connect(int sockfd, fr_time_delta_t timeout)
Wait for a socket to be connected, with an optional timeout.
Definition socket.c:801
int fr_socket_client_unix(UNUSED char const *path, UNUSED bool async)
Definition socket.c:562
char const * fr_syserror(int num)
Guaranteed to be thread-safe version of strerror.
Definition syserror.c:243
#define fr_time_delta_ispos(_a)
Definition time.h:290
#define fr_time_delta_to_timeval(_delta)
Convert a delta to a timeval.
Definition time.h:656
A time delta, a difference in time measured in nanoseconds.
Definition time.h:80
close(uq->fd)
int udpfromto_init(int s, int af)
Definition udpfromto.c:92
void fr_strerror_clear(void)
Clears all pending messages from the talloc pools.
Definition strerror.c:576
#define fr_strerror_printf(_fmt,...)
Log to thread local error buffer.
Definition strerror.h:64
#define fr_strerror_printf_push(_fmt,...)
Add a message to an existing stack of messages at the tail.
Definition strerror.h:84
#define fr_strerror_const(_msg)
Definition strerror.h:223
#define fr_box_ipaddr(_val)
Definition value.h:305
#define fr_box_strvalue(_val)
Definition value.h:296
#define fr_box_int16(_val)
Definition value.h:328
#define fr_box_time_delta(_val)
Definition value.h:354