diff options
author | Jakub Zawadzki <darkjames-ws@darkjames.pl> | 2011-08-30 15:20:41 -0700 |
---|---|---|
committer | Guy Harris <guy@alum.mit.edu> | 2011-08-30 15:20:41 -0700 |
commit | 487fd900c46519c4e2a2d33247c8f4654712e22b (patch) | |
tree | 83c65319db1abf38f5c82bfe433e5f2a28d7bb8d /pcap-netfilter-linux.c | |
parent | 34042f15e03680dddec4e81024b850c47621febe (diff) |
Support capturing raw NFLOG headers on netfilter devices.
Reviewed-And-Tweaked-By: Guy Harris <guy@alum.mit.edu>
Diffstat (limited to 'pcap-netfilter-linux.c')
-rw-r--r-- | pcap-netfilter-linux.c | 65 |
1 files changed, 44 insertions, 21 deletions
diff --git a/pcap-netfilter-linux.c b/pcap-netfilter-linux.c index d55b5c35..1c34a095 100644 --- a/pcap-netfilter-linux.c +++ b/pcap-netfilter-linux.c @@ -92,34 +92,42 @@ nflog_read_linux(pcap_t *handle, int max_packets, pcap_handler callback, u_char if (NFNL_SUBSYS_ID(nlh->nlmsg_type) == NFNL_SUBSYS_ULOG && NFNL_MSG_TYPE(nlh->nlmsg_type) == NFULNL_MSG_PACKET) { - const struct nfattr *payload_attr = NULL; + const unsigned char *payload = NULL; + struct pcap_pkthdr pkth; - if (nlh->nlmsg_len < HDR_LENGTH) { - snprintf(handle->errbuf, PCAP_ERRBUF_SIZE, "Malformed message: (nlmsg_len: %u)", nlh->nlmsg_len); - return -1; - } + if (handle->linktype != DLT_NFLOG) { + const struct nfattr *payload_attr = NULL; - if (nlh->nlmsg_len > HDR_LENGTH) { - struct nfattr *attr = NFM_NFA(NLMSG_DATA(nlh)); - int attr_len = nlh->nlmsg_len - NLMSG_ALIGN(HDR_LENGTH); + if (nlh->nlmsg_len < HDR_LENGTH) { + snprintf(handle->errbuf, PCAP_ERRBUF_SIZE, "Malformed message: (nlmsg_len: %u)", nlh->nlmsg_len); + return -1; + } - while (NFA_OK(attr, attr_len)) { - switch (NFA_TYPE(attr)) { - case NFULA_PAYLOAD: - payload_attr = attr; - break; + if (nlh->nlmsg_len > HDR_LENGTH) { + struct nfattr *attr = NFM_NFA(NLMSG_DATA(nlh)); + int attr_len = nlh->nlmsg_len - NLMSG_ALIGN(HDR_LENGTH); + + while (NFA_OK(attr, attr_len)) { + switch (NFA_TYPE(attr)) { + case NFULA_PAYLOAD: + payload_attr = attr; + break; + } + attr = NFA_NEXT(attr, attr_len); } - attr = NFA_NEXT(attr, attr_len); } - } - if (payload_attr) { - struct pcap_pkthdr pkth; + if (payload_attr) { + payload = NFA_DATA(payload_attr); + pkth.len = pkth.caplen = NFA_PAYLOAD(payload_attr); + } - const unsigned char *payload = NFA_DATA(payload_attr); - int payload_len = NFA_PAYLOAD(payload_attr); + } else { + payload = NLMSG_DATA(nlh); + pkth.caplen = pkth.len = nlh->nlmsg_len-NLMSG_ALIGN(sizeof(struct nlmsghdr)); + } - pkth.len = pkth.caplen = payload_len; + if (payload) { /* pkth.caplen = min (payload_len, handle->snapshot); */ gettimeofday(&pkth.ts, NULL); @@ -144,6 +152,13 @@ nflog_read_linux(pcap_t *handle, int max_packets, pcap_handler callback, u_char } static int +netfilter_set_datalink(pcap_t *handle, int dlt) +{ + handle->linktype = dlt; + return 0; +} + +static int netfilter_stats_linux(pcap_t *handle, struct pcap_stat *stats) { stats->ps_recv = handle->md.packets_read; @@ -334,12 +349,13 @@ nflog_activate(pcap_t* handle) /* Initialize some components of the pcap structure. */ handle->bufsize = 128 + handle->snapshot; handle->offset = 0; - handle->linktype = DLT_IPV4; + handle->linktype = DLT_NFLOG; handle->read_op = nflog_read_linux; handle->inject_op = netfilter_inject_linux; handle->setfilter_op = install_bpf_program; /* no kernel filtering */ handle->setdirection_op = NULL; handle->set_datalink_op = NULL; + handle->set_datalink_op = netfilter_set_datalink; handle->getnonblock_op = pcap_getnonblock_fd; handle->setnonblock_op = pcap_setnonblock_fd; handle->stats_op = netfilter_stats_linux; @@ -351,6 +367,13 @@ nflog_activate(pcap_t* handle) return PCAP_ERROR; } + handle->dlt_list = (u_int *) malloc(sizeof(u_int) * 2); + if (handle->dlt_list != NULL) { + handle->dlt_list[0] = DLT_NFLOG; + handle->dlt_list[1] = DLT_IPV4; + handle->dlt_count = 2; + } + handle->buffer = malloc(handle->bufsize); if (!handle->buffer) { snprintf(handle->errbuf, PCAP_ERRBUF_SIZE, "Can't allocate dump buffer: %s", pcap_strerror(errno)); |