From: Alan T. DeKok Date: Fri, 16 Jun 2017 17:42:06 +0000 (-0400) Subject: track RADIUS packets via fr_tracking_t X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=a45f3c0629f2768081beebae591f0fff2c27d47a;p=thirdparty%2Ffreeradius-server.git track RADIUS packets via fr_tracking_t --- diff --git a/src/modules/proto_radius/proto_radius_udp.c b/src/modules/proto_radius/proto_radius_udp.c index 64516b39204..62bbe2d9cff 100644 --- a/src/modules/proto_radius/proto_radius_udp.c +++ b/src/modules/proto_radius/proto_radius_udp.c @@ -28,20 +28,22 @@ #include #include #include +#include #include #include "proto_radius.h" typedef struct { - uint8_t header[20]; - uint8_t id; + int if_index; fr_ipaddr_t src_ipaddr; fr_ipaddr_t dst_ipaddr; uint16_t src_port; uint16_t dst_port; + fr_time_t timestamp; + RADCLIENT *client; -} fr_proto_radius_packet_ctx_t; +} fr_udp_src_dst_t; typedef struct { int sockfd; @@ -60,6 +62,8 @@ typedef struct { bool recv_buff_is_set; //!< Whether we were provided with a receive //!< buffer value. + fr_tracking_t *ft; //!< tracking table + RADCLIENT *dummy_client; } fr_proto_radius_udp_t; @@ -79,19 +83,20 @@ static const CONF_PARSER udp_listen_config[] = { static ssize_t mod_read(void const *instance, void **packet_ctx, uint8_t *buffer, size_t buffer_len) { fr_proto_radius_udp_t const *inst = talloc_get_type_abort(instance, fr_proto_radius_udp_t); - fr_proto_radius_packet_ctx_t *pctx; ssize_t data_size; size_t packet_len; decode_fail_t reason; - struct sockaddr_storage sockaddr; - socklen_t salen = sizeof(sockaddr); - - - memset(&sockaddr, 0, sizeof(sockaddr)); + struct timeval timestamp; + fr_tracking_status_t tracking_status; + fr_tracking_entry_t *track; + fr_udp_src_dst_t src_dst; - data_size = recvfrom(inst->sockfd, buffer, buffer_len, 0, (struct sockaddr *)&sockaddr, &salen); + data_size = udp_recv(inst->sockfd, buffer, buffer_len, 0, + &src_dst.src_ipaddr, &src_dst.src_port, + &src_dst.dst_ipaddr, &src_dst.dst_port, + &src_dst.if_index, ×tamp); if (data_size <= 0) return data_size; packet_len = data_size; @@ -99,29 +104,39 @@ static ssize_t mod_read(void const *instance, void **packet_ctx, uint8_t *buffer /* * If it's not a RADIUS packet, ignore it. */ - if (!fr_radius_ok(buffer, &packet_len, false, &reason)) return -1; + if (!fr_radius_ok(buffer, &packet_len, false, &reason)) { + return -1; + } + + src_dst.timestamp = fr_time(); /* * If the signature fails validation, ignore it. */ if (fr_radius_verify(buffer, NULL, (uint8_t const *)inst->dummy_client->secret, - talloc_array_length(inst->dummy_client->secret)) < 0) return -1; + talloc_array_length(inst->dummy_client->secret)) < 0) { + return -1; + } - /* - * Populate the packet context - */ - pctx = talloc_zero(NULL, fr_proto_radius_packet_ctx_t); - pctx->client = inst->dummy_client; - if (fr_ipaddr_from_sockaddr(&sockaddr, salen, &pctx->src_ipaddr, &pctx->src_port) < 0) { - PERROR("Read failed"); - talloc_free(pctx); + src_dst.client = inst->dummy_client; + + tracking_status = fr_radius_tracking_entry_insert(inst->ft, buffer, src_dst.timestamp, &src_dst, &track); + + switch (tracking_status) { + case FR_TRACKING_ERROR: + case FR_TRACKING_UNUSED: return -1; + + case FR_TRACKING_SAME: + return 0; + + case FR_TRACKING_NEW: + case FR_TRACKING_DIFFERENT: + break; } - pctx->id = buffer[1]; - memcpy(pctx->header, buffer, sizeof(pctx->header)); - *packet_ctx = pctx; + *packet_ctx = track; return packet_len; } @@ -130,29 +145,18 @@ static ssize_t mod_read(void const *instance, void **packet_ctx, uint8_t *buffer static ssize_t mod_write(void const *instance, void *packet_ctx, uint8_t *buffer, size_t buffer_len) { fr_proto_radius_udp_t const *inst = talloc_get_type_abort(instance, fr_proto_radius_udp_t); - fr_proto_radius_packet_ctx_t *pctx = talloc_get_type_abort(packet_ctx, fr_proto_radius_packet_ctx_t); + fr_tracking_entry_t *track = packet_ctx; + fr_udp_src_dst_t *src_dst = track->src_dst; ssize_t data_size; - struct sockaddr_storage sockaddr; - socklen_t salen; - - if (fr_ipaddr_to_sockaddr(&pctx->src_ipaddr, pctx->src_port, &sockaddr, &salen) < 0) { - PERROR("Write failed"); - talloc_free(packet_ctx); - return -1; - } - /* - * @todo - do more stuff - */ - data_size = sendto(inst->sockfd, buffer, buffer_len, 0, (struct sockaddr *) &sockaddr, salen); - if (data_size <= 0) return data_size; + data_size = udp_send(inst->sockfd, buffer, buffer_len, 0, + &src_dst->src_ipaddr, src_dst->src_port, + src_dst->if_index, + &src_dst->dst_ipaddr, src_dst->dst_port); - talloc_free(packet_ctx); /* Probably a bad idea */ + (void) fr_radius_tracking_entry_delete(inst->ft, track); - /* - * @todo - post-write cleanups - */ return data_size; } @@ -187,6 +191,11 @@ static int mod_open(void *instance) return 0; } +static void *allowed_packets[FR_MAX_PACKET_CODE] = { + [FR_CODE_STATUS_SERVER] = mod_open, +}; + + static int mod_instantiate(void *instance, CONF_SECTION *cs) { fr_proto_radius_udp_t *inst = talloc_get_type_abort(instance, fr_proto_radius_udp_t); @@ -224,6 +233,11 @@ static int mod_instantiate(void *instance, CONF_SECTION *cs) inst->dummy_client = client_afrom_query(inst, "127.0.0.1", "testing123", "test", "test", NULL, false); + inst->ft = fr_radius_tracking_create(inst, sizeof(fr_udp_src_dst_t), allowed_packets); + if (!inst->ft) { + cf_log_err(cs, "Failed to create tracking table: %s", fr_strerror()); + } + return 0; }