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

« back to all changes in this revision

Viewing changes to iwtan/iwtan_data.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 context process and browse functions.*/
 
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
 
 
14
#include <pcap.h>
 
15
#include <pthread.h>
 
16
#include <stdlib.h>
 
17
#include <netinet/ether.h>
 
18
#include <time.h>
 
19
#include <string.h>
 
20
 
 
21
#include "iwtan_data.h"
 
22
 
 
23
/* ++++++++++++++ Data refreshing  +++++++++++++++++++ */
 
24
 
 
25
/*
 
26
  Initialize a clear IWTAN context. Returns 0 on success or !=0 on error.
 
27
*/
 
28
int iwtan_context_initialize(iwtan_context* context){
 
29
  if (pthread_mutex_init(&(context->mutex), NULL)) return -1;
 
30
  if (context==NULL) return -1;
 
31
  context->allAss = 10;
 
32
  context->assN = 0;
 
33
  context->ap_ass = calloc(context->allAss, sizeof(iwtan_association));
 
34
  context->st_ass = calloc(context->allAss, sizeof(iwtan_association));
 
35
  context->apN=0;
 
36
  context->allAP=2;
 
37
  context->ap_list = calloc(context->allAP, sizeof(iwtan_ap*));
 
38
  return 0;
 
39
}
 
40
 
 
41
/*
 
42
  Destroy an IWTAN context. No other threads should use the context when this method is called. Returns 0 on success or !=0 on failure.
 
43
*/
 
44
int iwtan_context_destroy(iwtan_context* context){
 
45
  if (pthread_mutex_lock(&(context->mutex))) return -1;
 
46
  int i;
 
47
  /*Free all stations*/
 
48
  for (i=0;i<context->assN;i++)
 
49
    iwtan_free_station(((iwtan_association*)context->st_ass + i)->station);
 
50
  /*Free all APs*/
 
51
  for (i=0;i<context->apN;i++)
 
52
    iwtan_free_AP((iwtan_ap*)(*(context->ap_list + i)));
 
53
  free(context->ap_ass);
 
54
  free(context->st_ass);
 
55
  free(context->ap_list);
 
56
  if (pthread_mutex_unlock(&(context->mutex))) return -1;
 
57
  if (pthread_mutex_destroy(&(context->mutex))) return -1;
 
58
  return 0;
 
59
}
 
60
 
 
61
/* +++++++++++++++++++++++ DATA BROWSING FUNCTIONS ++++++++++++++++++++++++++ */
 
62
 
 
63
/*
 
64
  Get a linked list of wi_stations_el containing a copy of the stations currently part of the BSS with the given id.
 
65
  All the stations properties are copied so that they may be used thread-safely.
 
66
  The function iwtan_free_stations_ll() should be called when the list and the stations are no longer needed.
 
67
  Returns NULL if no associations were found, otherwise a reference to the first element of the list.
 
68
  Function is thread-safe.*/
 
69
iwtan_station_el* iwtan_get_by_AP(mac_address* bssId, iwtan_context* context){
 
70
  int i;
 
71
  pthread_mutex_lock(&(context->mutex));
 
72
  iwtan_station_el* ret;
 
73
 
 
74
  int firstPos = _iwtan_first_bsearch_by_AP(bssId, context);
 
75
  if (firstPos == -1) {
 
76
    ret = NULL;
 
77
  }
 
78
  else {
 
79
    unsigned int currentAssI = firstPos;
 
80
    iwtan_association* currentAss = context->ap_ass + currentAssI;
 
81
    
 
82
    iwtan_station_el* firstListEl=calloc(1, sizeof(iwtan_station_el));
 
83
    firstListEl->station = _iwtan_copy_station(currentAss->station);
 
84
    currentAssI++;
 
85
    currentAss = context->ap_ass + currentAssI;
 
86
 
 
87
    iwtan_station_el* currListEl = firstListEl;
 
88
    while (currentAssI < context->assN && !iwtan_cmp_mac(currentAss->ap->bssId, bssId)){
 
89
      currListEl->next = malloc(sizeof(iwtan_station_el));
 
90
      currListEl = currListEl->next;
 
91
      currListEl->station = _iwtan_copy_station(currentAss->station);
 
92
      currListEl->next = NULL;
 
93
      currentAssI++;
 
94
      currentAss = context->ap_ass + currentAssI;
 
95
    }
 
96
    ret = firstListEl;
 
97
  }
 
98
  pthread_mutex_unlock(&(context->mutex));
 
99
  return ret;
 
100
}
 
