tcpdump mailing list archives

Re: Patch to return a pcap_pkthdr (pcap_ng_pkthdr) to caller suited for writing pcap-ng files


From: Anders Broman <anders.broman () ericsson com>
Date: Thu, 21 Nov 2013 11:48:50 +0000

Hi,
Resending with the patch inline as I got indication the attachment got lost...

diff --git a/pcap-int.h b/pcap-int.h
index 08bbcc3..d7f3929 100644
--- a/pcap-int.h
+++ b/pcap-int.h
@@ -97,7 +97,7 @@ struct pcap_opt {
 typedef int    (*activate_op_t)(pcap_t *);
typedef int    (*can_set_rfmon_op_t)(pcap_t *);
-typedef int    (*read_op_t)(pcap_t *, int cnt, pcap_handler, u_char *);
+typedef int    (*read_op_t)(pcap_t *, int cnt, pcap_handler, pcap_ng_handler, const u_int, u_char *);
typedef int    (*inject_op_t)(pcap_t *, const void *, size_t);
typedef int    (*setfilter_op_t)(pcap_t *, struct bpf_program *);
typedef int    (*setdirection_op_t)(pcap_t *, pcap_direction_t);
@@ -213,6 +213,8 @@ struct pcap {
     * Routine to use as callback for pcap_next()/pcap_next_ex().
     */
    pcap_handler oneshot_callback;
+    pcap_ng_handler oneshot_callback_ng;
+        u_int if_id;
 #ifdef WIN32
    /*
diff --git a/pcap-linux.c b/pcap-linux.c
index 20767f2..f2e6eca 100644
--- a/pcap-linux.c
+++ b/pcap-linux.c
@@ -329,8 +329,8 @@ static int activate_old(pcap_t *);
static int activate_new(pcap_t *);
static int activate_mmap(pcap_t *, int *);
static int pcap_can_set_rfmon_linux(pcap_t *);
-static int pcap_read_linux(pcap_t *, int, pcap_handler, u_char *);
-static int pcap_read_packet(pcap_t *, pcap_handler, u_char *);
+static int pcap_read_linux(pcap_t *, int, pcap_handler, pcap_ng_handler, u_int if_id, u_char *);
+static int pcap_read_packet(pcap_t *, pcap_handler, pcap_ng_handler, u_int if_id, u_char *);
static int pcap_inject_linux(pcap_t *, const void *, size_t);
static int pcap_stats_linux(pcap_t *, struct pcap_stat *);
static int pcap_setfilter_linux(pcap_t *, struct bpf_program *);
@@ -356,12 +356,12 @@ static void destroy_ring(pcap_t *handle);
static int create_ring(pcap_t *handle, int *status);
static int prepare_tpacket_socket(pcap_t *handle);
static void pcap_cleanup_linux_mmap(pcap_t *);
-static int pcap_read_linux_mmap_v1(pcap_t *, int, pcap_handler , u_char *);
+static int pcap_read_linux_mmap_v1(pcap_t *, int, pcap_handler, pcap_ng_handler , u_int, u_char *);
#ifdef HAVE_TPACKET2
-static int pcap_read_linux_mmap_v2(pcap_t *, int, pcap_handler , u_char *);
+static int pcap_read_linux_mmap_v2(pcap_t *, int, pcap_handler, pcap_ng_handler , u_int, u_char *);
#endif
#ifdef HAVE_TPACKET3
-static int pcap_read_linux_mmap_v3(pcap_t *, int, pcap_handler , u_char *);
+static int pcap_read_linux_mmap_v3(pcap_t *, int, pcap_handler, pcap_ng_handler , u_int, u_char *);
#endif
static int pcap_setfilter_linux_mmap(pcap_t *, struct bpf_program *);
static int pcap_setnonblock_mmap(pcap_t *p, int nonblock, char *errbuf);
@@ -1394,13 +1394,13 @@ fail:
  *  error occured.
  */
static int
-pcap_read_linux(pcap_t *handle, int max_packets, pcap_handler callback, u_char *user)
+pcap_read_linux(pcap_t *handle, int max_packets, pcap_handler callback, pcap_ng_handler callback_ng, u_int 
if_id,u_char *user)
{
    /*
     * Currently, on Linux only one packet is delivered per read,
     * so we don't loop.
     */
-    return pcap_read_packet(handle, callback, user);
+    return pcap_read_packet(handle, callback, callback_ng, if_id, user);
}
 static int
@@ -1452,7 +1452,7 @@ linux_check_direction(const pcap_t *handle, const struct sockaddr_ll *sll)
  *  error occured.
  */
static int
-pcap_read_packet(pcap_t *handle, pcap_handler callback, u_char *userdata)
+pcap_read_packet(pcap_t *handle, pcap_handler callback, pcap_ng_handler callback_ng, u_int if_id, u_char *userdata)
{
    struct pcap_linux    *handlep = handle->priv;
    u_char               *bp;
@@ -1476,6 +1476,9 @@ pcap_read_packet(pcap_t *handle, pcap_handler callback, u_char *userdata)
#endif /* defined(HAVE_PACKET_AUXDATA) && defined(HAVE_LINUX_TPACKET_AUXDATA_TP_VLAN_TCI) */
    int             packet_len, caplen;
    struct pcap_pkthdr   pcap_header;
+    struct pcap_ng_pkthdr pcap_ng_header;
+        u_int64_t               timestamp;
+        u_int                   ts_mul    = handle->opt.tstamp_precision == PCAP_TSTAMP_PRECISION_NANO ? 1000000000 : 
1000000;
 #ifdef HAVE_PF_PACKET_SOCKETS
    /*
@@ -1734,6 +1737,23 @@ pcap_read_packet(pcap_t *handle, pcap_handler callback, u_char *userdata)
     pcap_header.caplen   = caplen;
    pcap_header.len      = packet_len;
+
+    /* Build a pcap-ng enhanced packet block header */
+        timestamp = (u_int64_t)pcap_header.ts.tv_sec * ts_mul + (u_int64_t)pcap_header.ts.tv_usec;
+        pcap_ng_header.block_type = PCAP_NG_ENHANCED_PACKET_BLOCK_TYPE;
+        pcap_ng_header.block_total_length   = (u_int32_t)(sizeof(struct pcap_ng_pkthdr) + caplen);
+        pcap_ng_header.interface_id         = if_id;
+        pcap_ng_header.timestamp_high       = (u_int32_t)((timestamp>>32) & 0xffffffff);
+        pcap_ng_header.timestamp_low        = (u_int32_t)(timestamp & 0xffffffff);
+        pcap_ng_header.captured_len         = caplen;
+        pcap_ng_header.packet_len           = packet_len;
+    /* XXX if the buffer is aligned to 32 bits we should have a flag indicating that and
+    * pad the buffer with 0 in order to be able to write an entire packet data block without
+    * having to pad it in the write sequence.
+    *
+    * XXX should we fill a "options buffer" and return that too? epb_flags and possibly epb_dropcount
+    * could be included.
+    */
     /*
     * Count the packet.
@@ -1782,9 +1802,16 @@ pcap_read_packet(pcap_t *handle, pcap_handler callback, u_char *userdata)
    handlep->packets_read++;
     /* Call the user supplied callback function */
-    callback(userdata, &pcap_header, bp);
+        if(callback){
+        callback(userdata, &pcap_header, bp);
+            return 1;
+        }
+        if(callback_ng){
+        callback_ng(userdata, &pcap_ng_header, bp);
+            return 1;
+        }
-    return 1;
+    return PCAP_ERROR;
}
 static int
@@ -4148,6 +4175,8 @@ static int pcap_wait_for_frames_mmap(pcap_t *handle)
static int pcap_handle_packet_mmap(
          pcap_t *handle,
          pcap_handler callback,
+          pcap_ng_handler callback_ng,
+          const unsigned int if_id,
          u_char *user,
          unsigned char *frame,
          unsigned int tp_len,
@@ -4163,6 +4192,9 @@ static int pcap_handle_packet_mmap(
    int run_bpf;
    struct sockaddr_ll *sll;
    struct pcap_pkthdr pcaphdr;
+    struct pcap_ng_pkthdr pcap_ng_header;
+    u_int64_t timestamp;
+        u_int ts_mul    = handle->opt.tstamp_precision == PCAP_TSTAMP_PRECISION_NANO ? 1000000000 : 1000000;
     /* perform sanity check on internal offset. */
    if (tp_mac + tp_snaplen > handle->bufsize) {
@@ -4200,6 +4232,23 @@ static int pcap_handle_packet_mmap(
    pcaphdr.caplen = tp_snaplen;
    pcaphdr.len = tp_len;
+    /* Build a pcap-ng enhanced packet block header */
+        timestamp = (u_int64_t)pcaphdr.ts.tv_sec * ts_mul + (u_int64_t)pcaphdr.ts.tv_usec;
+        pcap_ng_header.block_type = PCAP_NG_ENHANCED_PACKET_BLOCK_TYPE;
+        pcap_ng_header.block_total_length   = (u_int32_t)(sizeof(struct pcap_ng_pkthdr) + tp_snaplen);
+        pcap_ng_header.interface_id         = if_id;
+        pcap_ng_header.timestamp_high       = (u_int32_t)((timestamp>>32) & 0xffffffff);
+        pcap_ng_header.timestamp_low        = (u_int32_t)(timestamp & 0xffffffff);
+        pcap_ng_header.captured_len         = tp_snaplen;
+        pcap_ng_header.packet_len           = tp_len;
+    /* XXX if the buffer is aligned to 32 bits we should have a flag indicating that and
+    * pad the buffer with 0 in order to be able to write an entire packet data block without
+    * having to pad it in the write sequence.
+    *
+    * XXX should we fill a "options buffer" and return that too? epb_flags and possibly epb_dropcount
+    * could be included.
+    */
+
    /* if required build in place the sll header*/
    if (handlep->cooked) {
          struct sll_header *hdrp;
@@ -4276,14 +4325,21 @@ static int pcap_handle_packet_mmap(
          pcaphdr.caplen = handle->snapshot;
     /* pass the packet to the user */
-    callback(user, &pcaphdr, bp);
+    if(callback){
+          callback(user, &pcaphdr, bp);
+          return 1;
+    }
+    if(callback_ng){
+          callbac_ngk(user, &pcap_ng_header, bp);
+          return 1;
+    }
-    return 1;
+    return -1;
}
 static int
pcap_read_linux_mmap_v1(pcap_t *handle, int max_packets, pcap_handler callback,
-          u_char *user)
+          pcap_ng_handler callback_ng, const u_int if_id, u_char *user)
{
    struct pcap_linux *handlep = handle->priv;
    int pkts = 0;
@@ -4307,6 +4363,8 @@ pcap_read_linux_mmap_v1(pcap_t *handle, int max_packets, pcap_handler callback,
          ret = pcap_handle_packet_mmap(
                    handle,
                    callback,
+                    callback_ng,
+                    if_id,
                     user,
                    h.raw,
                    h.h1->tp_len,
@@ -4341,7 +4399,7 @@ pcap_read_linux_mmap_v1(pcap_t *handle, int max_packets, pcap_handler callback,
#ifdef HAVE_TPACKET2
static int
pcap_read_linux_mmap_v2(pcap_t *handle, int max_packets, pcap_handler callback,
-          u_char *user)
+          pcap_ng_handler callback_ng, const u_int if_id, u_char *user)
{
    struct pcap_linux *handlep = handle->priv;
    int pkts = 0;
@@ -4365,6 +4423,8 @@ pcap_read_linux_mmap_v2(pcap_t *handle, int max_packets, pcap_handler callback,
          ret = pcap_handle_packet_mmap(
                    handle,
                    callback,
+                    callback_ng,
+                    if_id,
                    user,
                    h.raw,
                    h.h2->tp_len,
@@ -4404,7 +4464,7 @@ pcap_read_linux_mmap_v2(pcap_t *handle, int max_packets, pcap_handler callback,
#ifdef HAVE_TPACKET3
static int
pcap_read_linux_mmap_v3(pcap_t *handle, int max_packets, pcap_handler callback,
-          u_char *user)
+          pcap_ng_handler callback_ng, const u_int if_id, u_char *user)
{
    struct pcap_linux *handlep = handle->priv;
    union thdr h;
@@ -4444,6 +4504,8 @@ pcap_read_linux_mmap_v3(pcap_t *handle, int max_packets, pcap_handler callback,
               ret = pcap_handle_packet_mmap(
                          handle,
                          callback,
+                          callback_ng,
+                          if_id,
                          user,
                          handlep->current_packet,
                          tp3_hdr->tp_len,
diff --git a/pcap.c b/pcap.c
index 626938c..88885b1 100644
--- a/pcap.c
+++ b/pcap.c
@@ -268,7 +268,7 @@ pcap_next_ex(pcap_t *p, struct pcap_pkthdr **pkt_header,
     * The first one ('0') conflicts with the return code of 0 from
     * pcap_offline_read() meaning "end of file".
    */
-    return (p->read_op(p, 1, p->oneshot_callback, (u_char *)&s));
+    return (p->read_op(p, 1, p->oneshot_callback, p->oneshot_callback_ng, p->if_id, (u_char *)&s));
}
 #if defined(DAG_ONLY)
@@ -823,7 +823,7 @@ pcap_open_offline_common(char *ebuf, size_t size)
int
pcap_dispatch(pcap_t *p, int cnt, pcap_handler callback, u_char *user)
{
-    return (p->read_op(p, cnt, callback, user));
+    return (p->read_op(p, cnt, callback, NULL, 0, user));
}
 /*
@@ -833,7 +833,7 @@ int
pcap_read(pcap_t *p, int cnt, pcap_handler callback, u_char *user)
{
-    return (p->read_op(p, cnt, callback, user));
+    return (p->read_op(p, cnt, callback, NULL, 0, user));
}
 int
@@ -853,7 +853,7 @@ pcap_loop(pcap_t *p, int cnt, pcap_handler callback, u_char *user)
                * (or an error occurs)
                */
               do {
-                    n = p->read_op(p, cnt, callback, user);
+                    n = p->read_op(p, cnt, callback, NULL, 0, user);
               } while (n == 0);
          }
          if (n <= 0)
diff --git a/pcap/pcap.h b/pcap/pcap.h
index f2dd2d6..9223b6d 100644
--- a/pcap/pcap.h
+++ b/pcap/pcap.h
@@ -165,6 +165,22 @@ struct pcap_pkthdr {
    bpf_u_int32 len;     /* length this packet (off wire) */
};
+/* Enhanced Packet Block without actual packet, options, and trailing
+   Block Total Length */
+struct pcap_ng_pkthdr {
+        bpf_u_int32 block_type;
+        bpf_u_int32 block_total_length;
+        bpf_u_int32 interface_id;
+        bpf_u_int32 timestamp_high;     /* Timestamp (High) and Timestamp (Low): high and low 32-bits of a 64-bit 
quantity representing the timestamp.
+                                         * The timestamp is a single 64-bit unsigned integer representing the number 
of units since 1/1/1970.
+                                         * The way to interpret this field is specified by the tstamp_precision option
+                          */
+        bpf_u_int32 timestamp_low;
+        bpf_u_int32 captured_len;
+        bpf_u_int32 packet_len;
+};
+#define PCAP_NG_ENHANCED_PACKET_BLOCK_TYPE 0x00000006
+
/*
  * As returned by the pcap_stats()
  */
@@ -237,6 +253,9 @@ struct pcap_addr {
typedef void (*pcap_handler)(u_char *, const struct pcap_pkthdr *,
                    const u_char *);
+typedef void (*pcap_ng_handler)(u_char *, const struct pcap_ng_pkthdr *,
+                    const u_char *);
+
/*
  * Error codes for the pcap API.
  * These will all be negative, so you can check for the success or



From: Anders Broman
Sent: den 20 november 2013 18:05
To: tcpdump-workers () lists tcpdump org
Subject: Patch to return a pcap_pkthdr (pcap_ng_pkthdr) to caller suited for writing pcap-ng files

Hi,
Included a patch (I'm not used to git) to return a packet header suited for writing pacp-ng files only 
pcap_dispatch_ng() has been added so far. The patch is only compile tested.
But I'd be grateful for some feedback if this approach is acceptable and if it's worth my while to continue work on it 
or any other suggestion on how to proceed.
If someone wants to improve on the patch even better.

Best regards
Anders Broman
_______________________________________________
tcpdump-workers mailing list
tcpdump-workers () lists tcpdump org
https://lists.sandelman.ca/mailman/listinfo/tcpdump-workers

Current thread: