1511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall/* 2511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall * Copyright (c) 2011 Jakub Zawadzki 3511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall * All rights reserved. 4511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall * 5511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall * Redistribution and use in source and binary forms, with or without 6511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall * modification, are permitted provided that the following conditions 7511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall * are met: 8511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall * 9511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall * 1. Redistributions of source code must retain the above copyright 10511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall * notice, this list of conditions and the following disclaimer. 11511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall * 2. Redistributions in binary form must reproduce the above copyright 12511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall * notice, this list of conditions and the following disclaimer in the 13511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall * documentation and/or other materials provided with the distribution. 14511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall * 3. The name of the author may not be used to endorse or promote 15511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall * products derived from this software without specific prior written 16511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall * permission. 17511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall * 18511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 19511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 20511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 21511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 22511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 23511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 24511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 25511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 26511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 27511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 28511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 29511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall */ 30511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall 31511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall#ifdef HAVE_CONFIG_H 32511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall#include "config.h" 33511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall#endif 34511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall 35511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall#include "pcap-int.h" 36511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall 37511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall#ifdef NEED_STRERROR_H 38511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall#include "strerror.h" 39511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall#endif 40511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall 41511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall#include <errno.h> 42511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall#include <stdlib.h> 43511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall#include <unistd.h> 44511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall#include <string.h> 45511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall#include <sys/socket.h> 46511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall#include <arpa/inet.h> 47511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall 48511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall#include <time.h> 49511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall#include <sys/time.h> 50511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall#include <netinet/in.h> 51511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall#include <linux/types.h> 52511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall 53511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall#include <linux/netlink.h> 54511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall#include <linux/netfilter.h> 55511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall#include <linux/netfilter/nfnetlink.h> 56511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall#include <linux/netfilter/nfnetlink_log.h> 57511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall#include <linux/netfilter/nfnetlink_queue.h> 58511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall 59511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall/* NOTE: if your program drops privilages after pcap_activate() it WON'T work with nfqueue. 60511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall * It took me quite some time to debug ;/ 61511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall * 62511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall * Sending any data to nfnetlink socket requires CAP_NET_ADMIN privilages, 63511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall * and in nfqueue we need to send verdict reply after recving packet. 64511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall * 65511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall * In tcpdump you can disable dropping privilages with -Z root 66511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall */ 67511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall 68511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall#include "pcap-netfilter-linux.h" 69511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall 70511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall#define HDR_LENGTH (NLMSG_LENGTH(NLMSG_ALIGN(sizeof(struct nfgenmsg)))) 71511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall 72511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall#define NFLOG_IFACE "nflog" 73511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall#define NFQUEUE_IFACE "nfqueue" 74511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall 75511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgralltypedef enum { OTHER = -1, NFLOG, NFQUEUE } nftype_t; 76511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall 77511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall/* 78511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall * Private data for capturing on Linux netfilter sockets. 79511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall */ 80511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrallstruct pcap_netfilter { 81511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall u_int packets_read; /* count of packets read with recvfrom() */ 82511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall}; 83511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall 84511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrallstatic int nfqueue_send_verdict(const pcap_t *handle, u_int16_t group_id, u_int32_t id, u_int32_t verdict); 85511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall 86511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrallstatic int 87511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrallnetfilter_read_linux(pcap_t *handle, int max_packets, pcap_handler callback, u_char *user) 88511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall{ 89511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall struct pcap_netfilter *handlep = handle->priv; 90511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall const unsigned char *buf; 91511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall int count = 0; 92511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall int len; 93511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall 94511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall /* ignore interrupt system call error */ 95511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall do { 96511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall len = recv(handle->fd, handle->buffer, handle->bufsize, 0); 97511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall if (handle->break_loop) { 98511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall handle->break_loop = 0; 99511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall return -2; 100511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall } 101511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall } while ((len == -1) && (errno == EINTR)); 102511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall 103511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall if (len < 0) { 104511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall snprintf(handle->errbuf, PCAP_ERRBUF_SIZE, "Can't receive packet %d:%s", errno, pcap_strerror(errno)); 105511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall return -1; 106511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall } 107511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall 108511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall buf = handle->buffer; 109511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall while (len >= NLMSG_SPACE(0)) { 110511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall const struct nlmsghdr *nlh = (const struct nlmsghdr *) buf; 111511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall u_int32_t msg_len; 112511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall nftype_t type = OTHER; 113511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall 114511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall if (nlh->nlmsg_len < sizeof(struct nlmsghdr) || len < nlh->nlmsg_len) { 115511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall snprintf(handle->errbuf, PCAP_ERRBUF_SIZE, "Message truncated: (got: %d) (nlmsg_len: %u)", len, nlh->nlmsg_len); 116511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall return -1; 117511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall } 118511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall 119511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall if (NFNL_SUBSYS_ID(nlh->nlmsg_type) == NFNL_SUBSYS_ULOG && 120511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall NFNL_MSG_TYPE(nlh->nlmsg_type) == NFULNL_MSG_PACKET) 121511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall type = NFLOG; 122511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall 123511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall if (NFNL_SUBSYS_ID(nlh->nlmsg_type) == NFNL_SUBSYS_QUEUE && 124511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall NFNL_MSG_TYPE(nlh->nlmsg_type) == NFQNL_MSG_PACKET) 125511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall type = NFQUEUE; 126511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall 127511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall if (type != OTHER) { 128511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall const unsigned char *payload = NULL; 129511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall struct pcap_pkthdr pkth; 130511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall 131511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall const struct nfgenmsg *nfg; 132511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall int id = 0; 133511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall 134511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall if (handle->linktype != DLT_NFLOG) { 135511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall const struct nfattr *payload_attr = NULL; 136511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall 137511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall if (nlh->nlmsg_len < HDR_LENGTH) { 138511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall snprintf(handle->errbuf, PCAP_ERRBUF_SIZE, "Malformed message: (nlmsg_len: %u)", nlh->nlmsg_len); 139511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall return -1; 140511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall } 141511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall 142511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall nfg = NLMSG_DATA(nlh); 143511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall if (nlh->nlmsg_len > HDR_LENGTH) { 144511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall struct nfattr *attr = NFM_NFA(nfg); 145511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall int attr_len = nlh->nlmsg_len - NLMSG_ALIGN(HDR_LENGTH); 146511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall 147511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall while (NFA_OK(attr, attr_len)) { 148511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall if (type == NFQUEUE) { 149511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall switch (NFA_TYPE(attr)) { 150511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall case NFQA_PACKET_HDR: 151511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall { 152511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall const struct nfqnl_msg_packet_hdr *pkt_hdr = (const struct nfqnl_msg_packet_hdr *) NFA_DATA(attr); 153511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall 154511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall id = ntohl(pkt_hdr->packet_id); 155511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall break; 156511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall } 157511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall case NFQA_PAYLOAD: 158511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall payload_attr = attr; 159511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall break; 160511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall } 161511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall 162511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall } else if (type == NFLOG) { 163511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall switch (NFA_TYPE(attr)) { 164511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall case NFULA_PAYLOAD: 165511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall payload_attr = attr; 166511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall break; 167511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall } 168511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall } 169511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall attr = NFA_NEXT(attr, attr_len); 170511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall } 171511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall } 172511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall 173511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall if (payload_attr) { 174511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall payload = NFA_DATA(payload_attr); 175511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall pkth.len = pkth.caplen = NFA_PAYLOAD(payload_attr); 176511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall } 177511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall 178511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall } else { 179511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall payload = NLMSG_DATA(nlh); 180511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall pkth.caplen = pkth.len = nlh->nlmsg_len-NLMSG_ALIGN(sizeof(struct nlmsghdr)); 181511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall } 182511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall 183511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall if (payload) { 184511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall /* pkth.caplen = min (payload_len, handle->snapshot); */ 185511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall 186511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall gettimeofday(&pkth.ts, NULL); 187511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall if (handle->fcode.bf_insns == NULL || 188511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall bpf_filter(handle->fcode.bf_insns, payload, pkth.len, pkth.caplen)) 189511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall { 190511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall handlep->packets_read++; 191511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall callback(user, &pkth, payload); 192511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall count++; 193511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall } 194511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall } 195511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall 196511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall if (type == NFQUEUE) { 197511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall /* XXX, possible responses: NF_DROP, NF_ACCEPT, NF_STOLEN, NF_QUEUE, NF_REPEAT, NF_STOP */ 198511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall nfqueue_send_verdict(handle, ntohs(nfg->res_id), id, NF_ACCEPT); 199511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall } 200511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall } 201511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall 202511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall msg_len = NLMSG_ALIGN(nlh->nlmsg_len); 203511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall if (msg_len > len) 204511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall msg_len = len; 205511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall 206511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall len -= msg_len; 207511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall buf += msg_len; 208511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall } 209511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall return count; 210511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall} 211511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall 212511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrallstatic int 213511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrallnetfilter_set_datalink(pcap_t *handle, int dlt) 214511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall{ 215511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall handle->linktype = dlt; 216511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall return 0; 217511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall} 218511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall 219511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrallstatic int 220511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrallnetfilter_stats_linux(pcap_t *handle, struct pcap_stat *stats) 221511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall{ 222511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall struct pcap_netfilter *handlep = handle->priv; 223511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall 224511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall stats->ps_recv = handlep->packets_read; 225511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall stats->ps_drop = 0; 226511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall stats->ps_ifdrop = 0; 227511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall return 0; 228511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall} 229511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall 230511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrallstatic int 231511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrallnetfilter_inject_linux(pcap_t *handle, const void *buf, size_t size) 232511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall{ 233511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall snprintf(handle->errbuf, PCAP_ERRBUF_SIZE, "inject not supported on netfilter devices"); 234511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall return (-1); 235511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall} 236511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall 237511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrallstruct my_nfattr { 238511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall u_int16_t nfa_len; 239511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall u_int16_t nfa_type; 240511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall void *data; 241511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall}; 242511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall 243511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrallstatic int 244511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrallnetfilter_send_config_msg(const pcap_t *handle, u_int16_t msg_type, int ack, u_int8_t family, u_int16_t res_id, const struct my_nfattr *mynfa) 245511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall{ 246511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall char buf[1024] __attribute__ ((aligned)); 247511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall 248511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall struct nlmsghdr *nlh = (struct nlmsghdr *) buf; 249511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall struct nfgenmsg *nfg = (struct nfgenmsg *) (buf + sizeof(struct nlmsghdr)); 250511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall 251511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall struct sockaddr_nl snl; 252511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall static unsigned int seq_id; 253511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall 254511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall if (!seq_id) 255511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall seq_id = time(NULL); 256511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall ++seq_id; 257511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall 258511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall nlh->nlmsg_len = NLMSG_LENGTH(sizeof(struct nfgenmsg)); 259511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall nlh->nlmsg_type = msg_type; 260511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall nlh->nlmsg_flags = NLM_F_REQUEST | (ack ? NLM_F_ACK : 0); 261511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall nlh->nlmsg_pid = 0; /* to kernel */ 262511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall nlh->nlmsg_seq = seq_id; 263511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall 264511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall nfg->nfgen_family = family; 265511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall nfg->version = NFNETLINK_V0; 266511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall nfg->res_id = htons(res_id); 267511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall 268511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall if (mynfa) { 269511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall struct nfattr *nfa = (struct nfattr *) (buf + NLMSG_ALIGN(nlh->nlmsg_len)); 270511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall 271511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall nfa->nfa_type = mynfa->nfa_type; 272511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall nfa->nfa_len = NFA_LENGTH(mynfa->nfa_len); 273511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall memcpy(NFA_DATA(nfa), mynfa->data, mynfa->nfa_len); 274511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall nlh->nlmsg_len = NLMSG_ALIGN(nlh->nlmsg_len) + NFA_ALIGN(nfa->nfa_len); 275511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall } 276511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall 277511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall memset(&snl, 0, sizeof(snl)); 278511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall snl.nl_family = AF_NETLINK; 279511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall 280511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall if (sendto(handle->fd, nlh, nlh->nlmsg_len, 0, (struct sockaddr *) &snl, sizeof(snl)) == -1) 281511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall return -1; 282511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall 283511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall if (!ack) 284511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall return 0; 285511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall 286511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall /* waiting for reply loop */ 287511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall do { 288511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall socklen_t addrlen = sizeof(snl); 289511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall int len; 290511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall 291511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall /* ignore interrupt system call error */ 292511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall do { 293511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall len = recvfrom(handle->fd, buf, sizeof(buf), 0, (struct sockaddr *) &snl, &addrlen); 294511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall } while ((len == -1) && (errno == EINTR)); 295511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall 296511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall if (len <= 0) 297511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall return len; 298511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall 299511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall if (addrlen != sizeof(snl) || snl.nl_family != AF_NETLINK) { 300511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall errno = EINVAL; 301511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall return -1; 302511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall } 303511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall 304511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall nlh = (struct nlmsghdr *) buf; 305511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall if (snl.nl_pid != 0 || seq_id != nlh->nlmsg_seq) /* if not from kernel or wrong sequence skip */ 306511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall continue; 307511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall 308511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall while (len >= NLMSG_SPACE(0) && NLMSG_OK(nlh, len)) { 309511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall if (nlh->nlmsg_type == NLMSG_ERROR || (nlh->nlmsg_type == NLMSG_DONE && nlh->nlmsg_flags & NLM_F_MULTI)) { 310511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall if (nlh->nlmsg_len < NLMSG_ALIGN(sizeof(struct nlmsgerr))) { 311511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall errno = EBADMSG; 312511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall return -1; 313511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall } 314511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall errno = -(*((int *)NLMSG_DATA(nlh))); 315511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall return (errno == 0) ? 0 : -1; 316511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall } 317511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall nlh = NLMSG_NEXT(nlh, len); 318511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall } 319511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall } while (1); 320511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall 321511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall return -1; /* never here */ 322511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall} 323511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall 324511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrallstatic int 325511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrallnflog_send_config_msg(const pcap_t *handle, u_int8_t family, u_int16_t group_id, const struct my_nfattr *mynfa) 326511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall{ 327511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall return netfilter_send_config_msg(handle, (NFNL_SUBSYS_ULOG << 8) | NFULNL_MSG_CONFIG, 1, family, group_id, mynfa); 328511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall} 329511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall 330511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrallstatic int 331511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrallnflog_send_config_cmd(const pcap_t *handle, u_int16_t group_id, u_int8_t cmd, u_int8_t family) 332511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall{ 333511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall struct nfulnl_msg_config_cmd msg; 334511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall struct my_nfattr nfa; 335511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall 336511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall msg.command = cmd; 337511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall 338511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall nfa.data = &msg; 339511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall nfa.nfa_type = NFULA_CFG_CMD; 340511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall nfa.nfa_len = sizeof(msg); 341511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall 342511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall return nflog_send_config_msg(handle, family, group_id, &nfa); 343511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall} 344511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall 345511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrallstatic int 346511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrallnflog_send_config_mode(const pcap_t *handle, u_int16_t group_id, u_int8_t copy_mode, u_int32_t copy_range) 347511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall{ 348511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall struct nfulnl_msg_config_mode msg; 349511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall struct my_nfattr nfa; 350511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall 351511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall msg.copy_range = htonl(copy_range); 352511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall msg.copy_mode = copy_mode; 353511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall 354511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall nfa.data = &msg; 355511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall nfa.nfa_type = NFULA_CFG_MODE; 356511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall nfa.nfa_len = sizeof(msg); 357511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall 358511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall return nflog_send_config_msg(handle, AF_UNSPEC, group_id, &nfa); 359511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall} 360511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall 361511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrallstatic int 362511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrallnfqueue_send_verdict(const pcap_t *handle, u_int16_t group_id, u_int32_t id, u_int32_t verdict) 363511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall{ 364511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall struct nfqnl_msg_verdict_hdr msg; 365511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall struct my_nfattr nfa; 366511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall 367511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall msg.id = htonl(id); 368511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall msg.verdict = htonl(verdict); 369511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall 370511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall nfa.data = &msg; 371511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall nfa.nfa_type = NFQA_VERDICT_HDR; 372511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall nfa.nfa_len = sizeof(msg); 373511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall 374511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall return netfilter_send_config_msg(handle, (NFNL_SUBSYS_QUEUE << 8) | NFQNL_MSG_VERDICT, 0, AF_UNSPEC, group_id, &nfa); 375511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall} 376511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall 377511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrallstatic int 378511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrallnfqueue_send_config_msg(const pcap_t *handle, u_int8_t family, u_int16_t group_id, const struct my_nfattr *mynfa) 379511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall{ 380511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall return netfilter_send_config_msg(handle, (NFNL_SUBSYS_QUEUE << 8) | NFQNL_MSG_CONFIG, 1, family, group_id, mynfa); 381511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall} 382511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall 383511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrallstatic int 384511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrallnfqueue_send_config_cmd(const pcap_t *handle, u_int16_t group_id, u_int8_t cmd, u_int16_t pf) 385511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall{ 386511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall struct nfqnl_msg_config_cmd msg; 387511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall struct my_nfattr nfa; 388511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall 389511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall msg.command = cmd; 390511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall msg.pf = htons(pf); 391511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall 392511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall nfa.data = &msg; 393511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall nfa.nfa_type = NFQA_CFG_CMD; 394511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall nfa.nfa_len = sizeof(msg); 395511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall 396511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall return nfqueue_send_config_msg(handle, AF_UNSPEC, group_id, &nfa); 397511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall} 398511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall 399511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrallstatic int 400511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrallnfqueue_send_config_mode(const pcap_t *handle, u_int16_t group_id, u_int8_t copy_mode, u_int32_t copy_range) 401511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall{ 402511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall struct nfqnl_msg_config_params msg; 403511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall struct my_nfattr nfa; 404511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall 405511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall msg.copy_range = htonl(copy_range); 406511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall msg.copy_mode = copy_mode; 407511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall 408511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall nfa.data = &msg; 409511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall nfa.nfa_type = NFQA_CFG_PARAMS; 410511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall nfa.nfa_len = sizeof(msg); 411511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall 412511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall return nfqueue_send_config_msg(handle, AF_UNSPEC, group_id, &nfa); 413511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall} 414511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall 415511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrallstatic int 416511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrallnetfilter_activate(pcap_t* handle) 417511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall{ 418511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall const char *dev = handle->opt.source; 419511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall unsigned short groups[32]; 420511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall int group_count = 0; 421511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall nftype_t type = OTHER; 422511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall int i; 423511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall 424511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall if (strncmp(dev, NFLOG_IFACE, strlen(NFLOG_IFACE)) == 0) { 425511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall dev += strlen(NFLOG_IFACE); 426511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall type = NFLOG; 427511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall 428511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall } else if (strncmp(dev, NFQUEUE_IFACE, strlen(NFQUEUE_IFACE)) == 0) { 429511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall dev += strlen(NFQUEUE_IFACE); 430511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall type = NFQUEUE; 431511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall } 432511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall 433511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall if (type != OTHER && *dev == ':') { 434511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall dev++; 435511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall while (*dev) { 436511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall long int group_id; 437511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall char *end_dev; 438511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall 439511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall if (group_count == 32) { 440511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall snprintf(handle->errbuf, PCAP_ERRBUF_SIZE, 441511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall "Maximum 32 netfilter groups! dev: %s", 442511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall handle->opt.source); 443511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall return PCAP_ERROR; 444511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall } 445511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall 446511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall group_id = strtol(dev, &end_dev, 0); 447511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall if (end_dev != dev) { 448511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall if (group_id < 0 || group_id > 65535) { 449511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall snprintf(handle->errbuf, PCAP_ERRBUF_SIZE, 450511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall "Netfilter group range from 0 to 65535 (got %ld)", 451511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall group_id); 452511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall return PCAP_ERROR; 453511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall } 454511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall 455511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall groups[group_count++] = (unsigned short) group_id; 456511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall dev = end_dev; 457511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall } 458511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall if (*dev != ',') 459511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall break; 460511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall dev++; 461511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall } 462511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall } 463511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall 464511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall if (type == OTHER || *dev) { 465511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall snprintf(handle->errbuf, PCAP_ERRBUF_SIZE, 466511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall "Can't get netfilter group(s) index from %s", 467511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall handle->opt.source); 468511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall return PCAP_ERROR; 469511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall } 470511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall 471511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall /* if no groups, add default: 0 */ 472511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall if (!group_count) { 473511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall groups[0] = 0; 474511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall group_count = 1; 475511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall } 476511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall 477511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall /* Initialize some components of the pcap structure. */ 478511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall handle->bufsize = 128 + handle->snapshot; 479511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall handle->offset = 0; 480511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall handle->read_op = netfilter_read_linux; 481511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall handle->inject_op = netfilter_inject_linux; 482511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall handle->setfilter_op = install_bpf_program; /* no kernel filtering */ 483511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall handle->setdirection_op = NULL; 484511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall handle->set_datalink_op = netfilter_set_datalink; 485511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall handle->getnonblock_op = pcap_getnonblock_fd; 486511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall handle->setnonblock_op = pcap_setnonblock_fd; 487511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall handle->stats_op = netfilter_stats_linux; 488511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall 489511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall /* Create netlink socket */ 490511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall handle->fd = socket(AF_NETLINK, SOCK_RAW, NETLINK_NETFILTER); 491511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall if (handle->fd < 0) { 492511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall snprintf(handle->errbuf, PCAP_ERRBUF_SIZE, "Can't create raw socket %d:%s", errno, pcap_strerror(errno)); 493511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall return PCAP_ERROR; 494511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall } 495511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall 496511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall if (type == NFLOG) { 497511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall handle->linktype = DLT_NFLOG; 498511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall handle->dlt_list = (u_int *) malloc(sizeof(u_int) * 2); 499511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall if (handle->dlt_list != NULL) { 500511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall handle->dlt_list[0] = DLT_NFLOG; 501511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall handle->dlt_list[1] = DLT_IPV4; 502511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall handle->dlt_count = 2; 503511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall } 504511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall 505511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall } else 506511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall handle->linktype = DLT_IPV4; 507511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall 508511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall handle->buffer = malloc(handle->bufsize); 509511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall if (!handle->buffer) { 510511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall snprintf(handle->errbuf, PCAP_ERRBUF_SIZE, "Can't allocate dump buffer: %s", pcap_strerror(errno)); 511511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall goto close_fail; 512511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall } 513511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall 514511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall if (type == NFLOG) { 515511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall if (nflog_send_config_cmd(handle, 0, NFULNL_CFG_CMD_PF_UNBIND, AF_INET) < 0) { 516511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall snprintf(handle->errbuf, PCAP_ERRBUF_SIZE, "NFULNL_CFG_CMD_PF_UNBIND: %s", pcap_strerror(errno)); 517511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall goto close_fail; 518511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall } 519511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall 520511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall if (nflog_send_config_cmd(handle, 0, NFULNL_CFG_CMD_PF_BIND, AF_INET) < 0) { 521511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall snprintf(handle->errbuf, PCAP_ERRBUF_SIZE, "NFULNL_CFG_CMD_PF_BIND: %s", pcap_strerror(errno)); 522511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall goto close_fail; 523511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall } 524511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall 525511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall /* Bind socket to the nflog groups */ 526511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall for (i = 0; i < group_count; i++) { 527511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall if (nflog_send_config_cmd(handle, groups[i], NFULNL_CFG_CMD_BIND, AF_UNSPEC) < 0) { 528511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall snprintf(handle->errbuf, PCAP_ERRBUF_SIZE, "Can't listen on group group index: %s", pcap_strerror(errno)); 529511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall goto close_fail; 530511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall } 531511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall 532511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall if (nflog_send_config_mode(handle, groups[i], NFULNL_COPY_PACKET, handle->snapshot) < 0) { 533511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall snprintf(handle->errbuf, PCAP_ERRBUF_SIZE, "NFULNL_COPY_PACKET: %s", pcap_strerror(errno)); 534511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall goto close_fail; 535511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall } 536511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall } 537511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall 538511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall } else { 539511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall if (nfqueue_send_config_cmd(handle, 0, NFQNL_CFG_CMD_PF_UNBIND, AF_INET) < 0) { 540511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall snprintf(handle->errbuf, PCAP_ERRBUF_SIZE, "NFQNL_CFG_CMD_PF_UNBIND: %s", pcap_strerror(errno)); 541511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall goto close_fail; 542511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall } 543511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall 544511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall if (nfqueue_send_config_cmd(handle, 0, NFQNL_CFG_CMD_PF_BIND, AF_INET) < 0) { 545511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall snprintf(handle->errbuf, PCAP_ERRBUF_SIZE, "NFQNL_CFG_CMD_PF_BIND: %s", pcap_strerror(errno)); 546511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall goto close_fail; 547511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall } 548511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall 549511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall /* Bind socket to the nfqueue groups */ 550511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall for (i = 0; i < group_count; i++) { 551511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall if (nfqueue_send_config_cmd(handle, groups[i], NFQNL_CFG_CMD_BIND, AF_UNSPEC) < 0) { 552511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall snprintf(handle->errbuf, PCAP_ERRBUF_SIZE, "Can't listen on group group index: %s", pcap_strerror(errno)); 553511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall goto close_fail; 554511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall } 555511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall 556511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall if (nfqueue_send_config_mode(handle, groups[i], NFQNL_COPY_PACKET, handle->snapshot) < 0) { 557511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall snprintf(handle->errbuf, PCAP_ERRBUF_SIZE, "NFQNL_COPY_PACKET: %s", pcap_strerror(errno)); 558511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall goto close_fail; 559511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall } 560511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall } 561511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall } 562511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall 563511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall if (handle->opt.rfmon) { 564511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall /* 565511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall * Monitor mode doesn't apply to netfilter devices. 566511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall */ 567511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall pcap_cleanup_live_common(handle); 568511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall return PCAP_ERROR_RFMON_NOTSUP; 569511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall } 570511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall 571511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall if (handle->opt.buffer_size != 0) { 572511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall /* 573511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall * Set the socket buffer size to the specified value. 574511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall */ 575511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall if (setsockopt(handle->fd, SOL_SOCKET, SO_RCVBUF, &handle->opt.buffer_size, sizeof(handle->opt.buffer_size)) == -1) { 576511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall snprintf(handle->errbuf, PCAP_ERRBUF_SIZE, "SO_RCVBUF: %s", pcap_strerror(errno)); 577511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall goto close_fail; 578511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall } 579511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall } 580511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall 581511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall handle->selectable_fd = handle->fd; 582511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall return 0; 583511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall 584511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrallclose_fail: 585511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall pcap_cleanup_live_common(handle); 586511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall return PCAP_ERROR; 587511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall} 588511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall 589511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrallpcap_t * 590511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrallnetfilter_create(const char *device, char *ebuf, int *is_ours) 591511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall{ 592511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall const char *cp; 593511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall pcap_t *p; 594511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall 595511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall /* Does this look like an netfilter device? */ 596511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall cp = strrchr(device, '/'); 597511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall if (cp == NULL) 598511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall cp = device; 599511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall 600511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall /* Does it begin with NFLOG_IFACE or NFQUEUE_IFACE? */ 601511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall if (strncmp(cp, NFLOG_IFACE, sizeof NFLOG_IFACE - 1) == 0) 602511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall cp += sizeof NFLOG_IFACE - 1; 603511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall else if (strncmp(cp, NFQUEUE_IFACE, sizeof NFQUEUE_IFACE - 1) == 0) 604511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall cp += sizeof NFQUEUE_IFACE - 1; 605511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall else { 606511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall /* Nope, doesn't begin with NFLOG_IFACE nor NFQUEUE_IFACE */ 607511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall *is_ours = 0; 608511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall return NULL; 609511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall } 610511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall 611511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall /* 612511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall * Yes - is that either the end of the name, or is it followed 613511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall * by a colon? 614511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall */ 615511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall if (*cp != ':' && *cp != '\0') { 616511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall /* Nope */ 617511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall *is_ours = 0; 618511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall return NULL; 619511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall } 620511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall 621511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall /* OK, it's probably ours. */ 622511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall *is_ours = 1; 623511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall 624511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall p = pcap_create_common(device, ebuf, sizeof (struct pcap_netfilter)); 625511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall if (p == NULL) 626511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall return (NULL); 627511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall 628511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall p->activate_op = netfilter_activate; 629511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall return (p); 630511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall} 631511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall 632511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrallint 633511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrallnetfilter_findalldevs(pcap_if_t **alldevsp, char *err_str) 634511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall{ 635511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall int sock; 636511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall 637511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall sock = socket(AF_NETLINK, SOCK_RAW, NETLINK_NETFILTER); 638511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall if (sock < 0) { 639511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall /* if netlink is not supported this is not fatal */ 640511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall if (errno == EAFNOSUPPORT || errno == EPROTONOSUPPORT) 641511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall return 0; 642511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall snprintf(err_str, PCAP_ERRBUF_SIZE, "Can't open netlink socket %d:%s", 643511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall errno, pcap_strerror(errno)); 644511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall return -1; 645511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall } 646511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall close(sock); 647511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall 648511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall if (pcap_add_if(alldevsp, NFLOG_IFACE, 0, "Linux netfilter log (NFLOG) interface", err_str) < 0) 649511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall return -1; 650511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall if (pcap_add_if(alldevsp, NFQUEUE_IFACE, 0, "Linux netfilter queue (NFQUEUE) interface", err_str) < 0) 651511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall return -1; 652511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall return 0; 653511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall} 654