26 RCSID(
"$Id: ab15108eea328b709a49969ad465ce5d3a491efb $")
33 #include <freeradius-devel/util/udp.h>
34 #include <freeradius-devel/util/syserror.h>
64 if (ret != 0)
return ret;
76 request->
id = reply->
id;
97 #define FNV_MAGIC_PRIME (0x01000193)
98 #define MAX_SOCKETS (256)
99 #define SOCKOFFSET_MASK (MAX_SOCKETS - 1)
100 #define SOCK2OFFSET(_sockfd) ((_sockfd * FNV_MAGIC_PRIME) & SOCKOFFSET_MASK)
131 }
while (i != start);
159 if (!pl)
return false;
162 if (!ps)
return false;
173 if (!pl)
return false;
176 if (!ps)
return false;
192 struct sockaddr_storage src;
193 socklen_t sizeof_src;
196 if (!pl || !dst_ipaddr || (dst_ipaddr->
af == AF_UNSPEC)) {
216 }
while (i != start);
223 memset(ps, 0,
sizeof(*ps));
234 sizeof_src =
sizeof(src);
235 memset(&src, 0, sizeof_src);
236 if (getsockname(
sockfd, (
struct sockaddr *) &src, &sizeof_src) < 0) {
246 ps->
socket.inet.dst_ipaddr = *dst_ipaddr;
247 ps->
socket.inet.dst_port = dst_port;
250 if (ps->
src_any < 0)
return false;
253 if (ps->
dst_any < 0)
return false;
282 if (!pl)
return NULL;
306 if (!pl || !request)
return 0;
313 if (!pl || !request)
return 0;
328 if (!pl || !reply)
return NULL;
331 if (!ps)
return NULL;
343 my_request.
socket.inet.dst_ipaddr = reply->
socket.inet.src_ipaddr;
344 my_request.
socket.inet.dst_port = reply->
socket.inet.src_port;
354 my_request.
id = reply->
id;
355 request = &my_request;
363 if (!pl || !request)
return false;
398 int i, j, k, fd, id, start_i, start_j, start_k;
403 if ((request->
socket.inet.dst_ipaddr.
af == AF_UNSPEC) ||
404 (request->
socket.inet.dst_port == 0)) {
412 if (request->
socket.inet.src_ipaddr.
af == AF_UNSPEC) {
413 memset(&request->
socket.inet.src_ipaddr, 0,
sizeof(request->
socket.inet.src_ipaddr));
452 if (request->
id >= 0 && request->
id < 256)
456 type = (
proto == IPPROTO_TCP) ? SOCK_STREAM : SOCK_DGRAM;
458 #define ID_i ((i + start_i) & SOCKOFFSET_MASK)
481 if (ps->
socket.inet.src_ipaddr.
af != request->
socket.inet.dst_ipaddr.
af)
continue;
486 if ((ps->
socket.inet.dst_port != 0) &&
487 (ps->
socket.inet.dst_port != request->
socket.inet.dst_port))
continue;
492 if ((request->
socket.inet.src_port != 0) &&
493 (ps->
socket.inet.src_port != request->
socket.inet.src_port))
continue;
500 if (src_any && (ps->
socket.inet.src_ipaddr.
af == AF_INET) &&
501 (((ps->
socket.inet.src_ipaddr.addr.v4.s_addr >> 24) & 0xff) == 127) &&
502 (((request->
socket.inet.dst_ipaddr.addr.v4.s_addr >> 24) & 0xff) != 127))
continue;
508 if (ps->
src_any && !src_any)
continue;
515 if (!ps->
src_any && !src_any &&
517 &ps->
socket.inet.src_ipaddr) != 0))
continue;
531 &ps->
socket.inet.dst_ipaddr) != 0))
continue;
542 if ((ps->
id[(
id >> 3) & 0x1f] & (1 << (
id & 0x07))) != 0)
continue;
544 ps->
id[(
id >> 3) & 0x1f] |= (1 << (
id & 0x07));
553 #define ID_j ((j + start_j) & 0x1f)
554 for (j = 0; j < 32; j++) {
555 if (ps->
id[
ID_j] == 0xff)
continue;
559 #define ID_k ((k + start_k) & 0x07)
560 for (k = 0; k < 8; k++) {
561 if ((ps->
id[
ID_j] & (1 <<
ID_k)) != 0)
continue;
590 request->
socket.inet.src_ipaddr = ps->
socket.inet.src_ipaddr;
591 request->
socket.inet.src_port = ps->
socket.inet.src_port;
597 if (pctx) *pctx = ps->
ctx;
607 ps->
id[(request->
id >> 3) & 0x1f] &= ~(1 << (request->
id & 0x07));
611 request->
socket.inet.src_ipaddr.
af = AF_UNSPEC;
612 request->
socket.inet.src_port = 0;
626 if (!pl || !request)
return false;
631 if (!ps)
return false;
633 ps->
id[(request->
id >> 3) & 0x1f] &= ~(1 << (request->
id & 0x07));
639 request->
socket.inet.src_ipaddr.
af = AF_UNSPEC;
640 request->
socket.inet.src_port = 0;
649 if (!pl || !set)
return 0;
661 if (maxfd < 0)
return -1;
677 if (!pl || !set)
return NULL;
692 max_attributes, require_message_authenticator);
693 if (!packet)
continue;
715 if (num_elements < pl->num_outgoing)
return 0;
#define CMP_RETURN(_a, _b, _field)
Return if the comparison is not 0 (is unequal)
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.
int8_t fr_ipaddr_cmp(fr_ipaddr_t const *a, fr_ipaddr_t const *b)
Compare two ip addresses.
fr_packet_t * fr_packet_list_recv(fr_packet_list_t *pl, fd_set *set, uint32_t max_attributes, bool require_message_authenticator)
uint32_t fr_packet_list_num_incoming(fr_packet_list_t *pl)
void fr_packet_list_free(fr_packet_list_t *pl)
uint32_t fr_packet_list_num_outgoing(fr_packet_list_t *pl)
static fr_packet_socket_t * fr_socket_find(fr_packet_list_t *pl, int sockfd)
int8_t fr_packet_cmp(void const *a_v, void const *b_v)
bool fr_packet_list_socket_del(fr_packet_list_t *pl, int sockfd)
fr_packet_socket_t sockets[MAX_SOCKETS]
fr_packet_t * fr_packet_list_find(fr_packet_list_t *pl, fr_packet_t *request)
bool fr_packet_list_socket_freeze(fr_packet_list_t *pl, int sockfd)
fr_packet_list_t * fr_packet_list_create(int alloc_id)
fr_packet_t * fr_packet_list_find_byreply(fr_packet_list_t *pl, fr_packet_t *reply)
#define SOCK2OFFSET(_sockfd)
bool fr_packet_list_socket_thaw(fr_packet_list_t *pl, int sockfd)
bool fr_packet_list_id_alloc(fr_packet_list_t *pl, int proto, fr_packet_t *request, void **pctx)
bool fr_packet_list_yank(fr_packet_list_t *pl, fr_packet_t *request)
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)
void fr_request_from_reply(fr_packet_t *request, fr_packet_t const *reply)
bool fr_packet_list_insert(fr_packet_list_t *pl, fr_packet_t *request)
uint32_t fr_packet_list_num_elements(fr_packet_list_t *pl)
int fr_packet_list_fd_set(fr_packet_list_t *pl, fd_set *set)
bool fr_packet_list_id_free(fr_packet_list_t *pl, fr_packet_t *request, bool yank)
Constants for the RADIUS protocol.
fr_packet_t * fr_packet_recv(TALLOC_CTX *ctx, int fd, int flags, uint32_t max_attributes, bool require_message_authenticator)
Receive UDP client requests, and fill in the basics of a fr_packet_t structure.
static char const * proto(int id, int porttype)
uint32_t fr_rand(void)
Return a 32-bit random number.
uint32_t fr_rb_num_elements(fr_rb_tree_t *tree)
#define fr_rb_inline_alloc(_ctx, _type, _field, _data_cmp, _data_free)
Allocs a red black tree.
bool fr_rb_insert(fr_rb_tree_t *tree, void const *data)
bool fr_rb_delete(fr_rb_tree_t *tree, void const *data)
void * fr_rb_find(fr_rb_tree_t const *tree, void const *data)
The main red black tree structure.
fr_aka_sim_id_type_t type
char const * fr_syserror(int num)
Guaranteed to be thread-safe version of strerror.
fr_packet_t * fr_tcp_recv(int sockfd, int flags)
fr_socket_t socket
This packet was received on.
int id
Packet ID (used to link requests/responses).
int af
AF_INET, AF_INET6, or AF_UNIX.
int fd
File descriptor if this is a live socket.
int type
SOCK_STREAM, SOCK_DGRAM, etc.
static void fr_socket_addr_swap(fr_socket_t *dst, fr_socket_t const *src)
Swap src/dst information of a fr_socket_t.
Holds information necessary for binding or connecting to a socket.
#define fr_strerror_printf(_fmt,...)
Log to thread local error buffer.
#define fr_strerror_const(_msg)