101
 
 
102
/*
 
103
  Get a copy of the access point currently associated to the station with given MAC address.
 
104
  All the AP properties are copied so that they may be used thread-safely.
 
105
  The function iwtan_free_AP() should be called when the AP is no longer needed.
 
106
  Returns NULL if no associations were found, otherwise a reference to the Access Point.
 
107
  Function is thread-safe.*/
 
108
iwtan_ap* iwtan_get_by_station(mac_address* stMac, iwtan_context* context){
 
109
  int i;
 
110
  pthread_mutex_lock(&(context->mutex));
 
111
  iwtan_ap* ap;
 
112
  iwtan_association* ass = context->st_ass + _iwtan_bsearch_by_station(stMac, context);
 
113
  ap = (ass==NULL) ? NULL : _iwtan_copy_AP(ass->ap);
 
114
  pthread_mutex_unlock(&(context->mutex));
 
115
  return ap;
 
116
}
 
117
 
 
118
/*
 
119
  Get a list of (elements referring copies of) all the stations currently present in the database ordered by their MAC address.
 
120
  All the stations properties are copied so that they may be used thread-safely.
 
121
  The function iwtan_free_stations_ll() should be called when the list and the stations are no longer needed.
 
122
  Returns the first element of the list.
 
123
  Function is thread-safe.*/
 
124
iwtan_station_el* iwtan_get_all_stations(iwtan_context* context){
 
125
  pthread_mutex_lock(&(context->mutex));
 
126
  iwtan_station_el* ret = NULL;
 
127
  if (context->assN != 0){
 
128
    int i;
 
129
    iwtan_station_el* curr = malloc(sizeof(iwtan_station_el));
 
130
    curr->station = _iwtan_copy_station(context->ap_ass->station);
 
131
    curr->next = NULL;
 
132
    ret = curr;
 
133
    for (i=1; i<context->assN; i++){
 
134
      curr->next = malloc(sizeof(iwtan_station_el));
 
135
      curr = curr->next;
 
136
      curr->station = _iwtan_copy_station(((iwtan_association*)(context->ap_ass + i))->station);
 
137
      curr->next = NULL;
 
138
    }
 
139
  }
 
140
  
 
141
  pthread_mutex_unlock(&(context->mutex));
 
142
  return ret;
 
143
}
 
144
 
 
145
/*
 
146
  Get a list of (elements referring copies of) all the Access points currently present in the database ordered by their MAC address.
 
147
  All the APs properties are copied so that they may be used thread-safely.
 
148
  The function iwtan_free_ap_ll() should be called when the list and the stations are no longer needed.
 
149
  Returns the first element of the list.
 
150
  Function is thread-safe.
 
151
*/
 
152
iwtan_ap_el* iwtan_get_all_APs(iwtan_context* context){
 
153
  pthread_mutex_lock(&(context->mutex));
 
154
  iwtan_ap_el* ret = NULL;
 
155
  if (context->apN != 0){
 
156
    int i;
 
157
    iwtan_ap_el* curr = malloc(sizeof(iwtan_ap_el));
 
158
    curr->ap = _iwtan_copy_AP(*(context->ap_list + 0));
 
159
    curr->next = NULL;
 
160
    ret = curr;
 
161
    for (i=1; i<context->apN; i++){
 
162
      curr->next = malloc(sizeof(iwtan_ap_el));
 
163
      curr = curr->next;
 
164
      curr->ap = _iwtan_copy_AP(*(context->ap_list + i));
 
165
      curr->next = NULL;
 
166
    }
 
167
  }
 
168
  
 
169
  pthread_mutex_unlock(&(context->mutex));
 
170
  return ret;
 
171
}
 
172
 
 
173
/*
 
174
  Get an array of (copies of) all the associations between APs and Stations currently present in the database, ordered by the stations MAC address.
 
175
  All the elements properties are copied so that they may be used thread-safely.
 
176
  The function iwtan_free_ass_array() should be called when the array of associations are no longer needed.
 
177
  Returns a pointer to the first element of the array and writes in elementsN the number of element (array size).
 
178
  Function is thread-safe.
 
179
*/
 
