#include <arpa/inet.h>
#include <errno.h>
#include <linux/if_packet.h>
#include <linux/if_ether.h>
#include <linux/filter.h>
#include <stdarg.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/socket.h>
#include <sys/uio.h>
void die(char *errstr, ...) {
va_list ap;
va_start(ap, errstr);
vdprintf(2, errstr, ap);
va_end(ap);
exit(1);
}
#define NELEMS(x) (sizeof x / sizeof *x)
/* tcpdump -dd udp portrange 67-68 or udp portrange 546-547 or icmp6 */
struct sock_filter filter[] = {
{ 0x28, 0, 0, 0x0000000c },
{ 0x15, 0, 17, 0x000086dd },
{ 0x30, 0, 0, 0x00000014 },
{ 0x15, 0, 11, 0x00000011 },
{ 0x28, 0, 0, 0x00000036 },
{ 0x35, 0, 1, 0x00000043 },
{ 0x25, 0, 30, 0x00000044 },
{ 0x28, 0, 0, 0x00000038 },
{ 0x35, 0, 1, 0x00000043 },
{ 0x25, 0, 27, 0x00000044 },
{ 0x28, 0, 0, 0x00000036 },
{ 0x35, 0, 1, 0x00000222 },
{ 0x25, 0, 24, 0x00000223 },
{ 0x28, 0, 0, 0x00000038 },
{ 0x35, 21, 23, 0x00000222 },
{ 0x15, 21, 0, 0x0000003a },
{ 0x15, 0, 21, 0x0000002c },
{ 0x30, 0, 0, 0x00000036 },
{ 0x15, 18, 19, 0x0000003a },
{ 0x15, 0, 18, 0x00000800 },
{ 0x30, 0, 0, 0x00000017 },
{ 0x15, 0, 16, 0x00000011 },
{ 0x28, 0, 0, 0x00000014 },
{ 0x45, 14, 0, 0x00001fff },
{ 0xb1, 0, 0, 0x0000000e },
{ 0x48, 0, 0, 0x0000000e },
{ 0x35, 0, 1, 0x00000043 },
{ 0x25, 0, 9, 0x00000044 },
{ 0x48, 0, 0, 0x00000010 },
{ 0x35, 0, 1, 0x00000043 },
{ 0x25, 0, 6, 0x00000044 },
{ 0x48, 0, 0, 0x0000000e },
{ 0x35, 0, 1, 0x00000222 },
{ 0x25, 0, 3, 0x00000223 },
{ 0x48, 0, 0, 0x00000010 },
{ 0x35, 0, 2, 0x00000222 },
{ 0x25, 1, 0, 0x00000223 },
{ 0x6, 0, 0, 0x00040000 },
{ 0x6, 0, 0, 0x00000000 },
};
int main(int argc, char **argv) {
int sock;
int one = 1;
struct msghdr msg;
struct sockaddr_ll link;
struct packet_mreq mr;
struct iovec iov;
struct sock_fprog bpf;
sock = socket(AF_PACKET, SOCK_RAW, htons(ETH_P_ALL));
if (sock < 0) die("socket: %s\n", strerror(errno));
bpf.len = NELEMS(filter);
bpf.filter = filter;
if (setsockopt(sock, SOL_SOCKET, SO_ATTACH_FILTER, &bpf, sizeof bpf) < 0)
die("SO_ATTACH_FILTER: %s\n", strerror(errno));
if (setsockopt(sock, SOL_SOCKET, SO_LOCK_FILTER, &one, sizeof one) < 0)
die("SO_LOCK_FILTER: %s\n", strerror(errno));
memset(&msg, 0, sizeof msg);
iov.iov_base = malloc(1500);
iov.iov_len = 1500;
msg.msg_iov = &iov;
msg.msg_iovlen = 1;
msg.msg_name = calloc(1, sizeof (struct sockaddr_ll));
msg.msg_namelen = sizeof (struct sockaddr_ll);
while(1) {
if (recvmsg(sock, &msg, 0) < 0) die("recvmsg: %s\n", strerror(errno));
memmove(&link, msg.msg_name, sizeof link);
fprintf(stderr, "link index %d pkttype %d\n", link.sll_ifindex, link.sll_pkttype);
if (writev(1, msg.msg_iov, msg.msg_iovlen) < 0) die("writev: %s\n", strerror(errno));
msg.msg_iov = &iov;
msg.msg_iovlen = 1;
}
return 0;
}