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>
48 struct servent *service;
49 char const *proto_name;
76 service = getservbyname(port_name, proto_name);
82 return ntohs(service->s_port);
94 ret = fcntl(
sockfd, F_GETFD);
111#ifdef HAVE_STRUCT_SOCKADDR_IN6
131 if (ipaddr->
af == AF_INET6) {
134 if (IN6_IS_ADDR_UNSPECIFIED(
UNCONST(
struct in6_addr *, &ipaddr->
addr.v6))) {
137 if (setsockopt(
sockfd, IPPROTO_IPV6, IPV6_V6ONLY,
138 (
char *)&on,
sizeof(on)) < 0) {
155#if (defined(IP_MTU_DISCOVER) && defined(IP_PMTUDISC_DONT)) || defined(IP_DONTFRAG)
174# if defined(IP_MTU_DISCOVER) && defined(IP_PMTUDISC_DONT)
180 flag = IP_PMTUDISC_DONT;
182 if (setsockopt(
sockfd, IPPROTO_IP, IP_MTU_DISCOVER, &flag,
sizeof(flag)) < 0) {
188# if defined(IP_DONTFRAG)
194 if (setsockopt(
sockfd, IPPROTO_IP, IP_DONTFRAG, &flag,
sizeof(flag)) < 0) {
232 struct sockaddr_storage salocal;
243 if (src_port)
my_port = *src_port;
252#ifdef HAVE_CAPABILITY_H
258 if (src_port && (*src_port < 1024) && (geteuid() != 0)) {
259 (void)fr_cap_enable(CAP_NET_BIND_SERVICE, CAP_EFFECTIVE);
268 unsigned int scope_id;
270 scope_id = if_nametoindex(ifname);
282 "to another interface", ifname);
287#ifdef SO_BINDTODEVICE
305#ifdef HAVE_CAPABILITY_H
306 (void)fr_cap_enable(CAP_NET_RAW, CAP_EFFECTIVE);
308 ret = setsockopt(
sockfd, SOL_SOCKET, SO_BINDTODEVICE, ifname, strlen(ifname));
326#elif defined(IP_BOUND_IF) || defined(IPV6_BOUND_IF)
331 if (
unlikely(setsockopt(
sockfd, IPPROTO_IP, IP_BOUND_IF, &idx,
sizeof(idx)) < 0)) {
339 if (
unlikely(setsockopt(
sockfd, IPPROTO_IPV6, IPV6_BOUND_IF, &idx,
sizeof(idx)) < 0))
goto error;
351 struct ifaddrs *list = NULL;
357 if (getifaddrs(&list) == 0) {
360 for (i = list; i != NULL; i = i->ifa_next) {
361 if (i->ifa_addr && i->ifa_name && (strcmp(i->ifa_name, ifname) == 0)) {
370 if ((i->ifa_addr->sa_family == AF_INET) &&
373 (
struct sockaddr_storage *) i->ifa_addr,
374 sizeof(
struct sockaddr_in));
392 if (src_ipaddr && (src_ipaddr->
af == i->ifa_addr->sa_family)) {
408 "interface with the given IP address.", ifname);
430 ret = bind(
sockfd, (
struct sockaddr *) &salocal, salen);
435 ifname ? ifname :
"*",
440 if (!src_port)
goto done;
447 salen =
sizeof(salocal);
448 memset(&salocal, 0, salen);
449 if (getsockname(
sockfd, (
struct sockaddr *) &salocal, &salen) < 0) {
459#ifdef HAVE_CAPABILITY_H
503 struct sockaddr_un saremote;
506 if (len >=
sizeof(saremote.sun_path)) {
507 fr_strerror_printf(
"Path too long, maximum length is %zu",
sizeof(saremote.sun_path) - 1);
512 sockfd = socket(AF_UNIX, SOCK_STREAM, 0);
523 saremote.sun_family = AF_UNIX;
524 memcpy(saremote.sun_path, path, len + 1);
526 socklen = SUN_LEN(&saremote);
540 setsockopt(
sockfd, SOL_SOCKET, SO_NOSIGPIPE, (
void *)&set,
sizeof(
int));
544 if (connect(
sockfd, (
struct sockaddr *)&saremote, socklen) < 0) {
552 if (errno == EINPROGRESS)
return sockfd;
564 fprintf(stderr,
"Unix domain sockets not supported on this system");
569#if defined SO_BINDTODEVICE || defined IP_BOUND_IF
575#if defined(SO_BINDTODEVICE)
576 if (setsockopt(
sockfd, SOL_SOCKET, SO_BINDTODEVICE, ifname, strlen(ifname)) < 0) {
580#elif defined(IP_BOUND_IF)
582 int idx = if_nametoindex(ifname);
588 if (
unlikely(setsockopt(
sockfd, IPPROTO_IP, IP_BOUND_IF, &idx,
sizeof(idx)) < 0))
goto error;
591 fr_strerror_const(
"Binding sockets to interfaces not supported on this platform");
636 struct sockaddr_storage salocal;
639 if (!dst_ipaddr)
return -1;
641 sockfd = socket(dst_ipaddr->
af, SOCK_DGRAM, 0);
665 setsockopt(
sockfd, SOL_SOCKET, SO_NOSIGPIPE, (
void *)&set,
sizeof(
int));
679 if (connect(
sockfd, (
struct sockaddr *) &salocal, salen) < 0) {
687 if (errno == EINPROGRESS)
return sockfd;
731 struct sockaddr_storage salocal;
734 if (!dst_ipaddr)
return -1;
736 sockfd = socket(dst_ipaddr->
af, SOCK_STREAM, 0);
767 setsockopt(
sockfd, SOL_SOCKET, SO_NOSIGPIPE, (
void *)&set,
sizeof(
int));
771 if (connect(
sockfd, (
struct sockaddr *) &salocal, salen) < 0) {
779 if (errno == EINPROGRESS)
return sockfd;
810 FD_SET(
sockfd, &error_set);
811 FD_SET(
sockfd, &write_set);
816 }
while ((ret == -1) && (errno == EINTR));
822 socklen_t socklen =
sizeof(error);
824 if (getsockopt(
sockfd, SOL_SOCKET, SO_ERROR, (
void *)&error, &socklen)) {
829 if (FD_ISSET(
sockfd, &error_set)) {
870 if (src_port)
my_port = *src_port;
875 if (!src_ipaddr || ((src_ipaddr->
af != AF_INET) && (src_ipaddr->
af != AF_INET6))) {
887 if (ret < 0)
return -1;
895 sockfd = socket(src_ipaddr->
af, SOCK_DGRAM, IPPROTO_UDP);
942 if (setsockopt(
sockfd, SOL_SOCKET, SO_TIMESTAMP, &on,
sizeof(
int)) < 0) {
950 if (src_port) *src_port =
my_port;
972 if (src_port)
my_port = *src_port;
977 if (!src_ipaddr || ((src_ipaddr->
af != AF_INET) && (src_ipaddr->
af != AF_INET6))) {
989 if (ret < 0)
return -1;
997 sockfd = socket(src_ipaddr->
af, SOCK_STREAM, IPPROTO_TCP);
1025 if (setsockopt(
sockfd, SOL_SOCKET, SO_REUSEADDR, &on,
sizeof(on)) < 0) {
1032 if (src_port) *src_port =
my_port;
#define UNCONST(_type, _ptr)
Remove const qualification from a pointer.
#define fr_cond_assert(_x)
Calls panic_action ifndef NDEBUG, else logs error and evaluates to value of _x.
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.
int fr_ipaddr_is_inaddr_any(fr_ipaddr_t const *ipaddr)
Determine if an address is the INADDR_ANY address for its address family.
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.
union fr_ipaddr_t::@133 addr
uint32_t scope_id
A host may have multiple link-local interfaces the scope ID allows the application to specify which o...
int fr_nonblock(UNUSED int fd)
static fr_ipaddr_t my_ipaddr
static socket_dont_inherit(UNUSED int sockfd)
static int socket_inaddr_any_v6only(UNUSED int sockfd, UNUSED fr_ipaddr_t const *ipaddr)
static int socket_port_from_service(int proto, char const *port_name)
Resolve a named service to a port.
static int socket_bind_ifname(UNUSED int sockfd, UNUSED char const *ifname)
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.
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.
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.
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.
static int socket_dont_fragment(UNUSED int sockfd, UNUSED int af)
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.
int fr_socket_wait_for_connect(int sockfd, fr_time_delta_t timeout)
Wait for a socket to be connected, with an optional timeout.
int fr_socket_client_unix(UNUSED char const *path, UNUSED bool async)
char const * fr_syserror(int num)
Guaranteed to be thread-safe version of strerror.
#define fr_time_delta_ispos(_a)
#define fr_time_delta_to_timeval(_delta)
Convert a delta to a timeval.
A time delta, a difference in time measured in nanoseconds.
int udpfromto_init(int s, int af)
void fr_strerror_clear(void)
Clears all pending messages from the talloc pools.
#define fr_strerror_printf(_fmt,...)
Log to thread local error buffer.
#define fr_strerror_printf_push(_fmt,...)
Add a message to an existing stack of messages at the tail.
#define fr_strerror_const(_msg)
#define fr_box_ipaddr(_val)
#define fr_box_strvalue(_val)
#define fr_box_int16(_val)
#define fr_box_time_delta(_val)