DF-5847 / df5847_cycler.c
/* DF-5847 stock repro harness - IPv6 address add/delete cycler (ROOT). * * Derived from the DF-3389 pack cycler.c; lifetime handling made explicit: * the two panics captured in findings/poc/DF-3389/logs/ (transcripts show * "in6_update_ifa: valid lifetime is 0" spam) came from cycling with * ia6t_vltime=ia6t_pltime=0. Default here is 0 (transcript-faithful); * -l selects the infinite-lifetime variant (control). * * build: cc -O2 -o df5847_cycler df5847_cycler.c * run: ./df5847_cycler <seconds> [-l] */ #include <sys/types.h> #include <sys/socket.h> #include <sys/ioctl.h> #include <sys/time.h> #include <net/if.h> #include <netinet/in.h> #include <netinet6/in6_var.h> #include <unistd.h> #include <stdio.h> #include <stdlib.h> #include <string.h> #include <errno.h> int main(int argc, char **argv) { double dur = argc > 1 ? atof(argv[1]) : 60.0; int infinite = (argc > 2 && strcmp(argv[2], "-l") == 0); struct in6_aliasreq ifra; struct timeval t0, t1; unsigned long addok = 0, adderr = 0, delok = 0, delerr = 0, last = 0; double el, lastel = 0; int s; s = socket(AF_INET6, SOCK_DGRAM, 0); if (s < 0) { perror("socket"); return 1; } memset(&ifra, 0, sizeof(ifra)); strncpy(ifra.ifra_name, "lo0", sizeof(ifra.ifra_name) - 1); ifra.ifra_addr.sin6_family = AF_INET6; ifra.ifra_addr.sin6_len = sizeof(struct sockaddr_in6); if (inet_pton(AF_INET6, "fd99:3389::1", &ifra.ifra_addr.sin6_addr) != 1) { fprintf(stderr, "inet_pton\n"); return 1; } /* /64 prefix mask */ ifra.ifra_prefixmask.sin6_family = AF_INET6; ifra.ifra_prefixmask.sin6_len = sizeof(struct sockaddr_in6); memset(&ifra.ifra_prefixmask.sin6_addr, 0xff, 8); ifra.ifra_lifetime.ia6t_vltime = infinite ? 0xffffffffu : 0; ifra.ifra_lifetime.ia6t_pltime = infinite ? 0xffffffffu : 0; gettimeofday(&t0, NULL); for (;;) { if (ioctl(s, SIOCAIFADDR_IN6, &ifra) == 0) addok++; else adderr++; if (ioctl(s, SIOCDIFADDR_IN6, &ifra) == 0) delok++; else delerr++; gettimeofday(&t1, NULL); el = (t1.tv_sec - t0.tv_sec) + (t1.tv_usec - t0.tv_usec) / 1e6; if (el - lastel >= 5.0) { printf("cycler cycles=%.0f/s addok=%lu adderr=%lu " "delok=%lu delerr=%lu (lasterr=%d)\n", (addok - last) / (el - lastel), addok, adderr, delok, delerr, errno); fflush(stdout); last = addok; lastel = el; } if (el >= dur) break; } printf("cycler DONE addok=%lu adderr=%lu delok=%lu delerr=%lu\n", addok, adderr, delok, delerr); return 0; } |