On 06/18/2015 11:49 AM, Daniel Borkmann wrote:
On 06/18/2015 11:42 AM, Vadim Kochan wrote:
On Thu, Jun 18, 2015 at 10:45:29AM +0200, Daniel Borkmann wrote:
I've started splitting this into smaller digestible chunks,
couple of more evenings and it should be done from my side.
Thanks for your patience.

But implementation now is OK in the last original patch series v2 ?

The only missing piece from your first patch I need to go through
is the pcap i/o parts. I wanted to check if two new dummy types
are possible (where we'd have transparent mapping - so it would be
semantically the same as this patch), whether they result in a
smaller code diff and would have lesser impact on the fast path.
If that's the case, I'd go for that, if not I will take the current
remaining piece. Will let you know.

Okay, here it goes. I tested this with capturing from netsniff-ng,
reading via Wireshark and capturing from Wireshark and reading via
netsniff-ng.

Seems fine, please double check it.

All in all this should have less overhead and result in smaller
code diff. Apart from that, the pcap_io.h might need some cleanups
anyway.

[PATCH] pcap_io: add cooked mode support

Originally submitted by Vadim in a different form, he wrote:

  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 headers' 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 <vadi...@gmail.com>
Signed-off-by: Daniel Borkmann <dan...@iogearbox.net>
---
 netsniff-ng.c |  17 ++++++
 pcap_io.h     | 192 +++++++++++++++++++++++++++++++++++++++++++++++-----------
 2 files changed, 172 insertions(+), 37 deletions(-)

diff --git a/netsniff-ng.c b/netsniff-ng.c
index 0a9c620..e593b9d 100644
--- a/netsniff-ng.c
+++ b/netsniff-ng.c
@@ -1519,6 +1519,23 @@ int main(int argc, char **argv)

                if (!ctx.link_type)
                        ctx.link_type = pcap_dev_to_linktype(ctx.device_in);
+               if (link_has_sll_hdr(ctx.link_type)) {
+                       switch (ctx.magic) {
+                       case ORIGINAL_TCPDUMP_MAGIC:
+                               ctx.magic = ORIGINAL_TCPDUMP_MAGIC_LL;
+                               break;
+                       case NSEC_TCPDUMP_MAGIC:
+                               ctx.magic = NSEC_TCPDUMP_MAGIC_LL;
+                               break;
+                       case ___constant_swab32(ORIGINAL_TCPDUMP_MAGIC):
+                               ctx.magic = 
___constant_swab32(ORIGINAL_TCPDUMP_MAGIC_LL);
+                               break;
+                       case ___constant_swab32(NSEC_TCPDUMP_MAGIC):
+                               ctx.magic = 
___constant_swab32(NSEC_TCPDUMP_MAGIC_LL);
+                               break;
+                       }
+               }
+

                if (!ctx.device_out) {
                        ctx.dump = 0;
diff --git a/pcap_io.h b/pcap_io.h
index 497e453..5beccf9 100644
--- a/pcap_io.h
+++ b/pcap_io.h
@@ -27,6 +27,8 @@
 #define TCPDUMP_MAGIC                          0xa1b2c3d4
 #define ORIGINAL_TCPDUMP_MAGIC                 TCPDUMP_MAGIC
 #define NSEC_TCPDUMP_MAGIC                     0xa1b23c4d
+#define ORIGINAL_TCPDUMP_MAGIC_LL              0xb1b2c3d4      /* Internal 
dummy just for mapping */
+#define NSEC_TCPDUMP_MAGIC_LL                  0xb1b23c4d      /* Internal 
dummy just for mapping */
 #define KUZNETZOV_TCPDUMP_MAGIC                        0xa1b2cd34
 #define BORKMANN_TCPDUMP_MAGIC                 0xa1e2cb12

@@ -78,6 +80,20 @@ struct pcap_pkthdr_ns {
        uint32_t len;
 };

+struct pcap_pkthdr_ll {
+       struct pcap_timeval ts;
+       uint32_t caplen;
+       uint32_t len;
+       struct pcap_ll ll;
+};
+
+struct pcap_pkthdr_ns_ll {
+       struct pcap_timeval_ns ts;
+       uint32_t caplen;
+       uint32_t len;
+       struct pcap_ll ll;
+};
+
 struct pcap_pkthdr_kuz {
        struct pcap_timeval ts;
        uint32_t caplen;
@@ -99,21 +115,27 @@ struct pcap_pkthdr_bkm {
 };

 typedef union {
-       struct pcap_pkthdr      ppo;
-       struct pcap_pkthdr_ns   ppn;
-       struct pcap_pkthdr_kuz  ppk;
-       struct pcap_pkthdr_bkm  ppb;
-       uint8_t                 raw;
+       struct pcap_pkthdr              ppo;
+       struct pcap_pkthdr_ns           ppn;
+       struct pcap_pkthdr_ll           ppo_ll;
+       struct pcap_pkthdr_ns_ll        ppn_ll;
+       struct pcap_pkthdr_kuz          ppk;
+       struct pcap_pkthdr_bkm          ppb;
+       uint8_t                         raw;
 } pcap_pkthdr_t;

 enum pcap_type {
        DEFAULT           =     ORIGINAL_TCPDUMP_MAGIC,
        NSEC              =     NSEC_TCPDUMP_MAGIC,
+       DEFAULT_LL        =     ORIGINAL_TCPDUMP_MAGIC_LL,
+       NSEC_LL           =     NSEC_TCPDUMP_MAGIC_LL,
        KUZNETZOV         =     KUZNETZOV_TCPDUMP_MAGIC,
        BORKMANN          =     BORKMANN_TCPDUMP_MAGIC,

        DEFAULT_SWAPPED   =     ___constant_swab32(ORIGINAL_TCPDUMP_MAGIC),
        NSEC_SWAPPED      =     ___constant_swab32(NSEC_TCPDUMP_MAGIC),
+       DEFAULT_LL_SWAPPED =    ___constant_swab32(ORIGINAL_TCPDUMP_MAGIC_LL),
+       NSEC_LL_SWAPPED   =     ___constant_swab32(NSEC_TCPDUMP_MAGIC_LL),
        KUZNETZOV_SWAPPED =     ___constant_swab32(KUZNETZOV_TCPDUMP_MAGIC),
        BORKMANN_SWAPPED  =     ___constant_swab32(BORKMANN_TCPDUMP_MAGIC),
 };
@@ -244,6 +266,19 @@ static inline int pcap_devtype_to_linktype(int dev_type)
        }
 }