180
iwtan_association* iwtan_get_all_associations(iwtan_context* context, unsigned int* elementsN){
 
181
  pthread_mutex_lock(&(context->mutex));
 
182
  *elementsN = context->assN;
 
183
  iwtan_association* associations = calloc(context->assN, sizeof(iwtan_association));
 
184
  int i;
 
185
  iwtan_association* current;
 
186
  iwtan_association* currentNew;
 
187
  for (i=0; i<context->assN; i++){
 
188
    current = context->st_ass + i;
 
189
    currentNew = associations + i;
 
190
 
 
191
    currentNew->station = _iwtan_copy_station(current->station);
 
192
    currentNew->ap = _iwtan_copy_AP(current->ap);
 
193
  }
 
194
  pthread_mutex_unlock(&(context->mutex));
 
195
  return associations;
 
196
}
 
197
 
 
198
/* 
 
199
   Get an AP with the given essid.
 
200
   All the AP properties are copied so that they may be used thread-safely.
 
201
   The function iwtan_free_AP() should be called when the AP is no longer needed.
 
202
   Returns a pointer to the copied AP or NULL if an AP with the given MAC address was not found.
 
203
   Function is thread-safe.
 
204
 */
 
205
iwtan_ap* iwtan_get_by_essid(char* essid, iwtan_context* context){
 
206
  if (!essid) return NULL;
 
207
  iwtan_ap* ret = NULL;
 
208
  iwtan_ap* current;
 
209
  int i=0;
 
210
  pthread_mutex_lock(&(context->mutex));
 
211
  while (i < context->apN){
 
212
    current = *(context->ap_list + i);
 
213
    if (current->essid)
 
214
      if (!strcmp(current->essid, essid)) {
 
215
        ret=_iwtan_copy_AP(current);
 
216
        break;
 
217
      }
 
218
      i++;
 
219
  }
 
220
  pthread_mutex_unlock(&(context->mutex));
 
221
  return ret;
 
222
}
 
223
 
 
224
 
 
225
/* +++++++++++++++++++++++++++ UTILITY FUNCTIONS ++++++++++++++++++++++++++++ */
 
226
 
 
227
/*
 
228
  Free an access point and all its elements. Returns 0 only on success.
 
229
*/
 
230
int iwtan_free_AP(iwtan_ap* ap){
 
231
  free(ap->bssId);
 
232
  free(ap->essid);
 
233
  free(ap->description);
 
234
  free(ap);
 
235
  return 0;
 
236
}
 
237
 
 
238
/*
 
239
  Free a station and all its elements. Returns 0 only on success.
 
240
*/
 
241
int iwtan_free_station(iwtan_station* st){
 
242
  free(st->mac);  
 
243
  free(st->ip4);  
 
244
  free(st->ip6);
 
245
  free(st);
 
246
  return 0;
 
247
}
 
248
 
 
249
/*
 
250
  Free a linked list of iwtan_station_el elements (such as the one created by iwtan_get_by_AP). Free both the elements and the list.
 
251
*/
 
252
int iwtan_free_stations_ll(iwtan_station_el* freeEl){
 
253
  iwtan_station_el* next;
 
254
  while (freeEl != NULL){
 
255
    next=freeEl->next;
 
256
    iwtan_free_station(freeEl->station);
 
257
    free(freeEl);
 
258
    freeEl=next;
 
259
  }
 
260
  return 0;
 
261
}
 
262
 
 
263
/*
 
264
  Free a linked list of iwtan_ap_el elements (such as the one created by iwtan_get_all_aps). Free the elements and the list.
 
265
*/
 
266
int iwtan_free_AP_ll(iwtan_ap_el* freeEl){
 
267
  iwtan_ap_el* next;
 
268
  while (freeEl != NULL){
 
269
    next=freeEl->next;
 
270
    iwtan_free_AP(freeEl->ap);
 
271
    free(freeEl);
 
272
    freeEl=next;
 
273
  }
 
274
  return 0;
 
275
}
 
276
 
 
277
/*
 
278
  Free all the elements of an array containing associations with the number of elements given by argument. Also frees the array.
 
279
*/
 
280
int iwtan_free_ass_array(iwtan_association* ass, int size){
 
281
  int i;
 
282
  iwtan_association* curr;
 
283
  for (i=0; i<size; i++){
 
284
    curr = ass+i;
 
285
    iwtan_free_station(curr->station);
 
286
    iwtan_free_AP(curr->ap);
 
287
  }
 
288
  free(ass);
 
289
  return 0;
 
290
}
 
