]> The Tcpdump Group git mirrors - libpcap/blobdiff - pcap-netfilter-linux.c
If config.status changes, rebuild pcap-config.
[libpcap] / pcap-netfilter-linux.c
index d55b5c35fcf8491c49704732d8dcf7eb6cec36a7..225e49f904e25f5fe193b1f90bfdadd67ec26755 100644 (file)
@@ -54,6 +54,8 @@
 #include <linux/netfilter/nfnetlink.h>
 #include <linux/netfilter/nfnetlink_log.h>
 
+#include "pcap-netfilter-linux.h"
+
 #define HDR_LENGTH (NLMSG_LENGTH(NLMSG_ALIGN(sizeof(struct nfgenmsg))))
 
 #define NFLOG_IFACE "nflog"
@@ -92,34 +94,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);
@@ -143,6 +153,13 @@ nflog_read_linux(pcap_t *handle, int max_packets, pcap_handler callback, u_char
        return count;
 }
 
+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)
 {
@@ -334,12 +351,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 +369,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));