Switch to sending LLMNR packets
[kai/multicast.git] / listener.c
1 /* Multicast test, listener */
2
3 #include <sys/types.h>
4 #include <sys/socket.h>
5 #include <netinet/in.h>
6 #include <arpa/inet.h>
7 #include <net/if.h>
8 #include <netdb.h>
9 #include <stdio.h>
10 #include <string.h>
11 #include <stdlib.h>
12 #include <unistd.h>
13 #include <stdbool.h>
14
15 int main(int argc, char **argv)
16 {
17     int err;
18     int sock6 = -1;
19     struct sockaddr_in6 name6;
20     ssize_t len6 = sizeof(name6);
21     struct sockaddr_storage peer_addr;
22     struct ipv6_mreq mreq;
23     uint8_t buf[1024];
24     ssize_t msg_len;
25     socklen_t peer_addr_len;
26     char host[NI_MAXHOST], service[NI_MAXSERV];
27
28     sock6 = socket(AF_INET6, SOCK_DGRAM, 0);
29     if (sock6 == -1) {
30         perror("opening v6 listening socket");
31         goto die;
32     }
33
34     memset(&mreq, 0, sizeof(struct ipv6_mreq));
35     err = inet_pton(AF_INET6, "ff02::1:3", &mreq.ipv6mr_multiaddr);
36     if (err < 1) {
37         fprintf(stderr, "failed to convert ff02::1:3 to an address\n");
38         goto die;
39     }
40     mreq.ipv6mr_interface = if_nametoindex("wlan0");
41
42     err = setsockopt(sock6, IPPROTO_IPV6, IPV6_JOIN_GROUP, &mreq,
43                      sizeof(struct ipv6_mreq));
44     if (err != 0) {
45         perror("joining multicast group");
46         goto die;
47     }
48
49     memset(&name6, 0, len6);
50
51     name6.sin6_family = PF_INET6;
52     name6.sin6_addr = in6addr_any;
53     name6.sin6_port = htons(5355);
54
55     if (bind(sock6, (struct sockaddr *) &name6, len6) == -1) {
56         perror("binding to v6 socket");
57         goto die;
58     }
59
60     while(true) {
61         peer_addr_len = sizeof(struct sockaddr_storage);
62         msg_len = recvfrom(sock6, buf, 1024, 0,
63                            (struct sockaddr *)&peer_addr, &peer_addr_len);
64         if (msg_len == -1) {
65             perror("receiving data");
66             continue;
67         }
68
69         buf[2] |= 0x10; /* We're a reply, honest! */
70
71         err = getnameinfo((struct sockaddr *)&peer_addr, peer_addr_len,
72                           host, NI_MAXHOST, service, NI_MAXSERV, NI_NUMERICSERV);
73
74         if (err == 0) {
75             printf("Got %ld bytes from %s:%s\n", (long) msg_len,
76                    host, service);
77         } else {
78             fprintf(stderr, "getnameinfo: %s\n", gai_strerror(err));
79             continue;
80         }
81
82         if(sendto(sock6, buf, msg_len, 0,
83                   (struct sockaddr *)&peer_addr, peer_addr_len) != msg_len) {
84             perror("sending reply");
85             goto die;
86         } else {
87             printf("Sent %ld bytes back\n", (long) msg_len);
88         }
89
90     }
91
92     close(sock6);
93     return 0;
94
95 die:
96
97     if (sock6 != -1) {
98         close(sock6);
99     }
100     exit(1);
101 }
102