~ubuntu-branches/ubuntu/natty/ntop/natty

« back to all changes in this revision

Viewing changes to iwtan/iwtan_analyze.c

  • Committer: Bazaar Package Importer
  • Author(s): Ludovico Cavedon, Jordan Metzmeier, Ludovico Cavedon
  • Date: 2010-12-15 20:06:19 UTC
  • mfrom: (5.1.5 sid)
  • Revision ID: james.westby@ubuntu.com-20101215200619-0ojz3iak95ihibun
Tags: 3:4.0.3+dfsg1-1
[ Jordan Metzmeier ]
* New upstream release (Closes: #522042)
* Move data files to /usr/share/ntop (Closes: #595450).
* Package architecture independent data in a separate ntop-data package.
* Use debhelper 7.
* Update Standards-Version to 3.9.1.
* Depend on python-mako.
* Do not include ntop.txt in binary packages as it is a copy of the man
  page.
* Do not include NEWS, as it is outdated.
* Switch to package source version 3.0 (quilt).
* Add password creation to debconf
* Changed init script to fix localization problems (thanks to Alejandro
  Varas <alej0varas@gmail.com>, LP: #257466)
* Remove manual update-rc.d calls from postrm and postinst. debhelper adds
  this for us.
* Add pre-depends on adduser for postinst script.
* Fix errors in the manpages: fix-manpage-errors.patch.
* Added fixes for matching active interfaces.
* Added a watch file.

[ Ludovico Cavedon ]
* Remove direct changes to upstream tree, and move them into specific patch
  files:
  - fix-manpage-errors.patch: fix typos in ntop.8.
  - dot-path.patch: fix path of /usr/bin/dot executable
* Add patches:
  - reduce-autogen-purged-files.patch: prevent agutogen.sh from reamoving
  too many files during cleanup.
  - Add build-without-ntop-darwin.patch, to fix compilation without
  ntop_darwin.c.
* No longer add faq.html, as it is not distributed in the upstream tarball.
* Use ${source:Version} in control file. Have ntop-data recommend
  ntop.
* Rename dirs to ntop.dirs and keep only empty directories that need
  to be created.
* Remove var/lib from ntop.install file, as it is empty (keeping it in
  ntop.dirs).
* Update po files.
* Breaks and Replaces instead of Conflitcs for ntop-data.
* Use a longer package description.
* Remove useless configure options from debian/rules.
* Move private shared libraries libraries in /usr/lib/ntop.
* Add change-plugin-dir.patch for adjusting plugin directory.
* Remove development files.
* Use system library for MochiKit.js.
* Rewrite DEP5 copyright file.
* Repackage upstream tarball in order to remove non-DFSG-compliant code. Add
  get-orig-source.sh script and get-orig-source target in debian/rules.
* Add explanation to README.Debian why geolocation is no longer working.
* Add avoid-copy-maxmind-db.patch to prevent copying of Geo*.dat
  files.
* Remove old unused patches.

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/* IWTAN analyze functions and data structures.*/
 
2
 
 
3
/*
 
4
  Copyright (C) 2008 Marco Cornolti 
 
5
  
 
6
  IWTAN (IWTAN: Wireless Topology ANalyzer) is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 3, or (at your option) any later version.
 
7
  
 
8
  IWTAN is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
 
9
  
 
10
  You should have received a copy of the GNU General Public License along with IWTAN; see the file COPYING. If not, write to the Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA. 
 
11
*/
 
12
 
 
13
#include <stdlib.h>
 
14
#include <inttypes.h>
 
15
#include <pcap.h>
 
16
#include <sys/types.h>
 
17
#include <pthread.h>
 
18
#include <math.h>
 
19
#include <asm/byteorder.h>
 
20
#include <string.h>
 
21
 
 
22
#include "iwtan_analyze.h"
 
23
#include "iwtan_data.h"
 
24
 
 
25
/*
 
26
  Refresh the data structure extracting the information by a packet passed by argument. 
 
27
  length is the length of the packet in bytes.
 
28
  pktBody is a pointer to the packet body.
 
29
  packetType is the packet type as defined by pcap.h (DTL_*)
 
30
  Returns 0 in case of no errors. Returns 1 if the packet type could not be recognized. 
 
31
*/
 
32
int iwtan_refresh_data(unsigned int length, const u_char* pktBody, int packetType, iwtan_context* context){
 
33
  pthread_mutex_lock(&(context->mutex));
 
34
 
 
35
  int retVal=0;
 
36
  
 
37
  //all the data that may be obtained for an access point by the radiotap header, initialized to null values.
 
38
  short WEPped = -1;
 
39
  unsigned int dataRate = 0;
 
40
  unsigned short antenna = 0;
 
41
  unsigned int frequency = 0;
 
42
  short type = 0;
 
43
  short signal = 0;
 
44
 
 
45
  //data obtained by the 802.11 frame
 
46
  mac_address* stMac = NULL;
 
47
  mac_address* apMac = NULL;
 
48
  mac_address* bssId = NULL;
 
49
  
 
50
  //data obtained by the wlan management frame
 
51
  char* essid = NULL;
 
52
 
 
53
  //data obtained by the IP level
 
54
  ip4_address stIp4 = NULL;
 
55
  ip6_address stIp6 = NULL;
 
56
 
 
57
  //data obtained by an ethernet-emulated packet
 
58
  mac_address* srcMac = NULL;
 
59
  mac_address* destMac = NULL;
 
60
  ip4_address srcIp4 = NULL;
 
61
  ip6_address srcIp6 = NULL;
 
62
  ip4_address destIp4 = NULL;
 
63
  ip6_address destIp6 = NULL;
 
64
  
 
65
 
 
66
  //determine what's the kind of the analyzed packet and call the right processing function.
 
67
  switch (packetType){
 
68
  case DLT_IEEE802_11_RADIO: 
 
69
    if (_iwtan_validate_radiotap(pktBody, length)){
 
70
      _iwtan_process_radiotap(pktBody, length, &WEPped, &dataRate, &antenna, &frequency, &type, &signal, &stMac, &apMac, &bssId, &essid, &stIp4, &stIp6);
 
71
    }
 
72
    break;
 
73
  case DLT_IEEE802_11:
 
74
    _iwtan_process_802_11(pktBody, length, &apMac, &stMac, &bssId, &essid, &stIp4, &stIp6);
 
75
    break;
 
76
  case DLT_EN10MB:
 
77
    //We can't extract any useful information from a EN10MB frame, because from a packet we can't understand if the packet is coming from an access point or from a station.
 
78
 
 
79
  default:
 
80
    retVal = 1;
 
81
  }
 
82
 
 
83
  //pick the right ap to create it or update its data. An ap may exist without any associated station.
 
84
  if (bssId){
 
85
    iwtan_ap** apRef = _iwtan_bsearch_AP(bssId, context);
 
86
    iwtan_ap* ap;
 
87
    if (!apRef)
 
88
      ap = _iwtan_add_new_AP(bssId, context);
 
89
    else
 
90
      ap = *apRef;
 
91
 
 
92
    _iwtan_update_AP (ap, WEPped, dataRate, antenna, frequency, type, signal, bssId, essid, NULL, time(NULL));
 
93
 
 
94
    //if an AP and a station has been seen, create an association.
 
95
    if (stMac){
 
96
      _iwtan_add_association(bssId, stMac, context);
 
97
 
 
98
      //pick the right station and update its data.
 
99
      iwtan_station* sta = _iwtan_bsearch_station(stMac, context);
 
100
      _iwtan_update_station (sta, stIp4, stMac, stIp6, time(NULL));
 
101
    }
 
102
  } 
 
103
  else{ //no AP were found (e.g. a station sent a multicast packet)
 
104
    if (stMac){ //pick the right station, if present, and update its data.
 
105
      iwtan_station* sta = _iwtan_bsearch_station(stMac, context);
 
106
      if (sta) _iwtan_update_station (sta, stIp4, stMac, stIp6, time(NULL));
 
107
      else {      //otherwise, we don't create stations that aren't associated to an ap, and we just free the obtained addresses.
 
108
        free(stMac);
 
109
        free(stIp4);
 
110
        free(stIp6);
 
111
      }
 
112
    }
 
113
    //    free(ap_mac); //in any case, ap_mac is not useful. (TODO rename ap_mac to something else, it is not necessarily the AP MAC address!)
 
114
 
 
115
  }
 
116
 
 
117
  pthread_mutex_unlock(&(context->mutex));
 
118
 
 
119
  return retVal;
 
120
}
 
121
 
 
122
 
 
123
/*
 
124
  Process a radiotap header pointed by packetData.
 
125
  Stores the radiotap header size (just the header) in radioTapSize, writes wether or not the signal has a wep encription in WEPped, the dataRate in Mbps in dataRate, the antenna ID in antenna, the channel frequency in frequency, the signal type in type.
 
126
  Returns 1 in case of error, e.g. for broken packages.
 
127
*/
 
128
int _iwtan_process_radiotap(const u_char* radiotapData, unsigned int radioTapSize, short* WEPped, unsigned int* dataRate, short* antenna, unsigned int* frequency, short* type, short* signal, mac_address** stMac, mac_address** apMac, mac_address** bssId, char** essid, ip4_address* stIp4, ip6_address* stIp6){
 
129
  radiotap_header* rt =  (radiotap_header*) radiotapData; 
 
130
  *WEPped = _iwtan_byte_to_bool(rt->flags,5);
 
131
  *dataRate = rt->dataRate * 2;
 
132
  *antenna = rt->antenna;
 
133
  *frequency = _iwtan_le_to_host(rt->frequency);
 
134
  switch(_iwtan_le_to_host(rt->type)){
 
135
  case 0x00a0:
 
136
    *type = 1;
 
137
    break;
 
138
  default: 0; break;
 
139
  }
 
140
  *signal = rt->signal;
 
141
 
 
142
  //radiotap packets contain 802.11 packets.
 
143
  _iwtan_process_802_11(radiotapData+_iwtan_le_to_host(rt->length), radioTapSize -( _iwtan_le_to_host(rt->length) + 4), apMac, stMac, bssId, essid, stIp4, stIp6);
 
144
 
 
145
}
 
146
 
 
147
/*
 
148
  Validate a 802.11 radiotap packet pointed by body of length len, checking its CRC.
 
149
  Returns 1 if the packet is a valid radiotap header or 0 otherwise. 
 
150
*/
 
151
int _iwtan_validate_radiotap(const u_char* body, bpf_uint32 len){
 
152
  //  ieee_802_11_header* pkt (ieee_802_11_header*) ;
 
153
  //TODO:implement
 
154
  return 1;
 
155
}
 
156
 
 
157
/*
 
158
  Process a 802.11 packet extracting all its data.
 
159
  Set ap_mac to the MAC address of the access point sending the packet or NULL if no access points are meant.
 
160
  Set st_mac to the MAC address of the station if the packet has a single (not broadcast) destination, NULL otherwise.
 
161
  Set bssId to the BSS id.
 
162
  Set essid to the ESSID of the access point if the packet is a beacon frame, tu NULL otherwise.
 
163
  Set stationIP4 to the station IP4 address if the frame contained an IPv4 packet with a single destination (not broadcast).
 
164
  Set stationIP6 to the station IP6 address if the frame contained an IPv6 packet with a single destination (not broadcast).
 
165
  All the extracted data is allocated separetly and should be freed when no longer needed.
 
166
*/
 
167
int _iwtan_process_802_11(const u_char* body, bpf_uint32 len, mac_address** ap_mac, mac_address** st_mac, mac_address** bssId, char** essid, ip4_address* stationIP4, ip6_address* stationIP6){
 
168
  ieee_802_11_header* frm = (ieee_802_11_header*) body;
 
169
  switch (_iwtan_le_to_host(frm->control)){
 
170
  case 0x0208: //Frame contains data from a DS to a station via an access point. This means that MAC 1 is the destination (station) address, MAC2 is the BSS id, MAC3 is the source (AP) address
 
171
  case 0x0A08:
 
172
    if (_iwtan_mac_is_broadcast((mac_address*)frm->mac1)){ //Multicast and broadcast transmissions from stations are codified as frames from DS to Station. They have a multicast/bradcast destination (MAC 1), the MAC address 3 is the station address (instead of the AP's), and the BSS id is regular (MAC 2).
 
173
      *ap_mac = NULL;
 
174
      *bssId = _iwtan_copy_mac_by_array(frm->mac2);
 
175
      *st_mac = _iwtan_copy_mac_by_array(frm->mac3);
 
176
    }
 
177
    else {
 
178
      *st_mac = _iwtan_copy_mac_by_array(frm->mac1);
 
179
      *bssId = _iwtan_copy_mac_by_array(frm->mac2);
 
180
      *ap_mac = _iwtan_copy_mac_by_array(frm->mac3);
 
181
  }
 
182
  _iwtan_process_802_llc(body + IWTAN_DATA_HDR_LEN, len-IWTAN_DATA_HDR_LEN, NULL, stationIP4, NULL, stationIP6);
 
183
    break;
 
184
 
 
185
  case 0x0108: //Frame contains data from a Station to a DS via an access point. This means that MAC1 is the BSS id, MAC2 is the source (station) address, MAC3 is the destination (AP) address.
 
186
    *bssId = _iwtan_copy_mac_by_array(frm->mac1);
 
187
    *st_mac = _iwtan_copy_mac_by_array(frm->mac2);
 
188
    *ap_mac = _iwtan_mac_is_broadcast((mac_address*)frm->mac3) ? NULL : _iwtan_copy_mac_by_array(frm->mac3);
 
189
    _iwtan_process_802_llc(body + IWTAN_DATA_HDR_LEN, len-IWTAN_DATA_HDR_LEN, stationIP4, NULL, stationIP6, NULL);
 
190
    break;
 
191
 
 
192
  case 0x0080: //Frame is a beacon frame (contains a wlan management frame)
 
193
    *ap_mac = _iwtan_copy_mac_by_array(frm->mac2);
 
194
    *bssId = _iwtan_copy_mac_by_array(frm->mac3);
 
195
    _iwtan_process_802_11_mng(body + IWTAN_BEACON_HDR_LEN, len - IWTAN_BEACON_HDR_LEN - sizeof(ieee_802_11_mng_fixed_end), essid);
 
196
    break;
 
197
  }
 
198
}
 
199
 
 
200
/*
 
201
  Process a 802.11 management frame, extracting the ESSID.
 
202
  The ESSID is allocated as a string whose pointer is stored in *essid.
 
203
*/
 
204
int _iwtan_process_802_11_mng(const u_char* body, bpf_uint32 len, char** essid){
 
205
  ieee_802_11_mng_fixed_begin* begin = (ieee_802_11_mng_fixed_begin*) body;
 
206
  ieee_802_11_mng_tag* tag;
 
207
  u_char* tagByte = (u_char*)(body + sizeof(ieee_802_11_mng_fixed_begin));
 
208
 
 
209
  while(tagByte < body+len){
 
210
    tag = (ieee_802_11_mng_tag*) tagByte;
 
211
    switch (tag->tagNumber){
 
212
    case(0x0)://tag contains an ESSID
 
213
      *essid = calloc(tag->tagLen+1, sizeof(char));
 
214
      strncpy(*essid, tagByte+2, tag->tagLen);
 
215
      break;
 
216
    }
 
217
    tagByte += 2 + tag->tagLen;
 
218
  }
 
219
}
 
220
 
 
221
/*
 
222
  Process a Link Layer Control header. If an IP packet is found, the source and destination IP addresses are stored in the pointers given by argument.
 
223
  The addresses are allocated in the heap and should be freed when no longer needed.
 
224
  The addresses are stored in the pointers given by argument only if their value is not NULL.
 
225
*/
 
226
int _iwtan_process_802_llc(const u_char* body, bpf_uint32 len, ip4_address* fromIp4, ip4_address* toIp4, ip6_address* fromIp6, ip4_address* toIp6){
 
227
  ieee_802_11_llc* llc = (ieee_802_11_llc*) body;
 
228
  switch (_iwtan_be_to_host(llc->type)){
 
229
  case 0x0800: //llc contains an IPv4 packet
 
230
    _iwtan_process_ip4(body + sizeof(ieee_802_11_llc), len-sizeof(ieee_802_11_llc), fromIp4, toIp4);
 
231
    break;
 
232
  case 0x86dd: //llc contains an IPv6 packet
 
233
    _iwtan_process_ip6(body + sizeof(ieee_802_11_llc), len-sizeof(ieee_802_11_llc), fromIp6, toIp6);
 
234
    break;
 
235
  }
 
236
  return 0;
 
237
}
 
238
 
 
239
/*
 
240
  Process an ethernet header. If an IP packet is found, the source and destination IP addresses are stored in the pointers given by argument.
 
241
  The addresses are allocated in the heap and should be freed when no longer needed.
 
242
  The addresses are stored in the pointers given by argument only if their value is not NULL.
 
243
*/
 
244
/*int _iwtan_process_ethernet(const u_char* body, bpf_uint32 len, mac_address** sourceMac, mac_address** destMac, ip4_address* srcIp4, ip6_address* srcIp6, ip4_address* destIp4, ip6_address* destIp6){
 
245
  ethernet_hdr* eth = (ethernet_hdr*) body;
 
246
  *sourceMac =  _iwtan_mac_is_broadcast((mac_address*)eth->source)? NULL : _iwtan_copy_mac_by_array(eth->source);
 
247
  *destMac =  _iwtan_mac_is_broadcast((mac_address*)eth->destination)? NULL : _iwtan_copy_mac_by_array(eth->destination);
 
248
  switch (_iwtan_be_to_host(eth->type)){
 
249
  case 0x0800: //ethernet contains an IPv4 packet
 
250
    _iwtan_process_ip4(body + sizeof(ethernet_hdr), len-sizeof(ethernet_hdr), srcIp4, destIp4);
 
251
    break;
 
252
  case 0x86dd: //llc contains an IPv6 packet
 
253
    _iwtan_process_ip6(body + sizeof(ethernet_hdr), len-sizeof(ethernet_hdr), srcIp6, destIp6);
 
254
    break;
 
255
  }
 
256
  return 0;
 
257
  
 
258
 
 
259
  }*/
 
260
 
 
261
 
 
262
/*
 
263
  Process an IPv4 packet. The source and destination IP addresses are stored in the pointers given by argument.
 
264
  The addresses are allocated in the heap and should be freed when no longer needed.
 
265
  The addresses are stored in the pointers given by argument only if their value is not NULL.
 
266
*/
 
267
int _iwtan_process_ip4(const u_char* body, bpf_uint32 len, ip4_address* fromIp4, ip4_address* toIp4){
 
268
  ip4_hdr* ip = (ip4_hdr*) body;
 
269
  switch (ip->version){
 
270
  case 0x45: //version: IPv4, header length:20
 
271
    if (fromIp4)
 
272
      *fromIp4 = _iwtan_ip4_is_broadcast(ip->source) ? NULL : _iwtan_copy_ip4(ip->source);
 
273
    if (toIp4)
 
274
      *toIp4 = _iwtan_ip4_is_broadcast(ip->destination) ? NULL : _iwtan_copy_ip4(ip->destination);
 
275
    break;
 
276
    //other version of IP?
 
277
  }
 
278
  return 0;
 
279
}
 
280
 
 
281
/*
 
282
  Process an IPv6 packet pointed by body of the size len.
 
283
  Writes (a pointer to) the source and destination addresses in the given addresses pointers, if they are not NULL.
 
284
  A value of NULL is stored in these pointers if the addresses are broadcasts.
 
285
*/
 
286
int _iwtan_process_ip6(const u_char* body, bpf_uint32 len, ip6_address* fromIp6, ip6_address* toIp6){
 
287
  ip6_hdr* ip = (ip6_hdr*) body;
 
288
  switch (ip->firstByte / 0x10){
 
289
  case 0x6: //version: IPv6
 
290
    if (fromIp6)
 
291
      *fromIp6 = _iwtan_ip6_is_broadcast(ip->source) ? NULL : _iwtan_copy_ip6(ip->source);
 
292
    if (toIp6) 
 
293
      *toIp6 = _iwtan_ip6_is_broadcast(ip->destination) ? NULL : _iwtan_copy_ip6(ip->destination);
 
294
    break;
 
295
  }
 
296
  return 0;
 
297
}
 
298
 
 
299
 
 
300
/*
 
301
  Given a byte, returns the value of the Nth bit in the byte (beginning from zero at left), returns -1 on errors.
 
302
*/
 
303
short _iwtan_byte_to_bool(u_char byte, short position){
 
304
  if (position >=8 || position<0) return -1;
 
305
  position = 7-position;
 
306
  return (byte % (short)pow(2, position + 1)) / (short)pow(2, position);
 
307
}
 
308
 
 
309
/*
 
310
  Convert a 16-bit value from little endian notation to host notation.
 
311
*/
 
312
uint16_t _iwtan_le_to_host(uint16_t leData){
 
313
#if defined(__LITTLE_ENDIAN_BITFIELD)
 
314
  return leData;
 
315
#elif defined (__BIG_ENDIAN_BITFIELD)
 
316
  return (leData%256)*256+leData/256;
 
317
#else
 
318
#error  "Please fix <asm/byteorder.h>"
 
319
#endif
 
320
}
 
321
 
 
322
/*
 
323
  Convert a 16-bit value from little endian notation to host notation.
 
324
*/
 
325
uint16_t _iwtan_be_to_host(uint16_t beData){
 
326
#if defined(__LITTLE_ENDIAN_BITFIELD)
 
327
  return (beData%256)*256+beData/256;
 
328
#elif defined (__BIG_ENDIAN_BITFIELD)
 
329
  return beData;
 
330
#else
 
331
#error  "Please fix <asm/byteorder.h>"
 
332
#endif
 
333
}
 
334
 
 
335
/* Returns 1 if and only if the IPv4 address pointed by ip4 is a broadcast address.*/
 
336
int _iwtan_ip4_is_broadcast(ip4_address ip4){
 
337
  int i=3;
 
338
  uint8_t* bytei=ip4+i;
 
339
  do{
 
340
    if (*bytei == 0xff) return 1;
 
341
    bytei--;
 
342
    i--;
 
343
  } while (i>=0);
 
344
  return 0;    
 
345
}
 
346
 
 
347
/* Returns !=0 if and only if the IPv6 address pointed by ip6 does not have a single destination (i.e. is multicast).*/
 
348
int _iwtan_ip6_is_broadcast(ip6_address ip6){
 
349
  return (*ip6 == 0xff && *(ip6+1) == 0x00);
 
350
}
 
351
 
 
352
/*
 
353
  Returns !=0 if and only if the MAC address pointed by mac is not a single destination (broadcast or multicast).
 
354
*/
 
355
int _iwtan_mac_is_broadcast(mac_address* mac){
 
356
  if (mac->ether_addr_octet[0] == 0x01 &&
 
357
      mac->ether_addr_octet[1] == 0x00) return 1; //multicast destination
 
358
 
 
359
  if (mac->ether_addr_octet[0] == 0x33 &&
 
360
      mac->ether_addr_octet[1] == 0x33) return 1; //IPv6 Neighbor Discovery
 
361
 
 
362
  int i=0;
 
363
  while (i<6){
 
364
    if (mac->ether_addr_octet[i] != 0xff) return 0;
 
365
    i++;
 
366
  }
 
367
  return 1;
 
368
}