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