title: How to convert hex_dump of packets, which were captured in kernel module, to pcap file?
body: <p>I am writing a kernel module on Linux (Xubuntu x64). The version of the kernel is 5.4.0-52-generic. My kernel module is capturing traffic from an interface and printing it in hex:</p>
  <pre><code>Nov 10 14:04:34 ubuntu kernel: [404009.566887] Packet hex dump:
  Nov 10 14:04:34 ubuntu kernel: [404009.566889] 000000   00 00 00 00 00 00 00 00 00 00 00 00 08 00 45 00 
  Nov 10 14:04:34 ubuntu kernel: [404009.566899] 000010   00 54 49 4C 40 00 40 01 A7 EF C0 A8 64 0E C0 A8 
  Nov 10 14:04:34 ubuntu kernel: [404009.566907] 000020   64 0E 08 00 9E FE 00 03 00 08 72 0E AB 5F 00 00 
  Nov 10 14:04:34 ubuntu kernel: [404009.566914] 000030   00 00 7B B5 01 00 00 00 00 00 10 11 12 13 14 15 
  Nov 10 14:04:34 ubuntu kernel: [404009.566922] 000040   16 17 18 19 1A 1B 1C 1D 1E 1F 20 21 22 23 24 25 
  Nov 10 14:04:34 ubuntu kernel: [404009.566929] 000050   26 27 28 29
  </code></pre>
  <p>This output I've got using this command under root: <code>tail -f /var/log/kern.log</code></p>
  <p>The whole problem is that I need to save this output as pcap-file. I know that there is <code>text2pcap</code> but its library (libpcap) is user-mode only so I can't use it in kernel module (or maybe not? Correct me if I'm wrong).</p>
  <p>Is it possible to use text2pcap in kernel module? Otherwise, <strong>How can I save an output as pcap file while being in kernel module?</strong></p>
  <p>Source code:</p>
  <pre class="lang-c prettyprint-override"><code>#include &lt;linux/module.h&gt; // included for all kernel modules
  #include &lt;linux/kernel.h&gt; // included for KERN_INFO
  #include &lt;linux/init.h&gt; // included for __init and __exit macros
  #include &lt;linux/skbuff.h&gt; // included for struct sk_buff
  #include &lt;linux/if_packet.h&gt; // include for packet info
  #include &lt;linux/ip.h&gt; // include for ip_hdr 
  #include &lt;linux/netdevice.h&gt; // include for dev_add/remove_pack
  #include &lt;linux/if_ether.h&gt; // include for ETH_P_ALL
  #include &lt;linux/unistd.h&gt;
  
  MODULE_LICENSE(&quot;GPL&quot;);
  MODULE_AUTHOR(&quot;Tester&quot;);
  MODULE_DESCRIPTION(&quot;Sample linux kernel module program to capture all network packets&quot;);
  
  struct packet_type ji_proto;
  void pkt_hex_dump(struct sk_buff *skb)
  {
      size_t len;
      int rowsize = 16;
      int i, l, linelen, remaining;
      int li = 0;
      uint8_t *data, ch; 
  
      printk(&quot;Packet hex dump:\n&quot;);
      data = (uint8_t *) skb_mac_header(skb);
  
      if (skb_is_nonlinear(skb)) {
          len = skb-&gt;data_len;
      } else {
          len = skb-&gt;len;
      }
  
      remaining = len;
      for (i = 0; i &lt; len; i += rowsize) {
          printk(&quot;%06d\t&quot;, li);
  
          linelen = min(remaining, rowsize);
          remaining -= rowsize;
  
          for (l = 0; l &lt; linelen; l++) {
              ch = data[l];
              printk(KERN_CONT &quot;%02X &quot;, (uint32_t) ch);
          }
  
          data += linelen;
          li += 10; 
  
          printk(KERN_CONT &quot;\n&quot;);
      }
  }
  
  int ji_packet_rcv (struct sk_buff *skb, struct net_device *dev,struct packet_type *pt, struct net_device *orig_dev)
  {
   printk(KERN_INFO &quot;New packet captured.\n&quot;);
  
  /* linux/if_packet.h : Packet types */
   // #define PACKET_HOST 0 /* To us */
   // #define PACKET_BROADCAST 1 /* To all */
   // #define PACKET_MULTICAST 2 /* To group */
   // #define PACKET_OTHERHOST 3 /* To someone else */
   // #define PACKET_OUTGOING 4 /* Outgoing of any type */
   // #define PACKET_LOOPBACK 5 /* MC/BRD frame looped back */
   // #define PACKET_USER 6 /* To user space */
   // #define PACKET_KERNEL 7 /* To kernel space */
   /* Unused, PACKET_FASTROUTE and PACKET_LOOPBACK are invisible to user space */
   // #define PACKET_FASTROUTE 6 /* Fastrouted frame */
  
  switch (skb-&gt;pkt_type)
   {
   case PACKET_HOST:
   printk(KERN_INFO &quot;PACKET to us âˆ’ &quot;);
   break;
   case PACKET_BROADCAST:
   printk(KERN_INFO &quot;PACKET to all âˆ’ &quot;);
   break;
   case PACKET_MULTICAST:
   printk(KERN_INFO &quot;PACKET to group âˆ’ &quot;);
   break;
   case PACKET_OTHERHOST:
   printk(KERN_INFO &quot;PACKET to someone else âˆ’ &quot;);
   break;
   case PACKET_OUTGOING:
   printk(KERN_INFO &quot;PACKET outgoing âˆ’ &quot;);
   break;
   case PACKET_LOOPBACK:
   printk(KERN_INFO &quot;PACKET LOOPBACK âˆ’ &quot;);
   break;
   case PACKET_FASTROUTE:
   printk(KERN_INFO &quot;PACKET FASTROUTE âˆ’ &quot;);
   break;
   }
  //printk(KERN_CONT &quot;Dev: %s ; 0x%.4X ; 0x%.4X \n&quot;, skb-&gt;dev-&gt;name, ntohs(skb-&gt;protocol), ip_hdr(skb)-&gt;protocol);
  struct ethhdr *ether = eth_hdr(skb);
  
  //printk(&quot;Source: %x:%x:%x:%x:%x:%x\n&quot;, ether-&gt;h_source[0], ether-&gt;h_source[1], ether-&gt;h_source[2], ether-&gt;h_source[3], ether-&gt;h_source[4], ether-&gt;h_source[5]);
  
  //printk(&quot;Destination: %x:%x:%x:%x:%x:%x\n&quot;, ether-&gt;h_dest[0], ether-&gt;h_dest[1], ether-&gt;h_dest[2], ether-&gt;h_dest[3], ether-&gt;h_dest[4], ether-&gt;h_dest[5]);
  
  //printk(&quot;Protocol: %d\n&quot;, ether-&gt;h_proto);
  pkt_hex_dump(skb);
  kfree_skb (skb);
  return 0;
  }
  
  static int __init ji_init(void)
  {
   /* See the &lt;linux/if_ether.h&gt;
   When protocol is set to htons(ETH_P_ALL), then all protocols are received.
   All incoming packets of that protocol type will be passed to the packet
   socket before they are passed to the protocols implemented in the kernel. */
   /* Few examples */
   //ETH_P_LOOP 0x0060 /* Ethernet Loopback packet */
   //ETH_P_IP 0x0800 /* Internet Protocol packet */
   //ETH_P_ARP 0x0806 /* Address Resolution packet */
   //ETH_P_LOOPBACK 0x9000 /* Ethernet loopback packet, per IEEE 802.3 */
   //ETH_P_ALL 0x0003 /* Every packet (be careful!!!) */
   //ETH_P_802_2 0x0004 /* 802.2 frames */
   //ETH_P_SNAP 0x0005 /* Internal only */
  
  ji_proto.type = htons(ETH_P_IP);
  
  /* NULL is a wildcard */
   //ji_proto.dev = NULL;
   ji_proto.dev = dev_get_by_name (&amp;init_net, &quot;enp0s3&quot;);
  
  ji_proto.func = ji_packet_rcv;
  
  /* Packet sockets are used to receive or send raw packets at the device
   driver (OSI Layer 2) level. They allow the user to implement
   protocol modules in user space on top of the physical layer. */
  
  /* Add a protocol handler to the networking stack.
   The passed packet_type is linked into kernel lists and may not be freed until 
    it has been removed from the kernel lists. */
   dev_add_pack (&amp;ji_proto);
  
  printk(KERN_INFO &quot;Module insertion completed successfully!\n&quot;);
   return 0; // Non-zero return means that the module couldn't be loaded.
  }
  
  static void __exit ji_cleanup(void)
  {
   dev_remove_pack(&amp;ji_proto);
   printk(KERN_INFO &quot;Cleaning up module....\n&quot;);
  }
  
  module_init(ji_init);
  module_exit(ji_cleanup);
  </code></pre>