291
 
 
292
/*
 
293
  Compare two mac addresses. Returns 0 if the two given addresses are the same, >0 if mac1>mac2, <0 otherwise. Not thread safe.
 
294
*/
 
295
int iwtan_cmp_mac(mac_address* mac1, mac_address* mac2){
 
296
  int i=0;
 
297
  while (i < ETH_ALEN && mac1->ether_addr_octet[i]== mac2->ether_addr_octet[i]) i++;
 
298
  if (i==ETH_ALEN)
 
299
    return 0;
 
300
 
 
301
  return mac1->ether_addr_octet[i] - mac2->ether_addr_octet[i];
 
302
}
 
303
 
 
304
/*
 
305
  Convert an IPv4 address to a string in the standard notation.
 
306
  The string will be stored in the address pointed by result, that must be of size 16 at least.
 
307
  Returns a pointer to the string or NULL on errors.
 
308
*/
 
309
char* iwtan_ip4toa(ip4_address ip4, char* result){
 
310
  if (!ip4) return NULL;
 
311
  sprintf(result, "%d.%d.%d.%d", *(ip4), *(ip4+1), *(ip4+2), *(ip4+3));
 
312
  return result;
 
313
}
 
314
 
 
315
/* Convert an IPv6 address to a string in the standard notation.
 
316
   The string will be stored in the address pointed by result, that must be of size 40 at least.
 
317
   Returns a pointer to the string or NULL on errors.
 
318
*/
 
319
char* iwtan_ip6toa(ip6_address ip6, char* result){
 
320
  if (!ip6) return NULL;
 
321
  int group;
 
322
  char* str = result;
 
323
  for(group=0; group<8; group++){
 
324
    if (*(ip6+group*2)!=0 || *(ip6+group*2+1)!=0){
 
325
      sprintf(str, "%.2x%.2x\0", *(ip6+group*2), *(ip6+group*2+1));
 
326
      str+=4;
 
327
    }
 
328
    if (group != 7 ) {
 
329
      strcpy(str, ":");
 
330
      str++;
 
331
    }
 
332
  }
 
333
  return result;
 
334
}
 
335
 
 
336
 
 
337
/*+++++++++++++++++++ INTERNAL UTILITY FUNCTIONS +++++++++++++++++++++++++++++*/
 
338
 
 
339
/*
 
340
  Add an association between a wireless station and an access point.
 
341
  If the station mac address is already present in the database, the association gets refreshed with the new associated AP. 
 
342
  If the AP was not present in the database, a new one is created.
 
343
  Returns 0 if the new association has been made, !=0 on errors.
 
344
*/
 
345
int _iwtan_add_association(mac_address* bssId, mac_address* station_mac, iwtan_context* context){
 
346
  if (bssId == NULL || station_mac == NULL) return 1;
 
347
 
 
348
  /* Search for previousely existing associations for the station MAC address*/
 
349
  iwtan_station* station;
 
350
  int prevPos = _iwtan_bsearch_by_station(station_mac, context);
 
351
  if (prevPos == -1){
 
352
    /*If the station is not present, we have to create it*/
 
353
    station = calloc(1, sizeof(iwtan_station));
 
354
    _iwtan_init_station(station_mac, station);
 
355
 
 
356
    iwtan_ap** ap_ref = _iwtan_bsearch_AP(bssId, context);
 
357
    iwtan_ap* ap=NULL;
 
358
    if (ap_ref == NULL){
 
359
      /*If the access point is not present in the database, we have to create the new access point.*/
 
360
      ap = _iwtan_add_new_AP(bssId, context);
 
361
    } else
 
362
      ap = *ap_ref;
 
363
    
 
364
    _iwtan_add_new_association(station, ap, context);
 
365
    ap->lastSeen = time(NULL);
 
366
    ap->associations++;
 
367
  }
 
368
  else {
 
369
    /*If the station is already present, we have to re-associate it to the new access point*/
 
370
    iwtan_association* ass = context->st_ass + prevPos;
 
371
    ass->station->lastSeen = time(NULL);
 
372
    iwtan_ap* oldAP = ass->ap;
 
373
    oldAP->associations--;
 
374
    iwtan_ap** newAP_ref = _iwtan_bsearch_AP(bssId, context);
 
375
    iwtan_ap* newAP;
 
376
 
 
377
    if (newAP_ref == NULL){
 
378
      /*If the access point is not present in the database, we have to create the new access point.*/
 
379
      newAP = _iwtan_add_new_AP(bssId, context);
 
380
    } else {
 
381
      newAP = *newAP_ref;
 
382
    }
 
383
 
 
384
    newAP->lastSeen = time(NULL);
 
385
    newAP->associations++;
 
386
    ass->ap = newAP; //in any case edit the st_ass
 
387
    
 
388
    /*Find the association in ap_ass to the old access point and copy to it.*/
 
389
    int APPosI = _iwtan_first_bsearch_by_AP(oldAP->bssId, context);
 
390
    while (iwtan_cmp_mac(station_mac, ((iwtan_association*)(context->ap_ass + APPosI))->station->mac)) APPosI++;
 
391
    *(context->ap_ass + APPosI) = *ass;
 
392
  }
 
393
 
 
394
  /*In any case, reorder the lists.*/
 
395
  qsort(context->ap_ass, context->assN, sizeof(*(context->ap_ass)), (int(*)(const void *, const void *))_iwtan_cmp_assoc_by_AP);
 
396
  qsort(context->st_ass, context->assN, sizeof(*(context->st_ass)), (int(*)(const void *, const void *))_iwtan_cmp_assoc_by_station);
 
397
  
 
398
  return 0;
 
399
}
 
