diff --git a/ChangeLog.md b/ChangeLog.md index 07a8d38..f8e48db 100644 --- a/ChangeLog.md +++ b/ChangeLog.md @@ -3,6 +3,18 @@ Change Log All relevant, user visible, changes are documented in this file. +[v0.5][] - 2022-06-20 +--------------------- + +### Changes + - Add per interface proxy mode + - Any interface listed as disabled in configuration is considered a + proxy interface + - Proxy queries (with source 0.0.0.0) are sent until a real querier is + detected + - querierctl shows elected querier for proxy interfaces + - querierctl: Support for displaying discovered router ports + [v0.4][] - 2022-02-16 --------------------- @@ -63,7 +75,8 @@ Initial public release. Limited IGMPv1/v2/v3 querier with hard-coded query interval, etc. Put interfaces in a .conf file, whitespace separated to enable querier. -[UNRELEASED]: https://github.com/westermo/querierd/compare/v0.4...HEAD +[UNRELEASED]: https://github.com/westermo/querierd/compare/v0.5...HEAD +[v0.5]: https://github.com/westermo/querierd/compare/v0.4...v0.5 [v0.4]: https://github.com/westermo/querierd/compare/v0.3...v0.4 [v0.3]: https://github.com/westermo/querierd/compare/v0.2...v0.3 [v0.2]: https://github.com/westermo/querierd/compare/v0.1...v0.2 diff --git a/TODO.md b/TODO.md index dc87d69..4a2363f 100644 --- a/TODO.md +++ b/TODO.md @@ -1,7 +1,7 @@ Rough Plan for querierd ======================= -Planned for v0.5 +Planned for v0.6 ---------------- - Look for better IP than 169 for each interface diff --git a/configure.ac b/configure.ac index a51acd9..b520f06 100644 --- a/configure.ac +++ b/configure.ac @@ -1,5 +1,5 @@ AC_PREREQ(2.61) -AC_INIT([querierd], [0.4], [https://github.com/troglobit/querierd/issues],, +AC_INIT([querierd], [0.5], [https://github.com/troglobit/querierd/issues],, [https://troglobit.com/projects/querierd/]) AC_CONFIG_AUX_DIR(aux) AM_INIT_AUTOMAKE([1.11 foreign]) diff --git a/src/Makefile.am b/src/Makefile.am index 7b4a471..8d2a087 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -15,7 +15,7 @@ querierd_SOURCES = main.c cfparse.y config.c defs.h \ igmp.c igmpv2.h igmpv3.h \ inet.c ipc.c kern.c log.c \ bridge.c pev.c pev.h \ - pathnames.h queue.h bitstring.h + pathnames.h queue.h querierd_CPPFLAGS = $(AM_CPPFLAGS) querierd_LDADD = $(LIBS) $(LIBOBJS) diff --git a/src/bitstring.h b/src/bitstring.h deleted file mode 100644 index 1352874..0000000 --- a/src/bitstring.h +++ /dev/null @@ -1,128 +0,0 @@ -/* $OpenBSD: bitstring.h,v 1.6 2020/05/10 00:56:06 guenther Exp $ */ -/* $NetBSD: bitstring.h,v 1.5 1997/05/14 15:49:55 pk Exp $ */ - -/* - * Copyright (c) 1989, 1993 - * The Regents of the University of California. All rights reserved. - * - * This code is derived from software contributed to Berkeley by - * Paul Vixie. - * - * 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. - * 3. Neither the name of the University nor the names of its contributors - * may be used to endorse or promote products derived from this software - * without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE REGENTS 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 REGENTS 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. - * - * @(#)bitstring.h 8.1 (Berkeley) 7/19/93 - */ - -#ifndef _BITSTRING_H_ -#define _BITSTRING_H_ - -/* modified for SV/AT and bitstring bugfix by M.R.Murphy, 11oct91 - * bitstr_size changed gratuitously, but shorter - * bit_alloc spelling error fixed - * the following were efficient, but didn't work, they've been made to - * work, but are no longer as efficient :-) - * bit_nclear, bit_nset, bit_ffc, bit_ffs - */ -typedef unsigned char bitstr_t; - -/* internal macros */ - /* byte of the bitstring bit is in */ -#define _bit_byte(bit) \ - ((bit) >> 3) - - /* mask for the bit within its byte */ -#define _bit_mask(bit) \ - (1 << ((bit)&0x7)) - -/* external macros */ - /* bytes in a bitstring of nbits bits */ -#define bitstr_size(nbits) \ - (((nbits) + 7) >> 3) - - /* allocate a bitstring */ -#define bit_alloc(nbits) \ - (bitstr_t *)calloc((size_t)bitstr_size(nbits), sizeof(bitstr_t)) - - /* allocate a bitstring on the stack */ -#define bit_decl(name, nbits) \ - ((name)[bitstr_size(nbits)]) - - /* is bit N of bitstring name set? */ -#define bit_test(name, bit) \ - ((name)[_bit_byte(bit)] & _bit_mask(bit)) - - /* set bit N of bitstring name */ -#define bit_set(name, bit) \ - ((name)[_bit_byte(bit)] |= _bit_mask(bit)) - - /* clear bit N of bitstring name */ -#define bit_clear(name, bit) \ - ((name)[_bit_byte(bit)] &= ~_bit_mask(bit)) - - /* clear bits start ... stop in bitstring */ -#define bit_nclear(name, start, stop) do { \ - register bitstr_t *__name = (name); \ - register int __start = (start), __stop = (stop); \ - while (__start <= __stop) { \ - bit_clear(__name, __start); \ - __start++; \ - } \ -} while(0) - - /* set bits start ... stop in bitstring */ -#define bit_nset(name, start, stop) do { \ - register bitstr_t *__name = (name); \ - register int __start = (start), __stop = (stop); \ - while (__start <= __stop) { \ - bit_set(__name, __start); \ - __start++; \ - } \ -} while(0) - - /* find first bit clear in name */ -#define bit_ffc(name, nbits, value) do { \ - register bitstr_t *__name = (name); \ - register int __bit, __nbits = (nbits), __value = -1; \ - for (__bit = 0; __bit < __nbits; ++__bit) \ - if (!bit_test(__name, __bit)) { \ - __value = __bit; \ - break; \ - } \ - *(value) = __value; \ -} while(0) - - /* find first bit set in name */ -#define bit_ffs(name, nbits, value) do { \ - register bitstr_t *__name = (name); \ - register int __bit, __nbits = (nbits), __value = -1; \ - for (__bit = 0; __bit < __nbits; ++__bit) \ - if (bit_test(__name, __bit)) { \ - __value = __bit; \ - break; \ - } \ - *(value) = __value; \ -} while(0) - -#endif /* !_BITSTRING_H_ */ diff --git a/src/bridge.c b/src/bridge.c index 59e005d..bd4d123 100644 --- a/src/bridge.c +++ b/src/bridge.c @@ -22,7 +22,6 @@ #include #include #include -#include "bitstring.h" #include "defs.h" #include "queue.h" @@ -208,56 +207,74 @@ void bridge_prop(FILE *fp, char *prop, int setval) fprintf(fp, "\n"); } +/* + * Parse output from bridge -s -json vlan global: + * > bridge -s -json vlan global show br0 | jq + * [ + * { + * "ifname": "br0", + * "vlans": [ + * { + * "vlan": 1, + * ... + * "router_ports": [ + * { + * "port": "eth0", + * "timer": " 29.01", + * "type": "temp" + * } + * ] + * }, + * { + * "vlan": 2, + * ... + * "router_ports": [ + * { + * "port": "eth1", + * "timer": " 19.04", + * "type": "temp" + * } + * ] + * } + * ] + * } + * ] + */ void bridge_router_ports(FILE *fp) { - char cmd[80], buf[80]; - FILE *rfp; + static const char *bridge_args = "-json -s vlan global show dev"; + static const char *jq_filter = ".[].vlans[].router_ports[] | " \ + ".port + \" \" + .timer + \" \" + .type"; + char prev_ifname[20] = { 0 }; + char cmd[256], buf[80]; int num = 0; - int in_rport_context = 0; + FILE *rfp; int ret; - bitstr_t bit_decl(seen, CHAR_BIT * sizeof(unsigned long)); - ret = snprintf(cmd, sizeof(cmd), "bridge -s vlan global show dev %s", br); + ret = snprintf(cmd, sizeof(cmd), "bridge %s %s | jq -r '%s' | sort", + bridge_args, br, jq_filter); if (ret < 0 || ret >= (int)sizeof(cmd)) goto fail; rfp = popen(cmd, "r"); if (!rfp) goto fail; - /* - * Parse output from bridge -s vlan global: - * > bridge -s vlan global show br0 - * port vlan-id - * br0 1 - * mcast_snooping 1 mcast_querier 1 ... - * router ports: eth2 0.00 temp - * eth1 29.01 temp - * 2 - * mcast_snooping 1 mcast_querier 1 ... - * router ports: eth2 19.04 temp - */ while (fgets(buf, sizeof(buf), rfp)) { - const char *fmt; char ifname[20]; + int seen = 0; float timer; - if (in_rport_context) - fmt = " %19s %2f temp"; - else - fmt = " router ports: %19s %2f temp"; + if (sscanf(buf, "%19s %2f temp", ifname, &timer) != 2) + continue; - if (sscanf(buf, fmt, ifname, &timer) == 2) { - unsigned int ifi = if_nametoindex(ifname); + seen = prev_ifname[0] && !strncmp(ifname, prev_ifname, sizeof(ifname)); - logit(LOG_DEBUG, 0, "Found router port %s (%lu) with %.2f s timeout\n", ifname, ifi, timer); - if (timer > 0.0 && ifi && !bit_test(seen, ifi)) { - fprintf(fp, "%s%s", num ? ", " : "", ifname); - num++; - bit_set(seen, ifi); - } - in_rport_context = 1; - } else - in_rport_context = 0; + logit(LOG_DEBUG, 0, "Found router port %s with %.2f s timeout\n", ifname, timer); + if (timer > 0.0 && !seen) { + fprintf(fp, "%s%s", num ? ", " : "", ifname); + num++; + memcpy(prev_ifname, ifname, sizeof(prev_ifname)); + } } pclose(rfp);