DF-2610 / raw137listen.c
/* raw137listen.c -- receive raw ICMPv6 type-139 messages with ancillary * IPV6_PKTINFO (src/dst) and IPV6_HOPLIMIT data. Used to observe what the * kernel actually did with our injected ND_REDIRECT (DF-2610 harness). */ #include <sys/types.h> #include <sys/socket.h> #include <sys/time.h> #include <netinet/in.h> #include <netinet/icmp6.h> #include <arpa/inet.h> #include <stdio.h> #include <stdlib.h> #include <string.h> #include <unistd.h> #include <errno.h> int main(int argc, char **argv) { struct icmp6_filter filt; struct msghdr msg; struct iovec iov; struct cmsghdr *cmsg; struct sockaddr_in6 from; char cbuf[512], ip[64]; uint8_t buf[2048]; int s, n, secs = 3; struct timeval tv; if (argc > 1) secs = atoi(argv[1]); s = socket(AF_INET6, SOCK_RAW, 58); if (s < 0) { perror("socket"); return 2; } ICMP6_FILTER_SETBLOCKALL(&filt); ICMP6_FILTER_SETPASS(137, &filt); setsockopt(s, IPPROTO_ICMPV6, ICMP6_FILTER, &filt, sizeof(filt)); n = 1; setsockopt(s, IPPROTO_IPV6, IPV6_RECVPKTINFO, &n, sizeof(n)); setsockopt(s, IPPROTO_IPV6, IPV6_RECVHOPLIMIT, &n, sizeof(n)); tv.tv_sec = secs; tv.tv_usec = 0; setsockopt(s, SOL_SOCKET, SO_RCVTIMEO, &tv, sizeof(tv)); for (;;) { memset(&msg, 0, sizeof(msg)); iov.iov_base = buf; iov.iov_len = sizeof(buf); msg.msg_iov = &iov; msg.msg_iovlen = 1; msg.msg_name = &from; msg.msg_namelen = sizeof(from); msg.msg_control = cbuf; msg.msg_controllen = sizeof(cbuf); n = recvmsg(s, &msg, 0); if (n < 0) { if (errno == EAGAIN) break; perror("recvmsg"); break; } inet_ntop(AF_INET6, &from.sin6_addr, ip, sizeof(ip)); printf("GOT %d bytes from %s scope=%u", n, ip, from.sin6_scope_id); for (cmsg = CMSG_FIRSTHDR(&msg); cmsg; cmsg = CMSG_NXTHDR(&msg, cmsg)) { if (cmsg->cmsg_level == IPPROTO_IPV6 && cmsg->cmsg_type == IPV6_PKTINFO) { struct in6_pktinfo *pi = (void *)CMSG_DATA(cmsg); char d[64]; inet_ntop(AF_INET6, &pi->ipi6_addr, d, sizeof(d)); printf(" dst=%s ifindex=%d", d, pi->ipi6_ifindex); } else if (cmsg->cmsg_level == IPPROTO_IPV6 && cmsg->cmsg_type == IPV6_HOPLIMIT) { int *hl = (void *)CMSG_DATA(cmsg); printf(" hlim=%d", *hl); } } printf(" icmp6{type=%u code=%u}\n", buf[0], buf[1]); } return 0; } |