From: Alan T. DeKok Date: Mon, 15 Jan 2018 21:41:13 +0000 (-0500) Subject: glue mod_clone into the socket code. X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=e530c71f042138db44cdcd372148332be699eba6;p=thirdparty%2Ffreeradius-server.git glue mod_clone into the socket code. still a few TODO's. (i.e. you use it now, it crashes). But the basics are laid out --- diff --git a/src/modules/proto_radius/proto_radius_udp.c b/src/modules/proto_radius/proto_radius_udp.c index 6e9cb889114..950d2faede0 100644 --- a/src/modules/proto_radius/proto_radius_udp.c +++ b/src/modules/proto_radius/proto_radius_udp.c @@ -104,6 +104,7 @@ typedef struct proto_radius_udp_child_t { fr_time_t recv_time; //!< of the packet RADCLIENT *client; //!< static client for this connection dl_instance_t *dl_inst; //!< our library instance + fr_listen_t *listen; //!< listener for this socket struct proto_radius_udp_t *master; //!< for the master socket. } proto_radius_udp_child_t; @@ -666,10 +667,9 @@ static void dynamic_client_timer(proto_radius_udp_t *inst, RADCLIENT *client, ui } } -#if 0 -static int mod_clone(proto_radius_udp_t *inst, int sockfd, proto_radius_udp_address_t *address) +static int mod_clone(proto_radius_udp_t *inst, proto_radius_udp_address_t *address) { - int rcode; + int rcode, sockfd; proto_radius_udp_t *child; dl_instance_t *dl_inst; fr_listen_t *listen; @@ -687,6 +687,11 @@ static int mod_clone(proto_radius_udp_t *inst, int sockfd, proto_radius_udp_addr return -1; } + /* + * @todo - open a new socket + */ + sockfd = -1; + child = talloc_get_type_abort(dl_inst->data, proto_radius_udp_t); /* @@ -715,7 +720,7 @@ static int mod_clone(proto_radius_udp_t *inst, int sockfd, proto_radius_udp_addr /* * Create the new listener, and populate it's children. */ - listen = talloc(child, fr_listen_t); + listen = child->child.listen = talloc(child, fr_listen_t); if (!listen) { talloc_free(dl_inst); return -1; @@ -752,7 +757,6 @@ static int mod_clone(proto_radius_udp_t *inst, int sockfd, proto_radius_udp_addr return 0; } -#endif static ssize_t mod_read(void *instance, void **packet_ctx, fr_time_t **recv_time, uint8_t *buffer, size_t buffer_len, size_t *leftover, uint32_t *priority) { @@ -770,6 +774,13 @@ static ssize_t mod_read(void *instance, void **packet_ctx, fr_time_t **recv_time proto_radius_udp_address_t address; fr_dlist_t *entry; + /* + * @todo - have a way to change the read() routine for + * this listener. That avoids all of this if / then / + * else nonsense. Maybe we just put a new routine into + * "inst", and call that "good enough". + */ + /* * Check for injected packets first. */ @@ -1022,9 +1033,9 @@ found: received_packet: /* - * @todo - check for a socket that SHOULD be connected. - * If so, either create the socket, OR find it in the - * list of sockets, and send the packet there. + * Check for a socket that SHOULD be connected. If so, + * either create the socket, OR find it in the list of + * sockets, and send the packet there. * * We can then REMOVE the tracking table entry for this * packet, as it is no longer used. We ALSO need to mark @@ -1035,6 +1046,50 @@ received_packet: * i.e. if there's a client but no child socket, go back * and create a child socket... */ + if (inst->use_connected) { + proto_radius_udp_t *child, my_child; + + my_child.ipaddr = address.dst_ipaddr; + my_child.port = address.dst_port; + + my_child.child.src_ipaddr = address.src_ipaddr; + my_child.child.src_port = address.src_port; + + PTHREAD_MUTEX_LOCK(&inst->master.mutex); + child = fr_hash_table_finddata(inst->master.ht, &my_child); + if (child) { + (void) fr_network_listen_inject(child->nr, child->child.listen, + buffer, packet_len, track->timestamp); + } + PTHREAD_MUTEX_UNLOCK(&inst->master.mutex); + + /* + * If the child exists, remove the tracking table + * entry for this packet. The child will take + * care of dealing with the packet. + */ + if (child) goto untrack; + + /* + * Try to clone us into a child. If that + * succeeds, send the packet to the child. + */ + if (mod_clone(inst, &address) == 0) { + PTHREAD_MUTEX_LOCK(&inst->master.mutex); + (void) fr_network_listen_inject(child->nr, child->child.listen, + buffer, packet_len, track->timestamp); + PTHREAD_MUTEX_UNLOCK(&inst->master.mutex); + } + +untrack: + /* + * We're no longer tracking this packet. + * Instead, the client is. So we just discard it + * now. + */ + (void) fr_radius_tracking_entry_delete(track->ft, track); + return 0; + } inst->stats.total_requests++; rad_assert(address.client != NULL);