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