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);
85#ifdef HAVE_STRUCT_SOCKADDR_IN6
105 if (ipaddr->
af == AF_INET6) {
108 if (IN6_IS_ADDR_UNSPECIFIED(
UNCONST(
struct in6_addr *, &ipaddr->
addr.v6))) {
111 if (setsockopt(
sockfd, IPPROTO_IPV6, IPV6_V6ONLY,
112 (
char *)&on,
sizeof(on)) < 0) {
128#if (defined(IP_MTU_DISCOVER) && defined(IP_PMTUDISC_DONT)) || defined(IP_DONTFRAG)
147# if defined(IP_MTU_DISCOVER) && defined(IP_PMTUDISC_DONT)
153 flag = IP_PMTUDISC_DONT;
155 if (setsockopt(
sockfd, IPPROTO_IP, IP_MTU_DISCOVER, &flag,
sizeof(flag)) < 0) {
161# if defined(IP_DONTFRAG)
167 if (setsockopt(
sockfd, IPPROTO_IP, IP_DONTFRAG, &flag,
sizeof(flag)) < 0) {
205 struct sockaddr_storage salocal;
208 unsigned int scope_id = 0;
219 if (src_port)
my_port = *src_port;
228#ifdef HAVE_CAPABILITY_H
234 if (src_port && (*src_port < 1024) && (geteuid() != 0)) {
244 scope_id = if_nametoindex(ifname);
256 "to another interface", ifname);
261#ifdef SO_BINDTODEVICE
279#ifdef HAVE_CAPABILITY_H
282 ret = setsockopt(
sockfd, SOL_SOCKET, SO_BINDTODEVICE, ifname, strlen(ifname));
300#elif defined(IP_BOUND_IF) || defined(IPV6_BOUND_IF)
305 if (
unlikely(setsockopt(
sockfd, IPPROTO_IP, IP_BOUND_IF, &idx,
sizeof(idx)) < 0)) {
313 if (
unlikely(setsockopt(
sockfd, IPPROTO_IPV6, IPV6_BOUND_IF, &idx,
sizeof(idx)) < 0))
goto error;
325 struct ifaddrs *list = NULL;
331 if (getifaddrs(&list) == 0) {
334 for (i = list; i != NULL; i = i->ifa_next) {
335 if (i->ifa_addr && i->ifa_name && (strcmp(i->ifa_name, ifname) == 0)) {
344 if ((i->ifa_addr->sa_family == AF_INET) &&
364 if (src_ipaddr && (src_ipaddr->
af == i->ifa_addr->sa_family)) {
380 "interface with the given IP address.", ifname);
402 ret = bind(
sockfd, (
struct sockaddr *) &salocal, salen);
407 ifname ? ifname :
"*",
412 if (!src_port)
goto done;
419 salen =
sizeof(salocal);
420 memset(&salocal, 0, salen);
421 if (getsockname(
sockfd, (
struct sockaddr *) &salocal, &salen) < 0) {
438#ifdef HAVE_CAPABILITY_H
482 struct sockaddr_un saremote;
485 if (
len >=
sizeof(saremote.sun_path)) {
486 fr_strerror_printf(
"Path too long, maximum length is %zu",
sizeof(saremote.sun_path) - 1);
491 sockfd = socket(AF_UNIX, SOCK_STREAM, 0);
502 saremote.sun_family = AF_UNIX;
503 memcpy(saremote.sun_path, path,
len + 1);
505 socklen = SUN_LEN(&saremote);
519 setsockopt(
sockfd, SOL_SOCKET, SO_NOSIGPIPE, (
void *)&set,
sizeof(
int));
523 if (connect(
sockfd, (
struct sockaddr *)&saremote, socklen) < 0) {
531 if (errno == EINPROGRESS)
return sockfd;
543 fprintf(stderr,
"Unix domain sockets not supported on this system");
548#if defined SO_BINDTODEVICE || defined IP_BOUND_IF
554#if defined(SO_BINDTODEVICE)
555 if (setsockopt(
sockfd, SOL_SOCKET, SO_BINDTODEVICE, ifname, strlen(ifname)) < 0) {
559#elif defined(IP_BOUND_IF)
561 int idx = if_nametoindex(ifname);
567 if (
unlikely(setsockopt(
sockfd, IPPROTO_IP, IP_BOUND_IF, &idx,
sizeof(idx)) < 0))
goto error;
570 fr_strerror_const(
"Binding sockets to interfaces not supported on this platform");
615 struct sockaddr_storage salocal;
618 if (!dst_ipaddr)
return -1;
620 sockfd = socket(dst_ipaddr->
af, SOCK_DGRAM, 0);
644 setsockopt(
sockfd, SOL_SOCKET, SO_NOSIGPIPE, (
void *)&set,
sizeof(
int));
658 if (connect(
sockfd, (
struct sockaddr *) &salocal, salen) < 0) {
666 if (errno == EINPROGRESS)
return sockfd;
710 struct sockaddr_storage salocal;
713 if (!dst_ipaddr)
return -1;
715 sockfd = socket(dst_ipaddr->
af, SOCK_STREAM, 0);
743 setsockopt(
sockfd, SOL_SOCKET, SO_NOSIGPIPE, (
void *)&set,
sizeof(
int));
747 if (connect(
sockfd, (
struct sockaddr *) &salocal, salen) < 0) {
755 if (errno == EINPROGRESS)
return sockfd;
786 FD_SET(
sockfd, &error_set);
787 FD_SET(
sockfd, &write_set);
792 }
while ((ret == -1) && (errno == EINTR));
798 socklen_t socklen =
sizeof(error);
800 if (getsockopt(
sockfd, SOL_SOCKET, SO_ERROR, (
void *)&error, &socklen)) {
805 if (FD_ISSET(
sockfd, &error_set)) {
846 if (src_port)
my_port = *src_port;
851 if (!src_ipaddr || ((src_ipaddr->
af != AF_INET) && (src_ipaddr->
af != AF_INET6))) {
863 if (ret < 0)
return -1;
871 sockfd = socket(src_ipaddr->
af, SOCK_DGRAM, IPPROTO_UDP);
918 if (setsockopt(
sockfd, SOL_SOCKET, SO_TIMESTAMP, &on,
sizeof(
int)) < 0) {
926 if (src_port) *src_port =
my_port;
948 if (src_port)
my_port = *src_port;
953 if (!src_ipaddr || ((src_ipaddr->
af != AF_INET) && (src_ipaddr->
af != AF_INET6))) {
965 if (ret < 0)
return -1;
973 sockfd = socket(src_ipaddr->
af, SOCK_STREAM, IPPROTO_TCP);
1001 if (setsockopt(
sockfd, SOL_SOCKET, SO_REUSEADDR, &on,
sizeof(on)) < 0) {
1008 if (src_port) *src_port =
my_port;
1019 static char const *sense[2] = {
"to",
"from" };
1022#ifdef WITH_IFINDEX_NAME_RESOLUTION
1023 char if_name[IFNAMSIZ];
1029 src_ip =
fr_inet_ntop(src_ip_buffer,
sizeof(src_ip_buffer), &sock->inet.src_ipaddr);
1030 if (!src_ip)
return 0;
1032 dst_ip =
fr_inet_ntop(dst_ip_buffer,
sizeof(dst_ip_buffer), &sock->inet.dst_ipaddr);
1033 if (!dst_ip)
return 0;
1035 slen =
snprintf(
out, outlen,
"%s %s%s%s:%u %s %s%s%s:%u",
1037 sock->
af == AF_INET6 ?
"[" :
"",
1039 sock->
af == AF_INET6 ?
"]" :
"",
1040 sock->inet.src_port,
1043 sock->
af == AF_INET6 ?
"[" :
"",
1045 sock->
af == AF_INET6 ?
"]" :
"",
1046 sock->inet.dst_port);
1048#ifndef WITH_IFINDEX_NAME_RESOLUTION
1055 if (slen <= 0)
return slen;
1056 if ((
size_t) slen > outlen)
return -slen;
1061 if (!sock->inet.ifindex)
return slen;
1067 fr_ifname_from_ifindex(if_name, sock->inet.ifindex));
1072 slen =
snprintf(
out, outlen,
"%s unix path %s", sense[received], sock->unix.path);
1076 slen =
snprintf(
out, outlen,
"%s filename %s", sense[received], sock->file.path);
1080 slen =
snprintf(
out, outlen,
"%s virtual server %s", sense[received], sock->virtual.server);
1088 if (slen <= 0)
return slen;
1089 if ((
size_t) slen > outlen)
return -slen;
#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_ifaddr(fr_ipaddr_t *ipaddr, struct sockaddr const *ifa_addr)
Convert an address from getifaddrs() to our internal ip address representation.
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.
char * fr_inet_ntop(char out[static FR_IPADDR_STRLEN], size_t outlen, fr_ipaddr_t const *addr)
Print the address portion of a fr_ipaddr_t.
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.
#define FR_IPADDR_STRLEN
Like INET6_ADDRSTRLEN but includes space for the textual Zone ID.
#define AF_FR_VIRTUAL_SERVER
uint32_t scope_id
A host may have multiple link-local interfaces the scope ID allows the application to specify which o...
union fr_ipaddr_t::@161 addr
int fr_nonblock(UNUSED int fd)
int fr_cloexec(UNUSED int fd)
static fr_ipaddr_t my_ipaddr
PUBLIC int snprintf(char *string, size_t length, char *format, va_alist)
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.
ssize_t fr_socket_to_str(char *out, size_t outlen, fr_socket_t const *sock, bool received)
Print an fr_socket_t to a string.
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)
int af
AF_INET, AF_INET6, or AF_UNIX.
Holds information necessary for binding or connecting to a socket.
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)
static fr_sbuff_err_t char ** out
static fr_sbuff_err_t char size_t * len
#define fr_box_strvalue(_val)
#define fr_box_int16(_val)
#define fr_box_time_delta(_val)