400
 
 
401
/*
 
402
  Remove an access point from the list. Returns !=0 if and only if the given AP was not found or it was not empty (its associated stations was not 0). Not thread safe.
 
403
*/
 
404
int _iwtan_remove_AP (iwtan_ap* ap, iwtan_context* context){
 
405
  int i=0;  
 
406
  int r=-1;
 
407
  if (ap->associations != 0) return -1;
 
408
  while((i < context->apN) && (ap != ((iwtan_association*)(context->ap_ass + i))->ap)) i++;
 
409
  if (i != context->apN){
 
410
    i++;
 
411
    while (i<context->apN){
 
412
      *(context->ap_ass + i -1) = *(context->ap_ass + i);
 
413
      i++;
 
414
    }
 
415
    iwtan_free_AP(ap);
 
416
    r = 0;
 
417
  }
 
418
  return r;
 
419
}
 
420
 
 
421
/*
 
422
  Add an access point with the given BSS Id to the list of access points. The AP should not be present in the list before calling this function.
 
423
  The list gets ordered by the access points MAC address.
 
424
  Not thread safe.
 
425
  Returns a pointer to the Access Point
 
426
*/
 
427
iwtan_ap* _iwtan_add_new_AP(mac_address* bssId, iwtan_context* context){
 
428
  if (context->apN == context->allAP){
 
429
    context->allAP *= 2;
 
430
    context->ap_list = realloc(context->ap_list, context->allAP * sizeof(iwtan_ap*));
 
431
  }
 
432
  iwtan_ap* newAP = calloc(1, sizeof(iwtan_ap));
 
433
  _iwtan_init_AP(bssId, newAP);
 
434
  *(context->ap_list + context->apN) = newAP;
 
435
  context->apN++;
 
436
  qsort(context->ap_list, context->apN, sizeof(iwtan_ap*), (int(*)(const void *, const void *))_iwtan_cmp_AP);
 
437
  return newAP;
 
438
}
 
439
 
 
440
/*
 
441
  Add an association between a station and an AP to both ap_ass and st_ass.
 
442
  Note that no other corrispondences for that station should exist before.
 
443
  The list is not ordered and must be ordered after calling this function.
 
444
  The context mutex must be locked before calling this function (i.e. this function is not thread-safe).
 
445
  Returns 0 only on success.
 
446
*/
 
447
int _iwtan_add_new_association(iwtan_station* station, iwtan_ap* ap, iwtan_context* context){
 
448
  /* To preserve memory, if the allocated space is three times bigger than the contained elements, it get reduced to a third.*/
 
449
  if (context->allAss > 2*context->assN+10){
 
450
    context->allAss = context->allAss/2 + 1;
 
451
    context->ap_ass = realloc(context->ap_ass, context->allAss * sizeof(iwtan_association));
 
452
    context->st_ass = realloc(context->st_ass, context->allAss * sizeof(iwtan_association));    
 
453
  }
 
454
  /* If there is not enought allocated memory, the space is doubled.*/
 
455
  else if (context->allAss == context->assN){
 
456
    context->allAss *= 2;
 
457
    context->ap_ass = realloc(context->ap_ass, context->allAss * sizeof(iwtan_association));
 
458
    context->st_ass = realloc(context->st_ass, context->allAss * sizeof(iwtan_association));    
 
459
  }
 
460
 
 
461
  iwtan_association* newApAss = context->ap_ass + context->assN;
 
462
  newApAss->station = station;
 
463
  newApAss->ap = ap;
 
464
  iwtan_association* newStAss = context->st_ass + context->assN;
 
465
  newStAss->station = station;
 
466
  newStAss->ap = ap;
 
467
 
 
468
  context->assN++;
 
469
  return 0;
 
470
}
 
