~darkmoon/+junk/darkstat-pkg

« back to all changes in this revision

Viewing changes to decode.c

  • Committer: Bazaar Package Importer
  • Author(s): Rene Mayorga
  • Date: 2008-10-06 21:49:52 UTC
  • mfrom: (4.1.3 intrepid)
  • Revision ID: james.westby@ubuntu.com-20081006214952-rkg8moyd6izn7q5y
Tags: 3.0.708-2
* fix workaround to --import/--export at init script
  this prevent darkstat.db being replaced. Closes: #500070
* remove debconf note about the init script inclussion
* remove checks for 2.5-1 versions
* debian/copyright
  + Add 2-clause BSD license for tree.h and host_sort.c
    and remove the note for /usr/share/common-licenses/BSD
  + add conv.c, actc.c err.c, err.h, str.c and str.h copyright stanza
* debian/init.d
  + Set Conf variables to empty string before sourcing init.cfg
* debian/postint
  + only remove DB when version is lt 3.0.707-1
* debian/templates remove upgrade-note
* debian/rules
  + made build-stamp depends on configure-stamp not configure
  + made install-stamp depends on build-stamp not build
  + use DESTDIR instead prefix at install-stamp target
* debian/README.Debian - point to the correct section on the 
  reference to the manpage

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/* darkstat 3
 
2
 * copyright (c) 2001-2007 Emil Mikulic.
 
3
 *
 
4
 * decode.c: packet decoding.
 
5
 *
 
6
 * Given a captured packet, decode it and fill out a pktsummary struct which
 
7
 * will be sent to the accounting code in acct.c
 
8
 *
 
9
 * You may use, modify and redistribute this file under the terms of the
 
10
 * GNU General Public License version 2. (see COPYING.GPL)
 
11
 */
 
12
 
 
13
#include "darkstat.h"
 
14
#include "acct.h"
 
15
#include "cap.h"
 
16
 
 
17
#include <sys/ioctl.h>
 
18
#include <sys/socket.h>
 
19
#include <assert.h>
 
20
#include "err.h"
 
21
#include <pcap.h>
 
22
#include <string.h>
 
23
#include <unistd.h>
 
24
#include <arpa/inet.h> /* inet_ntoa() */
 
25
 
 
26
/* need struct ether_header */
 
27
#if defined(__NetBSD__) || defined(__OpenBSD__)
 
28
# include <sys/queue.h>
 
29
# include <net/if.h>
 
30
# include <net/if_arp.h>
 
31
# include <netinet/if_ether.h>
 
32
#else
 
33
# ifdef __sun
 
34
#  include <sys/ethernet.h>
 
35
#  define ETHER_HDR_LEN 14
 
36
# else
 
37
#  ifdef _AIX
 
38
#   include <netinet/if_ether.h>
 
39
#   define ETHER_HDR_LEN 14
 
40
#  else
 
41
#   include <net/ethernet.h>
 
42
#  endif
 
43
# endif
 
44
#endif
 
45
 
 
46
#include <net/if.h> /* struct ifreq */
 
47
#include <netinet/in_systm.h> /* n_long */
 
48
#include <netinet/ip.h> /* struct ip */
 
49
#define __FAVOR_BSD
 
50
#include <netinet/tcp.h> /* struct tcphdr */
 
51
#include <netinet/udp.h> /* struct udphdr */
 
52
 
 
53
static void decode_ether(u_char *, const struct pcap_pkthdr *,
 
54
   const u_char *);
 
55
static void decode_loop(u_char *, const struct pcap_pkthdr *,
 
56
   const u_char *);
 
57
static void decode_ppp(u_char *, const struct pcap_pkthdr *,
 
58
   const u_char *);
 
59
static void decode_pppoe(u_char *, const struct pcap_pkthdr *,
 
60
   const u_char *);
 
61
static void decode_linux_sll(u_char *, const struct pcap_pkthdr *,
 
62
   const u_char *);
 
63
static void decode_ip(const u_char *pdata, const uint32_t len,
 
64
   pktsummary *sm);
 
