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;
}
}
-#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;
return -1;
}
+ /*
+ * @todo - open a new socket
+ */
+ sockfd = -1;
+
child = talloc_get_type_abort(dl_inst->data, proto_radius_udp_t);
/*
/*
* 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;
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)
{
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.
*/
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
* 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);