471
 
 
472
/*
 
473
  Update the data of an Access Point with those passed by argument.
 
474
  Arguments are considered (and data is updated) only if their values are significant.
 
475
  For pointer-arguments, the old data is freed and replaced with the argument only if the old and new pointer are not the same.
 
476
  ap: the AP to update.
 
477
  wepped: 1 => wepped, 0 => not wepped, -1 => not significant.
 
478
  dataRate: the data rate in Mbps. 0 => not significant.
 
479
  antenna: the antenna number. 0 => non significant.
 
480
  frequency: the frequency in MHz. 0 => non significant.
 
481
  type: the AP type (see iwtan_ap). 0 => non significant.
 
482
  signal: the signal strenght. 0 => non significant.
 
483
  mac: a pointer to the AP MAC address. NULL => non significant.
 
484
  bssId: a pointer to the AP BSS id. NULL => non significant.
 
485
  essid: a pointer to the AP essid string. NULL => non significant.
 
486
  description: a pointer to the AP description set by the user. NULL => non significant.
 
487
  lastSeen: the time this access point was seen for the last time. NULL => non significant.
 
488
*/
 
489
int _iwtan_update_AP (iwtan_ap* ap, short wepped, unsigned int dataRate, unsigned short antenna, unsigned int frequency, short type, short signal, mac_address* bssId, char* essid, char* description, time_t lastSeen){
 
490
  if (wepped != -1) ap->WEPped = wepped;
 
491
  if (dataRate != 0) ap->dataRate = dataRate;
 
492
  if (antenna != 0) ap->antenna = antenna;
 
493
  if (frequency != 0) ap->frequency = frequency;
 
494
  if (type !=0) ap->type = type;
 
495
  if (signal != 0) ap->signal = signal;
 
496
  if (bssId && (bssId != ap->bssId)) {
 
497
    free(ap->bssId);
 
498
    ap->bssId = bssId;
 
499
  }
 
500
  if (essid && (essid != ap->essid)) {
 
501
    free(ap->essid);
 
502
    ap->essid = essid;
 
503
  }
 
504
  if (description && (description != ap->description)){
 
505
    free(ap->description);
 
506
    ap->description = description;
 
507
  }
 
508
  if (lastSeen)
 
509
    ap->lastSeen = lastSeen;
 
510
}
 
511
 
 
512
/*
 
513
  Update the data of a Station with those passed by argument.
 
514
  Arguments are considered (and data is updated) only if their values are significant.
 
515
  For pointer-arguments, the old data is freed and replaced with the argument only if the old and new pointer are not the same.
 
516
  st: the station to update.
 
517
  ip4: a pointer to the station IPv4. NULL => non significant.
 
518
  mac: a pointer to the station MAC address. NULL => non significant.
 
519
  ip6: a pointer to the station IPv6. NULL => non significant.
 
520
  lastSeen: the time this station was seen for the last time. 0 => non significant.
 
521
*/
 
522
int _iwtan_update_station (iwtan_station* st, ip4_address ip4, mac_address* mac, ip6_address ip6, time_t lastSeen){
 
523
  if (ip4 && (ip4 != st->ip4)){
 
524
    free(st->ip4); //TODO: may be optimized...
 
525
    st->ip4 = ip4;
 
526
  }
 
527
  if (mac && (mac != st->mac)) {
 
528
    free(st->mac);
 
529
    st->mac = mac; 
 
530
  }
 
531
  if (ip6 && (ip6 != st->ip6)) {
 
532
    free(st->ip6);
 
533
    st->ip6 = ip6; 
 
534
  }
 
535
  if (lastSeen)
 
536
    st->lastSeen = lastSeen;
 
537
}
 
538
 
 
539
 
 
540
/*
 
541
  Makes a binary search and returns the position in st_ass of the association whose Station MAC address is the one given by argument.
 
542
  Returns -1 if such an element is not found. The associations list must be ordered by the Station MAC address.
 
543
*/
 
