From: Vadim Kochan <[email protected]>
Use Linux "cooked" header for Netlink interface automatically
or as replacement of L2 header if "--cooked" option is specified.
http://www.tcpdump.org/linktypes/LINKTYPE_LINUX_SLL.html
"cooked" header makes sense to use for default or nsec pcap types
which does not contain protocol info.
Added new LINKTYPE_LINUX_SLL which indicates pcap file with
Linux "cooked" header as L2 layer header.This pcap file is
compatible with Wireshark's "cooked" header & vice-versa.
Signed-off-by: Vadim Kochan <[email protected]>
---
linktype.h | 1 +
netsniff-ng.8 | 12 +-
netsniff-ng.c | 26 +++-
pcap_io.h | 400 ++++++++++++++++++++++++++++++++++++----------------------
pcap_mm.c | 5 +-
pcap_rw.c | 4 +-
pcap_sg.c | 8 +-
sock.c | 10 ++
sock.h | 1 +
9 files changed, 305 insertions(+), 162 deletions(-)
diff --git a/linktype.h b/linktype.h
index a78f8be..80b5f2d 100644
--- a/linktype.h
+++ b/linktype.h
@@ -21,6 +21,7 @@
#define LINKTYPE_C_HDLC 104
#define LINKTYPE_IEEE802_11 105
#define LINKTYPE_FRELAY 107
+#define LINKTYPE_LINUX_SLL 113
#define LINKTYPE_ECONET 115
#define LINKTYPE_IEEE802_11_RADIOTAP 127
#define LINKTYPE_ARCNET_LINUX 129
diff --git a/netsniff-ng.8 b/netsniff-ng.8
index 677a78c..e7c50cd 100644
--- a/netsniff-ng.8
+++ b/netsniff-ng.8
@@ -84,7 +84,10 @@ input device is a pcap file. To specify a pcap file as the
output device, the
file name must have \[lq].pcap\[rq] as its extension. If stdout is given as a
device, then a trafgen configuration will be written to stdout if the input
device is a pcap file, or a pcap file if the input device is a networking
-device.
+device. In case if the input device is a Netlink monitor device and pcap type
is
+default or nsec then each packet will be wrapped with pcap cooked header [2] to
+keep Netlink family number (Kuznetzov's and netsniff-ng pcap types already
+contains family number in protocol number field).
.PP
.SS -C <id>, --fanout-group <id>
If multiple netsniff-ng instances are being started that all have the same
packet
@@ -254,6 +257,11 @@ possible addresses. Thus, to save bandwidth or for
mirroring of Maxmind's
databases (to bypass their traffic limit policy), different hosts or IP
addresses can be placed into geoip.conf, separated by a newline.
.PP
+.SS -w, --cooked
+Replace each frame link header with Linux "cooked" header [3] which keeps info
+about link type and protocol. It allows to dump and dissect frames captured
+from different link types when -i "any" was specified.
+.PP
.SS -V, --verbose
Be more verbose during startup i.e. show detailed ring setup information.
.PP
@@ -588,6 +596,8 @@ in the payload itself as reported here. However, the
filtering for VLANs works
reliable if your NIC supports it. See bpfc(8) for an example.
.PP
[1] http://lkml.indiana.edu/hypermail/linux/kernel/0710.3/3816.html
+ [2] http://www.tcpdump.org/linktypes/LINKTYPE_NETLINK.html
+ [3] http://www.tcpdump.org/linktypes/LINKTYPE_LINUX_SLL.html
.PP
.SH LEGAL
netsniff-ng is licensed under the GNU GPL version 2.0.
diff --git a/netsniff-ng.c b/netsniff-ng.c
index d3e9a13..1f7c5a5 100644
--- a/netsniff-ng.c
+++ b/netsniff-ng.c
@@ -69,7 +69,9 @@ struct ctx {
static volatile sig_atomic_t sigint = 0, sighup = 0;
static volatile bool next_dump = false;
-static const char *short_options =
"d:i:o:rf:MNJt:S:k:n:b:HQmcsqXlvhF:RGAP:Vu:g:T:DBUC:K:L:";
+static const char *short_options =
+ "d:i:o:rf:MNJt:S:k:n:b:HQmcsqXlvhF:RGAP:Vu:g:T:DBUC:K:L:w";
+
static const struct option long_options[] = {
{"dev", required_argument, NULL, 'd'},
{"in", required_argument, NULL, 'i'},
@@ -106,6 +108,7 @@ static const struct option long_options[] = {
{"ascii", no_argument, NULL, 'l'},
{"no-sock-mem", no_argument, NULL, 'A'},
{"update", no_argument, NULL, 'U'},
+ {"cooked", no_argument, NULL, 'w'},
{"verbose", no_argument, NULL, 'V'},
{"version", no_argument, NULL, 'v'},
{"help", no_argument, NULL, 'h'},
@@ -237,6 +240,8 @@ static void pcap_to_xmit(struct ctx *ctx)
if (ret)
panic("Error reading pcap header!\n");
+ pcap_pkthdr_init(&phdr, ctx->link_type);
+
if (__pcap_io->prepare_access_pcap) {
ret = __pcap_io->prepare_access_pcap(fd, PCAP_MODE_RD,
ctx->jumbo);
if (ret)
@@ -589,6 +594,8 @@ static void read_pcap(struct ctx *ctx)
if (ret)
panic("Error reading pcap header!\n");
+ pcap_pkthdr_init(&phdr, ctx->link_type);
+
if (__pcap_io->prepare_access_pcap) {
ret = __pcap_io->prepare_access_pcap(fd, PCAP_MODE_RD,
ctx->jumbo);
if (ret)
@@ -906,6 +913,8 @@ static void walk_t3_block(struct block_desc *pbd, struct
ctx *ctx,
uint8_t *packet = ((uint8_t *) hdr + hdr->tp_mac);
pcap_pkthdr_t phdr;
+ pcap_pkthdr_init(&phdr, ctx->link_type);
+
if (ctx->packet_type != -1)
if (ctx->packet_type != sll->sll_pkttype)
goto next;
@@ -956,7 +965,10 @@ static void recv_only_or_dump(struct ctx *ctx)
struct timeval start, end, diff;
unsigned long frame_count = 0;
- sock = pf_socket();
+ if (ctx->link_type == LINKTYPE_LINUX_SLL)
+ sock = pf_socket_dgram();
+ else
+ sock = pf_socket();
ifindex = device_ifindex(ctx->device_in);
@@ -1036,6 +1048,8 @@ static void recv_only_or_dump(struct ctx *ctx)
uint8_t *packet = ((uint8_t *) hdr) + hdr->tp_h.tp_mac;
pcap_pkthdr_t phdr;
+ pcap_pkthdr_init(&phdr, ctx->link_type);
+
if (ctx->packet_type != -1)
if (ctx->packet_type != hdr->s_ll.sll_pkttype)
goto next;
@@ -1138,6 +1152,7 @@ static void init_ctx(struct ctx *ctx)
ctx->magic = ORIGINAL_TCPDUMP_MAGIC;
ctx->print_mode = PRINT_NORM;
ctx->pcap = PCAP_OPS_SG;
+ ctx->link_type = 0;
ctx->dump_mode = DUMP_INTERVAL_TIME;
ctx->dump_interval = 60;
@@ -1196,6 +1211,7 @@ static void __noreturn help(void)
" -X|--hex Print packet data in hex
format\n"
" -l|--ascii Print human-readable packet
data\n"
" -U|--update Update GeoIP databases\n"
+ " -w|--cooked Use Linux sll \"cooked\" header
instead of link header\n"
" -V|--verbose Be more verbose\n"
" -v|--version Show version and exit\n"
" -h|--help Guess what?!\n\n"
@@ -1441,6 +1457,9 @@ int main(int argc, char **argv)
update_geoip();
die();
break;
+ case 'w':
+ ctx.link_type = LINKTYPE_LINUX_SLL;
+ break;
case 'v':
version();
break;
@@ -1512,7 +1531,8 @@ int main(int argc, char **argv)
if (ctx.rfraw)
setup_rfmon_mac80211_dev(&ctx, &ctx.device_in);
- ctx.link_type = pcap_devtype_to_linktype(ctx.device_in);
+ if (!ctx.link_type)
+ ctx.link_type = pcap_devtype_to_linktype(ctx.device_in);
if (!ctx.device_out) {
ctx.dump = 0;
diff --git a/pcap_io.h b/pcap_io.h
index 35faa51..4c4ec95 100644
--- a/pcap_io.h
+++ b/pcap_io.h
@@ -58,16 +58,31 @@ struct pcap_timeval_ns {
int32_t tv_nsec;
};
+struct linux_sll {
+ uint16_t pkttype;
+ uint16_t hatype;
+ uint16_t len;
+ uint8_t addr[8];
+ uint16_t protocol;
+};
+#define LINUX_SLL_SIZE (sizeof(struct linux_sll))
+
struct pcap_pkthdr {
struct pcap_timeval ts;
uint32_t caplen;
uint32_t len;
+
+ /* depends on link type */
+ struct linux_sll sll;
};
struct pcap_pkthdr_ns {
struct pcap_timeval_ns ts;
uint32_t caplen;
uint32_t len;
+
+ /* depends on link type */
+ struct linux_sll sll;
};
struct pcap_pkthdr_kuz {
@@ -90,12 +105,15 @@ struct pcap_pkthdr_bkm {
uint8_t pkttype;
};
-typedef union {
- struct pcap_pkthdr ppo;
- struct pcap_pkthdr_ns ppn;
- struct pcap_pkthdr_kuz ppk;
- struct pcap_pkthdr_bkm ppb;
- uint8_t raw;
+typedef struct {
+ union {
+ struct pcap_pkthdr ppo;
+ struct pcap_pkthdr_ns ppn;
+ struct pcap_pkthdr_kuz ppk;
+ struct pcap_pkthdr_bkm ppb;
+ uint8_t raw;
+ } h;
+ uint32_t link_type;
} pcap_pkthdr_t;
enum pcap_type {
@@ -192,6 +210,20 @@ static inline int pcap_devtype_to_linktype(const char
*ifname)
}
}
+static inline bool pcap_has_sll_hdr(pcap_pkthdr_t *phdr)
+{
+ switch (phdr->link_type) {
+ case LINKTYPE_NETLINK:
+ case ___constant_swab32(LINKTYPE_NETLINK):
+ return true;
+ case LINKTYPE_LINUX_SLL:
+ case ___constant_swab32(LINKTYPE_LINUX_SLL):
+ return true;
+ }
+
+ return false;
+}
+
static inline void pcap_check_magic(uint32_t magic)
{
switch (magic) {
@@ -229,21 +261,27 @@ static inline bool pcap_magic_is_swapped(uint32_t magic)
static inline u32 pcap_get_length(pcap_pkthdr_t *phdr, enum pcap_type type)
{
+ int caplen;
+
switch (type) {
-#define CASE_RET_CAPLEN(what, member, swap) \
+#define CASE_RET_CAPLEN(what, member, swap, check_sll) \
case (what): \
- return (swap ? ___constant_swab32(phdr->member.caplen) : \
- phdr->member.caplen)
-
- CASE_RET_CAPLEN(DEFAULT, ppo, 0);
- CASE_RET_CAPLEN(NSEC, ppn, 0);
- CASE_RET_CAPLEN(KUZNETZOV, ppk, 0);
- CASE_RET_CAPLEN(BORKMANN, ppb, 0);
-
- CASE_RET_CAPLEN(DEFAULT_SWAPPED, ppo, 1);
- CASE_RET_CAPLEN(NSEC_SWAPPED, ppn, 1);
- CASE_RET_CAPLEN(KUZNETZOV_SWAPPED, ppk, 1);
- CASE_RET_CAPLEN(BORKMANN_SWAPPED, ppb, 1);
+ caplen = swap ? ___constant_swab32(phdr->h.member.caplen) : \
+ phdr->h.member.caplen; \
+ if (check_sll && pcap_has_sll_hdr(phdr)) \
+ caplen -= swap ? ___constant_swab32(LINUX_SLL_SIZE) : \
+ LINUX_SLL_SIZE; \
+ return caplen;
+
+ CASE_RET_CAPLEN(DEFAULT, ppo, 0, true);
+ CASE_RET_CAPLEN(NSEC, ppn, 0, true);
+ CASE_RET_CAPLEN(KUZNETZOV, ppk, 0, false);
+ CASE_RET_CAPLEN(BORKMANN, ppb, 0, false);
+
+ CASE_RET_CAPLEN(DEFAULT_SWAPPED, ppo, 1, true);
+ CASE_RET_CAPLEN(NSEC_SWAPPED, ppn, 1, true);
+ CASE_RET_CAPLEN(KUZNETZOV_SWAPPED, ppk, 1, false);
+ CASE_RET_CAPLEN(BORKMANN_SWAPPED, ppb, 1, false);
default:
bug();
@@ -252,21 +290,27 @@ static inline u32 pcap_get_length(pcap_pkthdr_t *phdr,
enum pcap_type type)
static inline void pcap_set_length(pcap_pkthdr_t *phdr, enum pcap_type type,
u32 len)
{
+ int caplen;
+
switch (type) {
-#define CASE_SET_CAPLEN(what, member, swap) \
+#define CASE_SET_CAPLEN(what, member, swap, check_sll) \
case (what): \
- phdr->member.caplen = (swap ? ___constant_swab32(len) : len); \
- break
+ caplen = (swap ? ___constant_swab32(len) : len); \
+ if (check_sll && pcap_has_sll_hdr(phdr)) \
+ caplen += swap ? ___constant_swab32(LINUX_SLL_SIZE) : \
+ LINUX_SLL_SIZE; \
+ phdr->h.member.caplen = caplen; \
+ break;
- CASE_SET_CAPLEN(DEFAULT, ppo, 0);
- CASE_SET_CAPLEN(NSEC, ppn, 0);
- CASE_SET_CAPLEN(KUZNETZOV, ppk, 0);
- CASE_SET_CAPLEN(BORKMANN, ppb, 0);
+ CASE_SET_CAPLEN(DEFAULT, ppo, 0, true);
+ CASE_SET_CAPLEN(NSEC, ppn, 0, true);
+ CASE_SET_CAPLEN(KUZNETZOV, ppk, 0, false);
+ CASE_SET_CAPLEN(BORKMANN, ppb, 0, false);
- CASE_SET_CAPLEN(DEFAULT_SWAPPED, ppo, 1);
- CASE_SET_CAPLEN(NSEC_SWAPPED, ppn, 1);
- CASE_SET_CAPLEN(KUZNETZOV_SWAPPED, ppk, 1);
- CASE_SET_CAPLEN(BORKMANN_SWAPPED, ppb, 1);
+ CASE_SET_CAPLEN(DEFAULT_SWAPPED, ppo, 1, true);
+ CASE_SET_CAPLEN(NSEC_SWAPPED, ppn, 1, true);
+ CASE_SET_CAPLEN(KUZNETZOV_SWAPPED, ppk, 1, false);
+ CASE_SET_CAPLEN(BORKMANN_SWAPPED, ppb, 1, false);
default:
bug();
@@ -276,19 +320,21 @@ static inline void pcap_set_length(pcap_pkthdr_t *phdr,
enum pcap_type type, u32
static inline u32 pcap_get_hdr_length(pcap_pkthdr_t *phdr, enum pcap_type type)
{
switch (type) {
-#define CASE_RET_HDRLEN(what, member) \
+#define CASE_RET_HDRLEN(what, member, check_sll) \
case (what): \
- return sizeof(phdr->member)
+ if (check_sll && !pcap_has_sll_hdr(phdr)) \
+ return sizeof(phdr->h.member) - LINUX_SLL_SIZE; \
+ return sizeof(phdr->h.member);
- CASE_RET_HDRLEN(DEFAULT, ppo);
- CASE_RET_HDRLEN(NSEC, ppn);
- CASE_RET_HDRLEN(KUZNETZOV, ppk);
- CASE_RET_HDRLEN(BORKMANN, ppb);
+ CASE_RET_HDRLEN(DEFAULT, ppo, true);
+ CASE_RET_HDRLEN(NSEC, ppn, true);
+ CASE_RET_HDRLEN(KUZNETZOV, ppk, false);
+ CASE_RET_HDRLEN(BORKMANN, ppb, false);
- CASE_RET_HDRLEN(DEFAULT_SWAPPED, ppo);
- CASE_RET_HDRLEN(NSEC_SWAPPED, ppn);
- CASE_RET_HDRLEN(KUZNETZOV_SWAPPED, ppk);
- CASE_RET_HDRLEN(BORKMANN_SWAPPED, ppb);
+ CASE_RET_HDRLEN(DEFAULT_SWAPPED, ppo, true);
+ CASE_RET_HDRLEN(NSEC_SWAPPED, ppn, true);
+ CASE_RET_HDRLEN(KUZNETZOV_SWAPPED, ppk, false);
+ CASE_RET_HDRLEN(BORKMANN_SWAPPED, ppb, false);
default:
bug();
@@ -297,25 +343,32 @@ static inline u32 pcap_get_hdr_length(pcap_pkthdr_t
*phdr, enum pcap_type type)
static inline u32 pcap_get_total_length(pcap_pkthdr_t *phdr, enum pcap_type
type)
{
- switch (type) {
-#define CASE_RET_TOTLEN(what, member, swap) \
- case (what): \
- return ((swap ? ___constant_swab32(phdr->member.caplen) : \
- phdr->member.caplen) + sizeof(phdr->member))
+ return pcap_get_length(phdr, type) + pcap_get_hdr_length(phdr, type);
+}
- CASE_RET_TOTLEN(DEFAULT, ppo, 0);
- CASE_RET_TOTLEN(NSEC, ppn, 0);
- CASE_RET_TOTLEN(KUZNETZOV, ppk, 0);
- CASE_RET_TOTLEN(BORKMANN, ppb, 0);
+static inline void sockaddr_to_linux_sll(struct sockaddr_ll *sll,
+ struct linux_sll *ll)
+{
+ ll->protocol = sll->sll_protocol;
+ ll->hatype = cpu_to_be16(sll->sll_hatype);
+ ll->pkttype = cpu_to_be16(sll->sll_pkttype);
+ ll->len = cpu_to_be16(sll->sll_halen);
+ memcpy(ll->addr, sll->sll_addr, 8);
+}
- CASE_RET_TOTLEN(DEFAULT_SWAPPED, ppo, 1);
- CASE_RET_TOTLEN(NSEC_SWAPPED, ppn, 1);
- CASE_RET_TOTLEN(KUZNETZOV_SWAPPED, ppk, 1);
- CASE_RET_TOTLEN(BORKMANN_SWAPPED, ppb, 1);
+static inline void linux_sll_to_sockaddr(struct linux_sll *ll,
+ struct sockaddr_ll *sll)
+{
+ sll->sll_protocol = ll->protocol;
+ sll->sll_hatype = be16_to_cpu(ll->hatype);
+ sll->sll_pkttype = be16_to_cpu(ll->pkttype);
+ sll->sll_halen = be16_to_cpu(ll->len);
+ memcpy(sll->sll_addr, ll->addr, 8);
+}
- default:
- bug();
- }
+static inline void pcap_pkthdr_init(pcap_pkthdr_t *phdr, uint32_t link_type)
+{
+ phdr->link_type = link_type;
}
static inline void
@@ -324,77 +377,99 @@ __tpacket_hdr_to_pcap_pkthdr(uint32_t sec, uint32_t nsec,
uint32_t snaplen,
struct sockaddr_ll *sll, pcap_pkthdr_t *phdr,
enum pcap_type type)
{
+ int sll_len = 0;
+
switch (type) {
case DEFAULT:
- phdr->ppo.ts.tv_sec = sec;
- phdr->ppo.ts.tv_usec = nsec / 1000;
- phdr->ppo.caplen = snaplen;
- phdr->ppo.len = len;
+ if (pcap_has_sll_hdr(phdr)) {
+ sockaddr_to_linux_sll(sll, &phdr->h.ppo.sll);
+ sll_len = LINUX_SLL_SIZE;
+ }
+
+ phdr->h.ppo.ts.tv_sec = sec;
+ phdr->h.ppo.ts.tv_usec = nsec / 1000;
+ phdr->h.ppo.caplen = snaplen + sll_len;
+ phdr->h.ppo.len = len + sll_len;
break;
case DEFAULT_SWAPPED:
- phdr->ppo.ts.tv_sec = ___constant_swab32(sec);
- phdr->ppo.ts.tv_usec = ___constant_swab32(nsec / 1000);
- phdr->ppo.caplen = ___constant_swab32(snaplen);
- phdr->ppo.len = ___constant_swab32(len);
+ if (pcap_has_sll_hdr(phdr)) {
+ sockaddr_to_linux_sll(sll, &phdr->h.ppo.sll);
+ sll_len = ___constant_swab32(LINUX_SLL_SIZE);
+ }
+
+ phdr->h.ppo.ts.tv_sec = ___constant_swab32(sec);
+ phdr->h.ppo.ts.tv_usec = ___constant_swab32(nsec / 1000);
+ phdr->h.ppo.caplen = ___constant_swab32(snaplen) + sll_len;
+ phdr->h.ppo.len = ___constant_swab32(len) + sll_len;
break;
case NSEC:
- phdr->ppn.ts.tv_sec = sec;
- phdr->ppn.ts.tv_nsec = nsec;
- phdr->ppn.caplen = snaplen;
- phdr->ppn.len = len;
+ if (pcap_has_sll_hdr(phdr)) {
+ sockaddr_to_linux_sll(sll, &phdr->h.ppn.sll);
+ sll_len = LINUX_SLL_SIZE;
+ }
+
+ phdr->h.ppn.ts.tv_sec = sec;
+ phdr->h.ppn.ts.tv_nsec = nsec;
+ phdr->h.ppn.caplen = snaplen + sll_len;
+ phdr->h.ppn.len = len + sll_len;
break;
case NSEC_SWAPPED:
- phdr->ppn.ts.tv_sec = ___constant_swab32(sec);
- phdr->ppn.ts.tv_nsec = ___constant_swab32(nsec);
- phdr->ppn.caplen = ___constant_swab32(snaplen);
- phdr->ppn.len = ___constant_swab32(len);
+ if (pcap_has_sll_hdr(phdr)) {
+ sockaddr_to_linux_sll(sll, &phdr->h.ppn.sll);
+ sll_len = ___constant_swab32(LINUX_SLL_SIZE);
+ }
+
+ phdr->h.ppn.ts.tv_sec = ___constant_swab32(sec);
+ phdr->h.ppn.ts.tv_nsec = ___constant_swab32(nsec);
+ phdr->h.ppn.caplen = ___constant_swab32(snaplen) + sll_len;
+ phdr->h.ppn.len = ___constant_swab32(len) + sll_len;
break;
case KUZNETZOV:
- phdr->ppk.ts.tv_sec = sec;
- phdr->ppk.ts.tv_usec = nsec / 1000;
- phdr->ppk.caplen = snaplen;
- phdr->ppk.len = len;
- phdr->ppk.ifindex = sll->sll_ifindex;
- phdr->ppk.protocol = sll->sll_protocol;
- phdr->ppk.pkttype = sll->sll_pkttype;
+ phdr->h.ppk.ts.tv_sec = sec;
+ phdr->h.ppk.ts.tv_usec = nsec / 1000;
+ phdr->h.ppk.caplen = snaplen;
+ phdr->h.ppk.len = len;
+ phdr->h.ppk.ifindex = sll->sll_ifindex;
+ phdr->h.ppk.protocol = sll->sll_protocol;
+ phdr->h.ppk.pkttype = sll->sll_pkttype;
break;
case KUZNETZOV_SWAPPED:
- phdr->ppk.ts.tv_sec = ___constant_swab32(sec);
- phdr->ppk.ts.tv_usec = ___constant_swab32(nsec / 1000);
- phdr->ppk.caplen = ___constant_swab32(snaplen);
- phdr->ppk.len = ___constant_swab32(len);
- phdr->ppk.ifindex = ___constant_swab32(sll->sll_ifindex);
- phdr->ppk.protocol = ___constant_swab16(sll->sll_protocol);
- phdr->ppk.pkttype = sll->sll_pkttype;
+ phdr->h.ppk.ts.tv_sec = ___constant_swab32(sec);
+ phdr->h.ppk.ts.tv_usec = ___constant_swab32(nsec / 1000);
+ phdr->h.ppk.caplen = ___constant_swab32(snaplen);
+ phdr->h.ppk.len = ___constant_swab32(len);
+ phdr->h.ppk.ifindex = ___constant_swab32(sll->sll_ifindex);
+ phdr->h.ppk.protocol = ___constant_swab16(sll->sll_protocol);
+ phdr->h.ppk.pkttype = sll->sll_pkttype;
break;
case BORKMANN:
- phdr->ppb.ts.tv_sec = sec;
- phdr->ppb.ts.tv_nsec = nsec;
- phdr->ppb.caplen = snaplen;
- phdr->ppb.len = len;
- phdr->ppb.tsource = tp_to_pcap_tsource(status);
- phdr->ppb.ifindex = (u16) sll->sll_ifindex;
- phdr->ppb.protocol = sll->sll_protocol;
- phdr->ppb.hatype = sll->sll_hatype;
- phdr->ppb.pkttype = sll->sll_pkttype;
+ phdr->h.ppb.ts.tv_sec = sec;
+ phdr->h.ppb.ts.tv_nsec = nsec;
+ phdr->h.ppb.caplen = snaplen;
+ phdr->h.ppb.len = len;
+ phdr->h.ppb.tsource = tp_to_pcap_tsource(status);
+ phdr->h.ppb.ifindex = (u16) sll->sll_ifindex;
+ phdr->h.ppb.protocol = sll->sll_protocol;
+ phdr->h.ppb.hatype = sll->sll_hatype;
+ phdr->h.ppb.pkttype = sll->sll_pkttype;
break;
case BORKMANN_SWAPPED:
- phdr->ppb.ts.tv_sec = ___constant_swab32(sec);
- phdr->ppb.ts.tv_nsec = ___constant_swab32(nsec);
- phdr->ppb.caplen = ___constant_swab32(snaplen);
- phdr->ppb.len = ___constant_swab32(len);
- phdr->ppb.tsource =
___constant_swab16(tp_to_pcap_tsource(status));
- phdr->ppb.ifindex = ___constant_swab16((u16) sll->sll_ifindex);
- phdr->ppb.protocol = ___constant_swab16(sll->sll_protocol);
- phdr->ppb.hatype = sll->sll_hatype;
- phdr->ppb.pkttype = sll->sll_pkttype;
+ phdr->h.ppb.ts.tv_sec = ___constant_swab32(sec);
+ phdr->h.ppb.ts.tv_nsec = ___constant_swab32(nsec);
+ phdr->h.ppb.caplen = ___constant_swab32(snaplen);
+ phdr->h.ppb.len = ___constant_swab32(len);
+ phdr->h.ppb.tsource =
___constant_swab16(tp_to_pcap_tsource(status));
+ phdr->h.ppb.ifindex = ___constant_swab16((u16)
sll->sll_ifindex);
+ phdr->h.ppb.protocol = ___constant_swab16(sll->sll_protocol);
+ phdr->h.ppb.hatype = sll->sll_hatype;
+ phdr->h.ppb.pkttype = sll->sll_pkttype;
break;
default:
@@ -433,82 +508,106 @@ static inline void
pcap_pkthdr_to_tpacket_hdr(pcap_pkthdr_t *phdr,
struct tpacket2_hdr *thdr,
struct sockaddr_ll *sll)
{
+ int sll_len = 0;
+
switch (type) {
case DEFAULT:
- thdr->tp_sec = phdr->ppo.ts.tv_sec;
- thdr->tp_nsec = phdr->ppo.ts.tv_usec * 1000;
- thdr->tp_snaplen = phdr->ppo.caplen;
- thdr->tp_len = phdr->ppo.len;
+ if (pcap_has_sll_hdr(phdr)) {
+ linux_sll_to_sockaddr(&phdr->h.ppo.sll, sll);
+ sll_len = LINUX_SLL_SIZE;
+ }
+
+ thdr->tp_sec = phdr->h.ppo.ts.tv_sec;
+ thdr->tp_nsec = phdr->h.ppo.ts.tv_usec * 1000;
+ thdr->tp_snaplen = phdr->h.ppo.caplen - sll_len;
+ thdr->tp_len = phdr->h.ppo.len - sll_len;
break;
case DEFAULT_SWAPPED:
- thdr->tp_sec = ___constant_swab32(phdr->ppo.ts.tv_sec);
- thdr->tp_nsec = ___constant_swab32(phdr->ppo.ts.tv_usec) * 1000;
- thdr->tp_snaplen = ___constant_swab32(phdr->ppo.caplen);
- thdr->tp_len = ___constant_swab32(phdr->ppo.len);
+ if (pcap_has_sll_hdr(phdr)) {
+ linux_sll_to_sockaddr(&phdr->h.ppo.sll, sll);
+ sll_len = ___constant_swab32(LINUX_SLL_SIZE);
+ }
+
+ thdr->tp_sec = ___constant_swab32(phdr->h.ppo.ts.tv_sec);
+ thdr->tp_nsec = ___constant_swab32(phdr->h.ppo.ts.tv_usec) *
1000;
+ thdr->tp_snaplen = ___constant_swab32(phdr->h.ppo.caplen) -
+ sll_len;
+ thdr->tp_len = ___constant_swab32(phdr->h.ppo.len) - sll_len;
break;
case NSEC:
- thdr->tp_sec = phdr->ppn.ts.tv_sec;
- thdr->tp_nsec = phdr->ppn.ts.tv_nsec;
- thdr->tp_snaplen = phdr->ppn.caplen;
- thdr->tp_len = phdr->ppn.len;
+ if (pcap_has_sll_hdr(phdr)) {
+ linux_sll_to_sockaddr(&phdr->h.ppo.sll, sll);
+ sll_len = LINUX_SLL_SIZE;
+ }
+
+ thdr->tp_sec = phdr->h.ppn.ts.tv_sec;
+ thdr->tp_nsec = phdr->h.ppn.ts.tv_nsec;
+ thdr->tp_snaplen = phdr->h.ppn.caplen - sll_len;
+ thdr->tp_len = phdr->h.ppn.len - sll_len;
break;
case NSEC_SWAPPED:
- thdr->tp_sec = ___constant_swab32(phdr->ppn.ts.tv_sec);
- thdr->tp_nsec = ___constant_swab32(phdr->ppn.ts.tv_nsec);
- thdr->tp_snaplen = ___constant_swab32(phdr->ppn.caplen);
- thdr->tp_len = ___constant_swab32(phdr->ppn.len);
+ if (pcap_has_sll_hdr(phdr)) {
+ linux_sll_to_sockaddr(&phdr->h.ppo.sll, sll);
+ sll_len = ___constant_swab32(LINUX_SLL_SIZE);
+ }
+
+ thdr->tp_sec = ___constant_swab32(phdr->h.ppn.ts.tv_sec);
+ thdr->tp_nsec = ___constant_swab32(phdr->h.ppn.ts.tv_nsec);
+ thdr->tp_snaplen = ___constant_swab32(phdr->h.ppn.caplen) -
+ sll_len;
+ thdr->tp_len = ___constant_swab32(phdr->h.ppn.len) - sll_len;
break;
case KUZNETZOV:
- thdr->tp_sec = phdr->ppk.ts.tv_sec;
- thdr->tp_nsec = phdr->ppk.ts.tv_usec * 1000;
- thdr->tp_snaplen = phdr->ppk.caplen;
- thdr->tp_len = phdr->ppk.len;
+ thdr->tp_sec = phdr->h.ppk.ts.tv_sec;
+ thdr->tp_nsec = phdr->h.ppk.ts.tv_usec * 1000;
+ thdr->tp_snaplen = phdr->h.ppk.caplen;
+ thdr->tp_len = phdr->h.ppk.len;
if (sll) {
- sll->sll_ifindex = phdr->ppk.ifindex;
- sll->sll_protocol = phdr->ppk.protocol;
- sll->sll_pkttype = phdr->ppk.pkttype;
+ sll->sll_ifindex = phdr->h.ppk.ifindex;
+ sll->sll_protocol = phdr->h.ppk.protocol;
+ sll->sll_pkttype = phdr->h.ppk.pkttype;
}
break;
case KUZNETZOV_SWAPPED:
- thdr->tp_sec = ___constant_swab32(phdr->ppk.ts.tv_sec);
- thdr->tp_nsec = ___constant_swab32(phdr->ppk.ts.tv_usec) * 1000;
- thdr->tp_snaplen = ___constant_swab32(phdr->ppk.caplen);
- thdr->tp_len = ___constant_swab32(phdr->ppk.len);
+ thdr->tp_sec = ___constant_swab32(phdr->h.ppk.ts.tv_sec);
+ thdr->tp_nsec = ___constant_swab32(phdr->h.ppk.ts.tv_usec) *
1000;
+ thdr->tp_snaplen = ___constant_swab32(phdr->h.ppk.caplen);
+ thdr->tp_len = ___constant_swab32(phdr->h.ppk.len);
if (sll) {
- sll->sll_ifindex =
___constant_swab32(phdr->ppk.ifindex);
- sll->sll_protocol =
___constant_swab16(phdr->ppk.protocol);
- sll->sll_pkttype = phdr->ppk.pkttype;
+ sll->sll_ifindex =
___constant_swab32(phdr->h.ppk.ifindex);
+ sll->sll_protocol =
___constant_swab16(phdr->h.ppk.protocol);
+ sll->sll_pkttype = phdr->h.ppk.pkttype;
}
break;
case BORKMANN:
- thdr->tp_sec = phdr->ppb.ts.tv_sec;
- thdr->tp_nsec = phdr->ppb.ts.tv_nsec;
- thdr->tp_snaplen = phdr->ppb.caplen;
- thdr->tp_len = phdr->ppb.len;
+ thdr->tp_sec = phdr->h.ppb.ts.tv_sec;
+ thdr->tp_nsec = phdr->h.ppb.ts.tv_nsec;
+ thdr->tp_snaplen = phdr->h.ppb.caplen;
+ thdr->tp_len = phdr->h.ppb.len;
if (sll) {
- sll->sll_ifindex = phdr->ppb.ifindex;
- sll->sll_protocol = phdr->ppb.protocol;
- sll->sll_hatype = phdr->ppb.hatype;
- sll->sll_pkttype = phdr->ppb.pkttype;
+ sll->sll_ifindex = phdr->h.ppb.ifindex;
+ sll->sll_protocol = phdr->h.ppb.protocol;
+ sll->sll_hatype = phdr->h.ppb.hatype;
+ sll->sll_pkttype = phdr->h.ppb.pkttype;
}
break;
case BORKMANN_SWAPPED:
- thdr->tp_sec = ___constant_swab32(phdr->ppb.ts.tv_sec);
- thdr->tp_nsec = ___constant_swab32(phdr->ppb.ts.tv_nsec);
- thdr->tp_snaplen = ___constant_swab32(phdr->ppb.caplen);
- thdr->tp_len = ___constant_swab32(phdr->ppb.len);
+ thdr->tp_sec = ___constant_swab32(phdr->h.ppb.ts.tv_sec);
+ thdr->tp_nsec = ___constant_swab32(phdr->h.ppb.ts.tv_nsec);
+ thdr->tp_snaplen = ___constant_swab32(phdr->h.ppb.caplen);
+ thdr->tp_len = ___constant_swab32(phdr->h.ppb.len);
if (sll) {
- sll->sll_ifindex =
___constant_swab16(phdr->ppb.ifindex);
- sll->sll_protocol =
___constant_swab16(phdr->ppb.protocol);
- sll->sll_hatype = phdr->ppb.hatype;
- sll->sll_pkttype = phdr->ppb.pkttype;
+ sll->sll_ifindex =
___constant_swab16(phdr->h.ppb.ifindex);
+ sll->sll_protocol =
___constant_swab16(phdr->h.ppb.protocol);
+ sll->sll_hatype = phdr->h.ppb.hatype;
+ sll->sll_pkttype = phdr->h.ppb.pkttype;
}
break;
@@ -659,6 +758,7 @@ static const bool pcap_supported_linktypes[LINKTYPE_MAX]
__maybe_unused = {
[LINKTYPE_IEEE802_15_4_LINUX] = true,
[LINKTYPE_INFINIBAND] = true,
[LINKTYPE_NETLINK] = true,
+ [LINKTYPE_LINUX_SLL] = true,
};
static inline void pcap_validate_header(const struct pcap_filehdr *hdr)
diff --git a/pcap_mm.c b/pcap_mm.c
index f7b248e..b6a350d 100644
--- a/pcap_mm.c
+++ b/pcap_mm.c
@@ -56,7 +56,7 @@ static ssize_t pcap_mm_write(int fd, pcap_pkthdr_t *phdr,
enum pcap_type type,
if ((off_t) (ptr_va_curr - ptr_va_start) + hdrsize + len > map_size)
__pcap_mmap_write_need_remap(fd);
- fmemcpy(ptr_va_curr, &phdr->raw, hdrsize);
+ fmemcpy(ptr_va_curr, &phdr->h.raw, hdrsize);
ptr_va_curr += hdrsize;
fmemcpy(ptr_va_curr, packet, len);
ptr_va_curr += len;
@@ -72,8 +72,9 @@ static ssize_t pcap_mm_read(int fd __maybe_unused,
pcap_pkthdr_t *phdr,
if (unlikely((off_t) (ptr_va_curr + hdrsize - ptr_va_start) > (off_t)
map_size))
return -EIO;
- fmemcpy(&phdr->raw, ptr_va_curr, hdrsize);
+ fmemcpy(&phdr->h.raw, ptr_va_curr, hdrsize);
ptr_va_curr += hdrsize;
+
hdrlen = pcap_get_length(phdr, type);
if (unlikely((off_t) (ptr_va_curr + hdrlen - ptr_va_start) > (off_t)
map_size))
diff --git a/pcap_rw.c b/pcap_rw.c
index b6be922..e6ebc94 100644
--- a/pcap_rw.c
+++ b/pcap_rw.c
@@ -22,7 +22,7 @@ static ssize_t pcap_rw_write(int fd, pcap_pkthdr_t *phdr,
enum pcap_type type,
{
ssize_t ret, hdrsize = pcap_get_hdr_length(phdr, type), hdrlen = 0;
- ret = write_or_die(fd, &phdr->raw, hdrsize);
+ ret = write_or_die(fd, &phdr->h.raw, hdrsize);
if (unlikely(ret != hdrsize))
panic("Failed to write pkt header!\n");
@@ -42,7 +42,7 @@ static ssize_t pcap_rw_read(int fd, pcap_pkthdr_t *phdr, enum
pcap_type type,
{
ssize_t ret, hdrsize = pcap_get_hdr_length(phdr, type), hdrlen = 0;
- ret = read_or_die(fd, &phdr->raw, hdrsize);
+ ret = read_or_die(fd, &phdr->h.raw, hdrsize);
if (unlikely(ret != hdrsize))
return -EIO;
diff --git a/pcap_sg.c b/pcap_sg.c
index 80c2c5d..00793fe 100644
--- a/pcap_sg.c
+++ b/pcap_sg.c
@@ -33,7 +33,7 @@ static ssize_t pcap_sg_write(int fd, pcap_pkthdr_t *phdr,
enum pcap_type type,
iov_slot = 0;
}
- fmemcpy(iov[iov_slot].iov_base, &phdr->raw, hdrsize);
+ fmemcpy(iov[iov_slot].iov_base, &phdr->h.raw, hdrsize);
iov[iov_slot].iov_len = hdrsize;
fmemcpy(iov[iov_slot].iov_base + iov[iov_slot].iov_len, packet, len);
@@ -57,7 +57,7 @@ static ssize_t __pcap_sg_inter_iov_hdr_read(int fd,
pcap_pkthdr_t *phdr,
bug_on(offset + remainder != hdrsize);
- fmemcpy(&phdr->raw, iov[iov_slot].iov_base + iov_off_rd, offset);
+ fmemcpy(&phdr->h.raw, iov[iov_slot].iov_base + iov_off_rd, offset);
iov_off_rd = 0;
iov_slot++;
@@ -68,7 +68,7 @@ static ssize_t __pcap_sg_inter_iov_hdr_read(int fd,
pcap_pkthdr_t *phdr,
return -EIO;
}
- fmemcpy(&phdr->raw + offset, iov[iov_slot].iov_base + iov_off_rd,
remainder);
+ fmemcpy(&phdr->h.raw + offset, iov[iov_slot].iov_base + iov_off_rd,
remainder);
iov_off_rd += remainder;
return hdrsize;
@@ -111,7 +111,7 @@ static ssize_t pcap_sg_read(int fd, pcap_pkthdr_t *phdr,
enum pcap_type type,
size_t hdrsize = pcap_get_hdr_length(phdr, type), hdrlen;
if (likely(iov[iov_slot].iov_len - iov_off_rd >= hdrsize)) {
- fmemcpy(&phdr->raw, iov[iov_slot].iov_base + iov_off_rd,
hdrsize);
+ fmemcpy(&phdr->h.raw, iov[iov_slot].iov_base + iov_off_rd,
hdrsize);
iov_off_rd += hdrsize;
} else {
ret = __pcap_sg_inter_iov_hdr_read(fd, phdr, hdrsize);
diff --git a/sock.c b/sock.c
index 7cfa4a0..9c3d789 100644
--- a/sock.c
+++ b/sock.c
@@ -33,6 +33,16 @@ int pf_socket(void)
return sock;
}
+int pf_socket_dgram(void)
+{
+ int sock = socket(PF_PACKET, SOCK_DGRAM, 0);
+ if (unlikely(sock < 0))
+ panic("Creation of PF dgram socket failed: %s\n",
+ strerror(errno));
+
+ return sock;
+}
+
/* Avail in kernel >= 3.14
* in commit d346a3fae3 (packet: introduce PACKET_QDISC_BYPASS socket option)
*/
diff --git a/sock.h b/sock.h
index 50f7102..e63cd32 100644
--- a/sock.h
+++ b/sock.h
@@ -3,6 +3,7 @@
extern int af_socket(int af);
extern int pf_socket(void);
+extern int pf_socket_dgram(void);
extern void set_nonblocking(int fd);
extern int set_nonblocking_sloppy(int fd);
extern int set_reuseaddr(int fd);
--
2.4.2
--
You received this message because you are subscribed to the Google Groups
"netsniff-ng" group.
To unsubscribe from this group and stop receiving emails from it, send an email
to [email protected].
For more options, visit https://groups.google.com/d/optout.