+static inline bool link_has_sll_hdr(uint32_t link_type)
+{
+       switch (link_type) {
+       case LINKTYPE_NETLINK:
+       case LINKTYPE_LINUX_SLL:
+       case ___constant_swab32(LINKTYPE_NETLINK):
+       case ___constant_swab32(LINKTYPE_LINUX_SLL):
+               return true;
+       default:
+               return false;
+       }
+}
+
 static inline int pcap_dev_to_linktype(const char *ifname)
 {
        return pcap_devtype_to_linktype(device_type(ifname));
@@ -287,20 +322,24 @@ static inline bool pcap_magic_is_swapped(uint32_t magic)
 static inline u32 pcap_get_length(pcap_pkthdr_t *phdr, enum pcap_type type)
 {
        switch (type) {
-#define CASE_RET_CAPLEN(what, member, swap) \
+#define CASE_RET_CAPLEN(what, member, swap, extra) \
        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);
+                       phdr->member.caplen) - extra
+
+       CASE_RET_CAPLEN(DEFAULT, ppo, 0, 0);
+       CASE_RET_CAPLEN(NSEC, ppn, 0, 0);
+       CASE_RET_CAPLEN(DEFAULT_LL, ppo_ll, 0, sizeof(struct pcap_ll));
+       CASE_RET_CAPLEN(NSEC_LL, ppn_ll, 0, sizeof(struct pcap_ll));
+       CASE_RET_CAPLEN(KUZNETZOV, ppk, 0, 0);
+       CASE_RET_CAPLEN(BORKMANN, ppb, 0, 0);
+
+       CASE_RET_CAPLEN(DEFAULT_SWAPPED, ppo, 1, 0);
+       CASE_RET_CAPLEN(NSEC_SWAPPED, ppn, 1, 0);
+       CASE_RET_CAPLEN(DEFAULT_LL_SWAPPED, ppo_ll, 1, sizeof(struct pcap_ll));
+       CASE_RET_CAPLEN(NSEC_LL_SWAPPED, ppn_ll, 1, sizeof(struct pcap_ll));
+       CASE_RET_CAPLEN(KUZNETZOV_SWAPPED, ppk, 1, 0);
+       CASE_RET_CAPLEN(BORKMANN_SWAPPED, ppb, 1, 0);

        default:
                bug();
@@ -317,11 +356,15 @@ static inline void pcap_set_length(pcap_pkthdr_t *phdr, 
enum pcap_type type, u32

        CASE_SET_CAPLEN(DEFAULT, ppo, 0);
        CASE_SET_CAPLEN(NSEC, ppn, 0);
+       CASE_SET_CAPLEN(DEFAULT_LL, ppo_ll, 0);
+       CASE_SET_CAPLEN(NSEC_LL, ppn_ll, 0);
        CASE_SET_CAPLEN(KUZNETZOV, ppk, 0);
        CASE_SET_CAPLEN(BORKMANN, ppb, 0);

        CASE_SET_CAPLEN(DEFAULT_SWAPPED, ppo, 1);
        CASE_SET_CAPLEN(NSEC_SWAPPED, ppn, 1);
+       CASE_SET_CAPLEN(DEFAULT_LL_SWAPPED, ppo_ll, 1);
+       CASE_SET_CAPLEN(NSEC_LL_SWAPPED, ppn_ll, 1);
        CASE_SET_CAPLEN(KUZNETZOV_SWAPPED, ppk, 1);
        CASE_SET_CAPLEN(BORKMANN_SWAPPED, ppb, 1);

@@ -339,11 +382,15 @@ static inline u32 pcap_get_hdr_length(pcap_pkthdr_t 
*phdr, enum pcap_type type)

        CASE_RET_HDRLEN(DEFAULT, ppo);
        CASE_RET_HDRLEN(NSEC, ppn);
+       CASE_RET_HDRLEN(DEFAULT_LL, ppo_ll);
+       CASE_RET_HDRLEN(NSEC_LL, ppn_ll);
        CASE_RET_HDRLEN(KUZNETZOV, ppk);
        CASE_RET_HDRLEN(BORKMANN, ppb);

        CASE_RET_HDRLEN(DEFAULT_SWAPPED, ppo);
        CASE_RET_HDRLEN(NSEC_SWAPPED, ppn);
+       CASE_RET_HDRLEN(DEFAULT_LL_SWAPPED, ppo_ll);
+       CASE_RET_HDRLEN(NSEC_LL_SWAPPED, ppn_ll);
        CASE_RET_HDRLEN(KUZNETZOV_SWAPPED, ppk);
        CASE_RET_HDRLEN(BORKMANN_SWAPPED, ppb);

@@ -354,25 +401,7 @@ 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))
-
-       CASE_RET_TOTLEN(DEFAULT, ppo, 0);
-       CASE_RET_TOTLEN(NSEC, ppn, 0);
-       CASE_RET_TOTLEN(KUZNETZOV, ppk, 0);
-       CASE_RET_TOTLEN(BORKMANN, ppb, 0);
-
-       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);
-
-       default:
-               bug();
-       }
+       return pcap_get_hdr_length(phdr, type) + pcap_get_length(phdr, type);
 }

 static inline void
