From: Vadim Kochan <[email protected]>

Since Netlink messages are written in default pcap format there is no
way to identify Netlink family by socket protocol number, so
use pcap cooked header for Netlink messages as described here:

        http://www.tcpdump.org/linktypes/LINKTYPE_NETLINK.html

Signed-off-by: Vadim Kochan <[email protected]>
---
I am not sure if I do correct conversion in a new aded func sockaddr_to_pcap_ll:

        pcap_ll->protocol       = ___constant_swab16(sll->sll_protocol);
        pcap_ll->hatype         = ___constant_swab16(sll->sll_hatype);
        pcap_ll->pkttype        = ___constant_swab16(sll->sll_pkttype);

but Wireshark understands it OK.

 netsniff-ng.c |   8 ++
 pcap_io.h     | 351 +++++++++++++++++++++++++++++++++++++++-------------------
 pcap_mm.c     |  28 ++++-
 pcap_rw.c     |  30 ++++-
 pcap_sg.c     |  83 +++++++-------
 5 files changed, 341 insertions(+), 159 deletions(-)

diff --git a/netsniff-ng.c b/netsniff-ng.c
index afa522f..7dc29cb 100644
--- a/netsniff-ng.c
+++ b/netsniff-ng.c
@@ -237,6 +237,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 +591,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 +910,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;
@@ -1036,6 +1042,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;
diff --git a/pcap_io.h b/pcap_io.h
index 35faa51..4e6e41c 100644
--- a/pcap_io.h
+++ b/pcap_io.h
@@ -90,12 +90,25 @@ 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;
+/* DLT_LINUX_SLL - fake link-layer header */
+struct pcap_pkthdr_ll {
+       uint16_t pkttype;
+       uint16_t hatype;
+       uint16_t len;
+       uint8_t addr[8];
+       uint16_t protocol;
+};
+
+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;
+       struct pcap_pkthdr_ll ll_hdr;
+       uint32_t link_type;
 } pcap_pkthdr_t;
 
 enum pcap_type {
@@ -232,8 +245,8 @@ static inline u32 pcap_get_length(pcap_pkthdr_t *phdr, enum 
pcap_type type)
        switch (type) {
 #define CASE_RET_CAPLEN(what, member, swap) \
        case (what): \
-               return (swap ? ___constant_swab32(phdr->member.caplen) : \
-                       phdr->member.caplen)
+               return (swap ? ___constant_swab32(phdr->h.member.caplen) : \
+                       phdr->h.member.caplen)
 
        CASE_RET_CAPLEN(DEFAULT, ppo, 0);
        CASE_RET_CAPLEN(NSEC, ppn, 0);
@@ -255,7 +268,7 @@ static inline void pcap_set_length(pcap_pkthdr_t *phdr, 
enum pcap_type type, u32
        switch (type) {
 #define CASE_SET_CAPLEN(what, member, swap) \
        case (what): \
-               phdr->member.caplen = (swap ? ___constant_swab32(len) : len); \
+               phdr->h.member.caplen = (swap ? ___constant_swab32(len) : len); 
\
                break
 
        CASE_SET_CAPLEN(DEFAULT, ppo, 0);
@@ -278,7 +291,7 @@ static inline u32 pcap_get_hdr_length(pcap_pkthdr_t *phdr, 
enum pcap_type type)
        switch (type) {
 #define CASE_RET_HDRLEN(what, member) \
        case (what): \
-               return sizeof(phdr->member)
+               return sizeof(phdr->h.member)
 
        CASE_RET_HDRLEN(DEFAULT, ppo);
        CASE_RET_HDRLEN(NSEC, ppn);
@@ -300,8 +313,8 @@ 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 ((swap ? ___constant_swab32(phdr->h.member.caplen) : \
+                        phdr->h.member.caplen) + sizeof(phdr->h.member))
 
        CASE_RET_TOTLEN(DEFAULT, ppo, 0);
        CASE_RET_TOTLEN(NSEC, ppn, 0);
@@ -318,6 +331,76 @@ static inline u32 pcap_get_total_length(pcap_pkthdr_t 
*phdr, enum pcap_type type
        }
 }
 
+static inline void pcap_pkthdr_add_hdr(pcap_pkthdr_t *phdr,
+               enum pcap_type type, uint32_t len)
+{
+       switch (type) {
+#define CASE_ADD_TOTLEN(what, member, swap) \
+       case (what): \
+               phdr->h.member.caplen += swap ? ___constant_swab32(len) : len; \
+               phdr->h.member.len += swap ? ___constant_swab32(len) : len; \
+               break;
+
+       CASE_ADD_TOTLEN(DEFAULT, ppo, 0);
+       CASE_ADD_TOTLEN(NSEC, ppn, 0);
+       CASE_ADD_TOTLEN(KUZNETZOV, ppk, 0);
+       CASE_ADD_TOTLEN(BORKMANN, ppb, 0);
+
+       CASE_ADD_TOTLEN(DEFAULT_SWAPPED, ppo, 1);
+       CASE_ADD_TOTLEN(NSEC_SWAPPED, ppn, 1);
+       CASE_ADD_TOTLEN(KUZNETZOV_SWAPPED, ppk, 1);
+       CASE_ADD_TOTLEN(BORKMANN_SWAPPED, ppb, 1);
+
+       default:
+               bug();
+       }
+}
+
+static inline void pcap_pkthdr_sub_hdr(pcap_pkthdr_t *phdr,
+               enum pcap_type type, uint32_t len)
+{
+       switch (type) {
+#define CASE_SUB_TOTLEN(what, member, swap) \
+       case (what): \
+               phdr->h.member.caplen -= swap ? ___constant_swab32(len) : len; \
+               phdr->h.member.len -= swap ? ___constant_swab32(len) : len; \
+               break;
+
+       CASE_SUB_TOTLEN(DEFAULT, ppo, 0);
+       CASE_SUB_TOTLEN(NSEC, ppn, 0);
+       CASE_SUB_TOTLEN(KUZNETZOV, ppk, 0);
+       CASE_SUB_TOTLEN(BORKMANN, ppb, 0);
+
+       CASE_SUB_TOTLEN(DEFAULT_SWAPPED, ppo, 1);
+       CASE_SUB_TOTLEN(NSEC_SWAPPED, ppn, 1);
+       CASE_SUB_TOTLEN(KUZNETZOV_SWAPPED, ppk, 1);
+       CASE_SUB_TOTLEN(BORKMANN_SWAPPED, ppb, 1);
+
+       default:
+               bug();
+       }
+}
+
+static inline void sockaddr_to_pcap_ll(struct pcap_pkthdr_ll *pcap_ll,
+               struct sockaddr_ll *sll, enum pcap_type type)
+{
+       pcap_ll->protocol       = ___constant_swab16(sll->sll_protocol);
+       pcap_ll->hatype         = ___constant_swab16(sll->sll_hatype);
+       pcap_ll->pkttype        = ___constant_swab16(sll->sll_pkttype);
+}
+
+static inline void pcap_pkthdr_add_ll_hdr(pcap_pkthdr_t *phdr,
+               enum pcap_type type, struct sockaddr_ll *sll)
+{
+       pcap_pkthdr_add_hdr(phdr, type, sizeof(struct pcap_pkthdr_ll));
+       sockaddr_to_pcap_ll(&phdr->ll_hdr, sll, type);
+}
+
+static inline bool pcap_pkthdr_has_ll(pcap_pkthdr_t *phdr)
+{
+       return phdr->link_type == LINKTYPE_NETLINK;
+}
+
 static inline void
 __tpacket_hdr_to_pcap_pkthdr(uint32_t sec, uint32_t nsec, uint32_t snaplen,
                             uint32_t len, uint32_t status,
@@ -326,80 +409,83 @@ __tpacket_hdr_to_pcap_pkthdr(uint32_t sec, uint32_t nsec, 
uint32_t snaplen,
 {
        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;
+               phdr->h.ppo.ts.tv_sec = sec;
+               phdr->h.ppo.ts.tv_usec = nsec / 1000;
+               phdr->h.ppo.caplen = snaplen;
+               phdr->h.ppo.len = 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);
+               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);
+               phdr->h.ppo.len = ___constant_swab32(len);
                break;
 
        case NSEC:
-               phdr->ppn.ts.tv_sec = sec;
-               phdr->ppn.ts.tv_nsec = nsec;
-               phdr->ppn.caplen = snaplen;
-               phdr->ppn.len = len;
+               phdr->h.ppn.ts.tv_sec = sec;
+               phdr->h.ppn.ts.tv_nsec = nsec;
+               phdr->h.ppn.caplen = snaplen;
+               phdr->h.ppn.len = 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);
+               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);
+               phdr->h.ppn.len = ___constant_swab32(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:
                bug();
        }
+
+       if (pcap_pkthdr_has_ll(phdr))
+               pcap_pkthdr_add_ll_hdr(phdr, type, sll);
 }
 
 /* We need to do this crap here since member offsets are not interleaved,
@@ -428,6 +514,45 @@ static inline void tpacket3_hdr_to_pcap_pkthdr(struct 
tpacket3_hdr *thdr,
 }
 #endif
 
+static inline void pcap_pkthdr_to_sockaddr(pcap_pkthdr_t *phdr,
+               struct sockaddr_ll *sll, enum pcap_type type)
+{
+       switch (type) {
+       case DEFAULT:
+       case DEFAULT_SWAPPED:
+       case NSEC:
+       case NSEC_SWAPPED:
+               if (pcap_pkthdr_has_ll(phdr)) {
+                       sll->sll_protocol = 
___constant_swab16(phdr->ll_hdr.protocol);
+                       sll->sll_hatype = 
___constant_swab16(phdr->ll_hdr.hatype);
+                       sll->sll_pkttype = 
___constant_swab16(phdr->ll_hdr.pkttype);
+               }
+               break;
+       case KUZNETZOV:
+               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:
+               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:
+               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:
+               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;
+       }
+}
+
 static inline void pcap_pkthdr_to_tpacket_hdr(pcap_pkthdr_t *phdr,
                                              enum pcap_type type,
                                              struct tpacket2_hdr *thdr,
@@ -435,86 +560,84 @@ static inline void 
pcap_pkthdr_to_tpacket_hdr(pcap_pkthdr_t *phdr,
 {
        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_pkthdr_has_ll(phdr))
+                       pcap_pkthdr_sub_hdr(phdr, type, sizeof(phdr->ll_hdr));
+
+               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;
+               thdr->tp_len = phdr->h.ppo.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_pkthdr_has_ll(phdr))
+                       pcap_pkthdr_sub_hdr(phdr, type, sizeof(phdr->ll_hdr));
+
+               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);
+               thdr->tp_len = ___constant_swab32(phdr->h.ppo.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_pkthdr_has_ll(phdr))
+                       pcap_pkthdr_sub_hdr(phdr, type, sizeof(phdr->ll_hdr));
+
+               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;
+               thdr->tp_len = phdr->h.ppn.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_pkthdr_has_ll(phdr))
+                       pcap_pkthdr_sub_hdr(phdr, type, sizeof(phdr->ll_hdr));
+
+               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);
+               thdr->tp_len = ___constant_swab32(phdr->h.ppn.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;
-               if (sll) {
-                       sll->sll_ifindex = phdr->ppk.ifindex;
-                       sll->sll_protocol = phdr->ppk.protocol;
-                       sll->sll_pkttype = phdr->ppk.pkttype;
-               }
+               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;
                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);
-               if (sll) {
-                       sll->sll_ifindex = 
___constant_swab32(phdr->ppk.ifindex);
-                       sll->sll_protocol = 
___constant_swab16(phdr->ppk.protocol);
-                       sll->sll_pkttype = phdr->ppk.pkttype;
-               }
+               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);
                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;
-               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;
-               }
+               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;
                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);
-               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;
-               }
+               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);
                break;
 
        default:
                bug();
        }
+
+       if (sll)
+               pcap_pkthdr_to_sockaddr(phdr, sll, type);
+}
+
+static inline void pcap_pkthdr_init(pcap_pkthdr_t *phdr, uint32_t link_type)
+{
+       phdr->link_type = link_type;
 }
 
 #define FEATURE_UNKNOWN                (0 << 0)
diff --git a/pcap_mm.c b/pcap_mm.c
index f7b248e..dffe4b0 100644
--- a/pcap_mm.c
+++ b/pcap_mm.c
@@ -56,8 +56,18 @@ 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;
+
+       if (pcap_pkthdr_has_ll(phdr)) {
+               size_t ll_len = sizeof(struct pcap_pkthdr_ll);
+
+               fmemcpy(ptr_va_curr, &phdr->ll_hdr, ll_len);
+               ptr_va_curr     += ll_len;
+               len             -= ll_len;
+               hdrsize         += ll_len;
+       }
+
        fmemcpy(ptr_va_curr, packet, len);
        ptr_va_curr += len;
 
@@ -72,8 +82,22 @@ 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;
+
+       if (pcap_pkthdr_has_ll(phdr)) {
+               size_t ll_len = sizeof(struct pcap_pkthdr_ll);
+
+               if (unlikely((off_t) (ptr_va_curr + ll_len - ptr_va_start) >
+                                       (off_t) map_size))
+                       return -EIO;
+
+               fmemcpy(&phdr->ll_hdr, ptr_va_curr, ll_len);
+               ptr_va_curr     += hdrsize;
+               hdrsize         += ll_len;
+               len             -= ll_len;
+       }
+
        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..02d9e1d 100644
--- a/pcap_rw.c
+++ b/pcap_rw.c
@@ -21,12 +21,25 @@ static ssize_t pcap_rw_write(int fd, pcap_pkthdr_t *phdr, 
enum pcap_type type,
                             const uint8_t *packet, size_t len)
 {
        ssize_t ret, hdrsize = pcap_get_hdr_length(phdr, type), hdrlen = 0;
+       ssize_t ll_len = 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");
 
+       if (pcap_pkthdr_has_ll(phdr)) {
+               ll_len = sizeof(struct pcap_pkthdr_ll);
+               int ret_ll = write_or_die(fd, (uint8_t *)&phdr->ll_hdr, ll_len);
+
+               if (unlikely(ret_ll != sizeof(phdr->ll_hdr)))
+                       panic("Failed to write pkt header!\n");
+       }
+
        hdrlen = pcap_get_length(phdr, type);
+       hdrlen  -= ll_len;
+       len     -= ll_len;
+       hdrsize += ll_len;
+
        if (unlikely(hdrlen != (ssize_t) len))
                return -EINVAL;
 
@@ -41,12 +54,25 @@ static ssize_t pcap_rw_read(int fd, pcap_pkthdr_t *phdr, 
enum pcap_type type,
                            uint8_t *packet, size_t len)
 {
        ssize_t ret, hdrsize = pcap_get_hdr_length(phdr, type), hdrlen = 0;
+       ssize_t ll_len = 0;
 
-       ret = read_or_die(fd, &phdr->raw, hdrsize);
+       ret = read_or_die(fd, &phdr->h.raw, hdrsize);
        if (unlikely(ret != hdrsize))
                return -EIO;
 
+       if (pcap_pkthdr_has_ll(phdr)) {
+               ll_len = sizeof(struct pcap_pkthdr_ll);
+               int ret_ll = read(fd, &phdr->ll_hdr, ll_len);
+
+               if (unlikely(ret_ll != ll_len))
+                       return -EIO;
+       }
+
        hdrlen = pcap_get_length(phdr, type);
+       hdrlen  -= ll_len;
+       len     -= ll_len;
+       hdrsize += ll_len;
+
        if (unlikely(hdrlen == 0 || hdrlen > (ssize_t) len))
                 return -EINVAL;
 
diff --git a/pcap_sg.c b/pcap_sg.c
index 80c2c5d..5c9281e 100644
--- a/pcap_sg.c
+++ b/pcap_sg.c
@@ -33,61 +33,40 @@ 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);
-       ret = (iov[iov_slot].iov_len += len);
+       if (pcap_pkthdr_has_ll(phdr)) {
+               ssize_t ll_hdrlen = sizeof(struct pcap_pkthdr_ll);
 
-       iov_slot++;
-       return ret;
-}
-
-static ssize_t __pcap_sg_inter_iov_hdr_read(int fd, pcap_pkthdr_t *phdr,
-                                           size_t hdrsize)
-{
-       int ret;
-       size_t offset = 0;
-       ssize_t remainder;
-
-       offset = iov[iov_slot].iov_len - iov_off_rd;
-       remainder = hdrsize - offset;
-       if (remainder < 0)
-               remainder = 0;
-
-       bug_on(offset + remainder != hdrsize);
-
-       fmemcpy(&phdr->raw, iov[iov_slot].iov_base + iov_off_rd, offset);
-       iov_off_rd = 0;
-       iov_slot++;
+               fmemcpy(iov[iov_slot].iov_base + iov[iov_slot].iov_len,
+                               &phdr->ll_hdr, ll_hdrlen);
 
-       if (iov_slot == array_size(iov)) {
-               iov_slot = 0;
-               ret = readv(fd, iov, array_size(iov));
-               if (unlikely(ret <= 0))
-                       return -EIO;
+               ret = (iov[iov_slot].iov_len += ll_hdrlen);
+               len -= ll_hdrlen;
        }
 
-       fmemcpy(&phdr->raw + offset, iov[iov_slot].iov_base + iov_off_rd, 
remainder);
-       iov_off_rd += remainder;
+       fmemcpy(iov[iov_slot].iov_base + iov[iov_slot].iov_len, packet, len);
+       ret = (iov[iov_slot].iov_len += len);
 
-       return hdrsize;
+       iov_slot++;
+       return ret;
 }
 
-static ssize_t __pcap_sg_inter_iov_data_read(int fd, uint8_t *packet, size_t 
hdrlen)
+static ssize_t __pcap_sg_inter_iov_read(int fd, uint8_t *buf, size_t len)
 {
        int ret;
        size_t offset = 0;
        ssize_t remainder;
 
        offset = iov[iov_slot].iov_len - iov_off_rd;
-       remainder = hdrlen - offset;
+       remainder = len - offset;
        if (remainder < 0)
                remainder = 0;
 
-       bug_on(offset + remainder != hdrlen);
+       bug_on(offset + remainder != len);
 
-       fmemcpy(packet, iov[iov_slot].iov_base + iov_off_rd, offset);
+       fmemcpy(buf, iov[iov_slot].iov_base + iov_off_rd, offset);
        iov_off_rd = 0;
        iov_slot++;
 
@@ -98,10 +77,10 @@ static ssize_t __pcap_sg_inter_iov_data_read(int fd, 
uint8_t *packet, size_t hdr
                        return -EIO;
        }
 
-       fmemcpy(packet + offset, iov[iov_slot].iov_base + iov_off_rd, 
remainder);
+       fmemcpy(buf + offset, iov[iov_slot].iov_base + iov_off_rd, remainder);
        iov_off_rd += remainder;
 
-       return hdrlen;
+       return len;
 }
 
 static ssize_t pcap_sg_read(int fd, pcap_pkthdr_t *phdr, enum pcap_type type,
@@ -109,17 +88,39 @@ static ssize_t pcap_sg_read(int fd, pcap_pkthdr_t *phdr, 
enum pcap_type type,
 {
        ssize_t ret = 0;
        size_t hdrsize = pcap_get_hdr_length(phdr, type), hdrlen;
+       ssize_t ll_len = 0;
 
        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);
+               ret = __pcap_sg_inter_iov_read(fd, (uint8_t *)phdr, hdrsize);
                if (unlikely(ret < 0))
                        return ret;
        }
 
+       if (pcap_pkthdr_has_ll(phdr)) {
+               ll_len = sizeof(phdr->ll_hdr);
+
+               if (likely(iov[iov_slot].iov_len - iov_off_rd >= ll_len)) {
+                       fmemcpy((uint8_t *)&phdr->ll_hdr, 
iov[iov_slot].iov_base +
+                                       iov_off_rd, ll_len);
+
+                       iov_off_rd += ll_len;
+               } else {
+                       ret = __pcap_sg_inter_iov_read(fd, (uint8_t *)phdr,
+                                       ll_len);
+
+                       if (unlikely(ret < 0))
+                               return ret;
+               }
+       }
+
        hdrlen = pcap_get_length(phdr, type);
+       len     -= ll_len;
+       hdrlen  -= ll_len;
+       hdrsize += ll_len;
+
        if (unlikely(hdrlen == 0 || hdrlen > len))
                return -EINVAL;
 
@@ -127,7 +128,7 @@ static ssize_t pcap_sg_read(int fd, pcap_pkthdr_t *phdr, 
enum pcap_type type,
                fmemcpy(packet, iov[iov_slot].iov_base + iov_off_rd, hdrlen);
                iov_off_rd += hdrlen;
        } else {
-               ret = __pcap_sg_inter_iov_data_read(fd, packet, hdrlen);
+               ret = __pcap_sg_inter_iov_read(fd, (uint8_t *)packet, hdrlen);
                if (unlikely(ret < 0))
                        return ret;
        }
-- 
2.3.1

-- 
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.

Reply via email to