static int cb(struct nfq_q_handle *qh, struct nfgenmsg *nfmsg, struct nfq_data *nfa, void *data) { u_int32_t id = 0; int d; struct nfqnl_msg_packet_hdr *ph; ph = nfq_get_msg_packet_hdr(nfa); if(ph) id = ntohl(ph->packet_id); // verify some basic patterns and drop packet if it's // somehow unexpected if(verify_pkt(nfa) != 0) return nfq_set_verdict(qh, id, NF_DROP, 0, NULL); uint8_t ip_addr[4]; device_t dev; uint16_t port; if(get_info(nfa, &dev, ip_addr, &port) != 0) return nfq_set_verdict(qh, id, NF_DROP, 0, NULL); // check if this device already has an entry in the denied/allowed lists for(d=0;d<allowed_len;d++) { if(memcmp(allowed[d].hw_addr, dev.hw_addr, 6) == 0) return nfq_set_verdict(qh, id, NF_ACCEPT, 0, NULL); } for(d=0;d<denied_len;d++) if(memcmp(denied[d].hw_addr, dev.hw_addr, 6) == 0) return nfq_set_verdict(qh, id, NF_DROP, 0, NULL); // if we have a pending request then just drop everything // elso until the current request has been answered if(pending) return nfq_set_verdict(qh, id, NF_DROP, 0, NULL); pending = malloc(sizeof(device_t)); *pending = dev; printf("REQ "); // print the info int i; for (i = 0; i < 5; i++) printf("%02x:", pending->hw_addr[i]); printf("%02x ", pending->hw_addr[5]); for (i = 0; i < 3; i++) printf("%u.", ip_addr[i]); printf("%u ", ip_addr[3]); printf("%u\n", port); printf("-> A(ccept), D(eny), I(gnore), Q(uit): "); fflush(stdout); // return nfq_set_verdict(qh, id, NF_ACCEPT, 0, NULL); return nfq_set_verdict(qh, id, NF_DROP, 0, NULL); }
/* * This the main loop receiving, processing, and sending packets. */ int serve(ndd_t *nds) { ndpkt_t *pkt; int rc; /* * Since we process only packet at time, we need just one * preallocated buffer. */ if ((pkt = (ndpkt_t *)malloc(ND_MAXPKT)) == NULL) { log_msg(0, "Unable to allocate buffer: %s.", strerror(errno)); return (1); } do { ssize_t pkt_len; int op, err; /* Get packet from the network */ pkt_len = recv(nds->sc_fd, (void *)pkt, ND_MAXPKT, 0); if (nds->exiting) break; if (pkt_len == -1) { log_msg(0, "Unable to receive packet: %s.", strerror(errno)); break; } /* Verify just received packet */ err = verify_pkt(pkt, pkt_len); /* ND protocol supports only 2 operations: read and write */ op = pkt->np_op & ND_OP_CODE; if (op == ND_OP_READ) { rc = serve_read(nds, pkt, err); } else if (op == ND_OP_WRITE) { rc = serve_write(nds, pkt, err); } else { log_msg(1, "Unknown operation %d.", op); rc = 1; } } while (rc == 0 && nds->exiting == 0); free(pkt); return (rc); }