23 RCSID(
"$Id: 767168e032ce13288897a8657f2bd0ef6b42118e $")
25 #include <freeradius-devel/libradius.h>
28 #include <freeradius-devel/udpfromto.h>
47 if (a->
id < b->
id)
return -1;
48 if (a->
id > b->
id)
return +1;
57 if (rcode != 0)
return rcode;
63 if (rcode != 0)
return rcode;
71 if (rcode != 0)
return rcode;
94 if (ipaddr->
af == AF_INET) {
95 if (ipaddr->
ipaddr.ip4addr.s_addr == INADDR_ANY) {
99 #ifdef HAVE_STRUCT_SOCKADDR_IN6
100 }
else if (ipaddr->
af == AF_INET6) {
101 if (IN6_IS_ADDR_UNSPECIFIED(&(ipaddr->
ipaddr.ip6addr))) {
122 request->
id = reply->
id;
139 struct sockaddr_storage salocal;
142 sockfd = socket(ipaddr->
af, SOCK_DGRAM, 0);
148 #ifdef WITH_UDPFROMTO
152 if (udpfromto_init(sockfd) != 0) {
163 #ifdef HAVE_STRUCT_SOCKADDR_IN6
164 if (ipaddr->
af == AF_INET6) {
173 if (IN6_IS_ADDR_UNSPECIFIED(&ipaddr->
ipaddr.ip6addr)) {
176 if (setsockopt(sockfd, IPPROTO_IPV6, IPV6_V6ONLY,
177 (
char *)&on,
sizeof(on)) < 0) {
180 "IPPROTO_IPV6 - IPV6_V6ONLY"
189 #if (defined(IP_MTU_DISCOVER) && defined(IP_PMTUDISC_DONT)) || defined(IP_DONTFRAG)
190 if (ipaddr->
af == AF_INET) {
193 #if defined(IP_MTU_DISCOVER) && defined(IP_PMTUDISC_DONT)
200 flag = IP_PMTUDISC_DONT;
201 if (setsockopt(sockfd, IPPROTO_IP, IP_MTU_DISCOVER,
202 &flag,
sizeof(flag)) < 0) {
205 "IPPROTO_IP - IP_MTU_DISCOVER: %s",
211 #if defined(IP_DONTFRAG)
216 if (setsockopt(sockfd, IPPROTO_IP, IP_DONTFRAG,
217 &flag,
sizeof(flag)) < 0) {
220 "IPPROTO_IP - IP_DONTFRAG: %s",
228 if (bind(sockfd, (
struct sockaddr *) &salocal, salen) < 0) {
265 #define FNV_MAGIC_PRIME (0x01000193)
266 #define MAX_SOCKETS (256)
267 #define SOCKOFFSET_MASK (MAX_SOCKETS - 1)
268 #define SOCK2OFFSET(sockfd) ((sockfd * FNV_MAGIC_PRIME) & SOCKOFFSET_MASK)
300 }
while (i != start);
328 if (!pl)
return false;
331 if (!ps)
return false;
342 if (!pl)
return false;
345 if (!ps)
return false;
361 struct sockaddr_storage src;
362 socklen_t sizeof_src;
365 if (!pl || !dst_ipaddr || (dst_ipaddr->
af == AF_UNSPEC)) {
376 if (proto != IPPROTO_UDP) {
392 }
while (i != start);
399 memset(ps, 0,
sizeof(*ps));
412 sizeof_src =
sizeof(src);
413 memset(&src, 0, sizeof_src);
414 if (getsockname(sockfd, (
struct sockaddr *) &src,
430 if (ps->
src_any < 0)
return false;
433 if (ps->
dst_any < 0)
return false;
469 pl = malloc(
sizeof(*pl));
470 if (!pl)
return NULL;
471 memset(pl, 0,
sizeof(*pl));
496 if (!pl || !request_p || !*request_p)
return 0;
504 if (!pl || !request)
return 0;
519 if (!pl || !reply)
return NULL;
522 if (!ps)
return NULL;
531 my_request.
id = reply->
id;
537 if (ps->
proto == IPPROTO_TCP) {
565 request = &my_request;
575 if (!pl || !request)
return false;
578 if (!node)
return false;
614 int i, j, k, fd, id, start_i, start_j, start_k;
626 if ((proto != 0) && (proto != IPPROTO_UDP)) {
677 #define ID_i ((i + start_i) & SOCKOFFSET_MASK)
696 if (ps->
proto != proto)
continue;
723 (((request->
dst_ipaddr.
ipaddr.ip4addr.s_addr >> 24) & 0xff) != 127))
continue;
729 if (ps->
src_any && !src_any)
continue;
736 if (!ps->
src_any && !src_any &&
762 #define ID_j ((j + start_j) & 0x1f)
763 for (j = 0; j < 32; j++) {
764 if (ps->
id[
ID_j] == 0xff)
continue;
768 #define ID_k ((k + start_k) & 0x07)
769 for (k = 0; k < 8; k++) {
770 if ((ps->
id[
ID_j] & (1 <<
ID_k)) != 0)
continue;
806 if (pctx) *pctx = ps->
ctx;
816 ps->
id[(request->
id >> 3) & 0x1f] &= ~(1 << (request->
id & 0x07));
835 if (!pl || !request)
return false;
840 if (!ps)
return false;
843 if (!ps->
id[(request->
id >> 3) & 0x1f] & (1 << (request->
id & 0x07))) {
848 ps->
id[(request->
id >> 3) & 0x1f] &= ~(1 << (request->
id & 0x07));
869 if (!pl || !callback)
return 0;
878 if (!pl || !set)
return 0;
890 if (maxfd < 0)
return -1;
906 if (!pl || !set)
return NULL;
923 if (!packet)
continue;
942 uint32_t num_elements;
947 if (num_elements < pl->num_outgoing)
return 0;
966 #if defined(WITH_UDPFROMTO) && defined(WITH_IFINDEX_NAME_RESOLUTION)
967 char if_name[IFNAMSIZ];
980 fprintf(fp,
"%s %s Id %i from %s%s%s:%i to %s%s%s:%i "
981 #
if defined(WITH_UDPFROMTO) && defined(WITH_IFINDEX_NAME_RESOLUTION)
985 received ?
"Received" :
"Sent",
996 #
if defined(WITH_UDPFROMTO) && defined(WITH_IFINDEX_NAME_RESOLUTION)
997 received ?
"via " :
"",
998 received ? fr_ifname_from_ifindex(if_name, packet->
if_index) :
"",
1003 fprintf(fp,
"%s code %u Id %i from %s%s%s:%i to %s%s%s:%i "
1004 #
if defined(WITH_UDPFROMTO) && defined(WITH_IFINDEX_NAME_RESOLUTION)
1008 received ?
"Received" :
"Sent",
1019 #
if defined(WITH_UDPFROMTO) && defined(WITH_IFINDEX_NAME_RESOLUTION)
1020 received ?
"via " :
"",
1021 received ? fr_ifname_from_ifindex(if_name, packet->
if_index) :
"",
1022 received ?
" " :
"",
int sockfd
Socket this packet was read from.
int id
Packet ID (used to link requests/responses).
static fr_packet_socket_t * fr_socket_find(fr_packet_list_t *pl, int sockfd)
void rbtree_free(rbtree_t *tree)
uint32_t fr_packet_list_num_elements(fr_packet_list_t *pl)
int fr_ipaddr_from_sockaddr(struct sockaddr_storage const *sa, socklen_t salen, fr_ipaddr_t *ipaddr, uint16_t *port)
rbnode_t * rbtree_find(rbtree_t *tree, void const *data)
Find an element in the tree, returning the data, not the node.
bool fr_packet_list_socket_del(fr_packet_list_t *pl, int sockfd)
char const * fr_packet_codes[FR_MAX_PACKET_CODE]
void fr_request_from_reply(RADIUS_PACKET *request, RADIUS_PACKET const *reply)
uint32_t fr_rand(void)
Return a 32-bit random number.
fr_ipaddr_t src_ipaddr
Src IP address of packet.
uint32_t fr_packet_list_num_outgoing(fr_packet_list_t *pl)
bool fr_packet_list_id_alloc(fr_packet_list_t *pl, int proto, RADIUS_PACKET **request_p, void **pctx)
void * rbtree_finddata(rbtree_t *tree, void const *data)
Find the user data.
bool fr_packet_list_socket_thaw(fr_packet_list_t *pl, int sockfd)
uint16_t dst_port
DST Port of packet.
uint16_t src_port
Src port of packet.
fr_ipaddr_t dst_ipaddr
Dst IP address of packet.
struct fr_packet_socket_t fr_packet_socket_t
static char const * proto
#define FR_IPADDR_STRLEN
Like INET6_ADDRSTRLEN but includes space for the textual Zone ID.
char const * fr_syserror(int num)
Guaranteed to be thread-safe version of strerror.
rbtree_t * rbtree_create(TALLOC_CTX *ctx, rb_comparator_t compare, rb_free_t node_free, int flags)
Create a new RED-BLACK tree.
bool fr_packet_list_socket_freeze(fr_packet_list_t *pl, int sockfd)
fr_packet_socket_t sockets[MAX_SOCKETS]
void fr_packet_header_print(FILE *fp, RADIUS_PACKET *packet, bool received)
union fr_ipaddr_t::@1 ipaddr
int fr_packet_cmp(RADIUS_PACKET const *a, RADIUS_PACKET const *b)
unsigned int code
Packet code (type).
void rbtree_delete(rbtree_t *tree, rbnode_t *z)
bool fr_packet_list_socket_add(fr_packet_list_t *pl, int sockfd, int proto, fr_ipaddr_t *dst_ipaddr, uint16_t dst_port, void *ctx)
int rbtree_walk(rbtree_t *tree, rb_order_t order, rb_walker_t compare, void *context)
bool fr_packet_list_id_free(fr_packet_list_t *pl, RADIUS_PACKET *request, bool yank)
int(* rb_walker_t)(void *ctx, void *data)
int fr_packet_list_walk(fr_packet_list_t *pl, void *ctx, rb_walker_t callback)
int if_index
Index of receiving interface.
RADIUS_PACKET * fr_tcp_recv(int sockfd, int flags)
bool fr_packet_list_yank(fr_packet_list_t *pl, RADIUS_PACKET *request)
static int packet_entry_cmp(void const *one, void const *two)
int fr_packet_list_fd_set(fr_packet_list_t *pl, fd_set *set)
size_t data_len
Length of packet data.
bool rbtree_insert(rbtree_t *tree, void *data)
#define SOCK2OFFSET(sockfd)
void fr_strerror_printf(char const *,...) CC_HINT(format(printf
char * fr_inet_ntop(char out[FR_IPADDR_STRLEN], size_t outlen, fr_ipaddr_t *addr)
Print the address portion of a fr_ipaddr_t.
void fr_packet_list_free(fr_packet_list_t *pl)
int fr_socket(fr_ipaddr_t *ipaddr, uint16_t port)
RADIUS_PACKET ** fr_packet_list_find_byreply(fr_packet_list_t *pl, RADIUS_PACKET *reply)
int fr_is_inaddr_any(fr_ipaddr_t *ipaddr)
Determine if an address is the INADDR_ANY address for its address family.
RADIUS_PACKET * fr_radius_recv(TALLOC_CTX *ctx, int fd, int flags)
Receive UDP client requests, and fill in the basics of a RADIUS_PACKET structure. ...
fr_packet_list_t * fr_packet_list_create(int alloc_id)
RADIUS_PACKET * fr_packet_list_recv(fr_packet_list_t *pl, fd_set *set)
bool fr_packet_list_insert(fr_packet_list_t *pl, RADIUS_PACKET **request_p)
RADIUS_PACKET ** fr_packet_list_find(fr_packet_list_t *pl, RADIUS_PACKET *request)
int fr_ipaddr_cmp(fr_ipaddr_t const *a, fr_ipaddr_t const *b)
Compare two ip addresses.
uint32_t fr_packet_list_num_incoming(fr_packet_list_t *pl)
#define is_radius_code(_x)
int fr_ipaddr_to_sockaddr(fr_ipaddr_t const *ipaddr, uint16_t port, struct sockaddr_storage *sa, socklen_t *salen)
uint32_t rbtree_num_elements(rbtree_t *tree)