544
int _iwtan_bsearch_by_station (mac_address* st_mac, iwtan_context* con){
 
545
  iwtan_association hypApAss; //an hypotetical association whose Station has the given mac address
 
546
  iwtan_station hypSt;
 
547
  hypApAss.station = &hypSt;
 
548
  hypSt.mac = st_mac;
 
549
 
 
550
  iwtan_association* el = bsearch(&hypApAss, con->st_ass, con->assN, sizeof(iwtan_association), (int(*)(const void*, const void*))_iwtan_cmp_assoc_by_station);
 
551
  if (el==NULL) return -1;
 
552
  
 
553
  return el - con->st_ass;
 
554
}
 
555
 
 
556
/*
 
557
  Search for a station with the given MAC address. Returns a pointer to the station or NULL if not found.
 
558
*/
 
559
iwtan_station*  _iwtan_bsearch_station(mac_address* st_mac, iwtan_context* con){
 
560
  iwtan_association* ass = NULL;
 
561
  unsigned int idx = _iwtan_bsearch_by_station(st_mac, con);
 
562
  if (idx != -1) ass = con->st_ass + idx;
 
563
  return ass ? ass->station : NULL;
 
564
}
 
565
 
 
566
 
 
567
/*
 
568
  Search for an access point in the list and return its index. The context mutex must be locked before calling this function. Returns a pointer to the address where the Access Point is allocated.
 
569
*/
 
570
iwtan_ap** _iwtan_bsearch_AP(mac_address* bssId, iwtan_context* context){
 
571
  iwtan_ap hypAP;
 
572
  const iwtan_ap* hypAP_ref = &hypAP;
 
573
  hypAP.bssId = bssId;
 
574
  return bsearch(&hypAP_ref, context->ap_list, context->apN, sizeof(iwtan_ap*), (int(*)(const void*, const void*))_iwtan_cmp_AP);
 
575
}
 
576
 
 
577
/*
 
578
  Makes a binary search and returns the position of the first association whose Access Point MAC address is the one given by argument.
 
579
  Returns -1 if such an element is not found.
 
580
  The associations list must be ordered by the Access Point MAC address.
 
581
  The context mutex must be locked before calling this function.
 
582
*/
 
583
int _iwtan_first_bsearch_by_AP(mac_address* bssId, iwtan_context* con){
 
584
  iwtan_association hypApAss; //an hypotetical association whose AP has the given mac address
 
585
  iwtan_ap hypAP;
 
586
  hypApAss.ap = &hypAP;
 
587
  hypAP.bssId = bssId;
 
588
 
 
589
  iwtan_association* el = bsearch(&hypApAss, con->ap_ass, con->assN, sizeof(iwtan_association), (int(*)(const void*, const void*))_iwtan_cmp_assoc_by_AP);
 
590
  if (el==NULL) return -1;
 
591
  
 
592
  unsigned int i = el - con->ap_ass; //last certian element
 
593
  iwtan_association* assNext;
 
594
  while (i>=1){
 
595
    assNext = con->ap_ass+i-1;
 
596
    if (iwtan_cmp_mac(assNext->ap->bssId, bssId)) return i;
 
597
    i--;
 
598
  }
 
599
  return 0;
 
600
}
 
601
 
 
602
/*
 
603
  Initialize an empty AP with the given MAC address
 
604
*/
 
605
int _iwtan_init_AP(mac_address* bssId, iwtan_ap* ap){
 
606
  ap->bssId = bssId;
 
607
  ap->associations=0;
 
608
  ap->lastSeen = time(NULL);
 
609
  return 0;
 
610
}
 
611
 
 
612
/*
 
613
  Initialize a station with the given mac address
 
614
*/
 
615
int _iwtan_init_station(mac_address* st_mac, iwtan_station* station){
 
616
  station->mac = st_mac;
 
617
  station->lastSeen = time(NULL);
 
618
  return 0;
 
619
}  
 
620
 
 
621
/*
 
622
  Compare two associations by their Access Point mac address.
 
623
*/
 
624
int _iwtan_cmp_assoc_by_AP(const iwtan_association* ass1, const iwtan_association* ass2){
 
625
  return iwtan_cmp_mac(ass1->ap->bssId, ass2->ap->bssId);
 
626
}
 
627
 
 
628
/*
 
629
  Compare two associations by their station mac address
 
630
*/
 