65
 
 
66
/* Link-type header information */
 
67
static const linkhdr_t linkhdrs[] = {
 
68
  /* linktype       hdrlen         handler       */
 
69
   { DLT_EN10MB,    ETHER_HDR_LEN, decode_ether  },
 
70
   { DLT_LOOP,      NULL_HDR_LEN,  decode_loop  },
 
71
   { DLT_NULL,      NULL_HDR_LEN,  decode_loop  },
 
72
   { DLT_PPP,       PPP_HDR_LEN,   decode_ppp },
 
73
#if defined(__NetBSD__)
 
74
   { DLT_PPP_SERIAL, PPP_HDR_LEN, decode_ppp },
 
75
#endif
 
76
   { DLT_FDDI,      FDDI_HDR_LEN,  NULL },
 
77
   { DLT_PPP_ETHER, PPPOE_HDR_LEN, decode_pppoe },
 
78
#ifdef DLT_LINUX_SLL
 
79
   { DLT_LINUX_SLL, SLL_HDR_LEN,   decode_linux_sll },
 
80
#endif
 
81
   { -1, -1, NULL }
 
82
};
 
83
 
 
84
/*
 
85
 * Returns a pointer to the linkhdr_t record matching the given linktype, or
 
86
 * NULL if no matching entry found.
 
87
 */
 
88
const linkhdr_t *
 
89
getlinkhdr(int linktype)
 
90
{
 
91
   int i;
 
92
 
 
93
   for (i=0; linkhdrs[i].linktype != -1; i++)
 
94
      if (linkhdrs[i].linktype == linktype)
 
95
         return (&(linkhdrs[i]));
 
96
   return (NULL);
 
97
}
 
98
 
 
99
/*
 
100
 * Returns the minimum caplen needed to decode everything up to the TCP/UDP
 
101
 * packet headers.  Argument lh is not allowed to be NULL.
 
102
 */
 
103
int
 
104
getcaplen(const linkhdr_t *lh)
 
105
{
 
106
   assert(lh != NULL);
 
107
   return (lh->hdrlen + IP_HDR_LEN + max(TCP_HDR_LEN, UDP_HDR_LEN));
 
108
}
 
109
 
 
110
/*
 
111
 * Convert IP address to a numbers-and-dots notation in a static buffer
 
112
 * provided by inet_ntoa().
 
113
 */
 
114
char *
 
115
ip_to_str(const in_addr_t ip)
 
116
{
 
117
   struct in_addr in;
 
118
 
 
119
   in.s_addr = ip;
 
120
   return (inet_ntoa(in));
 
121
}
 
122
 
 
123
/* Decoding functions. */
 
124
static void
 
125
decode_ether(u_char *user _unused_,
 
126
      const struct pcap_pkthdr *pheader,
 
127
      const u_char *pdata)
 
128
{
 
129
   u_short type;
 
130
   const struct ether_header *hdr = (const struct ether_header *)pdata;
 
131
   pktsummary sm;
 
132
   memset(&sm, 0, sizeof(sm));
 
133
 
 
134
   if (pheader->caplen < ETHER_HDR_LEN) {
 
135
      verbosef("ether: packet too short (%u bytes)", pheader->caplen);
 
136
      return;
 
137
   }
 
138
 
 
139
#ifdef __sun
 
140
   memcpy(sm.src_mac, hdr->ether_shost.ether_addr_octet, sizeof(sm.src_mac));
 
141
   memcpy(sm.dst_mac, hdr->ether_dhost.ether_addr_octet, sizeof(sm.dst_mac));
 
142
#else
 
143
   memcpy(sm.src_mac, hdr->ether_shost, sizeof(sm.src_mac));
 
144
   memcpy(sm.dst_mac, hdr->ether_dhost, sizeof(sm.dst_mac));
 
145
#endif
 
146
 
 
147
   type = ntohs( hdr->ether_type );
 
148
   switch (type) {
 
149
   case ETHERTYPE_IP:
 
150
      decode_ip(pdata + ETHER_HDR_LEN, pheader->caplen - ETHER_HDR_LEN, &sm);
 
151
      sm.time = pheader->ts.tv_sec;
 
152
      acct_for(&sm);
 
153
      break;
 
154
   case ETHERTYPE_ARP:
 
155
      /* known protocol, don't complain about it. */
 
156
      break;
 
157
   default:
 
158
      verbosef("ether: unknown protocol (%04x)", type);
 
159
   }
 
160
}
 
