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#ifdef HAVE_NET_IF_H
235 unsigned int scope_id = 0;
236#endif
237
238 /*
239 * Clear the thread local error stack as we may
240 * push multiple errors onto the stack, and this
241 * is likely to be the function which returns
242 * the "original" error.
243 */
245
246 if (src_port) my_port = *src_port;
247 if (src_ipaddr) {
248 my_ipaddr = *src_ipaddr;
249 } else {
251 .af = AF_UNSPEC
252 };
253 }
254
255#ifdef HAVE_CAPABILITY_H
256 /*
257 * If we're binding to a special port as non-root, then
258 * check capabilities. If we're root, we already have
259 * equivalent capabilities so we don't need to check.
260 */
261 if (src_port && (*src_port < 1024) && (geteuid() != 0)) {
262 (void)fr_cap_enable(CAP_NET_BIND_SERVICE, CAP_EFFECTIVE); /* Sets error on failure, which will be seen if the bind fails */
263 }
264#endif
265
266 /*
267 * Bind to a device BEFORE touching IP addresses.
268 */
269 if (ifname) {
270#ifdef HAVE_NET_IF_H
271 scope_id = if_nametoindex(ifname);
272 if (!scope_id) {
273 fr_strerror_printf_push("Failed finding interface %s: %s", ifname, fr_syserror(errno));
274 return -1;
275 }
276
277 /*
278 * If the scope ID hasn't already been set, then
279 * set it. This allows us to get the scope from the interface name.
280 */
281 if ((my_ipaddr.scope_id != 0) && (scope_id != my_ipaddr.scope_id)) {
282 fr_strerror_printf_push("Cannot bind to interface %s: Socket is already bound "
283 "to another interface", ifname);
284 return -1;
285 }
286#endif
287
288#ifdef SO_BINDTODEVICE
289 /*
290 * The caller didn't specify a scope_id, but we
291 * have one from above. Call "bind to device",
292 * and set the scope_id.
293 */
294 if (!my_ipaddr.scope_id) {
295 /*
296 * The internet hints that CAP_NET_RAW
297 * is required to use SO_BINDTODEVICE.
298 *
299 * This function also sets fr_strerror()
300 * on failure, which will be seen if the
301 * bind fails. If the bind succeeds,
302 * then we don't really care that the
303 * capability change has failed. We must
304 * already have that capability.
305 */
306#ifdef HAVE_CAPABILITY_H
307 (void)fr_cap_enable(CAP_NET_RAW, CAP_EFFECTIVE);
308#endif
309 ret = setsockopt(sockfd, SOL_SOCKET, SO_BINDTODEVICE, ifname, strlen(ifname));
310 if (ret < 0) {
311 fr_strerror_printf_push("Failed binding socket to interface %s: %s",
312 ifname, fr_syserror(errno));
313 return -1;
314 } /* else it worked. */
315
316 /*
317 * Set the scope ID.
318 */
319 my_ipaddr.scope_id = scope_id;
320 }
321
322 /*
323 * SO_BINDTODEVICE succeeded, so we're always
324 * bound to the socket.
325 */
326
327#elif defined(IP_BOUND_IF) || defined(IPV6_BOUND_IF)
328 {
329 int idx = scope_id;
330
331 if (my_ipaddr.af == AF_INET) {
332 if (unlikely(setsockopt(sockfd, IPPROTO_IP, IP_BOUND_IF, &idx, sizeof(idx)) < 0)) {
333 error:
334 fr_strerror_printf_push("Failed binding socket to interface %s: %s",
335 ifname, fr_syserror(errno));
336 return -1;
337 }
338
339 } else if (my_ipaddr.af == AF_INET6) {
340 if (unlikely(setsockopt(sockfd, IPPROTO_IPV6, IPV6_BOUND_IF, &idx, sizeof(idx)) < 0)) goto error;
341
342 } else {
343 fr_strerror_printf("Invalid address family for 'interface = ...'");
344 return -1;
345 }
346
347 my_ipaddr.scope_id = scope_id;
348 }
349
350#else
351 {
352 struct ifaddrs *list = NULL;
353 bool bound = false;
354
355 /*
356 * Troll through all interfaces to see if there's
357 */
358 if (getifaddrs(&list) == 0) {
359 struct ifaddrs *i;
360
361 for (i = list; i != NULL; i = i->ifa_next) {
362 if (i->ifa_addr && i->ifa_name && (strcmp(i->ifa_name, ifname) == 0)) {
363 /*
364 * IPv4, and there's either no src_ip, OR src_ip is INADDR_ANY,
365 * it's a match.
366 *
367 * We also update my_ipaddr to point to this particular IP,
368 * so that we can later bind() to it. This gets us the same
369 * effect as SO_BINDTODEVICE.
370 */
371 if ((i->ifa_addr->sa_family == AF_INET) &&
372 (!src_ipaddr || fr_ipaddr_is_inaddr_any(src_ipaddr))) {
374 (struct sockaddr_storage *) i->ifa_addr,
375 sizeof(struct sockaddr_in));
376 my_ipaddr.scope_id = scope_id;
377 bound = true;
378 break;
379 }
380
381 /*
382 * The caller specified a source IP, and we find a matching
383 * address family. Allow it.
384 *
385 * Note that we do NOT check for matching IPs here. If we did,
386 * then binding to an interface and the *wrong* IP would get us
387 * a "bind to device is unsupported" message.
388 *
389 * Instead we say "yes, we found a matching interface", and then
390 * allow the bind() call below to run. If that fails, we get a
391 * "Can't assign requested address" error, which is more informative.
392 */
393 if (src_ipaddr && (src_ipaddr->af == i->ifa_addr->sa_family)) {
394 my_ipaddr.scope_id = scope_id;
395 bound = true;
396 break;
397 }
398 }
399 }
400
401 freeifaddrs(list);
402
403 if (!bound) {
404 /*
405 * IPv4: no link local addresses,
406 * and no bind to device.
407 */
408 fr_strerror_printf_push("Bind to interface %s failed: Unable to match "
409 "interface with the given IP address.", ifname);
410 return -1;
411 }
412 } else {
413 fr_strerror_printf_push("Bind to interface %s failed, unable to get list of interfaces: %s",
414 ifname, fr_syserror(errno));
415 return -1;
416 }
417 }
418#endif
419 } /* else no interface was passed in */
420
421 /*
422 * Don't bind to an IP address if there's no src IP address.
423 */
424 if (my_ipaddr.af == AF_UNSPEC) goto done;
425
426 /*
427 * Set up sockaddr stuff.
428 */
429 if (fr_ipaddr_to_sockaddr(&salocal, &salen, &my_ipaddr, my_port) < 0) return -1;
430
431 ret = bind(sockfd, (struct sockaddr *) &salocal, salen);
432 if (ret < 0) {
433 fr_strerror_printf_push("Bind failed with source address %pV:%pV on interface %s: %s",
434 src_ipaddr ? fr_box_ipaddr(*src_ipaddr) : fr_box_strvalue("*"),
435 src_port ? fr_box_int16(*src_port) : fr_box_strvalue("*"),
436 ifname ? ifname : "*",
437 fr_syserror(errno));
438 return ret;
439 }
440
441 if (!src_port) goto done;
442
443 /*
444 * FreeBSD jail issues. We bind to 0.0.0.0, but the
445 * kernel instead binds us to a 1.2.3.4. So once the
446 * socket is bound, ask it what it's IP address is.
447 */
448 salen = sizeof(salocal);
449 memset(&salocal, 0, salen);
450 if (getsockname(sockfd, (struct sockaddr *) &salocal, &salen) < 0) {
451 fr_strerror_printf_push("Failed getting socket name: %s", fr_syserror(errno));
452 return -1;
453 }
454
455 if (fr_ipaddr_from_sockaddr(&my_ipaddr, &my_port, &salocal, salen) < 0) return -1;
456
457#ifdef HAVE_NET_IF_H
458 /*
459 * fr_ipaddr_from_sockaddr clears scope_id for IPv4
460 */
461 if (ifname && scope_id && (my_ipaddr.af == AF_INET)) my_ipaddr.scope_id = scope_id;
462#endif
463 *src_port = my_port;
464 *src_ipaddr = my_ipaddr;
465
466done:
467#ifdef HAVE_CAPABILITY_H
468 /*
469 * Clear any errors we may have produced in the
470 * capabilities check.
471 */
473#endif
474 return 0;
475}
476
477#ifdef HAVE_SYS_UN_H
478/** Open a Unix socket
479 *
480 * @note If the file doesn't exist then errno will be set to ENOENT.
481 *
482 * The following code demonstrates using this function with a connection timeout:
483 @code {.c}
484 sockfd = fr_socket_client_unix(path, true);
485 if (sockfd < 0) {
486 fr_perror();
487 fr_exit_now(1);
488 }
489 if ((errno == EINPROGRESS) && (fr_socket_wait_for_connect(sockfd, timeout) < 0)) {
490 error:
491 fr_perror();
492 close(sockfd);
493 goto error;
494 }
495 //Optionally, if blocking operation is required
496 if (fr_blocking(sockfd) < 0) goto error;
497 @endcode
498 *
499 * @param path to the file bound to the unix socket.
500 * @param async Whether to set the socket to nonblocking, allowing use of
501 * #fr_socket_wait_for_connect.
502 * @return
503 * - Socket FD on success.
504 * - -1 on failure.
505 */
506int fr_socket_client_unix(char const *path, bool async)
507{
508 int sockfd = -1;
509 size_t len;
510 socklen_t socklen;
511 struct sockaddr_un saremote;
512
513 len = strlen(path);
514 if (len >= sizeof(saremote.sun_path)) {
515 fr_strerror_printf("Path too long, maximum length is %zu", sizeof(saremote.sun_path) - 1);
516 errno = EINVAL;
517 return -1;
518 }
519
520 sockfd = socket(AF_UNIX, SOCK_STREAM, 0);
521 if (sockfd < 0) {
522 fr_strerror_printf("Failed creating UNIX socket: %s", fr_syserror(errno));
523 return -1;
524 }
525
526 if (async && (fr_nonblock(sockfd) < 0)) {
527 close(sockfd);
528 return -1;
529 }
530
531 saremote.sun_family = AF_UNIX;
532 memcpy(saremote.sun_path, path, len + 1); /* SUN_LEN does strlen */
533
534 socklen = SUN_LEN(&saremote);
535
536 /*
537 * Although we ignore SIGPIPE, some operating systems
538 * like BSD and OSX ignore the ignoring.
539 *
540 * Fortunately, those operating systems usually support
541 * SO_NOSIGPIPE, to prevent them raising the signal in
542 * the first place.
543 */
544#ifdef SO_NOSIGPIPE
545 {
546 int set = 1;
547
548 setsockopt(sockfd, SOL_SOCKET, SO_NOSIGPIPE, (void *)&set, sizeof(int));
549 }
550#endif
551
552 if (connect(sockfd, (struct sockaddr *)&saremote, socklen) < 0) {
553 /*
554 * POSIX says the only time we will get this,
555 * is if the socket has been marked as
556 * nonblocking. This is not an error, the caller
557 * must check the state of errno, and wait for
558 * the connection to complete.
559 */
560 if (errno == EINPROGRESS) return sockfd;
561
562 close(sockfd);
563 fr_strerror_printf("Failed connecting to %s: %s", path, fr_syserror(errno));
564
565 return -1;
566 }
567 return sockfd;
568}
569#else
570int fr_socket_client_unix(UNUSED char const *path, UNUSED bool async)
571{
572 fprintf(stderr, "Unix domain sockets not supported on this system");
573 return -1;
574}
575#endif /* WITH_SYS_UN_H */
576
577#if defined SO_BINDTODEVICE || defined IP_BOUND_IF
578static inline CC_HINT(always_inline) int socket_bind_ifname(int sockfd, char const *ifname)
579#else
580static inline CC_HINT(always_inline) int socket_bind_ifname(UNUSED int sockfd, UNUSED char const *ifname)
581#endif
582{
583#if defined(SO_BINDTODEVICE)
584 if (setsockopt(sockfd, SOL_SOCKET, SO_BINDTODEVICE, ifname, strlen(ifname)) < 0) {
585 fr_strerror_printf("Failed binding socket to %s: %s", ifname, fr_syserror(errno));
586 return -1;
587 }
588#elif defined(IP_BOUND_IF)
589 {
590 int idx = if_nametoindex(ifname);
591 if (idx == 0) {
592 error:
593 fr_strerror_printf("Failed binding socket to %s: %s", ifname, fr_syserror(errno));
594 return -1;
595 }
596 if (unlikely(setsockopt(sockfd, IPPROTO_IP, IP_BOUND_IF, &idx, sizeof(idx)) < 0)) goto error;
597 }
598#else
599 fr_strerror_const("Binding sockets to interfaces not supported on this platform");
600 return -1;
601#endif
602
603 return 0;
604}
605
606/** Establish a connected UDP socket
607 *
608 * Connected UDP sockets can be used with write(), unlike unconnected sockets
609 * which must be used with sendto and recvfrom.
610 *
611 * The following code demonstrates using this function with a connection timeout:
612 @code {.c}
613 sockfd = fr_socket_client_udp(NULL, NULL, NULL, ipaddr, port, true);
614 if (sockfd < 0) {
615 fr_perror();
616 fr_exit_now(1);
617 }
618 if ((errno == EINPROGRESS) && (fr_socket_wait_for_connect(sockfd, timeout) < 0)) {
619 error:
620 fr_perror();
621 close(sockfd);
622 goto error;
623 }
624 //Optionally, if blocking operation is required
625 if (fr_blocking(sockfd) < 0) goto error;
626 @endcode
627 *
628 * @param[in] ifname If non-NULL, bind the socket to this interface.
629 * @param[in,out] src_ipaddr to bind socket to, may be NULL if socket is not bound to any specific
630 * address. If non-null, the bound IP is copied here, too.
631 * @param[out] src_port The source port we were bound to, may be NULL.
632 * @param[in] dst_ipaddr Where to send datagrams.
633 * @param[in] dst_port Where to send datagrams.
634 * @param[in] async Whether to set the socket to nonblocking, allowing use of
635 * #fr_socket_wait_for_connect.
636 * @return
637 * - FD on success.
638 * - -1 on failure.
639 */
640int fr_socket_client_udp(char const *ifname, fr_ipaddr_t *src_ipaddr, uint16_t *src_port,
641 fr_ipaddr_t const *dst_ipaddr, uint16_t dst_port, bool async)
642{
643 int sockfd;
644 struct sockaddr_storage salocal;
645 socklen_t salen;
646
647 if (!dst_ipaddr) return -1;
648
649 sockfd = socket(dst_ipaddr->af, SOCK_DGRAM, 0);
650 if (sockfd < 0) {
651 fr_strerror_printf("Error creating UDP socket: %s", fr_syserror(errno));
652 return -1;
653 }
654
655 if (async && (fr_nonblock(sockfd) < 0)) {
656 error:
657 close(sockfd);
658 return -1;
659 }
660
661 /*
662 * Although we ignore SIGPIPE, some operating systems
663 * like BSD and OSX ignore the ignoring.
664 *
665 * Fortunately, those operating systems usually support
666 * SO_NOSIGPIPE, to prevent them raising the signal in
667 * the first place.
668 */
669#ifdef SO_NOSIGPIPE
670 {
671 int set = 1;
672
673 setsockopt(sockfd, SOL_SOCKET, SO_NOSIGPIPE, (void *)&set, sizeof(int));
674 }
675#endif
676
677 if (unlikely(fr_socket_bind(sockfd, ifname, src_ipaddr, src_port) < 0)) goto error;
678
679 /*
680 * And now get our destination
681 */
682 if (fr_ipaddr_to_sockaddr(&salocal, &salen, dst_ipaddr, dst_port) < 0) {
683 close(sockfd);
684 return -1;
685 }
686
687 if (connect(sockfd, (struct sockaddr *) &salocal, salen) < 0) {
688 /*
689 * POSIX says the only time we will get this,
690 * is if the socket has been marked as
691 * nonblocking. This is not an error, the caller
692 * must check the state of errno, and wait for
693 * the connection to complete.
694 */
695 if (errno == EINPROGRESS) return sockfd;
696
697 fr_strerror_printf("Failed connecting socket: %s", fr_syserror(errno));
698 close(sockfd);
699 return -1;
700 }
701
702 return sockfd;
703}
704
705/** Establish a connected TCP socket
706 *
707 * The following code demonstrates using this function with a connection timeout:
708 @code {.c}
709 sockfd = fr_socket_client_tcp(NULL, NULL, ipaddr, port, true);
710 if (sockfd < 0) {
711 fr_perror();
712 fr_exit_now(1);
713 }
714 if ((errno == EINPROGRESS) && (fr_socket_wait_for_connect(sockfd, timeout) < 0)) {
715 error:
716 fr_perror();
717 close(sockfd);
718 goto error;
719 }
720 //Optionally, if blocking operation is required
721 if (fr_blocking(sockfd) < 0) goto error;
722 @endcode
723 *
724 * @param[in] ifname If non-NULL, bind the socket to this interface.
725 * @param src_ipaddr to bind socket to, may be NULL if socket is not bound to any specific
726 * address.
727 * @param dst_ipaddr Where to connect to.
728 * @param dst_port Where to connect to.
729 * @param async Whether to set the socket to nonblocking, allowing use of
730 * #fr_socket_wait_for_connect.
731 * @return
732 * - FD on success
733 * - -1 on failure.
734 */
735int fr_socket_client_tcp(char const *ifname, fr_ipaddr_t *src_ipaddr,
736 fr_ipaddr_t const *dst_ipaddr, uint16_t dst_port, bool async)
737{
738 int sockfd;
739 struct sockaddr_storage salocal;
740 socklen_t salen;
741
742 if (!dst_ipaddr) return -1;
743
744 sockfd = socket(dst_ipaddr->af, SOCK_STREAM, 0);
745 if (sockfd < 0) {
746 fr_strerror_printf("Error creating TCP socket: %s", fr_syserror(errno));
747 return sockfd;
748 }
749
750 if (async && (fr_nonblock(sockfd) < 0)) {
751 error:
752 close(sockfd);
753 return -1;
754 }
755
756 if (unlikely(fr_socket_bind(sockfd, ifname, src_ipaddr, NULL) < 0)) goto error;
757
758 if (fr_ipaddr_to_sockaddr(&salocal, &salen, dst_ipaddr, dst_port) < 0) {
759 close(sockfd);
760 return -1;
761 }
762
763 /*
764 * Although we ignore SIGPIPE, some operating systems
765 * like BSD and OSX ignore the ignoring.
766 *
767 * Fortunately, those operating systems usually support
768 * SO_NOSIGPIPE, to prevent them raising the signal in
769 * the first place.
770 */
771#ifdef SO_NOSIGPIPE
772 {
773 int set = 1;
774
775 setsockopt(sockfd, SOL_SOCKET, SO_NOSIGPIPE, (void *)&set, sizeof(int));
776 }
777#endif
778
779 if (connect(sockfd, (struct sockaddr *) &salocal, salen) < 0) {
780 /*
781 * POSIX says the only time we will get this,
782 * is if the socket has been marked as
783 * nonblocking. This is not an error, the caller
784 * must check the state of errno, and wait for
785 * the connection to complete.
786 */
787 if (errno == EINPROGRESS) return sockfd;
788
789 fr_strerror_printf("Failed connecting socket: %s", fr_syserror(errno));
790 close(sockfd);
791 return -1;
792 }
793
794 return sockfd;
795}
796
797/** Wait for a socket to be connected, with an optional timeout
798 *
799 * @note On error the caller is expected to ``close(sockfd)``.
800 *
801 * @param sockfd the socket to wait on.
802 * @param timeout How long to wait for socket to open.
803 * @return
804 * - 0 on success.
805 * - -1 on connection error.
806 * - -2 on timeout.
807 * - -3 on select error.
808 */
810{
811 int ret;
812 fd_set error_set;
813 fd_set write_set; /* POSIX says sockets are open when they become writable */
814
815 FD_ZERO(&error_set);
816 FD_ZERO(&write_set);
817
818 FD_SET(sockfd, &error_set);
819 FD_SET(sockfd, &write_set);
820
821 /* Don't let signals mess up the select */
822 do {
823 ret = select(sockfd + 1, NULL, &write_set, &error_set, &fr_time_delta_to_timeval(timeout));
824 } while ((ret == -1) && (errno == EINTR));
825
826 switch (ret) {
827 case 1: /* ok (maybe) */
828 {
829 int error;
830 socklen_t socklen = sizeof(error);
831
832 if (getsockopt(sockfd, SOL_SOCKET, SO_ERROR, (void *)&error, &socklen)) {
833 fr_strerror_printf("Failed connecting socket: %s", fr_syserror(errno));
834 return -1;
835 }
836
837 if (FD_ISSET(sockfd, &error_set)) {
838 fr_strerror_const("Failed connecting socket: Unknown error");
839 return -1;
840 }
841 }
842 return 0;
843
844 case 0: /* timeout */
845 if (!fr_cond_assert(fr_time_delta_ispos(timeout))) return -1;
846 fr_strerror_printf("Connection timed out after %pVs", fr_box_time_delta(timeout));
847 return -2;
848
849 case -1: /* select error */
850 fr_strerror_printf("Failed waiting for connection: %s", fr_syserror(errno));
851 return -3;
852
853 default:
854 (void)fr_cond_assert(0);
855 return -1;
856 }
857}
858
859/** Open an IPv4/IPv6 unconnected UDP socket
860 *
861 * Function name is a bit of a misnomer as it can also be used to create client sockets too,
862 * such is the nature of UDP.
863 *
864 * @param[in] src_ipaddr The IP address to listen on
865 * @param[in,out] src_port the port to listen on. If *port == 0, the resolved
866 * service port will be written here.
867 * @param[in] port_name if *port == 0, the name of the port
868 * @param[in] async whether we block or not on reads and writes
869 * @return
870 * - Socket FD on success.
871 * - -1 on failure.
872 */
873int fr_socket_server_udp(fr_ipaddr_t const *src_ipaddr, uint16_t *src_port, char const *port_name, bool async)
874{
875 int sockfd;
876 uint16_t my_port = 0;
877
878 if (src_port) my_port = *src_port;
879
880 /*
881 * Check IP looks OK
882 */
883 if (!src_ipaddr || ((src_ipaddr->af != AF_INET) && (src_ipaddr->af != AF_INET6))) {
884 fr_strerror_const("No address specified");
885 return -1;
886 }
887
888 /*
889 * Check we have a port value or stuff we can resolve to a port
890 */
891 if (!my_port && port_name) {
892 int ret;
893
894 ret = socket_port_from_service(IPPROTO_UDP, port_name);
895 if (ret < 0) return -1;
896
897 my_port = ret;
898 }
899
900 /*
901 * Open the socket
902 */
903 sockfd = socket(src_ipaddr->af, SOCK_DGRAM, IPPROTO_UDP);
904 if (sockfd < 0) {
905 fr_strerror_printf("Failed creating UDP socket: %s", fr_syserror(errno));
906 return -1;
907 }
908
909 /*
910 * Make it non-blocking if asked
911 */
912 if (async && (fr_nonblock(sockfd) < 0)) {
913 error:
914 close(sockfd);
915 return -1;
916 }
917
918 /*
919 * Don't allow child processes to inherit the socket
920 */
921 if (socket_dont_inherit(sockfd) < 0) goto error;
922
923 /*
924 * Initialize udpfromto for UDP sockets.
925 */
926 if (udpfromto_init(sockfd, src_ipaddr->af) != 0) {
927 fr_strerror_printf("Failed initializing udpfromto: %s", fr_syserror(errno));
928 goto error;
929 }
930
931 /*
932 * Make sure we don't get v4 and v6 packets on inaddr_any sockets.
933 */
934 if (socket_inaddr_any_v6only(sockfd, src_ipaddr) < 0) goto error;
935
936 /*
937 * Ensure don't fragment bit is set
938 */
939 if (socket_dont_fragment(sockfd, src_ipaddr->af) < 0) goto error;
940
941#ifdef SO_TIMESTAMP
942 {
943 int on = 1;
944
945 /*
946 * Enable receive timestamps, these should reflect
947 * when the packet was received, not when it was read
948 * from the socket.
949 */
950 if (setsockopt(sockfd, SOL_SOCKET, SO_TIMESTAMP, &on, sizeof(int)) < 0) {
951 close(sockfd);
952 fr_strerror_printf("Failed enabling socket timestamps: %s", fr_syserror(errno));
953 return -1;
954 }
955 }
956#endif
957
958 if (src_port) *src_port = my_port;
959
960 return sockfd;
961}
962
963/** Open an IPv4/IPv6 TCP socket
964 *
965 * @param[in] src_ipaddr The IP address to listen on
966 * @param[in,out] src_port the port to listen on. If *port == 0, the resolved
967 * service port will be written here.
968 * NULL if any port is allowed.
969 * @param[in] port_name if *port == 0, the name of the port
970 * @param[in] async whether we block or not on reads and writes
971 * @return
972 * - Socket FD on success.
973 * - -1 on failure.
974 */
975int fr_socket_server_tcp(fr_ipaddr_t const *src_ipaddr, uint16_t *src_port, char const *port_name, bool async)
976{
977 int sockfd;
978 uint16_t my_port = 0;
979
980 if (src_port) my_port = *src_port;
981
982 /*
983 * Check IP looks OK
984 */
985 if (!src_ipaddr || ((src_ipaddr->af != AF_INET) && (src_ipaddr->af != AF_INET6))) {
986 fr_strerror_const("No address specified");
987 return -1;
988 }
989
990 /*
991 * Check we have a port value or stuff we can resolve to a port
992 */
993 if (!my_port && port_name) {
994 int ret;
995
996 ret = socket_port_from_service(IPPROTO_TCP, port_name);
997 if (ret < 0) return -1;
998
999 my_port = ret;
1000 }
1001
1002 /*
1003 * Open the socket
1004 */
1005 sockfd = socket(src_ipaddr->af, SOCK_STREAM, IPPROTO_TCP);
1006 if (sockfd < 0) {
1007 fr_strerror_printf("Failed creating TCP socket: %s", fr_syserror(errno));
1008 return -1;
1009 }
1010
1011 /*
1012 * Make it non-blocking if asked
1013 */
1014 if (async && (fr_nonblock(sockfd) < 0)) {
1015 error:
1016 close(sockfd);
1017 return -1;
1018 }
1019
1020 /*
1021 * Don't allow child processes to inherit the socket
1022 */
1023 if (socket_dont_inherit(sockfd) < 0) goto error;
1024
1025 /*
1026 * Make sure we don't get v4 and v6 packets on inaddr_any sockets.
1027 */
1028 if (socket_inaddr_any_v6only(sockfd, src_ipaddr) < 0) goto error;
1029
1030 {
1031 int on = 1;
1032
1033 if (setsockopt(sockfd, SOL_SOCKET, SO_REUSEADDR, &on, sizeof(on)) < 0) {
1034 close(sockfd);
1035 fr_strerror_printf("Failed to reuse address: %s", fr_syserror(errno));
1036 return -1;
1037 }
1038 }
1039
1040 if (src_port) *src_port = my_port;
1041
1042 return sockfd;
1043}
#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:131
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:1442
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:63
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:1393
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
union fr_ipaddr_t::@136 addr
IPv4/6 prefix.
unsigned short uint16_t
int fr_nonblock(UNUSED int fd)
Definition misc.c:294
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:580
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:975
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:640
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:873
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:735
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:809
int fr_socket_client_unix(UNUSED char const *path, UNUSED bool async)
Definition socket.c:570
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:95
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:316
#define fr_box_strvalue(_val)
Definition value.h:307
#define fr_box_int16(_val)
Definition value.h:339
#define fr_box_time_delta(_val)
Definition value.h:365