#
# = 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 {
#
#
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"
}
#
typedef struct {
CONF_SECTION *cs; //!< our configuration
char const *interface; //!< Interface to bind to.
+ char const *filter; //!< Additional PCAP filter
} proto_arp_ethernet_t;
{ 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
};
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) {
}
/*
- * 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;
}