@@ -383,31 +412,55 @@ __tpacket_hdr_to_pcap_pkthdr(uint32_t sec, uint32_t nsec, 
uint32_t snaplen,
 {
        switch (type) {
        case DEFAULT:
+       case DEFAULT_LL:
                phdr->ppo.ts.tv_sec = sec;
                phdr->ppo.ts.tv_usec = nsec / 1000;
                phdr->ppo.caplen = snaplen;
                phdr->ppo.len = len;
+               if (type == DEFAULT_LL) {
+                       phdr->ppo.caplen += sizeof(struct pcap_ll);
+                       phdr->ppo.len += sizeof(struct pcap_ll);
+                       sockaddr_to_ll(sll, &phdr->ppo_ll.ll);
+               }
                break;

        case DEFAULT_SWAPPED:
+       case DEFAULT_LL_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 (type == DEFAULT_LL_SWAPPED) {
+                       phdr->ppo.caplen = ___constant_swab32(snaplen + 
sizeof(struct pcap_ll));
+                       phdr->ppo.len = ___constant_swab32(len + sizeof(struct 
pcap_ll));
+                       sockaddr_to_ll(sll, &phdr->ppo_ll.ll);
+               }
                break;

        case NSEC:
+       case NSEC_LL:
                phdr->ppn.ts.tv_sec = sec;
                phdr->ppn.ts.tv_nsec = nsec;
                phdr->ppn.caplen = snaplen;
                phdr->ppn.len = len;
+               if (type == NSEC_LL) {
+                       phdr->ppn.caplen += sizeof(struct pcap_ll);
+                       phdr->ppn.len += sizeof(struct pcap_ll);
+                       sockaddr_to_ll(sll, &phdr->ppn_ll.ll);
+               }
                break;

        case NSEC_SWAPPED:
+       case NSEC_LL_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 (type == NSEC_LL_SWAPPED) {
+                       phdr->ppn.caplen = ___constant_swab32(snaplen + 
sizeof(struct pcap_ll));
+                       phdr->ppn.len = ___constant_swab32(len + sizeof(struct 
pcap_ll));
+                       sockaddr_to_ll(sll, &phdr->ppn_ll.ll);
+               }
                break;

        case KUZNETZOV:
@@ -492,31 +545,59 @@ static inline void 
pcap_pkthdr_to_tpacket_hdr(pcap_pkthdr_t *phdr,
 {
        switch (type) {
        case DEFAULT:
+       case DEFAULT_LL:
                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 (type == DEFAULT_LL) {
+                       thdr->tp_snaplen -= sizeof(struct pcap_ll);
+                       thdr->tp_len -= sizeof(struct pcap_ll);
+                       if (sll)
+                               ll_to_sockaddr(&phdr->ppo_ll.ll, sll);
+               }
                break;

        case DEFAULT_SWAPPED:
+       case DEFAULT_LL_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 (type == DEFAULT_LL_SWAPPED) {
+                       thdr->tp_snaplen -= sizeof(struct pcap_ll);
+                       thdr->tp_len -= sizeof(struct pcap_ll);
+                       if (sll)
+                               ll_to_sockaddr(&phdr->ppo_ll.ll, sll);
+               }
                break;

        case NSEC:
+       case NSEC_LL:
                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 (type == NSEC_LL) {
+                       thdr->tp_snaplen -= sizeof(struct pcap_ll);
+                       thdr->tp_len -= sizeof(struct pcap_ll);
+                       if (sll)
+                               ll_to_sockaddr(&phdr->ppn_ll.ll, sll);
+               }
                break;

        case NSEC_SWAPPED:
+       case NSEC_LL_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 (type == NSEC_LL_SWAPPED) {
+                       thdr->tp_snaplen -= sizeof(struct pcap_ll);
+                       thdr->tp_len -= sizeof(struct pcap_ll);
+                       if (sll)
+                               ll_to_sockaddr(&phdr->ppn_ll.ll, sll);
+               }
                break;

        case KUZNETZOV:
@@ -682,6 +763,24 @@ static inline void pcap_prepare_header(struct pcap_filehdr 
*hdr, uint32_t magic,
 {
        bool swapped = pcap_magic_is_swapped(magic);

+       /* As *_LL types are just internal, we need to remap pcap
+        * magics to actually valid types.
+        */
+       switch (magic) {
+       case ORIGINAL_TCPDUMP_MAGIC_LL:
+               magic = ORIGINAL_TCPDUMP_MAGIC;
+               break;
+       case NSEC_TCPDUMP_MAGIC_LL:
+               magic = NSEC_TCPDUMP_MAGIC;
+               break;
+       case ___constant_swab32(ORIGINAL_TCPDUMP_MAGIC_LL):
+               magic = ___constant_swab32(ORIGINAL_TCPDUMP_MAGIC);
+               break;
+       case ___constant_swab32(NSEC_TCPDUMP_MAGIC_LL):
+               magic = ___constant_swab32(NSEC_TCPDUMP_MAGIC);
+               break;
+       }
+
        hdr->magic = magic;
        hdr->version_major = swapped ? ___constant_swab16(PCAP_VERSION_MAJOR) : 
PCAP_VERSION_MAJOR;
        hdr->version_minor = swapped ? ___constant_swab16(PCAP_VERSION_MINOR) : 
PCAP_VERSION_MINOR;
@@ -716,9 +815,10 @@ 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)
+static inline void pcap_validate_header(struct pcap_filehdr *hdr)
 {
        bool good = false;
        uint32_t linktype;
@@ -737,6 +837,24 @@ static inline void pcap_validate_header(const struct 
pcap_filehdr *hdr)
        if (unlikely(hdr->version_minor != PCAP_VERSION_MINOR) &&
                     ___constant_swab16(hdr->version_minor) != 
PCAP_VERSION_MINOR)
                panic("This file has an invalid pcap minor version (must be 
%d)\n", PCAP_VERSION_MINOR);
+
+       /* Remap to internal *_LL types in case of LINKTYPE_LINUX_SLL. */
+       if (linktype == LINKTYPE_LINUX_SLL) {
+               switch (hdr->magic) {
+               case ORIGINAL_TCPDUMP_MAGIC:
+                       hdr->magic = ORIGINAL_TCPDUMP_MAGIC_LL;
+                       break;
+               case NSEC_TCPDUMP_MAGIC:
+                       hdr->magic = NSEC_TCPDUMP_MAGIC_LL;
+                       break;
+               case ___constant_swab32(ORIGINAL_TCPDUMP_MAGIC):
+                       hdr->magic = 
___constant_swab32(ORIGINAL_TCPDUMP_MAGIC_LL);
+                       break;
+               case ___constant_swab32(NSEC_TCPDUMP_MAGIC):
+                       hdr->magic = ___constant_swab32(NSEC_TCPDUMP_MAGIC_LL);
+                       break;
+               }
+       }
 }

 static int pcap_generic_pull_fhdr(int fd, uint32_t *magic,
--
1.9.3


--
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 netsniff-ng+unsubscr...@googlegroups.com.
For more options, visit https://groups.google.com/d/optout.

Reply via email to