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/strerror.h>
31 #include <freeradius-devel/util/syserror.h>
32 #include <freeradius-devel/util/udpfromto.h>
33 #include <freeradius-devel/util/value.h>
34 #include <freeradius-devel/util/cap.h>
37 #include <sys/socket.h>
50 struct servent *service;
51 char const *proto_name;
78 service = getservbyname(port_name, proto_name);
84 return ntohs(service->s_port);
96 ret = fcntl(
sockfd, F_GETFD);
113 #ifdef HAVE_STRUCT_SOCKADDR_IN6
133 if (ipaddr->
af == AF_INET6) {
136 if (IN6_IS_ADDR_UNSPECIFIED(
UNCONST(
struct in6_addr *, &ipaddr->
addr.v6))) {
139 if (setsockopt(
sockfd, IPPROTO_IPV6, IPV6_V6ONLY,
140 (
char *)&on,
sizeof(on)) < 0) {
157 #if (defined(IP_MTU_DISCOVER) && defined(IP_PMTUDISC_DONT)) || defined(IP_DONTFRAG)
176 # if defined(IP_MTU_DISCOVER) && defined(IP_PMTUDISC_DONT)
182 flag = IP_PMTUDISC_DONT;
184 if (setsockopt(
sockfd, IPPROTO_IP, IP_MTU_DISCOVER, &flag,
sizeof(flag)) < 0) {
190 # if defined(IP_DONTFRAG)
196 if (setsockopt(
sockfd, IPPROTO_IP, IP_DONTFRAG, &flag,
sizeof(flag)) < 0) {
234 struct sockaddr_storage salocal;
245 if (src_port)
my_port = *src_port;
254 #ifdef HAVE_CAPABILITY_H
260 if (src_port && (*src_port < 1024) && (geteuid() != 0)) {
261 (void)fr_cap_enable(CAP_NET_BIND_SERVICE, CAP_EFFECTIVE);
270 unsigned int scope_id;
272 scope_id = if_nametoindex(ifname);
284 "to another interface", ifname);
289 #ifdef SO_BINDTODEVICE
307 #ifdef HAVE_CAPABILITY_H
308 (void)fr_cap_enable(CAP_NET_RAW, CAP_EFFECTIVE);
310 ret = setsockopt(
sockfd, SOL_SOCKET, SO_BINDTODEVICE, ifname, strlen(ifname));
328 #elif defined(IP_BOUND_IF) || defined(IPV6_BOUND_IF)
333 if (
unlikely(setsockopt(
sockfd, IPPROTO_IP, IP_BOUND_IF, &idx,
sizeof(idx)) < 0)) {
341 if (
unlikely(setsockopt(
sockfd, IPPROTO_IPV6, IPV6_BOUND_IF, &idx,
sizeof(idx)) < 0))
goto error;
353 struct ifaddrs *list = NULL;
359 if (getifaddrs(&list) == 0) {
362 for (i = list; i != NULL; i = i->ifa_next) {
363 if (i->ifa_addr && i->ifa_name && (strcmp(i->ifa_name, ifname) == 0)) {
372 if ((i->ifa_addr->sa_family == AF_INET) &&
375 (
struct sockaddr_storage *) i->ifa_addr,
376 sizeof(
struct sockaddr_in));
394 if (src_ipaddr && (src_ipaddr->
af == i->ifa_addr->sa_family)) {
410 "interface with the given IP address.", ifname);
432 ret = bind(
sockfd, (
struct sockaddr *) &salocal, salen);
437 ifname ? ifname :
"*",
442 if (!src_port)
goto done;
449 salen =
sizeof(salocal);
450 memset(&salocal, 0, salen);
451 if (getsockname(
sockfd, (
struct sockaddr *) &salocal, &salen) < 0) {
461 #ifdef HAVE_CAPABILITY_H
505 struct sockaddr_un saremote;
508 if (len >=
sizeof(saremote.sun_path)) {
509 fr_strerror_printf(
"Path too long, maximum length is %zu",
sizeof(saremote.sun_path) - 1);
514 sockfd = socket(AF_UNIX, SOCK_STREAM, 0);
525 saremote.sun_family = AF_UNIX;
526 memcpy(saremote.sun_path, path, len + 1);
528 socklen = SUN_LEN(&saremote);
542 setsockopt(
sockfd, SOL_SOCKET, SO_NOSIGPIPE, (
void *)&set,
sizeof(
int));
546 if (connect(
sockfd, (
struct sockaddr *)&saremote, socklen) < 0) {
554 if (errno == EINPROGRESS)
return sockfd;
566 fprintf(stderr,
"Unix domain sockets not supported on this system");
571 #if defined SO_BINDTODEVICE || defined IP_BOUND_IF
577 #if defined(SO_BINDTODEVICE)
578 if (setsockopt(
sockfd, SOL_SOCKET, SO_BINDTODEVICE, ifname, strlen(ifname)) < 0) {
582 #elif defined(IP_BOUND_IF)
584 int idx = if_nametoindex(ifname);
590 if (
unlikely(setsockopt(
sockfd, IPPROTO_IP, IP_BOUND_IF, &idx,
sizeof(idx)) < 0))
goto error;
593 fr_strerror_const(
"Binding sockets to interfaces not supported on this platform");
638 struct sockaddr_storage salocal;
641 if (!dst_ipaddr)
return -1;
643 sockfd = socket(dst_ipaddr->
af, SOCK_DGRAM, 0);
667 setsockopt(
sockfd, SOL_SOCKET, SO_NOSIGPIPE, (
void *)&set,
sizeof(
int));
681 if (connect(
sockfd, (
struct sockaddr *) &salocal, salen) < 0) {
689 if (errno == EINPROGRESS)
return sockfd;
733 struct sockaddr_storage salocal;
736 if (!dst_ipaddr)
return -1;
738 sockfd = socket(dst_ipaddr->
af, SOCK_STREAM, 0);
769 setsockopt(
sockfd, SOL_SOCKET, SO_NOSIGPIPE, (
void *)&set,
sizeof(
int));
773 if (connect(
sockfd, (
struct sockaddr *) &salocal, salen) < 0) {
781 if (errno == EINPROGRESS)
return sockfd;
812 FD_SET(
sockfd, &error_set);
813 FD_SET(
sockfd, &write_set);
818 }
while ((ret == -1) && (errno == EINTR));
824 socklen_t socklen =
sizeof(error);
826 if (getsockopt(
sockfd, SOL_SOCKET, SO_ERROR, (
void *)&error, &socklen)) {
831 if (FD_ISSET(
sockfd, &error_set)) {
872 if (src_port)
my_port = *src_port;
877 if (!src_ipaddr || ((src_ipaddr->
af != AF_INET) && (src_ipaddr->
af != AF_INET6))) {
889 if (ret < 0)
return -1;
897 sockfd = socket(src_ipaddr->
af, SOCK_DGRAM, IPPROTO_UDP);
944 if (setsockopt(
sockfd, SOL_SOCKET, SO_TIMESTAMP, &on,
sizeof(
int)) < 0) {
952 if (src_port) *src_port =
my_port;
974 if (src_port)
my_port = *src_port;
979 if (!src_ipaddr || ((src_ipaddr->
af != AF_INET) && (src_ipaddr->
af != AF_INET6))) {
991 if (ret < 0)
return -1;
999 sockfd = socket(src_ipaddr->
af, SOCK_STREAM, IPPROTO_TCP);
1027 if (setsockopt(
sockfd, SOL_SOCKET, SO_REUSEADDR, &on,
sizeof(on)) < 0) {
1034 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.
static fr_time_delta_t timeout
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::@130 addr
int fr_nonblock(UNUSED int fd)
static fr_ipaddr_t my_ipaddr
static char const * proto(int id, int porttype)
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)