Coverage Report

Created: 2026-01-10 06:14

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