From 06d95f23aa59bd7b1e8cafdd34bfb564797df54f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Linus=20L=C3=BCssing?= Date: Tue, 17 Aug 2021 05:24:31 +0200 Subject: [PATCH] gluon-statistics-mcast: adding initial package MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This package collects disected statistics on multicast and management traffic and provides them via respondd in "statistics-extended". Such information can be helpful for further development and comparison of mesh routing protocols and troubleshooting network issues. The statistics gathered disect into batman-adv packets as well. Statistics are collected both on client bridge ports and br-client as well as mesh interfaces. This introduces a performance penalty but tries to keep the impact on unicast traffic small. Note that respondd replies are rather large (several UDP datagrams, even when LZMA compressed). Therefore you might want to use slower intervals for querying respondd "statistics-extended". Signed-off-by: Linus Lüssing --- package/gluon-statistics-mcast/Makefile | 33 + .../files/etc/hotplug.d/iface/40-bpfcountd | 68 ++ .../files/lib/gluon/bpfcountd/mesh.filters | 604 ++++++++++++++++++ .../lib/gluon/core/mesh/setup.d/40-bpfcountd | 63 ++ .../gluon/core/mesh/teardown.d/40-bpfcountd | 33 + package/gluon-statistics-mcast/src/Makefile | 6 + package/gluon-statistics-mcast/src/respondd.c | 478 ++++++++++++++ 7 files changed, 1285 insertions(+) create mode 100644 package/gluon-statistics-mcast/Makefile create mode 100644 package/gluon-statistics-mcast/files/etc/hotplug.d/iface/40-bpfcountd create mode 100644 package/gluon-statistics-mcast/files/lib/gluon/bpfcountd/mesh.filters create mode 100755 package/gluon-statistics-mcast/files/lib/gluon/core/mesh/setup.d/40-bpfcountd create mode 100755 package/gluon-statistics-mcast/files/lib/gluon/core/mesh/teardown.d/40-bpfcountd create mode 100644 package/gluon-statistics-mcast/src/Makefile create mode 100644 package/gluon-statistics-mcast/src/respondd.c diff --git a/package/gluon-statistics-mcast/Makefile b/package/gluon-statistics-mcast/Makefile new file mode 100644 index 00000000000..517b6f0ffe7 --- /dev/null +++ b/package/gluon-statistics-mcast/Makefile @@ -0,0 +1,33 @@ +include $(TOPDIR)/rules.mk + +PKG_NAME:=gluon-statistics-mcast +PKG_VERSION:=1 + +include ../gluon.mk + +define Package/gluon-statistics-mcast + TITLE:=Gluon Statistics for Multicast Traffic + DEPENDS:= +bpfcountd +libgluonutil +endef + +define Package/gluon-statistics-mcast/description + This package collects disected statistics on multicast + and management traffic and provides them via respondd in + "statistics-extended". Such information can be helpful + for further development and comparison of mesh routing + protocols and troubleshooting network issues. + + The statistics gathered disect into batman-adv + packets as well. Statistics are collected both on client + bridge ports and br-client as well as mesh interfaces. + + This introduces a performance penalty but tries to + keep the impact on unicast traffic small. + + Note that respondd replies are rather large + (several UDP datagrams, even when LZMA compressed). + Therefore you might want to use slower intervals for + querying respondd "statistics-extended". +endef + +$(eval $(call BuildPackageGluon,gluon-statistics-mcast)) diff --git a/package/gluon-statistics-mcast/files/etc/hotplug.d/iface/40-bpfcountd b/package/gluon-statistics-mcast/files/etc/hotplug.d/iface/40-bpfcountd new file mode 100644 index 00000000000..bc963f14ff8 --- /dev/null +++ b/package/gluon-statistics-mcast/files/etc/hotplug.d/iface/40-bpfcountd @@ -0,0 +1,68 @@ +case "$INTERFACE" in + "client"|\ + "mmfd") + ;; + *) + exit 0 + ;; +esac + +BPFCOUNTD_RUN="/var/run/bpfcountd" +mkdir -p "${BPFCOUNTD_RUN}/gluon-ifaces" + +get_ifup_ifaces() { + local ifaces="$DEVICE" + local brports + + if [ -d "/sys/class/net/$DEVICE/bridge/" ]; then + brports="$(ls "/sys/class/net/$DEVICE/brif/")" + [ -n "$brports" ] && ifaces="$(echo -e "${brports}\n${ifaces}")" + fi + + echo "$ifaces" +} + +get_ifdown_ifaces() { + cat "${BPFCOUNTD_RUN}/gluon-ifaces/$INTERFACE" +} + +bpfcountd_start() { + local ifaces="$(get_ifup_ifaces)" + local iface + + [ -z "$ifaces" ] && return + [ -f "${BPFCOUNTD_RUN}/gluon-ifaces/$INTERFACE" ] && return + echo "$ifaces" > "${BPFCOUNTD_RUN}/gluon-ifaces/$INTERFACE" + + for iface in $ifaces; do + IFNAME="$iface" /lib/gluon/core/mesh/setup.d/40-bpfcountd "clients" + done +} + +bpfcountd_stop() { + local ifaces="$(get_ifdown_ifaces)" + local iface + + [ -z "$ifaces" ] && return + rm "${BPFCOUNTD_RUN}/gluon-ifaces/$INTERFACE" + + for iface in $ifaces; do + IFNAME="$iface" /lib/gluon/core/mesh/teardown.d/40-bpfcountd + done +} + +# synchronize reads+writes to /var/run/gluon-ifaces/$INTERFACE +lock /var/lock/gluon_bpfcountd_ifaces.lock + +case "$ACTION" in + "ifup") + bpfcountd_start + ;; + "ifdown") + bpfcountd_stop + ;; + *) + ;; +esac + +lock -u /var/lock/gluon_bpfcountd_ifaces.lock diff --git a/package/gluon-statistics-mcast/files/lib/gluon/bpfcountd/mesh.filters b/package/gluon-statistics-mcast/files/lib/gluon/bpfcountd/mesh.filters new file mode 100644 index 00000000000..2dddcceffdc --- /dev/null +++ b/package/gluon-statistics-mcast/files/lib/gluon/bpfcountd/mesh.filters @@ -0,0 +1,604 @@ +%SSDP;udp dst port 1900 +%LLMNR;udp dst port 5355 +%MDNS;udp dst port 5353 +%NB-NS;udp dst port 137 +%NB-DGM;udp dst port 138 +%DP-LSP;udp dst port 17500 +%TRAP-DAEMON;udp dst port 3600 +%DHCP4;udp port (67 || 68) +%DHCP6;udp port (546 || 547) +%WS-DISC;udp port 3702 +%WSP;udp dst port 9200 +%TEREDO;udp dst port 3544 +%SPOTIFY;udp dst port 57621 +%SIP;udp dst port 5060 +%BT-LPD;udp dst port 6771 +%NVBM;udp dst port 8225 +%SVRLOC;udp dst port 427 +%ENPC;udp dst port 3289 +%QTSTREAM;udp dst port 7555 +%HDHOMERUN;udp dst port 65001 +%PLEX-DISC0;udp dst port 32410 +%PLEX-DISC2;udp dst port 32412 +%PLEX-DISC3;udp dst port 32413 +%PLEX-DISC4;udp dst port 32414 +%BT-UTP;udp dst port 16680 +%WF-BSSERV;udp dst port 61117 +%FAXIMUM;udp dst port 7437 +%TOMCAT;udp dst port 9006 +%DISTINCT;udp dst port 9999 +%UDP-25412;udp dst port 25412 +%UDP-10203;udp dst port 10203 +%UDP-60128;udp dst port 60128 +%COREL-VNC;udp dst port 2654 +%HPVMMCTRL;udp dst port 1124 +%CBT;udp dst port 7777 +%MCAFEE;udp dst port 6646 +%UDP-39455;udp dst port 39455 +%UDP-889;udp dst port 889 +%UDP-16962;udp dst port 16962 +%TSEQ;udp dst port 0 +%CANON-BJNP;udp dst port 8612 +%RIP;udp dst port 520 +%RIPNG;udp dst port 521 +%BABEL;udp dst port 6696 +%MANET;udp dst port 269 +%RESPONDD-QRY;udp dst port 1001 +%SYNCTHING-LPD;udp dst port 21027 +%USTEER;udp dst port 16720 +%L3ROAMD;udp dst port 5523 +%MMFD;udp dst port 27275 + +IP4;ip +IP6;ip6 +BLA;arp and arp[0:2] = 0x0001 and arp[2:2] = 0x0800 and arp[6:2] = 0x0002 and arp[14:4] = 0x00000000 and arp[18:2] = 0xff43 and arp[20:1] = 0x05 and arp[24:4] = 0x00000000 +ARP;arp and not ${BLA} +IPX;ipx +NETBEUI;netbeui +LLDP;ether proto 0x88CC + +IP4:IGMP;${IP4} && igmp +IP4:IGMP:QUERY-V1;${IP4:IGMP} and igmp[0] = 0x11 and ip[2:2] = 0x0020 and igmp[1] = 0x00 +IP4:IGMP:QUERY-V2;${IP4:IGMP} and igmp[0] = 0x11 and ip[2:2] = 0x0020 and not (igmp[1] = 0x00) +IP4:IGMP:QUERY-V3;${IP4:IGMP} and igmp[0] = 0x11 and ip[2:2] >= 0x0024 +IP4:IGMP:QUERY-UNKNOWN;${IP4:IGMP} and igmp[0] = 0x11 and not ((ip[2:2] = 0x0020 and igmp[1] = 0x00) or (ip[2:2] = 0x0020 and not (igmp[1] = 0x00)) or ip[2:2] >= 0x0024) +IP4:IGMP:REPORT-V1;${IP4:IGMP} and igmp[0] = 0x12 +IP4:IGMP:REPORT-V2;${IP4:IGMP} and igmp[0] = 0x16 +IP4:IGMP:LEAVE-V2;${IP4:IGMP} and igmp[0] = 0x17 +IP4:IGMP:REPORT-V3;${IP4:IGMP} and igmp[0] = 0x22 +IP4:IGMP:MRD-ADV;${IP4:IGMP} and igmp[0] = 0x30 +IP4:IGMP:MRD-SOL;${IP4:IGMP} and igmp[0] = 0x31 +IP4:IGMP:MRD-TERM;${IP4:IGMP} and igmp[0] = 0x32 + +IP4:MC;${IP4} && ip multicast +IP4:MC:PIM;${IP4:MC} && ((ip proto 103) or ((ip proto 2) and (ip[20] == 0x14))) +IP4:MC:OSPF;${IP4:MC} && ip proto 89 +IP4:MC:MANET;${IP4:MC} && ip proto 138 +IP4:MC:UDP;${IP4:MC} && udp + +IP4:MC:UDP:SSDP;${IP4:MC:UDP} && ${%SSDP} +IP4:MC:UDP:LLMNR;${IP4:MC:UDP} && ${%LLMNR} +IP4:MC:UDP:MDNS;${IP4:MC:UDP} && ${%MDNS} +IP4:MC:UDP:NB-NS;${IP4:MC:UDP} && ${%NB-NS} +IP4:MC:UDP:NB-DGM;${IP4:MC:UDP} && ${%NB-DGM} +IP4:MC:UDP:DP-LSP;${IP4:MC:UDP} && ${%DP-LSP} +IP4:MC:UDP:TRAP-DAEMON;${IP4:MC:UDP} && ${%TRAP-DAEMON} +IP4:MC:UDP:DHCP4;${IP4:MC:UDP} && ${%DHCP4} +IP4:MC:UDP:DHCP6;${IP4:MC:UDP} && ${%DHCP6} +IP4:MC:UDP:WS-DISC;${IP4:MC:UDP} && ${%WS-DISC} +IP4:MC:UDP:WSP;${IP4:MC:UDP} && ${%WSP} +IP4:MC:UDP:TEREDO;${IP4:MC:UDP} && ${%TEREDO} +IP4:MC:UDP:SPOTIFY;${IP4:MC:UDP} && ${%SPOTIFY} +IP4:MC:UDP:SIP;${IP4:MC:UDP} && ${%SIP} +IP4:MC:UDP:BT-LPD;${IP4:MC:UDP} && ${%BT-LPD} +IP4:MC:UDP:NVBM;${IP4:MC:UDP} && ${%NVBM} +IP4:MC:UDP:SVRLOC;${IP4:MC:UDP} && ${%SVRLOC} +IP4:MC:UDP:ENPC;${IP4:MC:UDP} && ${%ENPC} +IP4:MC:UDP:QTSTREAM;${IP4:MC:UDP} && ${%QTSTREAM} +IP4:MC:UDP:HDHOMERUN;${IP4:MC:UDP} && ${%HDHOMERUN} +IP4:MC:UDP:PLEX-DISC0;${IP4:MC:UDP} && ${%PLEX-DISC0} +IP4:MC:UDP:PLEX-DISC2;${IP4:MC:UDP} && ${%PLEX-DISC2} +IP4:MC:UDP:PLEX-DISC3;${IP4:MC:UDP} && ${%PLEX-DISC3} +IP4:MC:UDP:PLEX-DISC4;${IP4:MC:UDP} && ${%PLEX-DISC4} +IP4:MC:UDP:BT-UTP;${IP4:MC:UDP} && ${%BT-UTP} +IP4:MC:UDP:WF-BSSERV;${IP4:MC:UDP} && ${%WF-BSSERV} +IP4:MC:UDP:FAXIMUM;${IP4:MC:UDP} && ${%FAXIMUM} +IP4:MC:UDP:TOMCAT;${IP4:MC:UDP} && ${%TOMCAT} +IP4:MC:UDP:DISTINCT;${IP4:MC:UDP} && ${%DISTINCT} +IP4:MC:UDP:UDP-25412;${IP4:MC:UDP} && ${%UDP-25412} +IP4:MC:UDP:UDP-10203;${IP4:MC:UDP} && ${%UDP-10203} +IP4:MC:UDP:UDP-60128;${IP4:MC:UDP} && ${%UDP-60128} +IP4:MC:UDP:COREL-VNC;${IP4:MC:UDP} && ${%COREL-VNC} +IP4:MC:UDP:HPVMMCTRL;${IP4:MC:UDP} && ${%HPVMMCTRL} +IP4:MC:UDP:CBT;${IP4:MC:UDP} && ${%CBT} +IP4:MC:UDP:MCAFEE;${IP4:MC:UDP} && ${%MCAFEE} +IP4:MC:UDP:UDP-39455;${IP4:MC:UDP} && ${%UDP-39455} +IP4:MC:UDP:UDP-889;${IP4:MC:UDP} && ${%UDP-889} +IP4:MC:UDP:UDP-16962;${IP4:MC:UDP} && ${%UDP-16962} +IP4:MC:UDP:TSEQ;${IP4:MC:UDP} && ${%TSEQ} +IP4:MC:UDP:CANON-BJNP;${IP4:MC:UDP} && ${%CANON-BJNP} +IP4:MC:UDP:RIP;${IP4:MC:UDP} && ${%RIP} +IP4:MC:UDP:RIPNG;${IP4:MC:UDP} && ${%RIPNG} +IP4:MC:UDP:BABEL;${IP4:MC:UDP} && ${%BABEL} +IP4:MC:UDP:MANET;${IP4:MC:UDP} && ${%MANET} +IP4:MC:UDP:RESPONDD-QRY;${IP4:MC:UDP} && ${%RESPONDD-QRY} +IP4:MC:UDP:SYNCTHING-LPD;${IP4:MC:UDP} && ${%SYNCTHING-LPD} +IP4:MC:UDP:USTEER;${IP4:MC:UDP} && ${%USTEER} +IP4:MC:UDP:L3ROAMD;${IP4:MC:UDP} && ${%L3ROAMD} +IP4:MC:UDP:MMFD;${IP4:MC:UDP} && ${%MMFD} + +IP6:MC;${IP6} && ip6 multicast +IP6:MC:PIM;${IP6:MC} && ip6 proto 103 +IP6:MC:OSPF;${IP6:MC} && ip6 proto 89 +IP6:MC:MANET;${IP6:MC} && ip6 proto 138 +IP6:MC:UDP;${IP6:MC} && udp + +IP6:MC:UDP:SSDP;${IP6:MC:UDP} && ${%SSDP} +IP6:MC:UDP:LLMNR;${IP6:MC:UDP} && ${%LLMNR} +IP6:MC:UDP:MDNS;${IP6:MC:UDP} && ${%MDNS} +IP6:MC:UDP:NB-NS;${IP6:MC:UDP} && ${%NB-NS} +IP6:MC:UDP:NB-DGM;${IP6:MC:UDP} && ${%NB-DGM} +IP6:MC:UDP:DP-LSP;${IP6:MC:UDP} && ${%DP-LSP} +IP6:MC:UDP:TRAP-DAEMON;${IP6:MC:UDP} && ${%TRAP-DAEMON} +IP6:MC:UDP:DHCP4;${IP6:MC:UDP} && ${%DHCP4} +IP6:MC:UDP:DHCP6;${IP6:MC:UDP} && ${%DHCP6} +IP6:MC:UDP:WS-DISC;${IP6:MC:UDP} && ${%WS-DISC} +IP6:MC:UDP:WSP;${IP6:MC:UDP} && ${%WSP} +IP6:MC:UDP:TEREDO;${IP6:MC:UDP} && ${%TEREDO} +IP6:MC:UDP:SPOTIFY;${IP6:MC:UDP} && ${%SPOTIFY} +IP6:MC:UDP:SIP;${IP6:MC:UDP} && ${%SIP} +IP6:MC:UDP:BT-LPD;${IP6:MC:UDP} && ${%BT-LPD} +IP6:MC:UDP:NVBM;${IP6:MC:UDP} && ${%NVBM} +IP6:MC:UDP:SVRLOC;${IP6:MC:UDP} && ${%SVRLOC} +IP6:MC:UDP:ENPC;${IP6:MC:UDP} && ${%ENPC} +IP6:MC:UDP:QTSTREAM;${IP6:MC:UDP} && ${%QTSTREAM} +IP6:MC:UDP:HDHOMERUN;${IP6:MC:UDP} && ${%HDHOMERUN} +IP6:MC:UDP:PLEX-DISC0;${IP6:MC:UDP} && ${%PLEX-DISC0} +IP6:MC:UDP:PLEX-DISC2;${IP6:MC:UDP} && ${%PLEX-DISC2} +IP6:MC:UDP:PLEX-DISC3;${IP6:MC:UDP} && ${%PLEX-DISC3} +IP6:MC:UDP:PLEX-DISC4;${IP6:MC:UDP} && ${%PLEX-DISC4} +IP6:MC:UDP:BT-UTP;${IP6:MC:UDP} && ${%BT-UTP} +IP6:MC:UDP:WF-BSSERV;${IP6:MC:UDP} && ${%WF-BSSERV} +IP6:MC:UDP:FAXIMUM;${IP6:MC:UDP} && ${%FAXIMUM} +IP6:MC:UDP:TOMCAT;${IP6:MC:UDP} && ${%TOMCAT} +IP6:MC:UDP:DISTINCT;${IP6:MC:UDP} && ${%DISTINCT} +IP6:MC:UDP:UDP-25412;${IP6:MC:UDP} && ${%UDP-25412} +IP6:MC:UDP:UDP-10203;${IP6:MC:UDP} && ${%UDP-10203} +IP6:MC:UDP:UDP-60128;${IP6:MC:UDP} && ${%UDP-60128} +IP6:MC:UDP:COREL-VNC;${IP6:MC:UDP} && ${%COREL-VNC} +IP6:MC:UDP:HPVMMCTRL;${IP6:MC:UDP} && ${%HPVMMCTRL} +IP6:MC:UDP:CBT;${IP6:MC:UDP} && ${%CBT} +IP6:MC:UDP:MCAFEE;${IP6:MC:UDP} && ${%MCAFEE} +IP6:MC:UDP:UDP-39455;${IP6:MC:UDP} && ${%UDP-39455} +IP6:MC:UDP:UDP-889;${IP6:MC:UDP} && ${%UDP-889} +IP6:MC:UDP:UDP-16962;${IP6:MC:UDP} && ${%UDP-16962} +IP6:MC:UDP:TSEQ;${IP6:MC:UDP} && ${%TSEQ} +IP6:MC:UDP:CANON-BJNP;${IP6:MC:UDP} && ${%CANON-BJNP} +IP6:MC:UDP:RIP;${IP6:MC:UDP} && ${%RIP} +IP6:MC:UDP:RIPNG;${IP6:MC:UDP} && ${%RIPNG} +IP6:MC:UDP:BABEL;${IP6:MC:UDP} && ${%BABEL} +IP6:MC:UDP:MANET;${IP6:MC:UDP} && ${%MANET} +IP6:MC:UDP:RESPONDD-QRY;${IP6:MC:UDP} && ${%RESPONDD-QRY} +IP6:MC:UDP:SYNCTHING-LPD;${IP6:MC:UDP} && ${%SYNCTHING-LPD} +IP6:MC:UDP:USTEER;${IP6:MC:UDP} && ${%USTEER} +IP6:MC:UDP:L3ROAMD;${IP6:MC:UDP} && ${%L3ROAMD} +IP6:MC:UDP:MMFD;${IP6:MC:UDP} && ${%MMFD} + +IP6:MC:HBH6;${IP6:MC} && ip6 proto 0 +IP6:MC:ICMP6;${IP6:MC} && ip6 proto 58 + +IP6:MC:HBH6:MLD;${IP6:MC:HBH6} and ip6[40] = 58 and ip6[41] = 0x00 and ip6[42:4] = 0x05020000 and (ip6[46:2] = 0x0000 or ip6[46:2] = 0x0100) +IP6:MC:HBH6:MLD:QUERY-V1;${IP6:MC:HBH6:MLD} and ip6[48] = 130 and ip6[4:2] = 0x0020 +IP6:MC:HBH6:MLD:QUERY-V1:GENERAL;${IP6:MC:HBH6:MLD:QUERY-V1} and ip6[56:4] = 0x00000000 and ip6[60:4] = 0x00000000 and ip6[64:4] = 0x00000000 and ip6[68:4] = 0x00000000 +IP6:MC:HBH6:MLD:QUERY-V1:ADDRSPEC;${IP6:MC:HBH6:MLD:QUERY-V1} and not (ip6[56:4] = 0x00000000 and ip6[60:4] = 0x00000000 and ip6[64:4] = 0x00000000 and ip6[68:4] = 0x00000000) +IP6:MC:HBH6:MLD:QUERY-V2;${IP6:MC:HBH6:MLD} and ip6[48] = 130 and ip6[4:2] >= 0x0024 +IP6:MC:HBH6:MLD:QUERY-V2:GENERAL;${IP6:MC:HBH6:MLD:QUERY-V2} and ip6[56:4] = 0x00000000 and ip6[60:4] = 0x00000000 and ip6[64:4] = 0x00000000 and ip6[68:4] = 0x00000000 +IP6:MC:HBH6:MLD:QUERY-V2:ADDRSPEC;${IP6:MC:HBH6:MLD:QUERY-V2} and not (ip6[56:4] = 0x00000000 and ip6[60:4] = 0x00000000 and ip6[64:4] = 0x00000000 and ip6[68:4] = 0x00000000) +IP6:MC:HBH6:MLD:QUERY-UNKNOWN;${IP6:MC:HBH6:MLD} and ip6[48] = 130 and not (ip6[4:2] = 0x0020 or ip6[4:2] >= 0x0024) +IP6:MC:HBH6:MLD:REPORT-V1;${IP6:MC:HBH6:MLD} and ip6[48] = 131 +IP6:MC:HBH6:MLD:DONE-V1;${IP6:MC:HBH6:MLD} and ip6[48] = 132 +IP6:MC:HBH6:MLD:REPORT-V2;${IP6:MC:HBH6:MLD} and ip6[48] = 143 +IP6:MC:HBH6:MLD:MRD-ADV;${IP6:MC:HBH6:MLD} and ip6[48] = 151 +IP6:MC:HBH6:MLD:MRD-SOL;${IP6:MC:HBH6:MLD} and ip6[48] = 152 +IP6:MC:HBH6:MLD:MRD-TERM;${IP6:MC:HBH6:MLD} and ip6[48] = 153 +IP6:MC:HBH6:OTHER;${IP6:MC:HBH6} and not ${IP6:MC:HBH6:MLD} + +IP6:MC:ICMP6:ECHOREQ;${IP6:MC:ICMP6} && icmp6[icmp6type] = icmp6-echo +IP6:MC:ICMP6:ECHOREP;${IP6:MC:ICMP6} && icmp6[icmp6type] = icmp6-echoreply +IP6:MC:ICMP6:NDSOL;${IP6:MC:ICMP6} && icmp6[icmp6type] = icmp6-neighborsolicit +IP6:MC:ICMP6:NDADV;${IP6:MC:ICMP6} && icmp6[icmp6type] = icmp6-neighboradvert +IP6:MC:ICMP6:NDADV:UNSOL;${IP6:MC:ICMP6:NDADV} and ip6 host ff02::1 +IP6:MC:ICMP6:NDADV:OTHER;${IP6:MC:ICMP6:NDADV} and not (ip6 host ff02::1) +IP6:MC:ICMP6:RTRSOL;${IP6:MC:ICMP6} && icmp6[icmp6type] = icmp6-routersolicit +IP6:MC:ICMP6:RTRADV;${IP6:MC:ICMP6} && icmp6[icmp6type] = icmp6-routeradvert +IP6:MC:ICMP6:OTHER;${IP6:MC:ICMP6} && not (${IP6:MC:ICMP6:ECHOREQ} || ${IP6:MC:ICMP6:ECHOREP} || ${IP6:MC:ICMP6:NDSOL} || ${IP6:MC:ICMP6:NDADV} || ${IP6:MC:ICMP6:RTRSOL} || ${IP6:MC:ICMP6:RTRADV}) + +BLA-CLAIM;${BLA} and arp[21:1] = 0x00 +BLA-UNCLAIM;${BLA} and arp[21:1] = 0x01 +BLA-ANNOUNCE;${BLA} and arp[21:1] = 0x02 +BLA-REQUEST;${BLA} and arp[21:1] = 0x03 +BLA-LOOPDETECT;${BLA} and arp[21:1] = 0x04 + +ARP:REQ;${ARP} and arp[6:2] = 0x0001 +ARP:REQ:UNSOL;${ARP:REQ} and arp[18:4] = 0xffffffff and arp[22:2] = 0xffff +ARP:REQ:OTHER;${ARP:REQ} and not (arp[18:4] = 0xffffffff and arp[22:2] = 0xffff) +ARP:REP;${ARP} and arp[6:2] = 0x0002 +ARP:REP:UNSOL;${ARP:REP} and arp[18:4] = 0xffffffff and arp[22:2] = 0xffff +ARP:REP:OTHER;${ARP:REP} and not (arp[18:4] = 0xffffffff and arp[22:2] = 0xffff) + +BAT;batadv +BAT:BAT-OGM_IV;batadv 15 iv_ogm +BAT:BAT-OGM_V;batadv 15 ogm2 +BAT:BAT-ELP;batadv 15 elp +BAT:BAT-UCAST;batadv 15 unicast +BAT:BAT-UCAST4;batadv 15 unicast_4addr +BAT:BAT-UCAST_FRAG;batadv 15 unicast_frag +BAT:BAT-UCAST_TVLV;batadv 15 unicast_tvlv +BAT:BAT-BCAST;batadv 15 bcast +BAT:BAT-ICMP;batadv 15 \icmp +BAT:BAT-CODED;batadv 15 coded +BAT:BAT-OTHER;batadv and not (${BAT:BAT-OGM_IV} || ${BAT:BAT-OGM_V} || ${BAT:BAT-ELP} || ${BAT:BAT-UCAST} || ${BAT:BAT-UCAST4} || ${BAT:BAT-UCAST_FRAG} || ${BAT:BAT-UCAST_TVLV} || ${BAT:BAT-BCAST} || ${BAT:BAT-ICMP} || ${BAT:BAT-CODED}) + + +BAT:BAT-BCAST:IP4;${BAT:BAT-BCAST} && ${IP4} +BAT:BAT-BCAST:IP6;${BAT:BAT-BCAST} && ${IP6} +BAT:BAT-BCAST:BLA;${BAT:BAT-BCAST} && ${BLA} +BAT:BAT-BCAST:ARP;${BAT:BAT-BCAST} && ${ARP} +BAT:BAT-BCAST:IPX;${BAT:BAT-BCAST} && ${IPX} +BAT:BAT-BCAST:NETBEUI;${BAT:BAT-BCAST} && ${NETBEUI} +BAT:BAT-BCAST:LLDP;${BAT:BAT-BCAST} && ${LLDP} +BAT:BAT-BCAST:OTHER;${BAT:BAT-BCAST} && not (${BAT:BAT-BCAST:IP4} || ${BAT:BAT-BCAST:IP6} || ${BAT:BAT-BCAST:BLA} || ${BAT:BAT-BCAST:ARP} || ${BAT:BAT-BCAST:IPX} || ${BAT:BAT-BCAST:NETBEUI} || ${BAT:BAT-BCAST:LLDP}) + +BAT:BAT-UCAST:IP4;${BAT:BAT-UCAST} && ${IP4} +BAT:BAT-UCAST:IP6;${BAT:BAT-UCAST} && ${IP6} +BAT:BAT-UCAST:BLA;${BAT:BAT-UCAST} && ${BLA} +BAT:BAT-UCAST:ARP;${BAT:BAT-UCAST} && ${ARP} +BAT:BAT-UCAST:IPX;${BAT:BAT-UCAST} && ${IPX} +BAT:BAT-UCAST:NETBEUI;${BAT:BAT-UCAST} && ${NETBEUI} +BAT:BAT-UCAST:LLDP;${BAT:BAT-UCAST} && ${LLDP} +BAT:BAT-UCAST:OTHER;${BAT:BAT-UCAST} && not (${BAT:BAT-UCAST:IP4} || ${BAT:BAT-UCAST:IP6} || ${BAT:BAT-UCAST:BLA} || ${BAT:BAT-UCAST:ARP} || ${BAT:BAT-UCAST:IPX} || ${BAT:BAT-UCAST:NETBEUI} || ${BAT:BAT-UCAST:LLDP}) + +BAT:BAT-UCAST4:IP4;${BAT:BAT-UCAST4} && ${IP4} +BAT:BAT-UCAST4:IP6;${BAT:BAT-UCAST4} && ${IP6} +BAT:BAT-UCAST4:BLA;${BAT:BAT-UCAST4} && ${BLA} +BAT:BAT-UCAST4:ARP;${BAT:BAT-UCAST4} && ${ARP} +BAT:BAT-UCAST4:IPX;${BAT:BAT-UCAST4} && ${IPX} +BAT:BAT-UCAST4:NETBEUI;${BAT:BAT-UCAST4} && ${NETBEUI} +BAT:BAT-UCAST4:LLDP;${BAT:BAT-UCAST4} && ${LLDP} +BAT:BAT-UCAST4:OTHER;${BAT:BAT-UCAST4} && not (${BAT:BAT-UCAST4:IP4} || ${BAT:BAT-UCAST4:IP6} || ${BAT:BAT-UCAST4:BLA} || ${BAT:BAT-UCAST4:ARP} || ${BAT:BAT-UCAST4:IPX} || ${BAT:BAT-UCAST4:NETBEUI} || ${BAT:BAT-UCAST4:LLDP}) + +BAT:BAT-UCAST_TVLV:IP4;${BAT:BAT-UCAST_TVLV} && ${IP4} +BAT:BAT-UCAST_TVLV:IP6;${BAT:BAT-UCAST_TVLV} && ${IP6} +BAT:BAT-UCAST_TVLV:BLA;${BAT:BAT-UCAST_TVLV} && ${BLA} +BAT:BAT-UCAST_TVLV:ARP;${BAT:BAT-UCAST_TVLV} && ${ARP} +BAT:BAT-UCAST_TVLV:IPX;${BAT:BAT-UCAST_TVLV} && ${IPX} +BAT:BAT-UCAST_TVLV:NETBEUI;${BAT:BAT-UCAST_TVLV} && ${NETBEUI} +BAT:BAT-UCAST_TVLV:LLDP;${BAT:BAT-UCAST_TVLV} && ${LLDP} +BAT:BAT-UCAST_TVLV:OTHER;${BAT:BAT-UCAST_TVLV} && not (${BAT:BAT-UCAST_TVLV:IP4} || ${BAT:BAT-UCAST_TVLV:IP6} || ${BAT:BAT-UCAST_TVLV:BLA} || ${BAT:BAT-UCAST_TVLV:ARP} || ${BAT:BAT-UCAST_TVLV:IPX} || ${BAT:BAT-UCAST_TVLV:NETBEUI} || ${BAT:BAT-UCAST_TVLV:LLDP}) + + +BAT:BAT-BCAST:IP4:IGMP;${BAT:BAT-BCAST} && ${IP4:IGMP} +BAT:BAT-BCAST:IP4:IGMP:QUERY-V1;${BAT:BAT-BCAST} && ${IP4:IGMP:QUERY-V1} +BAT:BAT-BCAST:IP4:IGMP:QUERY-V2;${BAT:BAT-BCAST} && ${IP4:IGMP:QUERY-V2} +BAT:BAT-BCAST:IP4:IGMP:QUERY-V3;${BAT:BAT-BCAST} && ${IP4:IGMP:QUERY-V3} +BAT:BAT-BCAST:IP4:IGMP:QUERY-UNKNOWN;${BAT:BAT-BCAST} && ${IP4:IGMP:QUERY-UNKNOWN} +BAT:BAT-BCAST:IP4:IGMP:REPORT-V1;${BAT:BAT-BCAST} && ${IP4:IGMP:REPORT-V1} +BAT:BAT-BCAST:IP4:IGMP:REPORT-V2;${BAT:BAT-BCAST} && ${IP4:IGMP:REPORT-V2} +BAT:BAT-BCAST:IP4:IGMP:LEAVE-V2;${BAT:BAT-BCAST} && ${IP4:IGMP:LEAVE-V2} +BAT:BAT-BCAST:IP4:IGMP:REPORT-V3;${BAT:BAT-BCAST} && ${IP4:IGMP:REPORT-V3} +BAT:BAT-BCAST:IP4:IGMP:MRD-ADV;${BAT:BAT-BCAST} && ${IP4:IGMP:MRD-ADV} +BAT:BAT-BCAST:IP4:IGMP:MRD-SOL;${BAT:BAT-BCAST} && ${IP4:IGMP:MRD-SOL} +BAT:BAT-BCAST:IP4:IGMP:MRD-TERM;${BAT:BAT-BCAST} && ${IP4:IGMP:MRD-TERM} + +BAT:BAT-BCAST:IP4:MC;${BAT:BAT-BCAST} && ${IP4:MC} +BAT:BAT-BCAST:IP4:MC:PIM;${BAT:BAT-BCAST} && ${IP4:MC:PIM} +BAT:BAT-BCAST:IP4:MC:OSPF;${BAT:BAT-BCAST} && ${IP4:MC:OSPF} +BAT:BAT-BCAST:IP4:MC:MANET;${BAT:BAT-BCAST} && ${IP4:MC:MANET} +BAT:BAT-BCAST:IP4:MC:UDP;${BAT:BAT-BCAST} && ${IP4:MC:UDP} + +BAT:BAT-BCAST:IP4:MC:UDP:SSDP;${BAT:BAT-BCAST:IP4:MC:UDP} && ${%SSDP} +BAT:BAT-BCAST:IP4:MC:UDP:LLMNR;${BAT:BAT-BCAST:IP4:MC:UDP} && ${%LLMNR} +BAT:BAT-BCAST:IP4:MC:UDP:MDNS;${BAT:BAT-BCAST:IP4:MC:UDP} && ${%MDNS} +BAT:BAT-BCAST:IP4:MC:UDP:NB-NS;${BAT:BAT-BCAST:IP4:MC:UDP} && ${%NB-NS} +BAT:BAT-BCAST:IP4:MC:UDP:NB-DGM;${BAT:BAT-BCAST:IP4:MC:UDP} && ${%NB-DGM} +BAT:BAT-BCAST:IP4:MC:UDP:DP-LSP;${BAT:BAT-BCAST:IP4:MC:UDP} && ${%DP-LSP} +BAT:BAT-BCAST:IP4:MC:UDP:TRAP-DAEMON;${BAT:BAT-BCAST:IP4:MC:UDP} && ${%TRAP-DAEMON} +BAT:BAT-BCAST:IP4:MC:UDP:DHCP4;${BAT:BAT-BCAST:IP4:MC:UDP} && ${%DHCP4} +BAT:BAT-BCAST:IP4:MC:UDP:DHCP6;${BAT:BAT-BCAST:IP4:MC:UDP} && ${%DHCP6} +BAT:BAT-BCAST:IP4:MC:UDP:WS-DISC;${BAT:BAT-BCAST:IP4:MC:UDP} && ${%WS-DISC} +BAT:BAT-BCAST:IP4:MC:UDP:WSP;${BAT:BAT-BCAST:IP4:MC:UDP} && ${%WSP} +BAT:BAT-BCAST:IP4:MC:UDP:TEREDO;${BAT:BAT-BCAST:IP4:MC:UDP} && ${%TEREDO} +BAT:BAT-BCAST:IP4:MC:UDP:SPOTIFY;${BAT:BAT-BCAST:IP4:MC:UDP} && ${%SPOTIFY} +BAT:BAT-BCAST:IP4:MC:UDP:SIP;${BAT:BAT-BCAST:IP4:MC:UDP} && ${%SIP} +BAT:BAT-BCAST:IP4:MC:UDP:BT-LPD;${BAT:BAT-BCAST:IP4:MC:UDP} && ${%BT-LPD} +BAT:BAT-BCAST:IP4:MC:UDP:NVBM;${BAT:BAT-BCAST:IP4:MC:UDP} && ${%NVBM} +BAT:BAT-BCAST:IP4:MC:UDP:SVRLOC;${BAT:BAT-BCAST:IP4:MC:UDP} && ${%SVRLOC} +BAT:BAT-BCAST:IP4:MC:UDP:ENPC;${BAT:BAT-BCAST:IP4:MC:UDP} && ${%ENPC} +BAT:BAT-BCAST:IP4:MC:UDP:QTSTREAM;${BAT:BAT-BCAST:IP4:MC:UDP} && ${%QTSTREAM} +BAT:BAT-BCAST:IP4:MC:UDP:HDHOMERUN;${BAT:BAT-BCAST:IP4:MC:UDP} && ${%HDHOMERUN} +BAT:BAT-BCAST:IP4:MC:UDP:PLEX-DISC0;${BAT:BAT-BCAST:IP4:MC:UDP} && ${%PLEX-DISC0} +BAT:BAT-BCAST:IP4:MC:UDP:PLEX-DISC2;${BAT:BAT-BCAST:IP4:MC:UDP} && ${%PLEX-DISC2} +BAT:BAT-BCAST:IP4:MC:UDP:PLEX-DISC3;${BAT:BAT-BCAST:IP4:MC:UDP} && ${%PLEX-DISC3} +BAT:BAT-BCAST:IP4:MC:UDP:PLEX-DISC4;${BAT:BAT-BCAST:IP4:MC:UDP} && ${%PLEX-DISC4} +BAT:BAT-BCAST:IP4:MC:UDP:BT-UTP;${BAT:BAT-BCAST:IP4:MC:UDP} && ${%BT-UTP} +BAT:BAT-BCAST:IP4:MC:UDP:WF-BSSERV;${BAT:BAT-BCAST:IP4:MC:UDP} && ${%WF-BSSERV} +BAT:BAT-BCAST:IP4:MC:UDP:FAXIMUM;${BAT:BAT-BCAST:IP4:MC:UDP} && ${%FAXIMUM} +BAT:BAT-BCAST:IP4:MC:UDP:TOMCAT;${BAT:BAT-BCAST:IP4:MC:UDP} && ${%TOMCAT} +BAT:BAT-BCAST:IP4:MC:UDP:DISTINCT;${BAT:BAT-BCAST:IP4:MC:UDP} && ${%DISTINCT} +BAT:BAT-BCAST:IP4:MC:UDP:UDP-25412;${BAT:BAT-BCAST:IP4:MC:UDP} && ${%UDP-25412} +BAT:BAT-BCAST:IP4:MC:UDP:UDP-10203;${BAT:BAT-BCAST:IP4:MC:UDP} && ${%UDP-10203} +BAT:BAT-BCAST:IP4:MC:UDP:UDP-60128;${BAT:BAT-BCAST:IP4:MC:UDP} && ${%UDP-60128} +BAT:BAT-BCAST:IP4:MC:UDP:COREL-VNC;${BAT:BAT-BCAST:IP4:MC:UDP} && ${%COREL-VNC} +BAT:BAT-BCAST:IP4:MC:UDP:HPVMMCTRL;${BAT:BAT-BCAST:IP4:MC:UDP} && ${%HPVMMCTRL} +BAT:BAT-BCAST:IP4:MC:UDP:CBT;${BAT:BAT-BCAST:IP4:MC:UDP} && ${%CBT} +BAT:BAT-BCAST:IP4:MC:UDP:MCAFEE;${BAT:BAT-BCAST:IP4:MC:UDP} && ${%MCAFEE} +BAT:BAT-BCAST:IP4:MC:UDP:UDP-39455;${BAT:BAT-BCAST:IP4:MC:UDP} && ${%UDP-39455} +BAT:BAT-BCAST:IP4:MC:UDP:UDP-889;${BAT:BAT-BCAST:IP4:MC:UDP} && ${%UDP-889} +BAT:BAT-BCAST:IP4:MC:UDP:UDP-16962;${BAT:BAT-BCAST:IP4:MC:UDP} && ${%UDP-16962} +BAT:BAT-BCAST:IP4:MC:UDP:TSEQ;${BAT:BAT-BCAST:IP4:MC:UDP} && ${%TSEQ} +BAT:BAT-BCAST:IP4:MC:UDP:CANON-BJNP;${BAT:BAT-BCAST:IP4:MC:UDP} && ${%CANON-BJNP} +BAT:BAT-BCAST:IP4:MC:UDP:RIP;${BAT:BAT-BCAST:IP4:MC:UDP} && ${%RIP} +BAT:BAT-BCAST:IP4:MC:UDP:RIPNG;${BAT:BAT-BCAST:IP4:MC:UDP} && ${%RIPNG} +BAT:BAT-BCAST:IP4:MC:UDP:BABEL;${BAT:BAT-BCAST:IP4:MC:UDP} && ${%BABEL} +BAT:BAT-BCAST:IP4:MC:UDP:MANET;${BAT:BAT-BCAST:IP4:MC:UDP} && ${%MANET} +BAT:BAT-BCAST:IP4:MC:UDP:RESPONDD-QRY;${BAT:BAT-BCAST:IP4:MC:UDP} && ${%RESPONDD-QRY} +BAT:BAT-BCAST:IP4:MC:UDP:SYNCTHING-LPD;${BAT:BAT-BCAST:IP4:MC:UDP} && ${%SYNCTHING-LPD} +BAT:BAT-BCAST:IP4:MC:UDP:USTEER;${BAT:BAT-BCAST:IP4:MC:UDP} && ${%USTEER} +BAT:BAT-BCAST:IP4:MC:UDP:L3ROAMD;${BAT:BAT-BCAST:IP4:MC:UDP} && ${%L3ROAMD} +BAT:BAT-BCAST:IP4:MC:UDP:MMFD;${BAT:BAT-BCAST:IP4:MC:UDP} && ${%MMFD} + +BAT:BAT-BCAST:IP6:MC;${BAT:BAT-BCAST} && ${IP6:MC} +BAT:BAT-BCAST:IP6:MC:PIM;${BAT:BAT-BCAST} && ${IP6:MC:PIM} +BAT:BAT-BCAST:IP6:MC:OSPF;${BAT:BAT-BCAST} && ${IP6:MC:OSPF} +BAT:BAT-BCAST:IP6:MC:MANET;${BAT:BAT-BCAST} && ${IP6:MC:MANET} +BAT:BAT-BCAST:IP6:MC:UDP;${BAT:BAT-BCAST} && ${IP6:MC:UDP} + +BAT:BAT-BCAST:IP6:MC:UDP:SSDP;${BAT:BAT-BCAST:IP6:MC:UDP} && ${%SSDP} +BAT:BAT-BCAST:IP6:MC:UDP:LLMNR;${BAT:BAT-BCAST:IP6:MC:UDP} && ${%LLMNR} +BAT:BAT-BCAST:IP6:MC:UDP:MDNS;${BAT:BAT-BCAST:IP6:MC:UDP} && ${%MDNS} +BAT:BAT-BCAST:IP6:MC:UDP:NB-NS;${BAT:BAT-BCAST:IP6:MC:UDP} && ${%NB-NS} +BAT:BAT-BCAST:IP6:MC:UDP:NB-DGM;${BAT:BAT-BCAST:IP6:MC:UDP} && ${%NB-DGM} +BAT:BAT-BCAST:IP6:MC:UDP:DP-LSP;${BAT:BAT-BCAST:IP6:MC:UDP} && ${%DP-LSP} +BAT:BAT-BCAST:IP6:MC:UDP:TRAP-DAEMON;${BAT:BAT-BCAST:IP6:MC:UDP} && ${%TRAP-DAEMON} +BAT:BAT-BCAST:IP6:MC:UDP:DHCP4;${BAT:BAT-BCAST:IP6:MC:UDP} && ${%DHCP4} +BAT:BAT-BCAST:IP6:MC:UDP:DHCP6;${BAT:BAT-BCAST:IP6:MC:UDP} && ${%DHCP6} +BAT:BAT-BCAST:IP6:MC:UDP:WS-DISC;${BAT:BAT-BCAST:IP6:MC:UDP} && ${%WS-DISC} +BAT:BAT-BCAST:IP6:MC:UDP:WSP;${BAT:BAT-BCAST:IP6:MC:UDP} && ${%WSP} +BAT:BAT-BCAST:IP6:MC:UDP:TEREDO;${BAT:BAT-BCAST:IP6:MC:UDP} && ${%TEREDO} +BAT:BAT-BCAST:IP6:MC:UDP:SPOTIFY;${BAT:BAT-BCAST:IP6:MC:UDP} && ${%SPOTIFY} +BAT:BAT-BCAST:IP6:MC:UDP:SIP;${BAT:BAT-BCAST:IP6:MC:UDP} && ${%SIP} +BAT:BAT-BCAST:IP6:MC:UDP:BT-LPD;${BAT:BAT-BCAST:IP6:MC:UDP} && ${%BT-LPD} +BAT:BAT-BCAST:IP6:MC:UDP:NVBM;${BAT:BAT-BCAST:IP6:MC:UDP} && ${%NVBM} +BAT:BAT-BCAST:IP6:MC:UDP:SVRLOC;${BAT:BAT-BCAST:IP6:MC:UDP} && ${%SVRLOC} +BAT:BAT-BCAST:IP6:MC:UDP:ENPC;${BAT:BAT-BCAST:IP6:MC:UDP} && ${%ENPC} +BAT:BAT-BCAST:IP6:MC:UDP:QTSTREAM;${BAT:BAT-BCAST:IP6:MC:UDP} && ${%QTSTREAM} +BAT:BAT-BCAST:IP6:MC:UDP:HDHOMERUN;${BAT:BAT-BCAST:IP6:MC:UDP} && ${%HDHOMERUN} +BAT:BAT-BCAST:IP6:MC:UDP:PLEX-DISC0;${BAT:BAT-BCAST:IP6:MC:UDP} && ${%PLEX-DISC0} +BAT:BAT-BCAST:IP6:MC:UDP:PLEX-DISC2;${BAT:BAT-BCAST:IP6:MC:UDP} && ${%PLEX-DISC2} +BAT:BAT-BCAST:IP6:MC:UDP:PLEX-DISC3;${BAT:BAT-BCAST:IP6:MC:UDP} && ${%PLEX-DISC3} +BAT:BAT-BCAST:IP6:MC:UDP:PLEX-DISC4;${BAT:BAT-BCAST:IP6:MC:UDP} && ${%PLEX-DISC4} +BAT:BAT-BCAST:IP6:MC:UDP:BT-UTP;${BAT:BAT-BCAST:IP6:MC:UDP} && ${%BT-UTP} +BAT:BAT-BCAST:IP6:MC:UDP:WF-BSSERV;${BAT:BAT-BCAST:IP6:MC:UDP} && ${%WF-BSSERV} +BAT:BAT-BCAST:IP6:MC:UDP:FAXIMUM;${BAT:BAT-BCAST:IP6:MC:UDP} && ${%FAXIMUM} +BAT:BAT-BCAST:IP6:MC:UDP:TOMCAT;${BAT:BAT-BCAST:IP6:MC:UDP} && ${%TOMCAT} +BAT:BAT-BCAST:IP6:MC:UDP:DISTINCT;${BAT:BAT-BCAST:IP6:MC:UDP} && ${%DISTINCT} +BAT:BAT-BCAST:IP6:MC:UDP:UDP-25412;${BAT:BAT-BCAST:IP6:MC:UDP} && ${%UDP-25412} +BAT:BAT-BCAST:IP6:MC:UDP:UDP-10203;${BAT:BAT-BCAST:IP6:MC:UDP} && ${%UDP-10203} +BAT:BAT-BCAST:IP6:MC:UDP:UDP-60128;${BAT:BAT-BCAST:IP6:MC:UDP} && ${%UDP-60128} +BAT:BAT-BCAST:IP6:MC:UDP:COREL-VNC;${BAT:BAT-BCAST:IP6:MC:UDP} && ${%COREL-VNC} +BAT:BAT-BCAST:IP6:MC:UDP:HPVMMCTRL;${BAT:BAT-BCAST:IP6:MC:UDP} && ${%HPVMMCTRL} +BAT:BAT-BCAST:IP6:MC:UDP:CBT;${BAT:BAT-BCAST:IP6:MC:UDP} && ${%CBT} +BAT:BAT-BCAST:IP6:MC:UDP:MCAFEE;${BAT:BAT-BCAST:IP6:MC:UDP} && ${%MCAFEE} +BAT:BAT-BCAST:IP6:MC:UDP:UDP-39455;${BAT:BAT-BCAST:IP6:MC:UDP} && ${%UDP-39455} +BAT:BAT-BCAST:IP6:MC:UDP:UDP-889;${BAT:BAT-BCAST:IP6:MC:UDP} && ${%UDP-889} +BAT:BAT-BCAST:IP6:MC:UDP:UDP-16962;${BAT:BAT-BCAST:IP6:MC:UDP} && ${%UDP-16962} +BAT:BAT-BCAST:IP6:MC:UDP:TSEQ;${BAT:BAT-BCAST:IP6:MC:UDP} && ${%TSEQ} +BAT:BAT-BCAST:IP6:MC:UDP:CANON-BJNP;${BAT:BAT-BCAST:IP6:MC:UDP} && ${%CANON-BJNP} +BAT:BAT-BCAST:IP6:MC:UDP:RIP;${BAT:BAT-BCAST:IP6:MC:UDP} && ${%RIP} +BAT:BAT-BCAST:IP6:MC:UDP:RIPNG;${BAT:BAT-BCAST:IP6:MC:UDP} && ${%RIPNG} +BAT:BAT-BCAST:IP6:MC:UDP:BABEL;${BAT:BAT-BCAST:IP6:MC:UDP} && ${%BABEL} +BAT:BAT-BCAST:IP6:MC:UDP:MANET;${BAT:BAT-BCAST:IP6:MC:UDP} && ${%MANET} +BAT:BAT-BCAST:IP6:MC:UDP:RESPONDD-QRY;${BAT:BAT-BCAST:IP6:MC:UDP} && ${%RESPONDD-QRY} +BAT:BAT-BCAST:IP6:MC:UDP:SYNCTHING-LPD;${BAT:BAT-BCAST:IP6:MC:UDP} && ${%SYNCTHING-LPD} +BAT:BAT-BCAST:IP6:MC:UDP:USTEER;${BAT:BAT-BCAST:IP6:MC:UDP} && ${%USTEER} +BAT:BAT-BCAST:IP6:MC:UDP:L3ROAMD;${BAT:BAT-BCAST:IP6:MC:UDP} && ${%L3ROAMD} +BAT:BAT-BCAST:IP6:MC:UDP:MMFD;${BAT:BAT-BCAST:IP6:MC:UDP} && ${%MMFD} + +BAT:BAT-BCAST:IP6:MC:HBH6;${BAT:BAT-BCAST} && ${IP6:MC:HBH6} +BAT:BAT-BCAST:IP6:MC:ICMP6;${BAT:BAT-BCAST} && ${IP6:MC:ICMP6} + +BAT:BAT-BCAST:IP6:MC:HBH6:MLD;${BAT:BAT-BCAST} && ${IP6:MC:HBH6:MLD} +BAT:BAT-BCAST:IP6:MC:HBH6:MLD:QUERY-V1;${BAT:BAT-BCAST} && ${IP6:MC:HBH6:MLD:QUERY-V1} +BAT:BAT-BCAST:IP6:MC:HBH6:MLD:QUERY-V1:GENERAL;${BAT:BAT-BCAST} && ${IP6:MC:HBH6:MLD:QUERY-V1:GENERAL} +BAT:BAT-BCAST:IP6:MC:HBH6:MLD:QUERY-V1:ADDRSPEC;${BAT:BAT-BCAST} && ${IP6:MC:HBH6:MLD:QUERY-V1:ADDRSPEC} +BAT:BAT-BCAST:IP6:MC:HBH6:MLD:QUERY-V2;${BAT:BAT-BCAST} && ${IP6:MC:HBH6:MLD:QUERY-V2} +BAT:BAT-BCAST:IP6:MC:HBH6:MLD:QUERY-V2:GENERAL;${BAT:BAT-BCAST} && ${IP6:MC:HBH6:MLD:QUERY-V2:GENERAL} +BAT:BAT-BCAST:IP6:MC:HBH6:MLD:QUERY-V2:ADDRSPEC;${BAT:BAT-BCAST} && ${IP6:MC:HBH6:MLD:QUERY-V2:ADDRSPEC} +BAT:BAT-BCAST:IP6:MC:HBH6:MLD:QUERY-UNKNOWN;${BAT:BAT-BCAST} && ${IP6:MC:HBH6:MLD:QUERY-UNKNOWN} +BAT:BAT-BCAST:IP6:MC:HBH6:MLD:REPORT-V1;${BAT:BAT-BCAST} && ${IP6:MC:HBH6:MLD:REPORT-V1} +BAT:BAT-BCAST:IP6:MC:HBH6:MLD:DONE-V1;${BAT:BAT-BCAST} && ${IP6:MC:HBH6:MLD:DONE-V1} +BAT:BAT-BCAST:IP6:MC:HBH6:MLD:REPORT-V2;${BAT:BAT-BCAST} && ${IP6:MC:HBH6:MLD:REPORT-V2} +BAT:BAT-BCAST:IP6:MC:HBH6:MLD:MRD-ADV;${BAT:BAT-BCAST} && ${IP6:MC:HBH6:MLD:MRD-ADV} +BAT:BAT-BCAST:IP6:MC:HBH6:MLD:MRD-SOL;${BAT:BAT-BCAST} && ${IP6:MC:HBH6:MLD:MRD-SOL} +BAT:BAT-BCAST:IP6:MC:HBH6:MLD:MRD-TERM;${BAT:BAT-BCAST} && ${IP6:MC:HBH6:MLD:MRD-TERM} +BAT:BAT-BCAST:IP6:MC:HBH6:OTHER;${BAT:BAT-BCAST} && ${IP6:MC:HBH6} and not (${BAT:BAT-BCAST:IP6:MC:HBH6:MLD}) + +BAT:BAT-BCAST:IP6:MC:ICMP6:ECHOREQ;${BAT:BAT-BCAST} && ${IP6:MC:ICMP6:ECHOREQ} +BAT:BAT-BCAST:IP6:MC:ICMP6:ECHOREP;${BAT:BAT-BCAST} && ${IP6:MC:ICMP6:ECHOREP} +BAT:BAT-BCAST:IP6:MC:ICMP6:NDSOL;${BAT:BAT-BCAST} && ${IP6:MC:ICMP6:NDSOL} +BAT:BAT-BCAST:IP6:MC:ICMP6:NDADV;${BAT:BAT-BCAST} && ${IP6:MC:ICMP6:NDADV} +BAT:BAT-BCAST:IP6:MC:ICMP6:NDADV:UNSOL;${BAT:BAT-BCAST} and ${IP6:MC:ICMP6:NDADV:UNSOL} +BAT:BAT-BCAST:IP6:MC:ICMP6:NDADV:OTHER;${BAT:BAT-BCAST} and ${IP6:MC:ICMP6:NDADV:OTHER} +BAT:BAT-BCAST:IP6:MC:ICMP6:RTRSOL;${BAT:BAT-BCAST} && ${IP6:MC:ICMP6:RTRSOL} +BAT:BAT-BCAST:IP6:MC:ICMP6:RTRADV;${BAT:BAT-BCAST} && ${IP6:MC:ICMP6:RTRADV} +BAT:BAT-BCAST:IP6:MC:ICMP6:OTHER;${BAT:BAT-BCAST} && ${IP6:MC:ICMP6:OTHER} + +BAT:BAT-BCAST:BLA:CLAIM;${BAT:BAT-BCAST} and ${BLA-CLAIM} +BAT:BAT-BCAST:BLA:UNCLAIM;${BAT:BAT-BCAST} and ${BLA-UNCLAIM} +BAT:BAT-BCAST:BLA:ANNOUNCE;${BAT:BAT-BCAST} and ${BLA-ANNOUNCE} +BAT:BAT-BCAST:BLA:REQUEST;${BAT:BAT-BCAST} and ${BLA-REQUEST} +BAT:BAT-BCAST:BLA:LOOPDETECT;${BAT:BAT-BCAST} and ${BLA-LOOPDETECT} + +BAT:BAT-BCAST:ARP:REQ;${BAT:BAT-BCAST} and ${ARP:REQ} +BAT:BAT-BCAST:ARP:REQ:UNSOL;${BAT:BAT-BCAST} and ${ARP:REQ:UNSOL} +BAT:BAT-BCAST:ARP:REQ:OTHER;${BAT:BAT-BCAST} and ${ARP:REQ:OTHER} +BAT:BAT-BCAST:ARP:REP;${BAT:BAT-BCAST} and ${ARP:REP} +BAT:BAT-BCAST:ARP:REP:UNSOL;${BAT:BAT-BCAST} and ${ARP:REP:UNSOL} +BAT:BAT-BCAST:ARP:REP:OTHER;${BAT:BAT-BCAST} and ${ARP:REP:OTHER} + + +BAT:BAT-UCAST:IP4:MC;${BAT:BAT-UCAST} && ${IP4:MC} +BAT:BAT-UCAST:IP4:MC:PIM;${BAT:BAT-UCAST} && ${IP4:MC:PIM} +BAT:BAT-UCAST:IP4:MC:OSPF;${BAT:BAT-UCAST} && ${IP4:MC:OSPF} +BAT:BAT-UCAST:IP4:MC:MANET;${BAT:BAT-UCAST} && ${IP4:MC:MANET} +BAT:BAT-UCAST:IP4:MC:UDP;${BAT:BAT-UCAST} && ${IP4:MC:UDP} + +BAT:BAT-UCAST:IP4:MC:UDP:SSDP;${BAT:BAT-UCAST:IP4:MC:UDP} && ${%SSDP} +BAT:BAT-UCAST:IP4:MC:UDP:LLMNR;${BAT:BAT-UCAST:IP4:MC:UDP} && ${%LLMNR} +BAT:BAT-UCAST:IP4:MC:UDP:MDNS;${BAT:BAT-UCAST:IP4:MC:UDP} && ${%MDNS} +BAT:BAT-UCAST:IP4:MC:UDP:NB-NS;${BAT:BAT-UCAST:IP4:MC:UDP} && ${%NB-NS} +BAT:BAT-UCAST:IP4:MC:UDP:NB-DGM;${BAT:BAT-UCAST:IP4:MC:UDP} && ${%NB-DGM} +BAT:BAT-UCAST:IP4:MC:UDP:DP-LSP;${BAT:BAT-UCAST:IP4:MC:UDP} && ${%DP-LSP} +BAT:BAT-UCAST:IP4:MC:UDP:TRAP-DAEMON;${BAT:BAT-UCAST:IP4:MC:UDP} && ${%TRAP-DAEMON} +BAT:BAT-UCAST:IP4:MC:UDP:DHCP4;${BAT:BAT-UCAST:IP4:MC:UDP} && ${%DHCP4} +BAT:BAT-UCAST:IP4:MC:UDP:DHCP6;${BAT:BAT-UCAST:IP4:MC:UDP} && ${%DHCP6} +BAT:BAT-UCAST:IP4:MC:UDP:WS-DISC;${BAT:BAT-UCAST:IP4:MC:UDP} && ${%WS-DISC} +BAT:BAT-UCAST:IP4:MC:UDP:WSP;${BAT:BAT-UCAST:IP4:MC:UDP} && ${%WSP} +BAT:BAT-UCAST:IP4:MC:UDP:TEREDO;${BAT:BAT-UCAST:IP4:MC:UDP} && ${%TEREDO} +BAT:BAT-UCAST:IP4:MC:UDP:SPOTIFY;${BAT:BAT-UCAST:IP4:MC:UDP} && ${%SPOTIFY} +BAT:BAT-UCAST:IP4:MC:UDP:SIP;${BAT:BAT-UCAST:IP4:MC:UDP} && ${%SIP} +BAT:BAT-UCAST:IP4:MC:UDP:BT-LPD;${BAT:BAT-UCAST:IP4:MC:UDP} && ${%BT-LPD} +BAT:BAT-UCAST:IP4:MC:UDP:NVBM;${BAT:BAT-UCAST:IP4:MC:UDP} && ${%NVBM} +BAT:BAT-UCAST:IP4:MC:UDP:SVRLOC;${BAT:BAT-UCAST:IP4:MC:UDP} && ${%SVRLOC} +BAT:BAT-UCAST:IP4:MC:UDP:ENPC;${BAT:BAT-UCAST:IP4:MC:UDP} && ${%ENPC} +BAT:BAT-UCAST:IP4:MC:UDP:QTSTREAM;${BAT:BAT-UCAST:IP4:MC:UDP} && ${%QTSTREAM} +BAT:BAT-UCAST:IP4:MC:UDP:HDHOMERUN;${BAT:BAT-UCAST:IP4:MC:UDP} && ${%HDHOMERUN} +BAT:BAT-UCAST:IP4:MC:UDP:PLEX-DISC0;${BAT:BAT-UCAST:IP4:MC:UDP} && ${%PLEX-DISC0} +BAT:BAT-UCAST:IP4:MC:UDP:PLEX-DISC2;${BAT:BAT-UCAST:IP4:MC:UDP} && ${%PLEX-DISC2} +BAT:BAT-UCAST:IP4:MC:UDP:PLEX-DISC3;${BAT:BAT-UCAST:IP4:MC:UDP} && ${%PLEX-DISC3} +BAT:BAT-UCAST:IP4:MC:UDP:PLEX-DISC4;${BAT:BAT-UCAST:IP4:MC:UDP} && ${%PLEX-DISC4} +BAT:BAT-UCAST:IP4:MC:UDP:BT-UTP;${BAT:BAT-UCAST:IP4:MC:UDP} && ${%BT-UTP} +BAT:BAT-UCAST:IP4:MC:UDP:WF-BSSERV;${BAT:BAT-UCAST:IP4:MC:UDP} && ${%WF-BSSERV} +BAT:BAT-UCAST:IP4:MC:UDP:FAXIMUM;${BAT:BAT-UCAST:IP4:MC:UDP} && ${%FAXIMUM} +BAT:BAT-UCAST:IP4:MC:UDP:TOMCAT;${BAT:BAT-UCAST:IP4:MC:UDP} && ${%TOMCAT} +BAT:BAT-UCAST:IP4:MC:UDP:DISTINCT;${BAT:BAT-UCAST:IP4:MC:UDP} && ${%DISTINCT} +BAT:BAT-UCAST:IP4:MC:UDP:UDP-25412;${BAT:BAT-UCAST:IP4:MC:UDP} && ${%UDP-25412} +BAT:BAT-UCAST:IP4:MC:UDP:UDP-10203;${BAT:BAT-UCAST:IP4:MC:UDP} && ${%UDP-10203} +BAT:BAT-UCAST:IP4:MC:UDP:UDP-60128;${BAT:BAT-UCAST:IP4:MC:UDP} && ${%UDP-60128} +BAT:BAT-UCAST:IP4:MC:UDP:COREL-VNC;${BAT:BAT-UCAST:IP4:MC:UDP} && ${%COREL-VNC} +BAT:BAT-UCAST:IP4:MC:UDP:HPVMMCTRL;${BAT:BAT-UCAST:IP4:MC:UDP} && ${%HPVMMCTRL} +BAT:BAT-UCAST:IP4:MC:UDP:CBT;${BAT:BAT-UCAST:IP4:MC:UDP} && ${%CBT} +BAT:BAT-UCAST:IP4:MC:UDP:MCAFEE;${BAT:BAT-UCAST:IP4:MC:UDP} && ${%MCAFEE} +BAT:BAT-UCAST:IP4:MC:UDP:UDP-39455;${BAT:BAT-UCAST:IP4:MC:UDP} && ${%UDP-39455} +BAT:BAT-UCAST:IP4:MC:UDP:UDP-889;${BAT:BAT-UCAST:IP4:MC:UDP} && ${%UDP-889} +BAT:BAT-UCAST:IP4:MC:UDP:UDP-16962;${BAT:BAT-UCAST:IP4:MC:UDP} && ${%UDP-16962} +BAT:BAT-UCAST:IP4:MC:UDP:TSEQ;${BAT:BAT-UCAST:IP4:MC:UDP} && ${%TSEQ} +BAT:BAT-UCAST:IP4:MC:UDP:CANON-BJNP;${BAT:BAT-UCAST:IP4:MC:UDP} && ${%CANON-BJNP} +BAT:BAT-UCAST:IP4:MC:UDP:RIP;${BAT:BAT-UCAST:IP4:MC:UDP} && ${%RIP} +BAT:BAT-UCAST:IP4:MC:UDP:RIPNG;${BAT:BAT-UCAST:IP4:MC:UDP} && ${%RIPNG} +BAT:BAT-UCAST:IP4:MC:UDP:BABEL;${BAT:BAT-UCAST:IP4:MC:UDP} && ${%BABEL} +BAT:BAT-UCAST:IP4:MC:UDP:MANET;${BAT:BAT-UCAST:IP4:MC:UDP} && ${%MANET} +BAT:BAT-UCAST:IP4:MC:UDP:RESPONDD-QRY;${BAT:BAT-UCAST:IP4:MC:UDP} && ${%RESPONDD-QRY} +BAT:BAT-UCAST:IP4:MC:UDP:SYNCTHING-LPD;${BAT:BAT-UCAST:IP4:MC:UDP} && ${%SYNCTHING-LPD} +BAT:BAT-UCAST:IP4:MC:UDP:USTEER;${BAT:BAT-UCAST:IP4:MC:UDP} && ${%USTEER} +BAT:BAT-UCAST:IP4:MC:UDP:L3ROAMD;${BAT:BAT-UCAST:IP4:MC:UDP} && ${%L3ROAMD} +BAT:BAT-UCAST:IP4:MC:UDP:MMFD;${BAT:BAT-UCAST:IP4:MC:UDP} && ${%MMFD} + +BAT:BAT-UCAST:IP6:MC;${BAT:BAT-UCAST} && ${IP6:MC} +BAT:BAT-UCAST:IP6:MC:PIM;${BAT:BAT-UCAST} && ${IP6:MC:PIM} +BAT:BAT-UCAST:IP6:MC:OSPF;${BAT:BAT-UCAST} && ${IP6:MC:OSPF} +BAT:BAT-UCAST:IP6:MC:MANET;${BAT:BAT-UCAST} && ${IP6:MC:MANET} +BAT:BAT-UCAST:IP6:MC:UDP;${BAT:BAT-UCAST} && ${IP6:MC:UDP} + +BAT:BAT-UCAST:IP6:MC:UDP:SSDP;${BAT:BAT-UCAST:IP6:MC:UDP} && ${%SSDP} +BAT:BAT-UCAST:IP6:MC:UDP:LLMNR;${BAT:BAT-UCAST:IP6:MC:UDP} && ${%LLMNR} +BAT:BAT-UCAST:IP6:MC:UDP:MDNS;${BAT:BAT-UCAST:IP6:MC:UDP} && ${%MDNS} +BAT:BAT-UCAST:IP6:MC:UDP:NB-NS;${BAT:BAT-UCAST:IP6:MC:UDP} && ${%NB-NS} +BAT:BAT-UCAST:IP6:MC:UDP:NB-DGM;${BAT:BAT-UCAST:IP6:MC:UDP} && ${%NB-DGM} +BAT:BAT-UCAST:IP6:MC:UDP:DP-LSP;${BAT:BAT-UCAST:IP6:MC:UDP} && ${%DP-LSP} +BAT:BAT-UCAST:IP6:MC:UDP:TRAP-DAEMON;${BAT:BAT-UCAST:IP6:MC:UDP} && ${%TRAP-DAEMON} +BAT:BAT-UCAST:IP6:MC:UDP:DHCP4;${BAT:BAT-UCAST:IP6:MC:UDP} && ${%DHCP4} +BAT:BAT-UCAST:IP6:MC:UDP:DHCP6;${BAT:BAT-UCAST:IP6:MC:UDP} && ${%DHCP6} +BAT:BAT-UCAST:IP6:MC:UDP:WS-DISC;${BAT:BAT-UCAST:IP6:MC:UDP} && ${%WS-DISC} +BAT:BAT-UCAST:IP6:MC:UDP:WSP;${BAT:BAT-UCAST:IP6:MC:UDP} && ${%WSP} +BAT:BAT-UCAST:IP6:MC:UDP:TEREDO;${BAT:BAT-UCAST:IP6:MC:UDP} && ${%TEREDO} +BAT:BAT-UCAST:IP6:MC:UDP:SPOTIFY;${BAT:BAT-UCAST:IP6:MC:UDP} && ${%SPOTIFY} +BAT:BAT-UCAST:IP6:MC:UDP:SIP;${BAT:BAT-UCAST:IP6:MC:UDP} && ${%SIP} +BAT:BAT-UCAST:IP6:MC:UDP:BT-LPD;${BAT:BAT-UCAST:IP6:MC:UDP} && ${%BT-LPD} +BAT:BAT-UCAST:IP6:MC:UDP:NVBM;${BAT:BAT-UCAST:IP6:MC:UDP} && ${%NVBM} +BAT:BAT-UCAST:IP6:MC:UDP:SVRLOC;${BAT:BAT-UCAST:IP6:MC:UDP} && ${%SVRLOC} +BAT:BAT-UCAST:IP6:MC:UDP:ENPC;${BAT:BAT-UCAST:IP6:MC:UDP} && ${%ENPC} +BAT:BAT-UCAST:IP6:MC:UDP:QTSTREAM;${BAT:BAT-UCAST:IP6:MC:UDP} && ${%QTSTREAM} +BAT:BAT-UCAST:IP6:MC:UDP:HDHOMERUN;${BAT:BAT-UCAST:IP6:MC:UDP} && ${%HDHOMERUN} +BAT:BAT-UCAST:IP6:MC:UDP:PLEX-DISC0;${BAT:BAT-UCAST:IP6:MC:UDP} && ${%PLEX-DISC0} +BAT:BAT-UCAST:IP6:MC:UDP:PLEX-DISC2;${BAT:BAT-UCAST:IP6:MC:UDP} && ${%PLEX-DISC2} +BAT:BAT-UCAST:IP6:MC:UDP:PLEX-DISC3;${BAT:BAT-UCAST:IP6:MC:UDP} && ${%PLEX-DISC3} +BAT:BAT-UCAST:IP6:MC:UDP:PLEX-DISC4;${BAT:BAT-UCAST:IP6:MC:UDP} && ${%PLEX-DISC4} +BAT:BAT-UCAST:IP6:MC:UDP:BT-UTP;${BAT:BAT-UCAST:IP6:MC:UDP} && ${%BT-UTP} +BAT:BAT-UCAST:IP6:MC:UDP:WF-BSSERV;${BAT:BAT-UCAST:IP6:MC:UDP} && ${%WF-BSSERV} +BAT:BAT-UCAST:IP6:MC:UDP:FAXIMUM;${BAT:BAT-UCAST:IP6:MC:UDP} && ${%FAXIMUM} +BAT:BAT-UCAST:IP6:MC:UDP:TOMCAT;${BAT:BAT-UCAST:IP6:MC:UDP} && ${%TOMCAT} +BAT:BAT-UCAST:IP6:MC:UDP:DISTINCT;${BAT:BAT-UCAST:IP6:MC:UDP} && ${%DISTINCT} +BAT:BAT-UCAST:IP6:MC:UDP:UDP-25412;${BAT:BAT-UCAST:IP6:MC:UDP} && ${%UDP-25412} +BAT:BAT-UCAST:IP6:MC:UDP:UDP-10203;${BAT:BAT-UCAST:IP6:MC:UDP} && ${%UDP-10203} +BAT:BAT-UCAST:IP6:MC:UDP:UDP-60128;${BAT:BAT-UCAST:IP6:MC:UDP} && ${%UDP-60128} +BAT:BAT-UCAST:IP6:MC:UDP:COREL-VNC;${BAT:BAT-UCAST:IP6:MC:UDP} && ${%COREL-VNC} +BAT:BAT-UCAST:IP6:MC:UDP:HPVMMCTRL;${BAT:BAT-UCAST:IP6:MC:UDP} && ${%HPVMMCTRL} +BAT:BAT-UCAST:IP6:MC:UDP:CBT;${BAT:BAT-UCAST:IP6:MC:UDP} && ${%CBT} +BAT:BAT-UCAST:IP6:MC:UDP:MCAFEE;${BAT:BAT-UCAST:IP6:MC:UDP} && ${%MCAFEE} +BAT:BAT-UCAST:IP6:MC:UDP:UDP-39455;${BAT:BAT-UCAST:IP6:MC:UDP} && ${%UDP-39455} +BAT:BAT-UCAST:IP6:MC:UDP:UDP-889;${BAT:BAT-UCAST:IP6:MC:UDP} && ${%UDP-889} +BAT:BAT-UCAST:IP6:MC:UDP:UDP-16962;${BAT:BAT-UCAST:IP6:MC:UDP} && ${%UDP-16962} +BAT:BAT-UCAST:IP6:MC:UDP:TSEQ;${BAT:BAT-UCAST:IP6:MC:UDP} && ${%TSEQ} +BAT:BAT-UCAST:IP6:MC:UDP:CANON-BJNP;${BAT:BAT-UCAST:IP6:MC:UDP} && ${%CANON-BJNP} +BAT:BAT-UCAST:IP6:MC:UDP:RIP;${BAT:BAT-UCAST:IP6:MC:UDP} && ${%RIP} +BAT:BAT-UCAST:IP6:MC:UDP:RIPNG;${BAT:BAT-UCAST:IP6:MC:UDP} && ${%RIPNG} +BAT:BAT-UCAST:IP6:MC:UDP:BABEL;${BAT:BAT-UCAST:IP6:MC:UDP} && ${%BABEL} +BAT:BAT-UCAST:IP6:MC:UDP:MANET;${BAT:BAT-UCAST:IP6:MC:UDP} && ${%MANET} +BAT:BAT-UCAST:IP6:MC:UDP:RESPONDD-QRY;${BAT:BAT-UCAST:IP6:MC:UDP} && ${%RESPONDD-QRY} +BAT:BAT-UCAST:IP6:MC:UDP:SYNCTHING-LPD;${BAT:BAT-UCAST:IP6:MC:UDP} && ${%SYNCTHING-LPD} +BAT:BAT-UCAST:IP6:MC:UDP:USTEER;${BAT:BAT-UCAST:IP6:MC:UDP} && ${%USTEER} +BAT:BAT-UCAST:IP6:MC:UDP:L3ROAMD;${BAT:BAT-UCAST:IP6:MC:UDP} && ${%L3ROAMD} +BAT:BAT-UCAST:IP6:MC:UDP:MMFD;${BAT:BAT-UCAST:IP6:MC:UDP} && ${%MMFD} + +BAT:BAT-UCAST:IP6:MC:HBH6;${BAT:BAT-UCAST} && ${IP6:MC:HBH6} +BAT:BAT-UCAST:IP6:MC:ICMP6;${BAT:BAT-UCAST} && ${IP6:MC:ICMP6} + +BAT:BAT-UCAST:IP6:MC:HBH6:MLD;${BAT:BAT-UCAST} && ${IP6:MC:HBH6:MLD} +BAT:BAT-UCAST:IP6:MC:HBH6:MLD:QUERY-V1;${BAT:BAT-UCAST} && ${IP6:MC:HBH6:MLD:QUERY-V1} +BAT:BAT-UCAST:IP6:MC:HBH6:MLD:QUERY-V1:GENERAL;${BAT:BAT-UCAST} && ${IP6:MC:HBH6:MLD:QUERY-V1:GENERAL} +BAT:BAT-UCAST:IP6:MC:HBH6:MLD:QUERY-V1:ADDRSPEC;${BAT:BAT-UCAST} && ${IP6:MC:HBH6:MLD:QUERY-V1:ADDRSPEC} +BAT:BAT-UCAST:IP6:MC:HBH6:MLD:QUERY-V2;${BAT:BAT-UCAST} && ${IP6:MC:HBH6:MLD:QUERY-V2} +BAT:BAT-UCAST:IP6:MC:HBH6:MLD:QUERY-V2:GENERAL;${BAT:BAT-UCAST} && ${IP6:MC:HBH6:MLD:QUERY-V2:GENERAL} +BAT:BAT-UCAST:IP6:MC:HBH6:MLD:QUERY-V2:ADDRSPEC;${BAT:BAT-UCAST} && ${IP6:MC:HBH6:MLD:QUERY-V2:ADDRSPEC} +BAT:BAT-UCAST:IP6:MC:HBH6:MLD:QUERY-UNKNOWN;${BAT:BAT-UCAST} && ${IP6:MC:HBH6:MLD:QUERY-UNKNOWN} +BAT:BAT-UCAST:IP6:MC:HBH6:MLD:REPORT-V1;${BAT:BAT-UCAST} && ${IP6:MC:HBH6:MLD:REPORT-V1} +BAT:BAT-UCAST:IP6:MC:HBH6:MLD:DONE-V1;${BAT:BAT-UCAST} && ${IP6:MC:HBH6:MLD:DONE-V1} +BAT:BAT-UCAST:IP6:MC:HBH6:MLD:REPORT-V2;${BAT:BAT-UCAST} && ${IP6:MC:HBH6:MLD:REPORT-V2} +BAT:BAT-UCAST:IP6:MC:HBH6:MLD:MRD-ADV;${BAT:BAT-UCAST} && ${IP6:MC:HBH6:MLD:MRD-ADV} +BAT:BAT-UCAST:IP6:MC:HBH6:MLD:MRD-SOL;${BAT:BAT-UCAST} && ${IP6:MC:HBH6:MLD:MRD-SOL} +BAT:BAT-UCAST:IP6:MC:HBH6:MLD:MRD-TERM;${BAT:BAT-UCAST} && ${IP6:MC:HBH6:MLD:MRD-TERM} +BAT:BAT-UCAST:IP6:MC:HBH6:OTHER;${BAT:BAT-UCAST} && ${IP6:MC:HBH6} and not (${BAT:BAT-UCAST:IP6:MC:HBH6:MLD}) + +BAT:BAT-UCAST:IP6:MC:ICMP6:ECHOREQ;${BAT:BAT-UCAST} && ${IP6:MC:ICMP6:ECHOREQ} +BAT:BAT-UCAST:IP6:MC:ICMP6:ECHOREP;${BAT:BAT-UCAST} && ${IP6:MC:ICMP6:ECHOREP} +BAT:BAT-UCAST:IP6:MC:ICMP6:NDSOL;${BAT:BAT-UCAST} && ${IP6:MC:ICMP6:NDSOL} +BAT:BAT-UCAST:IP6:MC:ICMP6:NDADV;${BAT:BAT-UCAST} && ${IP6:MC:ICMP6:NDADV} +BAT:BAT-UCAST:IP6:MC:ICMP6:NDADV:UNSOL;${BAT:BAT-UCAST} && ${IP6:MC:ICMP6:NDADV:UNSOL} +BAT:BAT-UCAST:IP6:MC:ICMP6:NDADV:OTHER;${BAT:BAT-UCAST} && ${IP6:MC:ICMP6:NDADV:OTHER} +BAT:BAT-UCAST:IP6:MC:ICMP6:RTRSOL;${BAT:BAT-UCAST} && ${IP6:MC:ICMP6:RTRSOL} +BAT:BAT-UCAST:IP6:MC:ICMP6:RTRADV;${BAT:BAT-UCAST} && ${IP6:MC:ICMP6:RTRADV} +BAT:BAT-UCAST:IP6:MC:ICMP6:OTHER;${BAT:BAT-UCAST} && ${IP6:MC:ICMP6:OTHER} + +BAT:BAT-UCAST:BLA:CLAIM;${BAT:BAT-UCAST} and ${BLA-CLAIM} +BAT:BAT-UCAST:BLA:UNCLAIM;${BAT:BAT-UCAST} and ${BLA-UNCLAIM} +BAT:BAT-UCAST:BLA:ANNOUNCE;${BAT:BAT-UCAST} and ${BLA-ANNOUNCE} +BAT:BAT-UCAST:BLA:REQUEST;${BAT:BAT-UCAST} and ${BLA-REQUEST} +BAT:BAT-UCAST:BLA:LOOPDETECT;${BAT:BAT-UCAST} and ${BLA-LOOPDETECT} + +BAT:BAT-UCAST:ARP:REQ;${BAT:BAT-UCAST} and ${ARP:REQ} +BAT:BAT-UCAST:ARP:REQ:UNSOL;${BAT:BAT-UCAST} and ${ARP:REQ:UNSOL} +BAT:BAT-UCAST:ARP:REQ:OTHER;${BAT:BAT-UCAST} and ${ARP:REQ:OTHER} +BAT:BAT-UCAST:ARP:REP;${BAT:BAT-UCAST} and ${ARP:REP} +BAT:BAT-UCAST:ARP:REP:UNSOL;${BAT:BAT-UCAST} and ${ARP:REP:UNSOL} +BAT:BAT-UCAST:ARP:REP:OTHER;${BAT:BAT-UCAST} and ${ARP:REP:OTHER} diff --git a/package/gluon-statistics-mcast/files/lib/gluon/core/mesh/setup.d/40-bpfcountd b/package/gluon-statistics-mcast/files/lib/gluon/core/mesh/setup.d/40-bpfcountd new file mode 100755 index 00000000000..2d3a1aad58c --- /dev/null +++ b/package/gluon-statistics-mcast/files/lib/gluon/core/mesh/setup.d/40-bpfcountd @@ -0,0 +1,63 @@ +#!/bin/sh + +[ -z "$IFNAME" ] && exit 0 + +if [ -z "$1" ]; then + SOCKETSSUB="mesh" +else + SOCKETSSUB="$1" +fi + +. /lib/functions.sh + +lock /var/lock/gluon_bpfcountd.lock + +BPFCOUNTD_RUN="/var/run/bpfcountd" +mkdir -p "${BPFCOUNTD_RUN}/gluon-sockets/$SOCKETSSUB" + +export UCI_CONFIG_DIR="${BPFCOUNTD_RUN}/gluon-config" +mkdir -p "${UCI_CONFIG_DIR}" +touch "${UCI_CONFIG_DIR}/bpfcountd" + + +# Skip anything which might be unicast payload to avoid +# a noticeable performance impact: +# -> a batadv unicast packet with an IP unicast destination in +# the inner ethernet header; all batadv unicast fragments +# Note: batadv unicast fragments might contain a multicast +# packet, too (though unlikely, usually they are smaller +# than MTU). + +# All IP packets with a unicast destination, except +# IGMP, OSPF (89), PIM (103) or MANET (138) +PREFILTER_IP4_UC="(ip and not ip multicast and not igmp and not (ip proto (89 or 103 or 138)))" +PREFILTER_IP6_UC="(ip6 and not ip6 multicast and not ip6 proto 0 and not (ip6 proto (89 or 103 or 138)))" +PREFILTER_IP_UC="(${PREFILTER_IP4_UC} or ${PREFILTER_IP6_UC})" + +PREFILTER_CLIENT="not ${PREFILTER_IP_UC}" +PREFILTER_MESH="not (batadv 15 unicast and ${PREFILTER_IP_UC}) and not batadv 15 unicast_frag" +PREFILTER="${PREFILTER_CLIENT} and ${PREFILTER_MESH}" + +SECTION_IN="$(uci -c ${UCI_CONFIG_DIR} add bpfcountd bpfcountd)" +SECTION_OUT="$(uci -c ${UCI_CONFIG_DIR} add bpfcountd bpfcountd)" +uci -c "${UCI_CONFIG_DIR}" batch <<-EOF + set bpfcountd.${SECTION_IN}.ifname=${IFNAME} + set bpfcountd.${SECTION_IN}.prefilter="inbound and (${PREFILTER})" + set bpfcountd.${SECTION_IN}.filterfile='/lib/gluon/bpfcountd/mesh.filters' + set bpfcountd.${SECTION_IN}.disabled='0' + + set bpfcountd.${SECTION_OUT}.ifname=${IFNAME} + set bpfcountd.${SECTION_OUT}.prefilter="outbound and (${PREFILTER})" + set bpfcountd.${SECTION_OUT}.filterfile='/lib/gluon/bpfcountd/mesh.filters' + set bpfcountd.${SECTION_OUT}.disabled='0' + + commit bpfcountd +EOF + +ln -s "../../bpfcountd.${IFNAME}.in.sock" "${BPFCOUNTD_RUN}/gluon-sockets/$SOCKETSSUB/bpfcountd.${IFNAME}.in.sock" +ln -s "../../bpfcountd.${IFNAME}.out.sock" "${BPFCOUNTD_RUN}/gluon-sockets/$SOCKETSSUB/bpfcountd.${IFNAME}.out.sock" + +/etc/init.d/bpfcountd start "${IFNAME}.in" "${SECTION_IN}" +/etc/init.d/bpfcountd start "${IFNAME}.out" "${SECTION_OUT}" + +lock -u /var/lock/gluon_bpfcountd.lock diff --git a/package/gluon-statistics-mcast/files/lib/gluon/core/mesh/teardown.d/40-bpfcountd b/package/gluon-statistics-mcast/files/lib/gluon/core/mesh/teardown.d/40-bpfcountd new file mode 100755 index 00000000000..25a0a3a7c18 --- /dev/null +++ b/package/gluon-statistics-mcast/files/lib/gluon/core/mesh/teardown.d/40-bpfcountd @@ -0,0 +1,33 @@ +#!/bin/sh + +[ -z "$IFNAME" ] && exit 0 + +. /lib/functions.sh + +BPFCOUNTD_RUN="/var/run/bpfcountd" + +lock /var/lock/gluon_bpfcountd.lock +export UCI_CONFIG_DIR="${BPFCOUNTD_RUN}/gluon-config" + + +bpfcountd_uci_delete() { + local cfg="$1" + local uci_ifname + + config_get uci_ifname "$cfg" ifname + [ "${uci_ifname}" = "$IFNAME" ] || return + + uci -c "${UCI_CONFIG_DIR}" delete "bpfcountd.$cfg" +} + +/etc/init.d/bpfcountd stop "$IFNAME.in" +/etc/init.d/bpfcountd stop "$IFNAME.out" + +rm "${BPFCOUNTD_RUN}/gluon-sockets/"*"/bpfcountd.${IFNAME}.in.sock" +rm "${BPFCOUNTD_RUN}/gluon-sockets/"*"/bpfcountd.${IFNAME}.out.sock" + +config_load bpfcountd +config_foreach bpfcountd_uci_delete bpfcountd +uci -c "${UCI_CONFIG_DIR}" commit bpfcountd + +lock -u /var/lock/gluon_bpfcountd.lock diff --git a/package/gluon-statistics-mcast/src/Makefile b/package/gluon-statistics-mcast/src/Makefile new file mode 100644 index 00000000000..3ddc8a5861d --- /dev/null +++ b/package/gluon-statistics-mcast/src/Makefile @@ -0,0 +1,6 @@ +all: respondd.so + +CFLAGS += -Wall + +respondd.so: respondd.c + $(CC) $(CPPFLAGS) $(CFLAGS) $(LDFLAGS) -shared -fPIC -D_GNU_SOURCE -o $@ $^ $(LDLIBS) -lgluonutil -luci diff --git a/package/gluon-statistics-mcast/src/respondd.c b/package/gluon-statistics-mcast/src/respondd.c new file mode 100644 index 00000000000..635167c4e89 --- /dev/null +++ b/package/gluon-statistics-mcast/src/respondd.c @@ -0,0 +1,478 @@ +/* + Copyright (c) 2021, Linus Lüssing + All rights reserved. + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE + FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*/ + + +#include + +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include + +#define BPFCOUNTD_SOCKS_DIR "/var/run/bpfcountd/gluon-sockets" + +enum capdir { + CAP_IN, + CAP_OUT, + __CAP_COUNT, +}; + +static const char *dirstr[__CAP_COUNT] = { + [CAP_IN] = "in", + [CAP_OUT] = "out", +}; + +static int check_socket_suffix(char *socketname) +{ + unsigned int offset; + + if (strlen(socketname) <= strlen(".sock")) + return -EINVAL; + + offset = strlen(socketname) - strlen(".sock"); + if (strcmp(&socketname[offset], ".sock")) + return -EINVAL; + + return 0; +} + +static int parse_socket_dir(char *socketname, enum capdir *dir) +{ + char *dir_start, *dir_end; + + dir_end = strrchr(socketname, '.'); + if (!dir_end) + return -EINVAL; + + /* check for .in */ + dir_start = dir_end - strlen(".in"); + if (dir_start < socketname) + return -EINVAL; + + if (!strncmp(dir_start, ".in", strlen(".in"))) { + *dir = CAP_IN; + return 0; + } + + /* check for .out */ + dir_start = dir_end - strlen(".out"); + if (dir_start < socketname) + return -EINVAL; + + if (!strncmp(dir_start, ".out", strlen(".out"))) { + *dir = CAP_OUT; + return 0; + } + + return -EINVAL; +} + +static int parse_socket_iface(char *socketname, enum capdir dir, char *iface) +{ + char *iface_start, *iface_end; + + /* skip UCI section name */ + iface_start = strchr(socketname, '.'); + if (!iface_start || iface_start[1] == '\0') + return -EINVAL; + + iface_start += 1; + iface_end = socketname + strlen(socketname); + + if (dir == CAP_IN) + iface_end -= strlen(".in.sock"); + else if (dir == CAP_OUT) + iface_end -= strlen(".out.sock"); + else + return -EINVAL; + + if (*iface_end != '.' || iface_start >= iface_end || + (iface_end - iface_start) >= IFNAMSIZ) + return -EINVAL; + + memset(iface, 0, IFNAMSIZ); + strncpy(iface, iface_start, iface_end - iface_start); + + return 0; +} + +static struct json_object *get_json_new(struct json_object *parent, + const char *key) +{ + struct json_object *child = NULL; + json_bool ret; + + ret = json_object_object_get_ex(parent, key, &child); + if (ret && child) { + /* sanity check */ + if (!json_object_is_type(child, json_type_object)) + return NULL; + + return child; + } + + child = json_object_new_object(); + if (!child) + return NULL; + + /* json-c 0.12, should check return codes for >= 0.13 */ + json_object_object_add(parent, key, child); + + return child; +} + +static struct json_object *parse_socket_name(char *socketname, + struct json_object *obj, + enum capdir *dir) +{ + int ret = check_socket_suffix(socketname); + char iface[IFNAMSIZ]; + + if (ret < 0) + return NULL; + + ret = parse_socket_dir(socketname, dir); + if (ret < 0) + return NULL; + + ret = parse_socket_iface(socketname, *dir, iface); + if (ret < 0) + return NULL; + + return get_json_new(obj, iface); +} + +static int parse_num(const char *start, int64_t *num) +{ + unsigned long long __num; + char *endptr; + + if (*start == '-') + return -EINVAL; + + __num = strtoull(start, &endptr, 10); + if ((__num == ULLONG_MAX && errno == ERANGE) || + start == endptr) + return -EINVAL; + + /* limit to int64 max for json-c */ + if (__num > INT64_MAX) + return -EINVAL; + + *num = (int64_t)__num; + return 0; +} + +static int add_num_to_json(struct json_object *dir_obj, const char *key, + int64_t *num) +{ + struct json_object *elem; + + elem = json_object_new_int64(*num); + if (!elem) + return -ENOMEM; + + /* json-c < 0.13 */ + json_object_object_add(dir_obj, key, elem); + return 0; +} + +/* + * Example: + * { + * "bytes": 12345, + * "packets": 456 + * } + */ +static struct json_object *create_dir_object(int64_t *bytes, int64_t *packets) +{ + struct json_object *dir_obj; + int ret; + + dir_obj = json_object_new_object(); + if (!dir_obj) + return NULL; + + ret = add_num_to_json(dir_obj, "bytes", bytes); + if (ret < 0) + goto err; + + ret = add_num_to_json(dir_obj, "packets", packets); + if (ret < 0) + goto err; + + return dir_obj; +err: + json_object_put(dir_obj); + return NULL; +} + +static int add_line_to_json(struct json_object *iface_obj, enum capdir dir, + const char *rule, int64_t *bytes, int64_t *packets) +{ + struct json_object *dir_obj, *rule_obj = NULL; + int ret; + + dir_obj = create_dir_object(bytes, packets); + if (!dir_obj) + return -ENOMEM; + + rule_obj = get_json_new(iface_obj, rule); + if (!rule_obj) + goto err; + + /* sanity check, should not exist yet */ + ret = json_object_object_get_ex(rule_obj, dirstr[dir], NULL); + if (ret) + goto err; + + /* json-c < 0.13 */ + json_object_object_add(rule_obj, dirstr[dir], dir_obj); + return 0; +err: + json_object_put(dir_obj); + return -ENOMEM; +} + +static int parse_line(struct json_object *obj, enum capdir dir, char *line) +{ + int64_t bytes; + int64_t packets; + char *start; + int ret; + + /* skip lines prefixed with '%' */ + if (line[0] == '%') + return 0; + + /* packets */ + start = strrchr(line, ':'); + if (!start) + return -EINVAL; + + ret = parse_num(&start[1], &packets); + if (ret < 0) + return ret; + + *start = '\0'; + + /* bytes */ + start = strrchr(line, ':'); + if (!start) + return -EINVAL; + + ret = parse_num(&start[1], &bytes); + if (ret < 0) + return ret; + + *start = '\0'; + /* line: is now rule name */ + + ret = add_line_to_json(obj, dir, line, &bytes, &packets); + if (ret < 0) + return -EINVAL; + + return 0; +} + +static int parse_socket(const char *socketname, struct json_object *iface_obj, + enum capdir dir) +{ + char linebuf[1024]; + struct sockaddr_un addr; + int sd, ret; + FILE *file; + + sd = socket(AF_UNIX, SOCK_STREAM, 0); + if (sd < 0) + return sd; + + memset(&addr, 0, sizeof(addr)); + addr.sun_family = AF_UNIX; + strncpy(addr.sun_path, socketname, sizeof(addr.sun_path) - 1); + + ret = connect(sd, (const struct sockaddr *)&addr, + sizeof(addr)); + if (ret < 0) + goto out; + + file = fdopen(sd, "r"); + if (!file) { + ret = -EACCES; + goto out; + } + + /* Does this really help or maybe even worsen performance? */ + setlinebuf(file); + + while (!feof(file)) { + if (!fgets(linebuf, sizeof(linebuf)-1, file)) + break; + + parse_line(iface_obj, dir, linebuf); + } + + ret = 0; +out: + close(sd); + return ret; +} + +static void parse_socket_subdir(struct dirent *subdir, struct json_object *obj) +{ + struct json_object *subdir_obj; + struct dirent *dp; + DIR *dir; + + if (chdir(subdir->d_name) < 0) + return; + + dir = opendir("./"); + if (!dir) + goto err; + + subdir_obj = json_object_new_object(); + if (!subdir_obj) + goto err2; + + json_object_object_add(obj, subdir->d_name, subdir_obj); + + while ((dp = readdir(dir))) { + struct json_object *iface_obj; + enum capdir capdir; + + if (!strcmp(dp->d_name, ".") || !strcmp(dp->d_name, "..")) + continue; + + iface_obj = parse_socket_name(dp->d_name, subdir_obj, &capdir); + if (!iface_obj) + continue; + + parse_socket(dp->d_name, iface_obj, capdir); + } + +err2: + closedir(dir); +err: + chdir(".."); +} + +static struct json_object *get_mcaststats(void) +{ + struct json_object *obj; + struct dirent *dp; + DIR *dir; + + obj = json_object_new_object(); + if (!obj) + return NULL; + + if (chdir(BPFCOUNTD_SOCKS_DIR) < 0) + return obj; + + dir = opendir("./"); + if (!dir) + return obj; + + while ((dp = readdir(dir))) { + if (!strcmp(dp->d_name, ".") || !strcmp(dp->d_name, "..")) + continue; + + parse_socket_subdir(dp, obj); + } + + closedir(dir); + return obj; +} + +static struct json_object *respondd_provider_mcaststats(void) +{ + struct json_object *ret, *traffic, *mcaststats; + + ret = json_object_new_object(); + if (!ret) + return NULL; + + traffic = json_object_new_object(); + if (!traffic) + goto err1; + + mcaststats = get_mcaststats(); + if (!mcaststats) + goto err2; + + /* json-c 0.12, should check return codes for >= 0.13 */ + json_object_object_add(traffic, "mcast", mcaststats); + json_object_object_add(ret, "traffic", traffic); + + return ret; + +err2: + json_object_put(traffic); +err1: + json_object_put(ret); + return NULL; +} + +/* + * Example output: + * + * { + * "mesh": { + * "mesh-vpn": { + * "BAT-BCAST-ARP": { + * "in": { + * "bytes": 12345, + * "packets": 456 + * }, + * "out": { + * "bytes": 112233, + * "packets": 11 + * } + * }, + * "BAT-BCAST-IP6": { + * "in": { + * "bytes": 12345, + * "packets": 456 + * "out": { + * "bytes": 112233, + * "packets": 11 + * } + * } + * } + * } + * } +*/ +const struct respondd_provider_info respondd_providers[] = { + {"statistics-extended", respondd_provider_mcaststats}, + {} +};