28 #include <freeradius-devel/libradius.h>
29 #include <freeradius-devel/udpfromto.h>
36 # define SUN_LEN(su) (sizeof(*(su)) - sizeof((su)->sun_path) + strlen((su)->sun_path))
72 struct sockaddr_un saremote;
75 if (len >=
sizeof(saremote.sun_path)) {
76 fr_strerror_printf(
"Path too long, maximum length is %zu",
sizeof(saremote.sun_path) - 1);
81 sockfd = socket(AF_UNIX, SOCK_STREAM, 0);
92 saremote.sun_family = AF_UNIX;
93 memcpy(saremote.sun_path, path, len + 1);
95 socklen = SUN_LEN(&saremote);
109 setsockopt(sockfd, SOL_SOCKET, SO_NOSIGPIPE, (
void *)&set,
sizeof(
int));
113 if (connect(sockfd, (
struct sockaddr *)&saremote, socklen) < 0) {
121 if (errno == EINPROGRESS)
return sockfd;
133 fprintf(stderr,
"Unix domain sockets not supported on this system");
170 struct sockaddr_storage salocal;
173 if (!dst_ipaddr)
return -1;
175 sockfd = socket(dst_ipaddr->
af, SOCK_STREAM, 0);
189 if (src_ipaddr && (src_ipaddr->
af != AF_UNSPEC)) {
195 if (bind(sockfd, (
struct sockaddr *) &salocal, salen) < 0) {
219 setsockopt(sockfd, SOL_SOCKET, SO_NOSIGPIPE, (
void *)&set,
sizeof(
int));
223 if (connect(sockfd, (
struct sockaddr *) &salocal, salen) < 0) {
231 if (errno == EINPROGRESS)
return sockfd;
276 struct sockaddr_storage salocal;
279 if (!dst_ipaddr)
return -1;
281 sockfd = socket(dst_ipaddr->
af, SOCK_DGRAM, 0);
295 if (src_ipaddr && (src_ipaddr->
af != AF_UNSPEC)) {
301 if (bind(sockfd, (
struct sockaddr *) &salocal, salen) < 0) {
325 setsockopt(sockfd, SOL_SOCKET, SO_NOSIGPIPE, (
void *)&set,
sizeof(
int));
329 if (connect(sockfd, (
struct sockaddr *) &salocal, salen) < 0) {
337 if (errno == EINPROGRESS)
return sockfd;
369 FD_SET(sockfd, &error_set);
370 FD_SET(sockfd, &write_set);
374 ret = select(sockfd + 1, NULL, &write_set, &error_set, &tv);
375 }
while ((ret == -1) && (errno == EINTR));
381 socklen_t socklen =
sizeof(error);
383 if (getsockopt(sockfd, SOL_SOCKET, SO_ERROR, (
void *)&error, &socklen)) {
388 if (FD_ISSET(sockfd, &error_set)) {
398 (timeout->tv_sec * (uint64_t)1000) + (timeout->tv_usec / 1000));
430 if (!proto) proto = IPPROTO_UDP;
432 if ((proto != IPPROTO_UDP) && (proto != IPPROTO_TCP)) {
437 if (!ipaddr || ((ipaddr->
af != AF_INET) && (ipaddr->
af != AF_INET6))) {
444 char const *proto_name;
451 if (proto == IPPROTO_UDP) {
457 svp = getservbyname(port_name, proto_name);
464 *port = ntohs(svp->s_port);
467 if (proto == IPPROTO_UDP) {
468 sock_type = SOCK_DGRAM;
470 sock_type = SOCK_STREAM;
473 sockfd = socket(ipaddr->
af, sock_type, proto);
484 rcode = fcntl(sockfd, F_GETFD);
486 if (fcntl(sockfd, F_SETFD, rcode | FD_CLOEXEC) < 0) {
499 #ifdef WITH_UDPFROMTO
503 if ((proto == IPPROTO_UDP) && (udpfromto_init(sockfd) != 0)) {
510 #ifdef HAVE_STRUCT_SOCKADDR_IN6
517 if (ipaddr->
af == AF_INET6) {
519 if (IN6_IS_ADDR_UNSPECIFIED(&ipaddr->
ipaddr.ip6addr)) {
522 if (setsockopt(sockfd, IPPROTO_IPV6, IPV6_V6ONLY,
523 (
char *)&on,
sizeof(on)) < 0) {
533 #if (defined(IP_MTU_DISCOVER) && defined(IP_PMTUDISC_DONT)) || defined(IP_DONTFRAG)
539 if ((proto == IPPROTO_UDP) && (ipaddr->
af == AF_INET)) {
542 #if defined(IP_MTU_DISCOVER) && defined(IP_PMTUDISC_DONT)
549 flag = IP_PMTUDISC_DONT;
551 if (setsockopt(sockfd, IPPROTO_IP, IP_MTU_DISCOVER, &flag,
sizeof(flag)) < 0) {
558 #if defined(IP_DONTFRAG)
564 if (setsockopt(sockfd, IPPROTO_IP, IP_DONTFRAG, &flag,
sizeof(flag)) < 0) {
573 #if defined(WITH_TCP)
574 if (proto == IPPROTO_TCP) {
577 if (setsockopt(sockfd, SOL_SOCKET, SO_REUSEADDR, &on,
sizeof(on)) < 0) {
586 if (proto == IPPROTO_UDP) {
594 if (setsockopt(sockfd, SOL_SOCKET, SO_TIMESTAMP, &on,
sizeof(
int)) < 0) {
619 struct sockaddr_storage salocal;
626 #ifdef SO_BINDTODEVICE
629 memset(&ifreq, 0,
sizeof(ifreq));
630 strlcpy(ifreq.ifr_name, interface,
sizeof(ifreq.ifr_name));
632 rcode = setsockopt(sockfd, SOL_SOCKET, SO_BINDTODEVICE, (
char *)&ifreq,
sizeof(ifreq));
639 # ifdef HAVE_STRUCT_SOCKADDR_IN6
640 # ifdef HAVE_NET_IF_H
651 if (ipaddr->
af == AF_INET6) {
653 ipaddr->
zone_id = if_nametoindex(interface);
667 fr_strerror_printf(
"Failed binding to interface %s: \"bind to device\" is unsupported", interface);
683 rcode = bind(sockfd, (
struct sockaddr *) &salocal, salen);
684 if (rcode < 0)
return rcode;
691 salen =
sizeof(salocal);
692 memset(&salocal, 0, salen);
693 if (getsockname(sockfd, (
struct sockaddr *) &salocal, &salen) < 0) {
int fr_socket_client_unix(UNUSED char const *path, UNUSED bool async)
int fr_socket_client_udp(fr_ipaddr_t *src_ipaddr, fr_ipaddr_t *dst_ipaddr, uint16_t dst_port, bool async)
Establish a connected UDP socket.
int fr_ipaddr_from_sockaddr(struct sockaddr_storage const *sa, socklen_t salen, fr_ipaddr_t *ipaddr, uint16_t *port)
int fr_socket_server_bind(int sockfd, fr_ipaddr_t *ipaddr, int *port, char const *interface)
Bind to an IPv4 / IPv6, and UDP / TCP socket, server side.
static char const * proto
char const * fr_syserror(int num)
Guaranteed to be thread-safe version of strerror.
union fr_ipaddr_t::@1 ipaddr
int fr_socket_client_tcp(fr_ipaddr_t *src_ipaddr, fr_ipaddr_t *dst_ipaddr, uint16_t dst_port, bool async)
Establish a connected TCP socket.
uint32_t zone_id
A host may have multiple link-local interfaces the scope ID allows the application to specify which o...
int fr_socket_wait_for_connect(int sockfd, struct timeval const *timeout)
Wait for a socket to be connected, with an optional timeout.
void fr_strerror_printf(char const *,...) CC_HINT(format(printf
int fr_socket_server_base(int proto, fr_ipaddr_t *ipaddr, int *port, char const *port_name, bool async)
Open an IPv4 / IPv6, and UDP / TCP socket, server side.
size_t strlcpy(char *dst, char const *src, size_t siz)
int fr_ipaddr_to_sockaddr(fr_ipaddr_t const *ipaddr, uint16_t port, struct sockaddr_storage *sa, socklen_t *salen)