1 /*
2  * This file is part of PowerDNS or dnsdist.
3  * Copyright -- PowerDNS.COM B.V. and its contributors
4  *
5  * This program is free software; you can redistribute it and/or modify
6  * it under the terms of version 2 of the GNU General Public License as
7  * published by the Free Software Foundation.
8  *
9  * In addition, for the avoidance of any doubt, permission is granted to
10  * link this program with OpenSSL and to (re)distribute the binaries
11  * produced as the result of such linking.
12  *
13  * This program is distributed in the hope that it will be useful,
14  * but WITHOUT ANY WARRANTY; without even the implied warranty of
15  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16  * GNU General Public License for more details.
17  *
18  * You should have received a copy of the GNU General Public License
19  * along with this program; if not, write to the Free Software
20  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
21  */
22 #pragma once
23 #include <cstdio>
24 #include <stdexcept>
25 #include "iputils.hh"
26 #include <string>
27 #include "misc.hh"
28 #include <iostream>
29 #define __FAVOR_BSD
30 #include <netinet/in_systm.h>
31 #include <netinet/ip.h>
32 #include <netinet/ip6.h>
33 #include <netinet/udp.h>
34 #if defined(__NetBSD__)
35 #include <net/if.h>
36 #include <net/if_ether.h>
37 #elif defined (__OpenBSD__)
38 #include <net/if.h>
39 #include <netinet/if_ether.h>
40 #elif defined (__SVR4) && defined (__sun)
41 #include <sys/ethernet.h>
42 #else
43 #include <net/ethernet.h>
44 #endif
45 #include <vector>
46 #include <boost/format.hpp>
47 #include "namespaces.hh"
48 
49 struct pdns_pcap_file_header {
50   uint32_t magic;
51   uint16_t version_major;
52   uint16_t version_minor;
53   uint32_t thiszone;     /* gmt to local correction */
54   uint32_t sigfigs;    /* accuracy of timestamps */
55   uint32_t snaplen;    /* max length saved portion of each pkt */
56   uint32_t linktype;   /* data link type (LINKTYPE_*) */
57 };
58 
59 
60 struct pdns_timeval
61 {
62   uint32_t tv_sec{0};
63   uint32_t tv_usec{0};
64 };
65 
66 struct pdns_pcap_pkthdr {
67   struct pdns_timeval ts;      /* time stamp */
68   uint32_t caplen{0};     /* length of portion present */
69   uint32_t len{0};        /* length this packet (off wire) */
70 };
71 
72 struct pdns_lcc_header {
73   uint16_t lcc_pkttype;/* packet type */
74   uint16_t lcc_hatype;/* link-layer address type */
75   uint16_t lcc_halen;/* link-layer address length */
76   uint8_t lcc_addr[8];/* link-layer address */
77   uint16_t lcc_protocol;/* protocol */
78 };
79 
80 class PcapPacketReader
81 {
82 public:
83   class EofException : public runtime_error
84   {
85   public:
EofException(const string & str="PcapPacketReader::EofException")86     EofException(const string& str="PcapPacketReader::EofException") : runtime_error(str)
87     {
88     }
89   };
90 
91   PcapPacketReader(const string& fname);
92 
93   template<typename T>
checkedFread(T * ptr)94   void checkedFread(T* ptr)
95   {
96     checkedFreadSize(ptr, sizeof(*ptr));
97   }
98 
99   void checkedFreadSize(void* ptr, size_t size) ;
100 
101   bool getUDPPacket();
102 
103   ComboAddress getSource() const;
104   ComboAddress getDest() const;
105 
106   struct pdns_lcc_header* d_lcc{nullptr};
107   struct ether_header* d_ether{nullptr};
108   struct ip *d_ip{nullptr};
109   struct ip6_hdr *d_ip6{nullptr};
110   const struct tcphdr *d_tcp{nullptr};
111   const struct udphdr *d_udp{nullptr};
112   const uint8_t* d_payload{nullptr};
113   unsigned int d_len{0};
114   struct pdns_pcap_pkthdr d_pheader;
115 
116   pdns_pcap_file_header d_pfh;
117   unsigned int d_runts, d_oversized, d_correctpackets, d_nonetheripudp;
118   alignas (struct ip) char d_readbuffer[32768];
119   char *d_buffer;
120   size_t d_bufsize;
121 private:
122   std::unique_ptr<FILE, int(*)(FILE*)> d_fp{nullptr, fclose};
123   string d_fname;
124   unsigned int d_skipMediaHeader;
125 };
126 
127 class PcapPacketWriter
128 {
129 public:
130   PcapPacketWriter(const string& fname, const PcapPacketReader& ppr);
131   PcapPacketWriter(const string& fname);
132 
133   void write();
setPPR(const PcapPacketReader & ppr)134   void setPPR(const PcapPacketReader& ppr) { d_ppr = &ppr; }
135 
136 private:
137   string d_fname;
138   const PcapPacketReader* d_ppr{nullptr};
139 
140   std::unique_ptr<FILE, int(*)(FILE*)> d_fp{nullptr, fclose};
141   bool d_first{true};
142 };
143