/* * Ugh. Doing this on every sent/received packet is not nice. */ static fr_packet_socket_t *fr_socket_find(fr_packet_list_t *pl, int sockfd) { int i, start; i = start = SOCK2OFFSET(sockfd); do { /* make this hack slightly more efficient */ if (pl->sockets[i].sockfd == sockfd) return &pl->sockets[i]; i = (i + 1) & SOCKOFFSET_MASK; } while (i != start); return NULL; }
int fr_packet_list_socket_add(fr_packet_list_t *pl, int sockfd) { int i, start; struct sockaddr_storage src; socklen_t sizeof_src = sizeof(src); fr_packet_socket_t *ps; if (!pl) return 0; ps = NULL; i = start = SOCK2OFFSET(sockfd); do { if (pl->sockets[i].sockfd == -1) { ps = &pl->sockets[i]; start = i; break; } i = (i + 1) & SOCKOFFSET_MASK; } while (i != start); if (!ps) { return 0; } memset(ps, 0, sizeof(*ps)); ps->sockfd = sockfd; ps->offset = start; /* * Get address family, etc. first, so we know if we * need to do udpfromto. * * FIXME: udpfromto also does this, but it's not * a critical problem. */ memset(&src, 0, sizeof_src); if (getsockname(sockfd, (struct sockaddr *) &src, &sizeof_src) < 0) { return 0; } if (!fr_sockaddr2ipaddr(&src, sizeof_src, &ps->ipaddr, &ps->port)) { return 0; } /* * Grab IP addresses & ports from the sockaddr. */ if (src.ss_family == AF_INET) { if (ps->ipaddr.ipaddr.ip4addr.s_addr == INADDR_ANY) { ps->inaddr_any = 1; } #ifdef HAVE_STRUCT_SOCKADDR_IN6 } else if (src.ss_family == AF_INET6) { if (IN6_IS_ADDR_UNSPECIFIED(&ps->ipaddr.ipaddr.ip6addr)) { ps->inaddr_any = 1; } #endif } else { return 0; } pl->mask |= (1 << ps->offset); return 1; }
bool fr_packet_list_socket_add(fr_packet_list_t *pl, int sockfd, int proto, fr_ipaddr_t *dst_ipaddr, int dst_port, void *ctx) { int i, start; struct sockaddr_storage src; socklen_t sizeof_src; fr_packet_socket_t *ps; if (!pl || !dst_ipaddr || (dst_ipaddr->af == AF_UNSPEC)) { fr_strerror_printf("Invalid argument"); return false; } if (pl->num_sockets >= MAX_SOCKETS) { fr_strerror_printf("Too many open sockets"); return false; } #ifndef WITH_TCP if (proto != IPPROTO_UDP) { fr_strerror_printf("only UDP is supported"); return false; } #endif ps = NULL; i = start = SOCK2OFFSET(sockfd); do { if (pl->sockets[i].sockfd == -1) { ps = &pl->sockets[i]; break; } i = (i + 1) & SOCKOFFSET_MASK; } while (i != start); if (!ps) { fr_strerror_printf("All socket entries are full"); return false; } memset(ps, 0, sizeof(*ps)); ps->ctx = ctx; #ifdef WITH_TCP ps->proto = proto; #endif /* * Get address family, etc. first, so we know if we * need to do udpfromto. * * FIXME: udpfromto also does this, but it's not * a critical problem. */ sizeof_src = sizeof(src); memset(&src, 0, sizeof_src); if (getsockname(sockfd, (struct sockaddr *) &src, &sizeof_src) < 0) { fr_strerror_printf("%s", fr_syserror(errno)); return false; } if (!fr_sockaddr2ipaddr(&src, sizeof_src, &ps->src_ipaddr, &ps->src_port)) { fr_strerror_printf("Failed to get IP"); return false; } ps->dst_ipaddr = *dst_ipaddr; ps->dst_port = dst_port; ps->src_any = fr_inaddr_any(&ps->src_ipaddr); if (ps->src_any < 0) return false; ps->dst_any = fr_inaddr_any(&ps->dst_ipaddr); if (ps->dst_any < 0) return false; /* * As the last step before returning. */ ps->sockfd = sockfd; pl->num_sockets++; /* * Populate the ID array with a random list of IDs. */ ps->ids_index = 0; for (i = 0; i < 256; i++) { ps->ids[fr_rand() & 0xff] = i; } return true; }