The FreeRADIUS server $Id: f3670dba8951ca10eb4948feb3dc3db9423a334f $
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))) {
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) goto error;
732
733 /*
734 * Although we ignore SIGPIPE, some operating systems
735 * like BSD and OSX ignore the ignoring.
736 *
737 * Fortunately, those operating systems usually support
738 * SO_NOSIGPIPE, to prevent them raising the signal in
739 * the first place.
740 */
741#ifdef SO_NOSIGPIPE
742 {
743 int set = 1;
744
745 setsockopt(sockfd, SOL_SOCKET, SO_NOSIGPIPE, (void *)&set, sizeof(int));
746 }
747#endif
748
749 if (connect(sockfd, (struct sockaddr *) &salocal, salen) < 0) {
750 /*
751 * POSIX says the only time we will get this,
752 * is if the socket has been marked as
753 * nonblocking. This is not an error, the caller
754 * must check the state of errno, and wait for
755 * the connection to complete.
756 */
757 if (errno == EINPROGRESS) return sockfd;
758
759 fr_strerror_printf("Failed connecting socket: %s", fr_syserror(errno));
760 close(sockfd);
761 return -1;
762 }
763
764 return sockfd;
765}
766
767/** Wait for a socket to be connected, with an optional timeout
768 *
769 * @note On error the caller is expected to ``close(sockfd)``.
770 *
771 * @param sockfd the socket to wait on.
772 * @param timeout How long to wait for socket to open.
773 * @return
774 * - 0 on success.
775 * - -1 on connection error.
776 * - -2 on timeout.
777 * - -3 on select error.
778 */
780{
781 int ret;
782 fd_set error_set;
783 fd_set write_set; /* POSIX says sockets are open when they become writable */
784
785 FD_ZERO(&error_set);
786 FD_ZERO(&write_set);
787
788 FD_SET(sockfd, &error_set);
789 FD_SET(sockfd, &write_set);
790
791 /* Don't let signals mess up the select */
792 do {
793 ret = select(sockfd + 1, NULL, &write_set, &error_set, &fr_time_delta_to_timeval(timeout));
794 } while ((ret == -1) && (errno == EINTR));
795
796 switch (ret) {
797 case 1: /* ok (maybe) */
798 {
799 int error;
800 socklen_t socklen = sizeof(error);
801
802 if (getsockopt(sockfd, SOL_SOCKET, SO_ERROR, (void *)&error, &socklen)) {
803 fr_strerror_printf("Failed connecting socket: %s", fr_syserror(errno));
804 return -1;
805 }
806
807 if (FD_ISSET(sockfd, &error_set)) {
808 fr_strerror_const("Failed connecting socket: Unknown error");
809 return -1;
810 }
811 }
812 return 0;
813
814 case 0: /* timeout */
815 if (!fr_cond_assert(fr_time_delta_ispos(timeout))) return -1;
816 fr_strerror_printf("Connection timed out after %pVs", fr_box_time_delta(timeout));
817 return -2;
818
819 case -1: /* select error */
820 fr_strerror_printf("Failed waiting for connection: %s", fr_syserror(errno));
821 return -3;
822
823 default:
824 (void)fr_cond_assert(0);
825 return -1;
826 }
827}
828
829/** Open an IPv4/IPv6 unconnected UDP socket
830 *
831 * Function name is a bit of a misnomer as it can also be used to create client sockets too,
832 * such is the nature of UDP.
833 *
834 * @param[in] src_ipaddr The IP address to listen on
835 * @param[in,out] src_port the port to listen on. If *port == 0, the resolved
836 * service port will be written here.
837 * @param[in] port_name if *port == 0, the name of the port
838 * @param[in] async whether we block or not on reads and writes
839 * @return
840 * - Socket FD on success.
841 * - -1 on failure.
842 */
843int fr_socket_server_udp(fr_ipaddr_t const *src_ipaddr, uint16_t *src_port, char const *port_name, bool async)
844{
845 int sockfd;
846 uint16_t my_port = 0;
847
848 if (src_port) my_port = *src_port;
849
850 /*
851 * Check IP looks OK
852 */
853 if (!src_ipaddr || ((src_ipaddr->af != AF_INET) && (src_ipaddr->af != AF_INET6))) {
854 fr_strerror_const("No address specified");
855 return -1;
856 }
857
858 /*
859 * Check we have a port value or stuff we can resolve to a port
860 */
861 if (!my_port && port_name) {
862 int ret;
863
864 ret = socket_port_from_service(IPPROTO_UDP, port_name);
865 if (ret < 0) return -1;
866
867 my_port = ret;
868 }
869
870 /*
871 * Open the socket
872 */
873 sockfd = socket(src_ipaddr->af, SOCK_DGRAM, IPPROTO_UDP);
874 if (sockfd < 0) {
875 fr_strerror_printf("Failed creating UDP socket: %s", fr_syserror(errno));
876 return -1;
877 }
878
879 /*
880 * Make it non-blocking if asked
881 */
882 if (async && (fr_nonblock(sockfd) < 0)) {
883 error:
884 close(sockfd);
885 return -1;
886 }
887
888 /*
889 * Don't allow child processes to inherit the socket
890 */
891 if (fr_cloexec(sockfd) < 0) goto error;
892
893 /*
894 * Initialize udpfromto for UDP sockets.
895 */
896 if (udpfromto_init(sockfd, src_ipaddr->af) != 0) {
897 fr_strerror_printf("Failed initializing udpfromto: %s", fr_syserror(errno));
898 goto error;
899 }
900
901 /*
902 * Make sure we don't get v4 and v6 packets on inaddr_any sockets.
903 */
904 if (socket_inaddr_any_v6only(sockfd, src_ipaddr) < 0) goto error;
905
906 /*
907 * Ensure don't fragment bit is set
908 */
909 if (socket_dont_fragment(sockfd, src_ipaddr->af) < 0) goto error;
910
911#ifdef SO_TIMESTAMP
912 {
913 int on = 1;
914
915 /*
916 * Enable receive timestamps, these should reflect
917 * when the packet was received, not when it was read
918 * from the socket.
919 */
920 if (setsockopt(sockfd, SOL_SOCKET, SO_TIMESTAMP, &on, sizeof(int)) < 0) {
921 close(sockfd);
922 fr_strerror_printf("Failed enabling socket timestamps: %s", fr_syserror(errno));
923 return -1;
924 }
925 }
926#endif
927
928 if (src_port) *src_port = my_port;
929
930 return sockfd;
931}
932
933/** Open an IPv4/IPv6 TCP socket
934 *
935 * @param[in] src_ipaddr The IP address to listen on
936 * @param[in,out] src_port the port to listen on. If *port == 0, the resolved
937 * service port will be written here.
938 * NULL if any port is allowed.
939 * @param[in] port_name if *port == 0, the name of the port
940 * @param[in] async whether we block or not on reads and writes
941 * @return
942 * - Socket FD on success.
943 * - -1 on failure.
944 */
945int fr_socket_server_tcp(fr_ipaddr_t const *src_ipaddr, uint16_t *src_port, char const *port_name, bool async)
946{
947 int sockfd;
948 uint16_t my_port = 0;
949
950 if (src_port) my_port = *src_port;
951
952 /*
953 * Check IP looks OK
954 */
955 if (!src_ipaddr || ((src_ipaddr->af != AF_INET) && (src_ipaddr->af != AF_INET6))) {
956 fr_strerror_const("No address specified");
957 return -1;
958 }
959
960 /*
961 * Check we have a port value or stuff we can resolve to a port
962 */
963 if (!my_port && port_name) {
964 int ret;
965
966 ret = socket_port_from_service(IPPROTO_TCP, port_name);
967 if (ret < 0) return -1;
968
969 my_port = ret;
970 }
971
972 /*
973 * Open the socket
974 */
975 sockfd = socket(src_ipaddr->af, SOCK_STREAM, IPPROTO_TCP);
976 if (sockfd < 0) {
977 fr_strerror_printf("Failed creating TCP socket: %s", fr_syserror(errno));
978 return -1;
979 }
980
981 /*
982 * Make it non-blocking if asked
983 */
984 if (async && (fr_nonblock(sockfd) < 0)) {
985 error:
986 close(sockfd);
987 return -1;
988 }
989
990 /*
991 * Don't allow child processes to inherit the socket
992 */
993 if (fr_cloexec(sockfd) < 0) goto error;
994
995 /*
996 * Make sure we don't get v4 and v6 packets on inaddr_any sockets.
997 */
998 if (socket_inaddr_any_v6only(sockfd, src_ipaddr) < 0) goto error;
999
1000 {
1001 int on = 1;
1002
1003 if (setsockopt(sockfd, SOL_SOCKET, SO_REUSEADDR, &on, sizeof(on)) < 0) {
1004 close(sockfd);
1005 fr_strerror_printf("Failed to reuse address: %s", fr_syserror(errno));
1006 return -1;
1007 }
1008 }
1009
1010 if (src_port) *src_port = my_port;
1011
1012 return sockfd;
1013}
#define UNCONST(_type, _ptr)
Remove const qualification from a pointer.
Definition build.h:186
#define unlikely(_x)
Definition build.h:407
#define UNUSED
Definition build.h:336
#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:131
static int sockfd
Definition dhcpclient.c:55
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
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
int af
Address family.
Definition inet.h:63
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:69
union fr_ipaddr_t::@137 addr
IPv4/6 prefix.
unsigned short uint16_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
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:945
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:843
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:779
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: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: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