/* $ ping -c 8 172.25.197.158 PING 172.25.197.158 (172.25.197.158) 56(84) bytes of data. 64 bytes from 172.25.197.158: icmp_req=1 ttl=128 time=1010 ms 64 bytes from 172.25.197.158: icmp_req=3 ttl=128 time=1000 ms 64 bytes from 172.25.197.158: icmp_req=4 ttl=128 time=1000 ms 64 bytes from 172.25.197.158: icmp_req=5 ttl=128 time=999 ms 64 bytes from 172.25.197.158: icmp_req=6 ttl=128 time=1000 ms 64 bytes from 172.25.197.158: icmp_req=7 ttl=128 time=1010 ms --- 172.25.197.158 ping statistics --- 8 packets transmitted, 6 received, 25% packet loss, time 7020ms rtt min/avg/max/mdev = 999.452/1003.574/1010.633/4.883 ms, pipe 2 # grep -E ^ *13 /proc/net/netfilter/nfnetlink_queue 13 13584 1 1 0 0 0 8 1 ^queue_num, ^peer_pid, ^queue_total, ^copy_mode, ^copy_range, ^queue_dropped, ^queue_user_dropped, ^id_sequence, ^1 */ #include #include #include #include #include #include #include /* for NF_ACCEPT */ #include #include struct packet_data { u_int32_t id, good; }; static int cb(struct nfq_q_handle *qh, struct nfgenmsg *nu, struct nfq_data *nfa, void *data) { struct packet_data *pd = (struct packet_data*)data; struct nfqnl_msg_packet_hdr *ph = nfq_get_msg_packet_hdr(nfa); if (pd && ph) { if (pd->good) // since last time nfq_set_verdict(qh, pd->id, NF_ACCEPT, 0, NULL); pd->id = ntohl(ph->packet_id); pd->good = 1; printf("received packet %d\n", pd->id); } return 0; (void)nu; } int main() { struct nfq_handle *h; struct nfq_q_handle *qh; struct packet_data pd; int fd; int rv; char buf[4096] __attribute__ ((aligned)); printf("opening library handle\n"); h = nfq_open(); if (!h) { fprintf(stderr, "error during nfq_open()\n"); exit(1); } printf("unbinding existing nf_queue handler for AF_INET (if any)\n"); if (nfq_unbind_pf(h, AF_INET) < 0) { fprintf(stderr, "error during nfq_unbind_pf()\n"); exit(1); } printf("binding nfnetlink_queue as nf_queue handler for AF_INET\n"); if (nfq_bind_pf(h, AF_INET) < 0) { fprintf(stderr, "error during nfq_bind_pf()\n"); exit(1); } pd.good = 0; qh = nfq_create_queue(h, 13 /* <--queue number here */, &cb, &pd); if (!qh) { fprintf(stderr, "error during nfq_create_queue()\n"); exit(1); } if (nfq_set_mode(qh, NFQNL_COPY_META, 0) < 0) { fprintf(stderr, "can't set packet_copy mode\n"); exit(1); } fd = nfq_fd(h); for (;;) { if ((rv = recv(fd, buf, sizeof(buf), 0)) >= 0) { nfq_handle_packet(h, buf, rv); continue; } /* if the computer is slower than the network the buffer * may fill up. Depending on the application, this error * may be ignored */ if (errno == ENOBUFS) { printf("pkt lost!!\n"); continue; } printf("recv failed: errno=%d (%s)\n", errno, strerror(errno)); } printf("unbinding from queue 0\n"); nfq_destroy_queue(qh); #ifdef INSANE /* normally, applications SHOULD NOT issue this command, since * it detaches other programs/sockets from AF_INET, too ! */ printf("unbinding from AF_INET\n"); nfq_unbind_pf(h, AF_INET); #endif printf("closing library handle\n"); nfq_close(h); exit(0); }