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) &&
347 (
struct sockaddr_storage *) i->ifa_addr,
348 sizeof(
struct sockaddr_in));
366 if (src_ipaddr && (src_ipaddr->
af == i->ifa_addr->sa_family)) {
382 "interface with the given IP address.", ifname);
404 ret = bind(
sockfd, (
struct sockaddr *) &salocal, salen);
409 ifname ? ifname :
"*",
414 if (!src_port)
goto done;
421 salen =
sizeof(salocal);
422 memset(&salocal, 0, salen);
423 if (getsockname(
sockfd, (
struct sockaddr *) &salocal, &salen) < 0) {
440#ifdef HAVE_CAPABILITY_H
484 struct sockaddr_un saremote;
487 if (len >=
sizeof(saremote.sun_path)) {
488 fr_strerror_printf(
"Path too long, maximum length is %zu",
sizeof(saremote.sun_path) - 1);
493 sockfd = socket(AF_UNIX, SOCK_STREAM, 0);
504 saremote.sun_family = AF_UNIX;
505 memcpy(saremote.sun_path, path, len + 1);
507 socklen = SUN_LEN(&saremote);
521 setsockopt(
sockfd, SOL_SOCKET, SO_NOSIGPIPE, (
void *)&set,
sizeof(
int));
525 if (connect(
sockfd, (
struct sockaddr *)&saremote, socklen) < 0) {
533 if (errno == EINPROGRESS)
return sockfd;
545 fprintf(stderr,
"Unix domain sockets not supported on this system");
550#if defined SO_BINDTODEVICE || defined IP_BOUND_IF
556#if defined(SO_BINDTODEVICE)
557 if (setsockopt(
sockfd, SOL_SOCKET, SO_BINDTODEVICE, ifname, strlen(ifname)) < 0) {
561#elif defined(IP_BOUND_IF)
563 int idx = if_nametoindex(ifname);
569 if (
unlikely(setsockopt(
sockfd, IPPROTO_IP, IP_BOUND_IF, &idx,
sizeof(idx)) < 0))
goto error;
572 fr_strerror_const(
"Binding sockets to interfaces not supported on this platform");
617 struct sockaddr_storage salocal;
620 if (!dst_ipaddr)
return -1;
622 sockfd = socket(dst_ipaddr->
af, SOCK_DGRAM, 0);
646 setsockopt(
sockfd, SOL_SOCKET, SO_NOSIGPIPE, (
void *)&set,
sizeof(
int));
660 if (connect(
sockfd, (
struct sockaddr *) &salocal, salen) < 0) {
668 if (errno == EINPROGRESS)
return sockfd;
712 struct sockaddr_storage salocal;
715 if (!dst_ipaddr)
return -1;
717 sockfd = socket(dst_ipaddr->
af, SOCK_STREAM, 0);
748 setsockopt(
sockfd, SOL_SOCKET, SO_NOSIGPIPE, (
void *)&set,
sizeof(
int));
752 if (connect(
sockfd, (
struct sockaddr *) &salocal, salen) < 0) {
760 if (errno == EINPROGRESS)
return sockfd;
791 FD_SET(
sockfd, &error_set);
792 FD_SET(
sockfd, &write_set);
797 }
while ((ret == -1) && (errno == EINTR));
803 socklen_t socklen =
sizeof(error);
805 if (getsockopt(
sockfd, SOL_SOCKET, SO_ERROR, (
void *)&error, &socklen)) {
810 if (FD_ISSET(
sockfd, &error_set)) {
851 if (src_port)
my_port = *src_port;
856 if (!src_ipaddr || ((src_ipaddr->
af != AF_INET) && (src_ipaddr->
af != AF_INET6))) {
868 if (ret < 0)
return -1;
876 sockfd = socket(src_ipaddr->
af, SOCK_DGRAM, IPPROTO_UDP);
923 if (setsockopt(
sockfd, SOL_SOCKET, SO_TIMESTAMP, &on,
sizeof(
int)) < 0) {
931 if (src_port) *src_port =
my_port;
953 if (src_port)
my_port = *src_port;
958 if (!src_ipaddr || ((src_ipaddr->
af != AF_INET) && (src_ipaddr->
af != AF_INET6))) {
970 if (ret < 0)
return -1;
978 sockfd = socket(src_ipaddr->
af, SOCK_STREAM, IPPROTO_TCP);
1006 if (setsockopt(
sockfd, SOL_SOCKET, SO_REUSEADDR, &on,
sizeof(on)) < 0) {
1013 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.
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::@137 addr
int fr_nonblock(UNUSED int fd)
int fr_cloexec(UNUSED int fd)
static fr_ipaddr_t my_ipaddr
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)