161
 
 
162
static void
 
163
decode_loop(u_char *user _unused_,
 
164
      const struct pcap_pkthdr *pheader,
 
165
      const u_char *pdata)
 
166
{
 
167
   uint32_t family;
 
168
   pktsummary sm;
 
169
   memset(&sm, 0, sizeof(sm));
 
170
 
 
171
   if (pheader->caplen < NULL_HDR_LEN) {
 
172
      verbosef("loop: packet too short (%u bytes)", pheader->caplen);
 
173
      return;
 
174
   }
 
175
   family = *(const uint32_t *)pdata;
 
176
#ifdef __OpenBSD__
 
177
   family = ntohl(family);
 
178
#endif
 
179
   if (family == AF_INET) {
 
180
      /* OpenBSD tun or FreeBSD tun or FreeBSD lo */
 
181
      decode_ip(pdata + NULL_HDR_LEN, pheader->caplen - NULL_HDR_LEN, &sm);
 
182
      sm.time = pheader->ts.tv_sec;
 
183
      acct_for(&sm);
 
184
   }
 
185
   else
 
186
      verbosef("loop: unknown family (%x)", family);
 
187
}
 
188
 
 
189
static void
 
190
decode_ppp(u_char *user _unused_,
 
191
      const struct pcap_pkthdr *pheader,
 
192
      const u_char *pdata)
 
193
{
 
194
   pktsummary sm;
 
195
   memset(&sm, 0, sizeof(sm));
 
196
 
 
197
   if (pdata[2] == 0x00 && pdata[3] == 0x21) {
 
198
         decode_ip(pdata + PPP_HDR_LEN, pheader->caplen - PPP_HDR_LEN, &sm);
 
199
         sm.time = pheader->ts.tv_sec;
 
200
         acct_for(&sm);
 
201
   } else
 
202
      verbosef("non-IP PPP packet; ignoring.");
 
203
}
 
204
 
 
205
static void
 
206
decode_pppoe(u_char *user _unused_,
 
207
      const struct pcap_pkthdr *pheader,
 
208
      const u_char *pdata)
 
209
{
 
210
   pktsummary sm;
 
211
   memset(&sm, 0, sizeof(sm));
 
212
 
 
213
   if (pheader->caplen < PPPOE_HDR_LEN) {
 
214
      verbosef("loop: packet too short (%u bytes)", pheader->caplen);
 
215
      return;
 
216
   }
 
217
 
 
218
   /*
 
219
    * First, check if this is a session PPPoE packet
 
220
    * by checking the CODE part of the header
 
221
    * (2nd byte in header)
 
222
    */
 
223
   if (pdata[1] == 0x00) {
 
224
      /*
 
225
       * Next, check if PPP packet type is 0x0021,
 
226
       * which is PPP_IP
 
227
       */
 
228
      if (pdata[6] == 0x00 && pdata[7] == 0x21) {
 
229
         decode_ip(pdata + PPPOE_HDR_LEN, pheader->caplen - PPPOE_HDR_LEN, &sm);
 
230
         sm.time = pheader->ts.tv_sec;
 
231
         acct_for(&sm);
 
232
      }
 
233
      else
 
234
         verbosef("non-IP PPPoE packet; ignoring.");
 
235
   }
 
236
   else
 
237
      verbosef("non-session PPPoE packet; ignoring.");
 
238
}
 
239
 
 
240
/* very similar to decode_ether ... */
 
241
static void
 
242
decode_linux_sll(u_char *user _unused_,
 
243
      const struct pcap_pkthdr *pheader,
 
244
      const u_char *pdata)
 
