From: Alan T. DeKok Date: Tue, 5 May 2020 14:10:16 +0000 (-0400) Subject: add filter option X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=96da6d727c19b5dd9bc479f1816544c9e025a2d3;p=thirdparty%2Ffreeradius-server.git add filter option --- diff --git a/raddb/sites-available/arp b/raddb/sites-available/arp index c5a1ef30800..bac16ddf21e 100644 --- a/raddb/sites-available/arp +++ b/raddb/sites-available/arp @@ -7,29 +7,19 @@ # # = ARP Virtual Server # -# This is a virtual server that handles ARP. +# This is a virtual server which reads ARP packets # -# It allows the administrator to log ARP packets on the -# local network. The idea is that the ARP packets can be -# checked against a database (e.g. DHCP), or stored in -# an ARP-specific database. If something funny is -# going on, it can produce syslog messages informing the -# administrator. -# -# See `arpwatch` for examples of what it should do. For now, -# this is just a toy example. -# -# NOTE: It NEVER sends an ARP packet. -# - -# -# ## Example configuration +# It allows the administrator to log ARP packets on the local +# network. The idea is that the ARP packets can be checked against a +# database (e.g. DHCP), or stored in an ARP-specific database. If +# something funny is going on, this virtual server can produce syslog +# messages informing the administrator as to what happened. # # # ## server arp { ... } # -# This is the default `arp` virtual server. +# This is the `arp` virtual server. # server arp { # @@ -53,10 +43,20 @@ server arp { # listen { # - # interface:: The only configuration possible for ARP - # is the name of the interface. + # interface:: The name of the interface. # interface = en0 + + # + # filter:: An optional PCAP filter. + # + # If we want to receive only ARPs for a particular + # IP address, then we list it here as `host foo` + # + # You can also filter on ethernet via + # `ether src foo` or `ether dst foo`. + # +# filter = "host 192.0.2.1" } # diff --git a/src/modules/proto_arp/proto_arp_ethernet.c b/src/modules/proto_arp/proto_arp_ethernet.c index 2963f0ec446..faac9de5c23 100644 --- a/src/modules/proto_arp/proto_arp_ethernet.c +++ b/src/modules/proto_arp/proto_arp_ethernet.c @@ -46,6 +46,7 @@ typedef struct { typedef struct { CONF_SECTION *cs; //!< our configuration char const *interface; //!< Interface to bind to. + char const *filter; //!< Additional PCAP filter } proto_arp_ethernet_t; @@ -56,9 +57,7 @@ static CONF_PARSER const arp_listen_config[] = { { FR_CONF_OFFSET("interface", FR_TYPE_STRING | FR_TYPE_NOT_EMPTY, proto_arp_ethernet_t, interface), .dflt = "eth0" }, - /* - * @todo - allow for pcap filter - */ + { FR_CONF_OFFSET("filter", FR_TYPE_STRING, proto_arp_ethernet_t, filter) }, CONF_PARSER_TERMINATOR }; @@ -166,6 +165,8 @@ static int mod_open(fr_listen_t *li) CONF_SECTION *server_cs; CONF_ITEM *ci; + char const *filter; + char buffer[256]; thread->pcap = fr_pcap_init(thread, inst->interface, PCAP_INTERFACE_IN); if (!thread->pcap) { @@ -179,12 +180,17 @@ static int mod_open(fr_listen_t *li) } /* - * Ensure that we only get ARP. - * - * @todo - only get ARP requests? + * Ensure that we only get ARP, and an optional additional filter. */ - if (fr_pcap_apply_filter(thread->pcap, "arp") < 0) { - PERROR("Failed applying pcap filter"); + if (!inst->filter) { + filter = "arp"; + } else { + filter = buffer; + snprintf(buffer, sizeof(buffer), "arp and %s", filter); + } + + if (fr_pcap_apply_filter(thread->pcap, filter) < 0) { + PERROR("Failed applying pcap filter '%s'", filter); return -1; }