tcpflow  1.6.1
About: tcpflow is a TCP/IP packet demultiplexer that captures data transmitted as part of TCP connections (flows), and stores the data in a way that is convenient for protocol analysis and debugging.
  Fossies Dox: tcpflow-1.6.1.tar.gz  ("unofficial" and yet experimental doxygen-generated source code documentation)  

datalink.cpp
Go to the documentation of this file.
1 /**
2  *
3  * This file is part of tcpflow. Originally by Jeremy Elson
4  * <jelson@circlemud.org>, rewritten by Simson Garfinkel.
5  *
6  * Initial Release: 7 April 1999.
7  *
8  * This source code is under the GNU Public License (GPL). See
9  * COPYING for details.
10  *
11  * This file contains datalink handlers which are called by the pcap callback.
12  * The purpose of each handler is to make a packet_info() object and then call
13  * process_packet. The packet_info() object contains both the original
14  * MAC-layer (with some of the fields broken out) and the packet data layer.
15  *
16  * For wifi datalink handlers, please see datalink_wifi.cpp
17  */
18 
19 #include <stddef.h>
20 #include "tcpflow.h"
21 
22 /* The DLT_NULL packet header is 4 bytes long. It contains a network
23  * order 32 bit integer that specifies the family, e.g. AF_INET.
24  * DLT_NULL is used by the localhost interface.
25  */
26 #define NULL_HDRLEN 4
27 
28 /* Some systems hasn't defined ETHERTYPE_IPV6 */
29 #ifndef ETHERTYPE_IPV6
30 # define ETHERTYPE_IPV6 0x86DD
31 #endif
32 
33 #ifndef ETH_P_QINQ1
34 # define ETH_P_QINQ1 0x9100 /* deprecated QinQ VLAN [ NOT AN OFFICIALLY REGISTERED ID ] */
35 #endif
36 
37 #ifndef ETH_P_8021AD
38 # define ETH_P_8021AD 0x88A8 /* 802.1ad Service VLAN */
39 #endif
40 
41 
42 int32_t datalink_tdelta = 0;
43 
44 #pragma GCC diagnostic ignored "-Wcast-align"
45 void dl_null(u_char *user, const struct pcap_pkthdr *h, const u_char *p)
46 {
47  u_int caplen = h->caplen;
48  u_int length = h->len;
49  uint32_t family = (uint32_t)*p;
50 
51  if (length != caplen) {
52  DEBUG(6) ("warning: only captured %d bytes of %d byte null frame",
53  caplen, length);
54  }
55 
56  if (caplen < NULL_HDRLEN) {
57  DEBUG(6) ("warning: received incomplete null frame");
58  return;
59  }
60 
61  /* make sure this is AF_INET */
62  if (family != AF_INET && family != AF_INET6) {
63  DEBUG(6)("warning: received null frame with unknown type (type 0x%x) (AF_INET=%x; AF_INET6=%x)",
64  family,AF_INET,AF_INET6);
65  return;
66  }
67  struct timeval tv;
68  be13::packet_info pi(DLT_NULL,h,p,tvshift(tv,h->ts),p+NULL_HDRLEN,caplen - NULL_HDRLEN);
70 }
71 #pragma GCC diagnostic warning "-Wcast-align"
72 
73 static uint64_t counter=0;
74 /* DLT_RAW: just a raw IP packet, no encapsulation or link-layer
75  * headers. Used for PPP connections under some OSs including Linux
76  * and IRIX. */
77 void dl_raw(u_char *user, const struct pcap_pkthdr *h, const u_char *p)
78 {
79  if (h->caplen != h->len) {
80  DEBUG(6) ("warning: only captured %d bytes of %d byte raw frame",
81  h->caplen, h->len);
82  }
83  struct timeval tv;
84  be13::packet_info pi(DLT_RAW,h,p,tvshift(tv,h->ts),p, h->caplen);
85  counter++;
87 }
88 
89 /* Ethernet datalink handler; used by all 10 and 100 mbit/sec
90  * ethernet. We are given the entire ethernet header so we check to
91  * make sure it's marked as being IP.
92  */
93 #pragma GCC diagnostic ignored "-Wcast-align"
94 void dl_ethernet(u_char *user, const struct pcap_pkthdr *h, const u_char *p)
95 {
96  u_int caplen = h->caplen;
97  u_int length = h->len;
98  struct be13::ether_header *eth_header = (struct be13::ether_header *) p;
99  u_int ether_type_offset = offsetof(struct be13::ether_header, ether_type);
100 
101  /* Variables to support VLAN */
102  const u_short *ether_type = NULL;
103  const u_char *ether_data = NULL;
104 
105  if (caplen < ether_type_offset) {
106  DEBUG(0) ("error: the captured packet header bytes are shorter than the ether_type offset");
107  return;
108  }
109 
110  ether_type = &eth_header->ether_type; /* where the ether type is located */
111  ether_data = p+sizeof(struct be13::ether_header); /* where the data is located */
112 
113  if (length != caplen) {
114  DEBUG(6) ("warning: only captured %d bytes of %d byte ether frame",
115  caplen, length);
116  }
117 
118  /* Handle basic VLAN packets */
119  while (ntohs(*ether_type) == ETHERTYPE_VLAN
120 #ifdef ETH_P_QINQ1
121  || ntohs(*ether_type) == ETH_P_QINQ1
122 #endif
123 #ifdef ETH_P_8021AD
124  || ntohs(*ether_type) == ETH_P_8021AD
125 #endif
126  ) {
127  //vlan = ntohs(*(u_short *)(p+sizeof(struct ether_header)));
128  ether_type += 2; /* skip past VLAN header (note it skips by 2s) */
129  ether_data += 4; /* skip past VLAN header */
130  caplen -= 4;
131  if (caplen < ether_type_offset) {
132  DEBUG(0) ("error: the captured packet header bytes are shorter than the ether_type offset");
133  return;
134  }
135  }
136 
137  if (caplen < sizeof(struct be13::ether_header)) {
138  DEBUG(6) ("warning: received incomplete ethernet frame");
139  return;
140  }
141 
142  /* Create a packet_info structure with ip data and data length */
143  try {
144  struct timeval tv;
145  be13::packet_info pi(DLT_IEEE802,h,p,tvshift(tv,h->ts),
146  ether_data, caplen - sizeof(struct be13::ether_header));
147  switch (ntohs(*ether_type)){
148  case ETHERTYPE_IP:
149  case ETHERTYPE_IPV6:
151  break;
152 
153 #ifdef ETHERTYPE_ARP
154  case ETHERTYPE_ARP:
155  /* What should we do for ARP? */
156  break;
157 #endif
158 #ifdef ETHERTYPE_LOOPBACK
159  case ETHERTYPE_LOOPBACK:
160  /* What do do for loopback? */
161  break;
162 #endif
163 #ifdef ETHERTYPE_REVARP
164  case ETHERTYPE_REVARP:
165  /* What to do for REVARP? */
166  break;
167 #endif
168  default:
169  /* Unknown Ethernet Frame Type */
170  DEBUG(6) ("warning: received ethernet frame with unknown type 0x%x", ntohs(eth_header->ether_type));
171  break;
172  }
173  } catch( std::logic_error e){
174  std::string s(std::string("warning: caught std::logic_error ")
175  + e.what()
176  + std::string(" in packet"));
177  DEBUG(6)(s.c_str());
178  }
179 }
180 
181 #pragma GCC diagnostic warning "-Wcast-align"
182 
183 /* The DLT_PPP packet header is 4 bytes long. We just move past it
184  * without parsing it. It is used for PPP on some OSs (DLT_RAW is
185  * used by others; see below)
186  */
187 #define PPP_HDRLEN 4
188 
189 void dl_ppp(u_char *user, const struct pcap_pkthdr *h, const u_char *p)
190 {
191  u_int caplen = h->caplen;
192  u_int length = h->len;
193 
194  if (length != caplen) {
195  DEBUG(6) ("warning: only captured %d bytes of %d byte PPP frame",
196  caplen, length);
197  }
198 
199  if (caplen < PPP_HDRLEN) {
200  DEBUG(6) ("warning: received incomplete PPP frame");
201  return;
202  }
203 
204  struct timeval tv;
205  be13::packet_info pi(DLT_PPP,h,p,tvshift(tv,h->ts),p + PPP_HDRLEN, caplen - PPP_HDRLEN);
207 }
208 
209 
210 #ifdef DLT_LINUX_SLL
211 #define SLL_HDR_LEN 16
212 
213 #define SLL_ADDRLEN 8
214 
215 #ifndef ETHERTYPE_MPLS
216 #define ETHERTYPE_MPLS 0x8847
217 #endif
218 #ifndef ETHERTYPE_MPLS_MULTI
219 #define ETHERTYPE_MPLS_MULTI 0x8848
220 #endif
221 
222 #pragma GCC diagnostic ignored "-Wcast-align"
223 void dl_linux_sll(u_char *user, const struct pcap_pkthdr *h, const u_char *p)
224 {
225  u_int caplen = h->caplen;
226  u_int length = h->len;
227 
228  if (length != caplen) {
229  DEBUG(6) ("warning: only captured %d bytes of %d byte Linux cooked frame",
230  caplen, length);
231  }
232 
233  if (caplen < SLL_HDR_LEN) {
234  DEBUG(6) ("warning: received incomplete Linux cooked frame");
235  return;
236  }
237 
238  struct _sll_header {
239  u_int16_t sll_pkttype; /* packet type */
240  u_int16_t sll_hatype; /* link-layer address type */
241  u_int16_t sll_halen; /* link-layer address length */
242  u_int8_t sll_addr[SLL_ADDRLEN]; /* link-layer address */
243  u_int16_t sll_protocol; /* protocol */
244  };
245 
246  _sll_header *sllp = (_sll_header*)p;
247  u_int mpls_sz = 0;
248  if (ntohs(sllp->sll_protocol) == ETHERTYPE_MPLS) {
249  // unwind MPLS stack
250  do {
251  if(caplen < SLL_HDR_LEN + mpls_sz + 4){
252  DEBUG(6) ("warning: MPLS stack overrun");
253  return;
254  }
255  mpls_sz += 4;
256  caplen -= 4;
257  } while ((p[SLL_HDR_LEN + mpls_sz - 2] & 1) == 0 );
258  }
259 
260  struct timeval tv;
261  be13::packet_info pi(DLT_LINUX_SLL,h,p,tvshift(tv,h->ts),p + SLL_HDR_LEN + mpls_sz, caplen - SLL_HDR_LEN);
263 }
264 #endif
265 
266 #ifndef DLT_IEEE802_11_RADIO
267 #define DLT_IEEE802_11_RADIO 127 /* 802.11 plus radiotap radio header */
268 #endif
269 
270 /* List of callbacks for each data link type */
272  { dl_null, DLT_NULL },
273 /* Some systems define DLT_RAW as 12, some as 14, and some as 101.
274  * So it is hard-coded here.
275  */
276  { dl_raw, 12 },
277  { dl_raw, 14 },
278  { dl_raw, 101 },
279  { dl_ethernet, DLT_EN10MB },
281  { dl_ppp, DLT_PPP },
282 #ifdef DLT_LINUX_SLL
283  { dl_linux_sll, DLT_LINUX_SLL },
284 #endif
285 #if defined(USE_WIFI) && !defined(WIN32)
286  { dl_ieee802_11_radio, DLT_IEEE802_11 },
288  { dl_prism, DLT_PRISM_HEADER},
289 #endif
290  { NULL, 0 }
291 };
292 
293 pcap_handler find_handler(int datalink_type, const char *device)
294 {
295  int i;
296 
297  DEBUG(3) ("looking for handler for datalink type %d for interface %s",
298  datalink_type, device);
299 
300  for (i = 0; handlers[i].handler != NULL; i++){
301  if (handlers[i].type == datalink_type){
302  return handlers[i].handler;
303  }
304  }
305 
306  die("sorry - unknown datalink type %d on interface %s", datalink_type, device);
307  return NULL; /* NOTREACHED */
308 }
#define ETHERTYPE_MPLS
Definition: ethertype.h:119
#define ETHERTYPE_VLAN
#define ETHERTYPE_REVARP
static void process_packet(const be13::packet_info &pi)
Definition: plugin.cpp:707
#define ETHERTYPE_ARP
#define ETHERTYPE_LOOPBACK
#define ETHERTYPE_IPV6
#define ETHERTYPE_IP
unsigned int uint32_t
Definition: core.h:40
#define DLT_RAW
Definition: pcap_fake.h:79
#define DLT_IEEE802
Definition: pcap_fake.h:74
#define DLT_EN10MB
Definition: pcap_fake.h:69
#define DLT_NULL
Definition: pcap_fake.h:68
void(* pcap_handler)(uint8_t *, const struct pcap_pkthdr *, const uint8_t *)
Definition: pcap_fake.h:48
#define DLT_PPP
Definition: pcap_fake.h:77
pcap_handler handler
Definition: tcpflow.h:281
uint32_t caplen
Definition: pcap_fake.h:37
struct timeval ts
Definition: pcap_fake.h:36
uint32_t len
Definition: pcap_fake.h:38
void die(const char *fmt,...)
Definition: util.cpp:175
const timeval & tvshift(struct timeval &tv, const struct timeval &tv_)
Definition: tcpflow.h:293
#define DEBUG(message_level)
Definition: tcpflow.h:273