diff options
-rw-r--r-- | gencode.c | 10 | ||||
-rw-r--r-- | pcap-common.c | 11 | ||||
-rw-r--r-- | pcap-netfilter-linux.c | 65 | ||||
-rw-r--r-- | pcap.c | 3 | ||||
-rw-r--r-- | pcap/bpf.h | 8 |
5 files changed, 75 insertions, 22 deletions
@@ -1608,6 +1608,16 @@ init_linktype(p) off_nl = -1; off_nl_nosnap = -1; return; + + case DLT_NFLOG: + /* + * Currently, only raw "link[N:M]" filtering is supported. + */ + off_linktype = -1; + off_macpl = -1; + off_nl = -1; + off_nl_nosnap = -1; + return; } bpf_error("unknown data link type %d", linktype); /* NOTREACHED */ diff --git a/pcap-common.c b/pcap-common.c index 31234b82..d0a053c5 100644 --- a/pcap-common.c +++ b/pcap-common.c @@ -779,6 +779,14 @@ */ #define LINKTYPE_JUNIPER_ATM_CEMIC 238 +/* + * NetFilter LOG messages + * (payload of netlink NFNL_SUBSYS_ULOG/NFULNL_MSG_PACKET packets) + * + * Requested by Jakub Zawadzki <darkjames-ws@darkjames.pl> + */ +#define LINKTYPE_NFLOG 239 + static struct linktype_map { int dlt; int linktype; @@ -1151,6 +1159,9 @@ static struct linktype_map { /* Juniper ATM CE MIC */ { DLT_JUNIPER_ATM_CEMIC, LINKTYPE_JUNIPER_ATM_CEMIC }, + /* Linux NetFilter LOG messages */ + { DLT_NFLOG, LINKTYPE_NFLOG }, + { -1, -1 } }; 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)); @@ -858,9 +858,10 @@ static struct dlt_choice dlt_choices[] = { DLT_CHOICE(DLT_IEEE802_15_4_NOFCS, "IEEE 802.15.4 without FCS"), DLT_CHOICE(DLT_JUNIPER_VS, "Juniper Virtual Server"), DLT_CHOICE(DLT_JUNIPER_SRX_E2E, "Juniper SRX E2E"), - DLT_CHOICE(DLT_JUNIPER_FIBRECHANNEL, "Juniper Fibrechannel"), + DLT_CHOICE(DLT_JUNIPER_FIBRECHANNEL, "Juniper Fibre Channel"), DLT_CHOICE(DLT_DVB_CI, "DVB-CI"), DLT_CHOICE(DLT_JUNIPER_ATM_CEMIC, "Juniper ATM CEMIC"), + DLT_CHOICE(DLT_NFLOG, "Linux netfilter log messages"), DLT_CHOICE_SENTINEL }; @@ -1031,6 +1031,14 @@ struct bpf_program { * Hannes Gredler <hannes@juniper.net>. */ #define DLT_JUNIPER_ATM_CEMIC 238 + +/* + * NetFilter LOG messages + * (payload of netlink NFNL_SUBSYS_ULOG/NFULNL_MSG_PACKET packets) + * + * Requested by Jakub Zawadzki <darkjames-ws@darkjames.pl> + */ +#define DLT_NFLOG 239 /* * DLT and savefile link type values are split into a class and |