631
int _iwtan_cmp_assoc_by_station(const iwtan_association* ass1, const iwtan_association* ass2){
 
632
  return iwtan_cmp_mac(ass1->station->mac, ass2->station->mac);
 
633
}
 
634
 
 
635
/*
 
636
  Compare two access points by their BSS Id.
 
637
*/
 
638
int _iwtan_cmp_AP(const iwtan_ap** ap1_ref, const iwtan_ap** ap2_ref){
 
639
  const iwtan_ap* ap1 = *ap1_ref;
 
640
  const iwtan_ap* ap2 = *ap2_ref;
 
641
  return iwtan_cmp_mac(ap1->bssId, ap2->bssId);
 
642
}
 
643
 
 
644
/*
 
645
  Returns a copy of the station given by argument, with all its elements copied.
 
646
*/
 
647
iwtan_station* _iwtan_copy_station (iwtan_station* st){
 
648
  iwtan_station* newStation = calloc(1, sizeof(iwtan_station));
 
649
  newStation->ip4 = _iwtan_copy_ip4(st->ip4);
 
650
  newStation->ip6 = _iwtan_copy_ip6(st->ip6);
 
651
  newStation->mac = _iwtan_copy_mac(st->mac);
 
652
  newStation->lastSeen = st->lastSeen;
 
653
  return newStation;
 
654
}
 
655
 
 
656
/*
 
657
  Returns a copy of the Access Point given by argument, with all its elements copied.
 
658
*/
 
659
iwtan_ap* _iwtan_copy_AP (iwtan_ap* ap){
 
660
  iwtan_ap* newAP = calloc(1, sizeof(iwtan_ap));
 
661
  
 
662
  *newAP = *ap;
 
663
  if (ap->essid){
 
664
    newAP->essid = calloc(strlen(ap->essid) + 1, sizeof(char));
 
665
    strcpy(newAP->essid, ap->essid);
 
666
  } else 
 
667
    newAP->essid = NULL;
 
668
 
 
669
  if (ap->description){
 
670
    newAP->description = calloc(strlen(ap->description) + 1, sizeof(char));
 
671
    strcpy(newAP->description, ap->description);}
 
672
 
 
673
  newAP->bssId = _iwtan_copy_mac(ap->bssId);
 
674
 
 
675
  return newAP;
 
676
}
 
677
 
 
678
/*
 
679
  Returns a copy of the IPv4 address given by argument.
 
680
*/
 
681
ip4_address _iwtan_copy_ip4(ip4_address ip4){
 
682
  if (!ip4) return NULL;
 
683
  ip4_address newIP4 = calloc(IWTAN_IP4_LEN, sizeof(uint8_t));
 
684
  int i;
 
685
  for(i=0;i<IWTAN_IP4_LEN; i++)
 
686
    *(newIP4+i) = *(ip4+i);
 
687
  return newIP4;
 
688
}
 
689
 
 
690
/*
 
691
  Returns a copy of the IPv6 address given by argument.
 
692
*/
 
693
ip6_address _iwtan_copy_ip6(ip6_address ip6){
 
694
  if (!ip6) return NULL;
 
695
  ip6_address newIP6 = calloc(IWTAN_IP6_LEN, sizeof(uint8_t));
 
696
  int i;
 
697
  for(i=0;i<IWTAN_IP6_LEN; i++)
 
698
    *(newIP6 + i) = *(ip6 + i);
 
699
  return newIP6;
 
700
}
 
701
 
 
702
/*
 
703
  Returns a copy of the MAC address given by argument.
 
704
*/
 
705
mac_address* _iwtan_copy_mac(mac_address* mac){
 
706
  if (!mac) return NULL;
 
707
  mac_address* newMac = malloc(sizeof(mac_address));
 
708
  int i;
 
709
  for(i=0;i<sizeof(mac_address); i++)
 
710
    newMac->ether_addr_octet[i] = mac->ether_addr_octet[i];
 
711
  return newMac;
 
712
}
 
713
 
 
714
/*
 
715
  Copy a newly allocated MAC address with the bytes pointed by array.
 
716
*/
 
717
mac_address* _iwtan_copy_mac_by_array(uint8_t* array){
 
718
  if (!array) return NULL;
 
719
  mac_address* newMac = malloc(sizeof(mac_address));
 
720
  int i;
 
721
  for(i=0;i<sizeof(mac_address); i++)
 
722
    newMac->ether_addr_octet[i] = *(array+i);
 
723
  return newMac;
 
724
}