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