245
{
 
246
   const struct sll_header {
 
247
      uint16_t packet_type;
 
248
      uint16_t device_type;
 
249
      uint16_t addr_length;
 
250
#define SLL_MAX_ADDRLEN 8
 
251
      uint8_t addr[SLL_MAX_ADDRLEN];
 
252
      uint16_t ether_type;
 
253
   } *hdr = (const struct sll_header *)pdata;
 
254
   u_short type;
 
255
   pktsummary sm;
 
256
   memset(&sm, 0, sizeof(sm));
 
257
 
 
258
   if (pheader->caplen < SLL_HDR_LEN) {
 
259
      verbosef("linux_sll: packet too short (%u bytes)", pheader->caplen);
 
260
      return;
 
261
   }
 
262
 
 
263
   type = ntohs( hdr->ether_type );
 
264
   switch (type) {
 
265
   case ETHERTYPE_IP:
 
266
      decode_ip(pdata + SLL_HDR_LEN, pheader->caplen - SLL_HDR_LEN, &sm);
 
267
      sm.time = pheader->ts.tv_sec;
 
268
      acct_for(&sm);
 
269
      break;
 
270
   case ETHERTYPE_ARP:
 
271
      /* known protocol, don't complain about it. */
 
272
      break;
 
273
   default:
 
274
      verbosef("linux_sll: unknown protocol (%04x)", type);
 
275
   }
 
276
}
 
277
 
 
278
static void
 
279
decode_ip(const u_char *pdata, const uint32_t len, pktsummary *sm)
 
280
{
 
281
   const struct ip *hdr = (const struct ip *)pdata;
 
282
 
 
283
   if (len < IP_HDR_LEN) {
 
284
      verbosef("ip: packet too short (%u bytes)", len);
 
285
      return;
 
286
   }
 
287
   if (hdr->ip_v != 4) {
 
288
      verbosef("ip: version %d (expecting 4)", hdr->ip_v);
 
289
      return;
 
290
   }
 
291
 
 
292
   sm->len = ntohs(hdr->ip_len);
 
293
   sm->proto = hdr->ip_p;
 
294
   sm->src_ip = hdr->ip_src.s_addr;
 
295
   sm->dest_ip = hdr->ip_dst.s_addr;
 
296
 
 
297
   switch (sm->proto) {
 
298
      case IPPROTO_TCP: {
 
299
         const struct tcphdr *thdr =
 
300
            (const struct tcphdr *)(pdata + IP_HDR_LEN);
 
301
         if (len < IP_HDR_LEN + TCP_HDR_LEN) {
 
302
            verbosef("tcp: packet too short (%u bytes)", len);
 
303
            return;
 
304
         }
 
305
         sm->src_port = ntohs(thdr->th_sport);
 
306
         sm->dest_port = ntohs(thdr->th_dport);
 
307
         sm->tcp_flags = thdr->th_flags &
 
308
            (TH_FIN|TH_SYN|TH_RST|TH_PUSH|TH_ACK|TH_URG);
 
309
         break;
 
310
      }
 
311
 
 
312
      case IPPROTO_UDP: {
 
313
         const struct udphdr *uhdr =
 
314
            (const struct udphdr *)(pdata + IP_HDR_LEN);
 
315
         if (len < IP_HDR_LEN + UDP_HDR_LEN) {
 
316
            verbosef("udp: packet too short (%u bytes)", len);
 
317
            return;
 
318
         }
 
319
         sm->src_port = ntohs(uhdr->uh_sport);
 
320
         sm->dest_port = ntohs(uhdr->uh_dport);
 
321
         break;
 
322
      }
 
323
 
 
324
      case IPPROTO_ICMP:
 
325
         /* known protocol, don't complain about it */
 
326
         break;
 
327
 
 
328
      default:
 
329
         verbosef("ip: unknown protocol %d", sm->proto);
 
330
   }
 
331
}
 
332
 
 
333
/* vim:set ts=3 sw=3 tw=78 expandtab: */