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;
235 unsigned int scope_id = 0;
246 if (src_port)
my_port = *src_port;
255#ifdef HAVE_CAPABILITY_H
261 if (src_port && (*src_port < 1024) && (geteuid() != 0)) {
262 (void)fr_cap_enable(CAP_NET_BIND_SERVICE, CAP_EFFECTIVE);
271 scope_id = if_nametoindex(ifname);
283 "to another interface", ifname);
288#ifdef SO_BINDTODEVICE
306#ifdef HAVE_CAPABILITY_H
307 (void)fr_cap_enable(CAP_NET_RAW, CAP_EFFECTIVE);
309 ret = setsockopt(
sockfd, SOL_SOCKET, SO_BINDTODEVICE, ifname, strlen(ifname));
327#elif defined(IP_BOUND_IF) || defined(IPV6_BOUND_IF)
332 if (
unlikely(setsockopt(
sockfd, IPPROTO_IP, IP_BOUND_IF, &idx,
sizeof(idx)) < 0)) {
340 if (
unlikely(setsockopt(
sockfd, IPPROTO_IPV6, IPV6_BOUND_IF, &idx,
sizeof(idx)) < 0))
goto error;
352 struct ifaddrs *list = NULL;
358 if (getifaddrs(&list) == 0) {
361 for (i = list; i != NULL; i = i->ifa_next) {
362 if (i->ifa_addr && i->ifa_name && (strcmp(i->ifa_name, ifname) == 0)) {
371 if ((i->ifa_addr->sa_family == AF_INET) &&
374 (
struct sockaddr_storage *) i->ifa_addr,
375 sizeof(
struct sockaddr_in));
393 if (src_ipaddr && (src_ipaddr->
af == i->ifa_addr->sa_family)) {
409 "interface with the given IP address.", ifname);
431 ret = bind(
sockfd, (
struct sockaddr *) &salocal, salen);
436 ifname ? ifname :
"*",
441 if (!src_port)
goto done;
448 salen =
sizeof(salocal);
449 memset(&salocal, 0, salen);
450 if (getsockname(
sockfd, (
struct sockaddr *) &salocal, &salen) < 0) {
467#ifdef HAVE_CAPABILITY_H
511 struct sockaddr_un saremote;
514 if (len >=
sizeof(saremote.sun_path)) {
515 fr_strerror_printf(
"Path too long, maximum length is %zu",
sizeof(saremote.sun_path) - 1);
520 sockfd = socket(AF_UNIX, SOCK_STREAM, 0);
531 saremote.sun_family = AF_UNIX;
532 memcpy(saremote.sun_path, path, len + 1);
534 socklen = SUN_LEN(&saremote);
548 setsockopt(
sockfd, SOL_SOCKET, SO_NOSIGPIPE, (
void *)&set,
sizeof(
int));
552 if (connect(
sockfd, (
struct sockaddr *)&saremote, socklen) < 0) {
560 if (errno == EINPROGRESS)
return sockfd;
572 fprintf(stderr,
"Unix domain sockets not supported on this system");
577#if defined SO_BINDTODEVICE || defined IP_BOUND_IF
583#if defined(SO_BINDTODEVICE)
584 if (setsockopt(
sockfd, SOL_SOCKET, SO_BINDTODEVICE, ifname, strlen(ifname)) < 0) {
588#elif defined(IP_BOUND_IF)
590 int idx = if_nametoindex(ifname);
596 if (
unlikely(setsockopt(
sockfd, IPPROTO_IP, IP_BOUND_IF, &idx,
sizeof(idx)) < 0))
goto error;
599 fr_strerror_const(
"Binding sockets to interfaces not supported on this platform");
644 struct sockaddr_storage salocal;
647 if (!dst_ipaddr)
return -1;
649 sockfd = socket(dst_ipaddr->
af, SOCK_DGRAM, 0);
673 setsockopt(
sockfd, SOL_SOCKET, SO_NOSIGPIPE, (
void *)&set,
sizeof(
int));
687 if (connect(
sockfd, (
struct sockaddr *) &salocal, salen) < 0) {
695 if (errno == EINPROGRESS)
return sockfd;
739 struct sockaddr_storage salocal;
742 if (!dst_ipaddr)
return -1;
744 sockfd = socket(dst_ipaddr->
af, SOCK_STREAM, 0);
775 setsockopt(
sockfd, SOL_SOCKET, SO_NOSIGPIPE, (
void *)&set,
sizeof(
int));
779 if (connect(
sockfd, (
struct sockaddr *) &salocal, salen) < 0) {
787 if (errno == EINPROGRESS)
return sockfd;
818 FD_SET(
sockfd, &error_set);
819 FD_SET(
sockfd, &write_set);
824 }
while ((ret == -1) && (errno == EINTR));
830 socklen_t socklen =
sizeof(error);
832 if (getsockopt(
sockfd, SOL_SOCKET, SO_ERROR, (
void *)&error, &socklen)) {
837 if (FD_ISSET(
sockfd, &error_set)) {
878 if (src_port)
my_port = *src_port;
883 if (!src_ipaddr || ((src_ipaddr->
af != AF_INET) && (src_ipaddr->
af != AF_INET6))) {
895 if (ret < 0)
return -1;
903 sockfd = socket(src_ipaddr->
af, SOCK_DGRAM, IPPROTO_UDP);
950 if (setsockopt(
sockfd, SOL_SOCKET, SO_TIMESTAMP, &on,
sizeof(
int)) < 0) {
958 if (src_port) *src_port =
my_port;
980 if (src_port)
my_port = *src_port;
985 if (!src_ipaddr || ((src_ipaddr->
af != AF_INET) && (src_ipaddr->
af != AF_INET6))) {
997 if (ret < 0)
return -1;
1005 sockfd = socket(src_ipaddr->
af, SOCK_STREAM, IPPROTO_TCP);
1033 if (setsockopt(
sockfd, SOL_SOCKET, SO_REUSEADDR, &on,
sizeof(on)) < 0) {
1040 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::@136 addr
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)