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

« back to all changes in this revision

Viewing changes to ntop/util.c

  • Committer: Bazaar Package Importer
  • Author(s): Ola Lundqvist
  • Date: 2005-01-30 21:59:13 UTC
  • mfrom: (2.1.1 warty)
  • Revision ID: james.westby@ubuntu.com-20050130215913-xc3ke963bw49b3k4
Tags: 2:3.0-5
* Updated README.Debian file so users will understand what to do at
  install, closes: #291794, #287802.
* Updated ntop init script to give better output.
* Also changed log directory from /var/lib/ntop to /var/log/ntop,
  closes: #252352.
* Quoted the interface list to allow whitespace, closes: #267248.
* Added a couple of logcheck ignores, closes: #269321, #269319.

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
/*
2
 
 *  Copyright (C) 1998-2001 Luca Deri <deri@ntop.org>
3
 
 *                          Portions by Stefano Suin <stefano@ntop.org>
4
 
 *
5
 
 *                          http://www.ntop.org/
6
 
 *
7
 
 *  This program is free software; you can redistribute it and/or modify
8
 
 *  it under the terms of the GNU General Public License as published by
9
 
 *  the Free Software Foundation; either version 2 of the License, or
10
 
 *  (at your option) any later version.
11
 
 *
12
 
 *  This program is distributed in the hope that it will be useful,
13
 
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
14
 
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15
 
 *  GNU General Public License for more details.
16
 
 *
17
 
 *  You should have received a copy of the GNU General Public License
18
 
 *  along with this program; if not, write to the Free Software
19
 
 *  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
20
 
 */
21
 
 
22
 
/*
23
 
 * Copyright (c) 1994, 1996
24
 
 *      The Regents of the University of California.  All rights reserved.
25
 
 *
26
 
 * Redistribution and use in source and binary forms, with or without
27
 
 * modification, are permitted provided that: (1) source code distributions
28
 
 * retain the above copyright notice and this paragraph in its entirety, (2)
29
 
 * distributions including binary code include the above copyright notice and
30
 
 * this paragraph in its entirety in the documentation or other materials
31
 
 * provided with the distribution, and (3) all advertising materials mentioning
32
 
 * features or use of this software display the following acknowledgement:
33
 
 * ``This product includes software developed by the University of California,
34
 
 * Lawrence Berkeley Laboratory and its contributors.'' Neither the name of
35
 
 * the University nor the names of its contributors may be used to endorse
36
 
 * or promote products derived from this software without specific prior
37
 
 * written permission.
38
 
 * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED
39
 
 * WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
40
 
 * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
41
 
 */
42
 
 
43
 
#define _UTIL_C_
44
 
 
45
 
/*
46
 
  #define STORAGE_DEBUG
47
 
  #define DEBUG
48
 
*/
49
 
 
50
 
#include "ntop.h"
51
 
#include <stdarg.h>
52
 
 
53
 
#ifndef WIN32
54
 
#include <syslog.h>
55
 
#endif
56
 
 
57
 
/* #define MEMORY_DEBUG  */
58
 
 
59
 
#define MAX_DEVICE_NAME_LEN   64
60
 
 
61
 
#ifdef MEMORY_DEBUG
62
 
#include "leaks.h"
63
 
#endif
64
 
 
65
 
/* Local */
66
 
#define MAX_NUM_NETWORKS      32
67
 
#define NETWORK                0
68
 
#define NETMASK                1
69
 
#define BROADCAST              2
70
 
#define INVALIDNETMASK        -1
71
 
 
72
 
#define NUM_SESSION_INFO                     128
73
 
#define MAX_NUM_SESSION_INFO  2*NUM_SESSION_INFO  /* Not yet used */
74
 
 
75
 
#define PASSIVE_SESSION_PURGE_TIMEOUT    60 /* seconds */
76
 
 
77
 
static SessionInfo *passiveSessions;
78
 
static u_short numLocalNets=0, passiveSessionsLen;
79
 
 
80
 
/* [0]=network, [1]=mask, [2]=broadcast */
81
 
static u_int32_t networks[MAX_NUM_NETWORKS][3];
82
 
 
83
 
/*
84
 
 * secure popen by Thomas Biege <thomas@suse.de>
85
 
 *
86
 
 * Fixes by Andreas Pfaller <a.pfaller@pop.gun.de>
87
 
 */
88
 
#define __SEC_POPEN_TOKEN " "
89
 
 
90
 
#ifndef WIN32
91
 
#ifdef SEC_POPEN
92
 
FILE *sec_popen(char *cmd, const char *type) {
93
 
  pid_t pid;
94
 
  int pfd[2];
95
 
  FILE *pfile;
96
 
  int rpipe = 0, wpipe = 0, i;
97
 
  char **argv, *ptr, *cmdcpy=NULL, *strtokState;
98
 
  if(cmd == NULL || cmd == "")
99
 
    return(NULL);
100
 
 
101
 
  if(strcmp(type, "r") && strcmp(type, "w"))
102
 
    return(NULL);
103
 
 
104
 
  if((cmdcpy = strdup(cmd)) == NULL)
105
 
    return(NULL);
106
 
 
107
 
  argv = NULL;
108
 
  if((ptr = strtok_r(cmdcpy, __SEC_POPEN_TOKEN, &strtokState)) == NULL) {
109
 
    free(cmdcpy);
110
 
    return(NULL);
111
 
  }
112
 
 
113
 
  for(i = 0;; i++) {
114
 
    if((argv = (char **)realloc(argv, (i+1) * sizeof(char*))) == NULL) {
115
 
      free(cmdcpy);
116
 
      return(NULL);
117
 
    }
118
 
 
119
 
    if((*(argv+i) = (char*)malloc((strlen(ptr)+1) * sizeof(char))) == NULL) {
120
 
      free(cmdcpy);
121
 
      return(NULL);
122
 
    }
123
 
 
124
 
    strcpy(argv[i], ptr);
125
 
 
126
 
    if((ptr = strtok_r(NULL, __SEC_POPEN_TOKEN, &strtokState)) == NULL) {
127
 
      if((argv = (char **) realloc(argv, (i+2) * sizeof(char*))) == NULL) {
128
 
        free(cmdcpy);
129
 
        return(NULL);
130
 
      }
131
 
      argv[i+1] = NULL;
132
 
      break;
133
 
    }
134
 
  }
135
 
 
136
 
  free(cmdcpy);
137
 
 
138
 
  if(type[0] == 'r')
139
 
    rpipe = 1;
140
 
  else
141
 
    wpipe = 1;
142
 
 
143
 
  if(pipe(pfd) < 0)
144
 
    return(NULL);
145
 
 
146
 
  if((pid = fork()) < 0) {
147
 
    close(pfd[0]);
148
 
    close(pfd[1]);
149
 
    return(NULL);
150
 
  }
151
 
 
152
 
  if(pid == 0) {
153
 
    /* child */
154
 
    if((pid = fork()) < 0) {
155
 
      close(pfd[0]);
156
 
      close(pfd[1]);
157
 
      return(NULL);
158
 
    }
159
 
 
160
 
    if(pid > 0) {
161
 
      /* parent */
162
 
      exit(0); /* child nr. 1 exits */
163
 
    } else {
164
 
      /* child nr. 2 */
165
 
      if(rpipe) {
166
 
        close(pfd[0]); /* close reading end, we don't need it */
167
 
        if(pfd[1] != STDOUT_FILENO)
168
 
          dup2(pfd[1], STDOUT_FILENO); /* redirect stdout to writing end of pipe */
169
 
        dup2(STDOUT_FILENO, STDERR_FILENO);
170
 
      } else {
171
 
        close(pfd[1]);  /* close writing end, we don't need it */
172
 
 
173
 
        if(pfd[0] != STDIN_FILENO)
174
 
          dup2(pfd[0], STDOUT_FILENO); /* redirect stdin to reading end of pipe */
175
 
      }
176
 
 
177
 
      if(strchr(argv[0], '/') == NULL)
178
 
        execvp(argv[0], argv);  /* search in $PATH */
179
 
      else
180
 
        execv(argv[0], argv);
181
 
 
182
 
      close(pfd[0]);
183
 
      close(pfd[1]);
184
 
      return(NULL); /* exec failed.. ooops! */
185
 
    }
186
 
  } else {
187
 
    /* parent */
188
 
    waitpid(pid, NULL, 0); /* wait for child nr. 1 */
189
 
 
190
 
    if(rpipe) {
191
 
      close(pfd[1]);
192
 
      return(fdopen(pfd[0], "r"));
193
 
    } else {
194
 
      close(pfd[0]);
195
 
      return(fdopen(pfd[1], "r"));
196
 
    }
197
 
  }
198
 
}
199
 
#endif /* SEC_POPEN */
200
 
 
201
 
#endif /* WIN32 */
202
 
 
203
 
/* ************************************ */
204
 
 
205
 
u_int findHostIdxByNumIP(struct in_addr hostIpAddress) {
206
 
  u_int idx;
207
 
 
208
 
  for(idx=1; idx<device[actualDeviceId].actualHashSize; idx++)
209
 
    if((device[actualDeviceId].hash_hostTraffic[idx] != NULL)
210
 
       && (device[actualDeviceId].hash_hostTraffic[idx]->hostNumIpAddress != NULL)
211
 
       && (device[actualDeviceId].hash_hostTraffic[idx]->hostIpAddress.s_addr == hostIpAddress.s_addr))
212
 
      return(idx);
213
 
 
214
 
  return(NO_PEER);
215
 
}
216
 
 
217
 
/* ************************************ */
218
 
 
219
 
HostTraffic* findHostByNumIP(char* numIPaddr) {
220
 
  u_int idx;
221
 
 
222
 
  for(idx=1; idx<device[actualDeviceId].actualHashSize; idx++)
223
 
    if((device[actualDeviceId].hash_hostTraffic[idx] != NULL)
224
 
       && (device[actualDeviceId].hash_hostTraffic[idx]->hostNumIpAddress != NULL)
225
 
       && (!strcmp(device[actualDeviceId].hash_hostTraffic[idx]->hostNumIpAddress, numIPaddr)))
226
 
      return(device[actualDeviceId].hash_hostTraffic[idx]);
227
 
 
228
 
  return(NULL);
229
 
}
230
 
 
231
 
/* ************************************ */
232
 
 
233
 
HostTraffic* findHostByMAC(char* macAddr) {
234
 
  u_int idx;
235
 
 
236
 
  for(idx=1; idx<device[actualDeviceId].actualHashSize; idx++)
237
 
    if(device[actualDeviceId].hash_hostTraffic[idx]
238
 
       && device[actualDeviceId].hash_hostTraffic[idx]->hostNumIpAddress
239
 
       && (!strcmp(device[actualDeviceId].hash_hostTraffic[idx]->ethAddressString, macAddr)))
240
 
      return(device[actualDeviceId].hash_hostTraffic[idx]);
241
 
 
242
 
  return(NULL);
243
 
}
244
 
 
245
 
/* ************************************ */
246
 
 
247
 
/*
248
 
 * Copy arg vector into a new buffer, concatenating arguments with spaces.
249
 
 */
250
 
char* copy_argv(register char **argv) {
251
 
  register char **p;
252
 
  register u_int len = 0;
253
 
  char *buf;
254
 
  char *src, *dst;
255
 
 
256
 
  p = argv;
257
 
  if(*p == 0)
258
 
    return 0;
259
 
 
260
 
  while (*p)
261
 
    len += strlen(*p++) + 1;
262
 
 
263
 
  buf = (char*)malloc(len);
264
 
  if(buf == NULL) {
265
 
    traceEvent(TRACE_INFO, "copy_argv: malloc");
266
 
    exit(-1);
267
 
  }
268
 
 
269
 
  p = argv;
270
 
  dst = buf;
271
 
  while ((src = *p++) != NULL) {
272
 
    while ((*dst++ = *src++) != '\0')
273
 
      ;
274
 
    dst[-1] = ' ';
275
 
  }
276
 
  dst[-1] = '\0';
277
 
 
278
 
  return buf;
279
 
}
280
 
 
281
 
/* ********************************* */
282
 
 
283
 
unsigned short isBroadcastAddress(struct in_addr *addr) {
284
 
  int i;
285
 
 
286
 
  if(addr == NULL)
287
 
    return 1;
288
 
  else if(addr->s_addr == 0x0)
289
 
    return 0; /* IP-less device (is it trying to boot via DHCP/BOOTP ?) */
290
 
  else {
291
 
    for(i=0; i<numDevices; i++)
292
 
      if(device[i].netmask.s_addr == 0xFFFFFFFF) /* PPP */
293
 
        return 0;
294
 
      else if(((addr->s_addr | device[i].netmask.s_addr) ==  addr->s_addr)
295
 
              || ((addr->s_addr & 0x000000FF) == 0x000000FF)
296
 
              || ((addr->s_addr & 0x000000FF) == 0x00000000) /* Network address */
297
 
              ) {
298
 
#ifdef DEBUG
299
 
        traceEvent(TRACE_INFO, "%s is a broadcast address", intoa(*addr));
300
 
#endif
301
 
        return 1;
302
 
      }
303
 
 
304
 
    return(isPseudoBroadcastAddress(addr));
305
 
  }
306
 
}
307
 
 
308
 
/* ********************************* */
309
 
 
310
 
unsigned short isMulticastAddress(struct in_addr *addr) {
311
 
  if((addr->s_addr & MULTICAST_MASK) == MULTICAST_MASK) {
312
 
#ifdef DEBUG
313
 
    traceEvent(TRACE_INFO, "%s is multicast [%X/%X]\n",
314
 
               intoa(*addr),
315
 
               ((unsigned long)(addr->s_addr) & MULTICAST_MASK),
316
 
               MULTICAST_MASK
317
 
               );
318
 
#endif
319
 
    return 1;
320
 
  } else
321
 
    return 0;
322
 
}
323
 
 
324
 
/* ********************************* */
325
 
 
326
 
unsigned short isLocalAddress(struct in_addr *addr) {
327
 
  int i;
328
 
 
329
 
  for(i=0; i<numDevices; i++)
330
 
    if((addr->s_addr & device[i].netmask.s_addr) == device[i].network.s_addr) {
331
 
#ifdef DEBUG
332
 
      traceEvent(TRACE_INFO, "%s is local\n", intoa(*addr));
333
 
#endif
334
 
      return 1;
335
 
    }
336
 
 
337
 
#ifdef DEBUG
338
 
  traceEvent(TRACE_INFO, "%s is %s\n", intoa(*addr),
339
 
             isLocalAddress (addr) ? "pseudolocal" : "remote");
340
 
#endif
341
 
  /* Broadcast is considered a local address */
342
 
  return(isBroadcastAddress(addr));
343
 
}
344
 
 
345
 
/* ********************************* */
346
 
 
347
 
unsigned short isPrivateAddress(struct in_addr *addr) {
348
 
 
349
 
  /* See http://www.isi.edu/in-notes/rfc1918.txt */
350
 
  
351
 
  /* Fixes below courtesy of Wies-Software <wies@wiessoft.de> */
352
 
  if(((addr->s_addr & 0xFF000000) == 0x0A000000)    /* 10/8      */
353
 
     || ((addr->s_addr & 0xFFF00000) == 0xAC100000) /* 172.16/12  */
354
 
     || ((addr->s_addr & 0xFFFF0000) == 0xC0A80000) /* 192.168/16 */
355
 
     )
356
 
    return(1);
357
 
  else
358
 
    return(0);
359
 
}
360
 
 
361
 
/* **********************************************
362
 
 *
363
 
 * Description:
364
 
 *
365
 
 *  It converts an integer in the range
366
 
 *  from  0 to 255 in number of bits
367
 
 *  useful for netmask  calculation.
368
 
 *  The conversion is  valid if there
369
 
 *  is an uninterrupted sequence of
370
 
 *  bits set to 1 at the most signi-
371
 
 *  ficant positions. Example:
372
 
 *
373
 
 *     1111 1000 -> valid
374
 
 *     1110 1000 -> invalid
375
 
 *
376
 
 * Return values:
377
 
 *     0 - 8 (number of subsequent
378
 
 *            bits set to 1)
379
 
 *    -1     (INVALIDNETMASK)
380
 
 *
381
 
 *
382
 
 * Courtesy of Antonello Maiorca <marty@tai.it>
383
 
 *
384
 
 *********************************************** */
385
 
 
386
 
static int int2bits(int number) {
387
 
  int bits = 8;
388
 
  int test;
389
 
 
390
 
  if((number > 255) || (number < 0))
391
 
    {
392
 
#ifdef DEBUG
393
 
      traceEvent(TRACE_ERROR, "int2bits (%3d) = %d\n", number, INVALIDNETMASK);
394
 
#endif
395
 
      return(INVALIDNETMASK);
396
 
    }
397
 
  else
398
 
    {
399
 
      test = ~number & 0xff;
400
 
      while (test & 0x1)
401
 
        {
402
 
          bits --;
403
 
          test = test >> 1;
404
 
        }
405
 
      if(number != ((~(0xff >> bits)) & 0xff))
406
 
        {
407
 
#ifdef DEBUG
408
 
          traceEvent(TRACE_ERROR, "int2bits (%3d) = %d\n", number, INVALIDNETMASK);
409
 
#endif
410
 
          return(INVALIDNETMASK);
411
 
        }
412
 
      else
413
 
        {
414
 
#ifdef DEBUG
415
 
          traceEvent(TRACE_ERROR, "int2bits (%3d) = %d\n", number, bits);
416
 
#endif
417
 
          return(bits);
418
 
        }
419
 
    }
420
 
}
421
 
 
422
 
/* ***********************************************
423
 
 *
424
 
 * Description:
425
 
 *
426
 
 *  Converts a dotted quad notation
427
 
 *  netmask  specification  to  the
428
 
 *  equivalent number of bits.
429
 
 *  from  0 to 255 in number of bits
430
 
 *  useful for netmask  calculation.
431
 
 *  The converion is  valid if there
432
 
 *  is an  uninterrupted sequence of
433
 
 *  bits set to 1 at the most signi-
434
 
 *  ficant positions. Example:
435
 
 *
436
 
 *     1111 1000 -> valid
437
 
 *     1110 1000 -> invalid
438
 
 *
439
 
 * Return values:
440
 
 *     0 - 32 (number of subsequent
441
 
 *             bits set to 1)
442
 
 *    -1      (INVALIDNETMASK)
443
 
 *
444
 
 *
445
 
 * Courtesy of Antonello Maiorca <marty@tai.it>
446
 
 *
447
 
 *********************************************** */
448
 
 
449
 
int dotted2bits(char *mask) {
450
 
  int           fields[4];
451
 
  int           fields_num, field_bits;
452
 
  int           bits = 0;
453
 
  int           i;
454
 
 
455
 
  fields_num = sscanf(mask, "%d.%d.%d.%d",
456
 
                      &fields[0], &fields[1], &fields[2], &fields[3]);
457
 
  if((fields_num == 1) && (fields[0] <= 32) && (fields[0] >= 0))
458
 
    {
459
 
#ifdef DEBUG
460
 
      traceEvent(TRACE_ERROR, "dotted2bits (%s) = %d\n", mask, fields[0]);
461
 
#endif
462
 
      return(fields[0]);
463
 
    }
464
 
  for (i=0; i < fields_num; i++)
465
 
    {
466
 
      /* We are in a dotted quad notation. */
467
 
      field_bits = int2bits (fields[i]);
468
 
      switch (field_bits)
469
 
        {
470
 
        case INVALIDNETMASK:
471
 
          return(INVALIDNETMASK);
472
 
 
473
 
        case 0:
474
 
          /* whenever a 0 bits field is reached there are no more */
475
 
          /* fields to scan                                       */
476
 
#ifdef DEBUG
477
 
          traceEvent(TRACE_ERROR, "dotted2bits (%15s) = %d\n", mask, bits);
478
 
#endif
479
 
          /* In this case we are in a bits (not dotted quad) notation */
480
 
          return(bits /* fields[0] - L.Deri 08/2001 */);
481
 
 
482
 
        default:
483
 
          bits += field_bits;
484
 
        }
485
 
    }
486
 
#ifdef DEBUG
487
 
  traceEvent(TRACE_ERROR, "dotted2bits (%15s) = %d\n", mask, bits);
488
 
#endif
489
 
  return(bits);
490
 
}
491
 
 
492
 
/* ********************************* */
493
 
 
494
 
/* Example: "131.114.0.0/16,193.43.104.0/255.255.255.0" */
495
 
 
496
 
void handleLocalAddresses(char* addresses) {
497
 
  char *strtokState, *address = strtok_r(addresses, ",", &strtokState);
498
 
  int i;
499
 
 
500
 
  while(address != NULL) {
501
 
    char *mask = strchr(address, '/');
502
 
 
503
 
    if(mask == NULL)
504
 
      traceEvent(TRACE_INFO, "Unknown network '%s' (empty mask!). It has been ignored.\n", 
505
 
                 address);
506
 
    else {
507
 
      u_int32_t network, networkMask, broadcast;
508
 
      int bits, a, b, c, d;
509
 
 
510
 
      mask[0] = '\0';
511
 
      mask++;
512
 
      bits = dotted2bits (mask);
513
 
 
514
 
      if(sscanf(address, "%d.%d.%d.%d", &a, &b, &c, &d) != 4) {
515
 
        traceEvent(TRACE_ERROR, "Unknown network '%s' .. skipping. Check network numbers.\n",
516
 
                   address);
517
 
        address = strtok_r(NULL, ",", &strtokState);
518
 
        continue;
519
 
      }
520
 
 
521
 
      if(bits == INVALIDNETMASK) {
522
 
        /* malformed netmask specification */
523
 
        traceEvent(TRACE_ERROR, 
524
 
                   "The specified netmask %s is not valid. Skipping it..\n",
525
 
                   mask);
526
 
        address = strtok_r(NULL, ",", &strtokState);
527
 
        continue;
528
 
      }
529
 
 
530
 
      network     = ((a & 0xff) << 24) + ((b & 0xff) << 16) + ((c & 0xff) << 8) + (d & 0xff);
531
 
      networkMask = 0xffffffff >> bits;
532
 
      networkMask = ~networkMask;
533
 
 
534
 
#ifdef DEBUG
535
 
      traceEvent(TRACE_INFO, "Nw=%08X - Mask: %08X [%08X]\n",
536
 
                 network, networkMask, (network & networkMask));
537
 
#endif
538
 
 
539
 
      if((networkMask >= 0xFFFFFF00) /* Courtesy of Roy-Magne Mo <romo@interpost.no> */
540
 
         && ((network & networkMask) != network))  {
541
 
        /* malformed network specification */
542
 
        traceEvent(TRACE_ERROR, "WARNING: %d.%d.%d.%d/%d is not a valid network number\n",
543
 
                   a, b, c, d, bits);
544
 
 
545
 
        /* correcting network numbers as specified in the netmask */
546
 
        network &= networkMask;
547
 
 
548
 
        a = (int) ((network >> 24) & 0xff);
549
 
        b = (int) ((network >> 16) & 0xff);
550
 
        c = (int) ((network >>  8) & 0xff);
551
 
        d = (int) ((network >>  0) & 0xff);
552
 
 
553
 
        traceEvent(TRACE_ERROR, "Assuming %d.%d.%d.%d/%d [0x%08x/0x%08x]\n\n",
554
 
                   a, b, c, d, bits, network, networkMask);
555
 
      }
556
 
#ifdef DEBUG
557
 
      traceEvent(TRACE_INFO, "%d.%d.%d.%d/%d [0x%08x/0x%08x]\n", 
558
 
                 a, b, c, d, bits, network, networkMask);
559
 
#endif
560
 
 
561
 
      broadcast = network | (~networkMask);
562
 
 
563
 
#ifdef DEBUG
564
 
      a = (int) ((broadcast >> 24) & 0xff);
565
 
      b = (int) ((broadcast >> 16) & 0xff);
566
 
      c = (int) ((broadcast >>  8) & 0xff);
567
 
      d = (int) ((broadcast >>  0) & 0xff);
568
 
 
569
 
      traceEvent(TRACE_INFO, "Broadcast: [net=0x%08x] [broadcast=%d.%d.%d.%d]\n",
570
 
                 network, a, b, c, d);
571
 
#endif
572
 
 
573
 
      if(numLocalNets < MAX_NUM_NETWORKS) {
574
 
        int found = 0;
575
 
 
576
 
        for(i=0; i<numDevices; i++)
577
 
          if((network == device[i].network.s_addr)
578
 
             && (device[i].netmask.s_addr == networkMask)) {
579
 
            a = (int) ((network >> 24) & 0xff);
580
 
            b = (int) ((network >> 16) & 0xff);
581
 
            c = (int) ((network >>  8) & 0xff);
582
 
            d = (int) ((network >>  0) & 0xff);
583
 
 
584
 
            traceEvent(TRACE_WARNING, "WARNING: Discarded network %d.%d.%d.%d/%d: "
585
 
                       "this is the local network.\n",
586
 
                       a, b, c, d, bits);
587
 
            found = 1;
588
 
          }
589
 
 
590
 
        if(found == 0) {
591
 
          networks[numLocalNets][NETWORK]   = network;
592
 
          networks[numLocalNets][NETMASK]   = networkMask;
593
 
          networks[numLocalNets][BROADCAST] = broadcast;
594
 
          numLocalNets++;
595
 
        }
596
 
      } else
597
 
        traceEvent(TRACE_WARNING, "Unable to handle network (too many entries!).\n");
598
 
    }
599
 
 
600
 
    address = strtok_r(NULL, ",", &strtokState);
601
 
  }
602
 
}
603
 
 
604
 
/* ********************************* */
605
 
 
606
 
/* This function returns true when a host is considered local
607
 
   as specified using the 'm' flag */
608
 
unsigned short isPseudoLocalAddress(struct in_addr *addr) {
609
 
  int i;
610
 
 
611
 
  i = isLocalAddress(addr);
612
 
 
613
 
  if(i == 1)
614
 
    return 1; /* This is a real local address */
615
 
  
616
 
  for(i=0; i<numLocalNets; i++) {
617
 
#ifdef DEBUG
618
 
    char buf[32], buf1[32], buf2[32];
619
 
    struct in_addr addr1, addr2;
620
 
 
621
 
    addr1.s_addr = networks[i][NETWORK];
622
 
    addr2.s_addr = networks[i][NETMASK];
623
 
 
624
 
    traceEvent(TRACE_INFO, "%s comparing [%s/%s]\n",
625
 
               _intoa(*addr, buf, sizeof(buf)),
626
 
               _intoa(addr1, buf1, sizeof(buf1)),
627
 
               _intoa(addr2, buf2, sizeof(buf2)));
628
 
#endif
629
 
    if((addr->s_addr & networks[i][NETMASK]) == networks[i][NETWORK]) {
630
 
#ifdef DEBUG
631
 
      traceEvent(TRACE_WARNING, "%s is pseudolocal\n", intoa(*addr));
632
 
#endif
633
 
      return 1;
634
 
    } else {
635
 
#ifdef DEBUG
636
 
      traceEvent(TRACE_WARNING, "%s is NOT pseudolocal\n", intoa(*addr));
637
 
#endif
638
 
    }
639
 
  }
640
 
 
641
 
  /* 
642
 
     We don't check for broadcast as this check has been
643
 
     performed already by isLocalAddress() just called 
644
 
  */
645
 
  return(0);
646
 
}
647
 
 
648
 
/* ********************************* */
649
 
 
650
 
/* This function returns true when an address is the broadcast
651
 
   for the specified (-m flag subnets */
652
 
 
653
 
unsigned short isPseudoBroadcastAddress(struct in_addr *addr) {
654
 
  int i;
655
 
 
656
 
#ifdef DEBUG
657
 
  traceEvent(TRACE_WARNING, "Checking %8X (pseudo broadcast)\n", addr->s_addr);
658
 
#endif
659
 
 
660
 
  for(i=0; i<numLocalNets; i++) {
661
 
    if(addr->s_addr == networks[i][BROADCAST]) {
662
 
#ifdef DEBUG
663
 
      traceEvent(TRACE_WARNING, "--> %8X is pseudo broadcast\n", addr->s_addr);
664
 
#endif
665
 
      return 1;
666
 
    }
667
 
#ifdef DEBUG
668
 
    else
669
 
      traceEvent(TRACE_WARNING, "%8X/%8X is NOT pseudo broadcast\n", addr->s_addr, networks[i][BROADCAST]);
670
 
#endif
671
 
  }
672
 
 
673
 
  return(0);
674
 
}
675
 
 
676
 
/* ********************************* */
677
 
 
678
 
/*
679
 
 * Returns the difference between gmt and local time in seconds.
680
 
 * Use gmtime() and localtime() to keep things simple.
681
 
 * [Borrowed from tcpdump]
682
 
 */
683
 
int32_t gmt2local(time_t t) {
684
 
  int dt, dir;
685
 
  struct tm *gmt, *myloc;
686
 
  struct tm loc;
687
 
 
688
 
  if(t == 0)
689
 
    t = time(NULL);
690
 
 
691
 
  gmt = gmtime(&t);
692
 
  myloc = localtime_r(&t, &loc);
693
 
 
694
 
  dt = (myloc->tm_hour - gmt->tm_hour)*60*60+(myloc->tm_min - gmt->tm_min)*60;
695
 
 
696
 
  /*
697
 
   * If the year or julian day is different, we span 00:00 GMT
698
 
   * and must add or subtract a day. Check the year first to
699
 
   * avoid problems when the julian day wraps.
700
 
   */
701
 
  dir = myloc->tm_year - gmt->tm_year;
702
 
  if(dir == 0)
703
 
    dir = myloc->tm_yday - gmt->tm_yday;
704
 
  dt += dir * 24 * 60 * 60;
705
 
  
706
 
  return(dt);
707
 
}
708
 
 
709
 
/* ********************************* */
710
 
 
711
 
/* Example: "flow1='host jake',flow2='dst host born2run'" */
712
 
void handleFlowsSpecs(char* flows) {
713
 
  FILE *fd = fopen(flows, "rb");
714
 
  char *flow, *buffer=NULL, *strtokState;;
715
 
 
716
 
  if(fd == NULL)
717
 
    flow = strtok_r(flows, ",", &strtokState);
718
 
  else {
719
 
    struct stat buf;
720
 
    int len, i;
721
 
 
722
 
    if(stat(flows, &buf) != 0) {
723
 
      traceEvent(TRACE_INFO, "Error while stat() of %s\n", flows);
724
 
      return;
725
 
    }
726
 
 
727
 
    buffer = (char*)malloc(buf.st_size+8) /* just to be safe */;
728
 
 
729
 
    for(i=0;i<buf.st_size;) {
730
 
      len = fread(&buffer[i], sizeof(char), buf.st_size-i, fd);
731
 
      if(len <= 0) break;
732
 
      i += len;
733
 
    }
734
 
 
735
 
    fclose(fd);
736
 
 
737
 
    /* remove trailing carriage return */
738
 
    if(buffer[strlen(buffer)-1] == '\n')
739
 
      buffer[strlen(buffer)-1] = 0;
740
 
 
741
 
    flow = strtok_r(buffer, ",", &strtokState);
742
 
  }
743
 
 
744
 
  while(flow != NULL) {
745
 
    char *flowSpec = strchr(flow, '=');
746
 
 
747
 
    if(flowSpec == NULL)
748
 
      traceEvent(TRACE_INFO, "Missing flow spec '%s'. It has been ignored.\n", flow);
749
 
    else {
750
 
      struct bpf_program fcode;
751
 
      int rc, len;
752
 
      char *flowName = flow;
753
 
 
754
 
      flowSpec[0] = '\0';
755
 
      flowSpec++;
756
 
      /* flowSpec should now point to 'host jake' */
757
 
      len = strlen(flowSpec);
758
 
 
759
 
      if((len <= 2)
760
 
         || (flowSpec[0] != '\'')
761
 
         || (flowSpec[len-1] != '\''))
762
 
        traceEvent(TRACE_WARNING, "Wrong flow specification \"%s\" (missing \'). "
763
 
                   "It has been ignored.\n", flowSpec);
764
 
      else {
765
 
        flowSpec[len-1] = '\0';
766
 
        flowSpec++;
767
 
 
768
 
        rc = pcap_compile(device[0].pcapPtr, &fcode, flowSpec, 1, device[0].netmask.s_addr);
769
 
 
770
 
        if(rc < 0)
771
 
          traceEvent(TRACE_INFO, "Wrong flow specification \"%s\" (syntax error). "
772
 
                     "It has been ignored.\n", flowSpec);
773
 
        else {
774
 
          FlowFilterList *newFlow;
775
 
 
776
 
          newFlow = (FlowFilterList*)calloc(1, sizeof(FlowFilterList));
777
 
 
778
 
          if(newFlow == NULL) {
779
 
            traceEvent(TRACE_INFO, "Fatal error: not enough memory. Bye!\n");
780
 
            if(buffer != NULL) free(buffer);
781
 
            exit(-1);
782
 
          } else {
783
 
            int i;
784
 
 
785
 
            newFlow->fcode = (struct bpf_program*)calloc(numDevices, sizeof(struct bpf_program));
786
 
 
787
 
            for(i=0; i<numDevices; i++) {
788
 
              rc = pcap_compile(device[i].pcapPtr, &newFlow->fcode[i],
789
 
                                flowSpec, 1, device[i].netmask.s_addr);
790
 
 
791
 
              if(rc < 0) {
792
 
                traceEvent(TRACE_WARNING, "Wrong flow specification \"%s\" (syntax error). "
793
 
                           "It has been ignored.\n", flowSpec);
794
 
                free(newFlow);
795
 
                return;
796
 
              }
797
 
            }
798
 
 
799
 
            newFlow->flowName = strdup(flowName);
800
 
            newFlow->pluginStatus.activePlugin = 1;
801
 
            newFlow->pluginStatus.pluginPtr = NULL; /* Added by Jacques Le Rest <jlerest@ifremer.fr> */
802
 
            newFlow->next = flowsList;
803
 
            flowsList = newFlow;
804
 
          }
805
 
        }
806
 
      }
807
 
    }
808
 
 
809
 
    flow = strtok_r(NULL, ",", &strtokState);
810
 
  }
811
 
 
812
 
  if(buffer != NULL)
813
 
    free(buffer);
814
 
}
815
 
 
816
 
/* ********************************* */
817
 
 
818
 
int getLocalHostAddress(struct in_addr *hostAddress, char* device) {
819
 
  int rc = 0;
820
 
#ifdef WIN32
821
 
  hostAddress->s_addr = GetHostIPAddr();
822
 
  return(0);
823
 
#else
824
 
  register int fd;
825
 
  register struct sockaddr_in *sin;
826
 
  struct ifreq ifr;
827
 
#ifdef DEBUG
828
 
  int a, b, c, d;
829
 
#endif
830
 
 
831
 
  fd = socket(AF_INET, SOCK_DGRAM, 0);
832
 
  if(fd < 0) {
833
 
    traceEvent(TRACE_INFO, "socket error: %d", errno);
834
 
    return(-1);
835
 
  }
836
 
 
837
 
  memset(&ifr, 0, sizeof(ifr));
838
 
 
839
 
#ifdef linux
840
 
  /* XXX Work around Linux kernel bug */
841
 
  ifr.ifr_addr.sa_family = AF_INET;
842
 
#endif
843
 
  strncpy(ifr.ifr_name, device, sizeof(ifr.ifr_name));
844
 
  if(ioctl(fd, SIOCGIFADDR, (char*)&ifr) < 0) {
845
 
#ifdef DEBUG
846
 
    traceEvent(TRACE_INFO, "SIOCGIFADDR error: %s/errno=%d", device, errno);
847
 
#endif
848
 
    rc = -1;
849
 
  } else {
850
 
    sin = (struct sockaddr_in *)&ifr.ifr_addr;
851
 
 
852
 
    if((hostAddress->s_addr = ntohl(sin->sin_addr.s_addr)) == 0)
853
 
      rc = -1;
854
 
  }
855
 
 
856
 
#ifdef DEBUG
857
 
  traceEvent(TRACE_INFO, "Local address is: %s\n", intoa(*hostAddress));
858
 
#endif
859
 
 
860
 
  /* ******************************* */
861
 
 
862
 
#ifdef DEBUG
863
 
  {
864
 
    int numHosts;
865
 
    
866
 
    if(ioctl(fd, SIOCGIFNETMASK, (char*)&ifr) >= 0) {
867
 
      sin = (struct sockaddr_in *)&ifr.ifr_broadaddr;  
868
 
      numHosts = 0xFFFFFFFF - ntohl(sin->sin_addr.s_addr)+1;
869
 
    } else 
870
 
      numHosts = 256; /* default C class */
871
 
    
872
 
    traceEvent(TRACE_INFO, "Num subnet hosts: %d\n", numHosts);
873
 
  }
874
 
#endif
875
 
    
876
 
  /* ******************************* */
877
 
 
878
 
close(fd);
879
 
#endif
880
 
 
881
 
  return(rc);
882
 
}
883
 
 
884
 
/* ********************************* */
885
 
 
886
 
#ifndef WIN32
887
 
#ifdef MULTITHREADED
888
 
 
889
 
/* *********** MULTITHREAD STUFF *********** */
890
 
 
891
 
int createThread(pthread_t *threadId,
892
 
                 void *(*__start_routine) (void *),
893
 
                 char* userParm) {
894
 
  int rc;
895
 
 
896
 
  rc = pthread_create(threadId, NULL, __start_routine, userParm);
897
 
  numThreads++;
898
 
  return(rc);
899
 
}
900
 
 
901
 
/* ************************************ */
902
 
 
903
 
void killThread(pthread_t *threadId) {
904
 
  pthread_detach(*threadId);
905
 
  numThreads--;
906
 
}
907
 
 
908
 
/* ************************************ */
909
 
 
910
 
int _createMutex(PthreadMutex *mutexId, char* fileName, int fileLine) {
911
 
  int rc;
912
 
 
913
 
  memset(mutexId, 0, sizeof(PthreadMutex));
914
 
 
915
 
  rc = pthread_mutex_init(&(mutexId->mutex), NULL);
916
 
 
917
 
#ifdef PTHREAD_MUTEX_ERRORCHECK_NP
918
 
 
919
 
  /* *************************************************
920
 
     There seems to be some problem with mutexes and some
921
 
     glibc versions. See
922
 
 
923
 
     http://sdb.suse.de/sdb/de/html/aj_pthread7.0.html
924
 
 
925
 
     (in German but an english version is probably available on their
926
 
     international web site). Suggested workaround is either to use
927
 
 
928
 
     pthread_mutexattr_settype (&mutattr, PTHREAD_MUTEX_ERRORCHECK_NP);
929
 
 
930
 
     as checked mutexes dont have the error or use a corrected
931
 
     glibc (Suse offers a patched version for their system).
932
 
 
933
 
     Andreas Pfaeller <a.pfaller@pop.gun.de>
934
 
 
935
 
     ************************************************* */
936
 
 
937
 
  pthread_mutexattr_settype (&(mutexId->mutex), 
938
 
                             PTHREAD_MUTEX_ERRORCHECK_NP);
939
 
 
940
 
#endif /* PTHREAD_MUTEX_ERRORCHECK_NP */
941
 
 
942
 
  mutexId->isInitialized = 1;
943
 
 
944
 
  return(rc);
945
 
}
946
 
 
947
 
/* ************************************ */
948
 
 
949
 
void _deleteMutex(PthreadMutex *mutexId, char* fileName, int fileLine) {
950
 
 
951
 
  if(!mutexId->isInitialized) {
952
 
    traceEvent(TRACE_ERROR, 
953
 
               "ERROR: deleteMutex() call with a NULL mutex [%s:%d]\n",
954
 
               fileName, fileLine);
955
 
    return;
956
 
  }  
957
 
 
958
 
  pthread_mutex_unlock(&(mutexId->mutex));
959
 
  pthread_mutex_destroy(&(mutexId->mutex));
960
 
 
961
 
  memset(mutexId, 0, sizeof(PthreadMutex));
962
 
}
963
 
 
964
 
/* ************************************ */
965
 
 
966
 
int _accessMutex(PthreadMutex *mutexId, char* where,
967
 
                 char* fileName, int fileLine) {
968
 
  int rc;
969
 
 
970
 
  if(!mutexId->isInitialized) {
971
 
    traceEvent(TRACE_ERROR, 
972
 
               "ERROR: accessMutex() call with a NULL mutex [%s:%d]\n",
973
 
               fileName, fileLine);
974
 
    return(-1);
975
 
  }
976
 
  
977
 
#ifdef SEMAPHORE_DEBUG
978
 
  traceEvent(TRACE_INFO, "Locking 0x%X @ %s [%s:%d]\n",
979
 
             &(mutexId->mutex), where, fileName, fileLine);
980
 
#endif
981
 
  rc = pthread_mutex_lock(&(mutexId->mutex));
982
 
 
983
 
  if(rc != 0)
984
 
    traceEvent(TRACE_ERROR, "ERROR: lock failed 0x%X [%s:%d] (rc=%d)\n",
985
 
               (void*)&(mutexId->mutex), fileName, fileLine, rc);
986
 
  else {
987
 
    /* traceEvent(TRACE_ERROR, "LOCKED 0x%X", &(mutexId->mutex)); */
988
 
    mutexId->numLocks++;
989
 
    mutexId->isLocked = 1;
990
 
    mutexId->lockTime = time(NULL);
991
 
    if(fileName != NULL) {
992
 
      strcpy(mutexId->lockFile, fileName);
993
 
      mutexId->lockLine = fileLine;
994
 
    }
995
 
  }
996
 
 
997
 
#ifdef SEMAPHORE_DEBUG
998
 
  traceEvent(TRACE_INFO, "Locked 0x%X @ %s [%s:%d]\n",
999
 
             &(mutexId->mutex), where, fileName, fileLine);
1000
 
#endif
1001
 
  return(rc);
1002
 
}
1003
 
 
1004
 
/* ************************************ */
1005
 
 
1006
 
int _tryLockMutex(PthreadMutex *mutexId, char* where,
1007
 
                  char* fileName, int fileLine) {
1008
 
  int rc;
1009
 
 
1010
 
  if(!mutexId->isInitialized) {
1011
 
    traceEvent(TRACE_ERROR, 
1012
 
               "ERROR: tryLockMutex() call with a NULL mutex [%s:%d]\n",
1013
 
               fileName, fileLine);
1014
 
    return(-1);
1015
 
  }
1016
 
  
1017
 
#ifdef SEMAPHORE_DEBUG
1018
 
  traceEvent(TRACE_INFO, "Try to Lock 0x%X @ %s [%s:%d]\n",
1019
 
             mutexId, where, fileName, fileLine);
1020
 
#endif
1021
 
 
1022
 
  /*
1023
 
     Return code:
1024
 
 
1025
 
     0:    lock succesful
1026
 
     EBUSY (mutex already locked)
1027
 
  */
1028
 
  rc = pthread_mutex_trylock(&(mutexId->mutex));
1029
 
 
1030
 
  if(rc != 0)
1031
 
    traceEvent(TRACE_ERROR, "ERROR: tryLockMutex failed 0x%X [%s:%d] (rc=%d)\n",
1032
 
               (void*)&(mutexId->mutex), fileName, fileLine, rc);
1033
 
  else {
1034
 
    /* traceEvent(TRACE_ERROR, "LOCKED 0x%X", &(mutexId->mutex)); */
1035
 
    mutexId->isLocked = 1;
1036
 
    mutexId->lockTime = time(NULL);
1037
 
    if(fileName != NULL) {
1038
 
      strcpy(mutexId->lockFile, fileName);
1039
 
      mutexId->lockLine = fileLine;
1040
 
    }
1041
 
  }
1042
 
 
1043
 
  return(rc);
1044
 
}
1045
 
 
1046
 
/* ************************************ */
1047
 
 
1048
 
int _isMutexLocked(PthreadMutex *mutexId, char* fileName, int fileLine) {
1049
 
  int rc;
1050
 
 
1051
 
  if(!mutexId->isInitialized) {
1052
 
    traceEvent(TRACE_ERROR, 
1053
 
               "ERROR: isMutexLocked() call with a NULL mutex [%s:%d]\n",
1054
 
               fileName, fileLine);
1055
 
    return(-1);
1056
 
  }
1057
 
  
1058
 
#ifdef SEMAPHORE_DEBUG
1059
 
  traceEvent(TRACE_INFO, "Checking whether 0x%X is locked [%s:%d]\n",
1060
 
             &(mutexId->mutex), fileName, fileLine);
1061
 
#endif
1062
 
 
1063
 
  rc = pthread_mutex_trylock(&(mutexId->mutex));
1064
 
 
1065
 
  /*
1066
 
     Return code:
1067
 
 
1068
 
     0:    lock succesful
1069
 
     EBUSY (mutex already locked)
1070
 
  */
1071
 
 
1072
 
  if(rc == 0) {
1073
 
    pthread_mutex_unlock(&(mutexId->mutex));
1074
 
    return(0);
1075
 
  } else
1076
 
    return(1);
1077
 
}
1078
 
 
1079
 
/* ************************************ */
1080
 
 
1081
 
int _releaseMutex(PthreadMutex *mutexId,
1082
 
                  char* fileName, int fileLine) {
1083
 
  int rc;
1084
 
 
1085
 
  if(!mutexId->isInitialized) {
1086
 
    traceEvent(TRACE_ERROR, 
1087
 
               "ERROR: releaseMutex() call with a NULL mutex [%s:%d]\n",
1088
 
               fileName, fileLine);
1089
 
    return(-1);
1090
 
  }
1091
 
  
1092
 
#ifdef SEMAPHORE_DEBUG
1093
 
  traceEvent(TRACE_INFO, "Unlocking 0x%X [%s:%d]\n",
1094
 
             &(mutexId->mutex), fileName, fileLine);
1095
 
#endif
1096
 
  rc = pthread_mutex_unlock(&(mutexId->mutex));
1097
 
 
1098
 
  if(rc != 0)
1099
 
    traceEvent(TRACE_ERROR, "ERROR: unlock failed 0x%X [%s:%d]\n",
1100
 
               (void*)&(mutexId->mutex), fileName, fileLine);
1101
 
  else {
1102
 
    time_t lockDuration = time(NULL) - mutexId->lockTime;
1103
 
 
1104
 
    if((mutexId->maxLockedDuration < lockDuration)
1105
 
       || (mutexId->maxLockedDurationUnlockLine == 0 /* Never set */)) {
1106
 
      mutexId->maxLockedDuration = lockDuration;
1107
 
 
1108
 
      if(fileName != NULL) {
1109
 
        strcpy(mutexId->maxLockedDurationUnlockFile, fileName);
1110
 
        mutexId->maxLockedDurationUnlockLine = fileLine;
1111
 
      }
1112
 
 
1113
 
#ifdef DEBUG
1114
 
      if(mutexId->maxLockedDuration > 0) {
1115
 
        traceEvent(TRACE_INFO, "INFO: semaphore 0x%X [%s:%d] locked for %d secs\n",
1116
 
                   (void*)&(mutexId->mutex), fileName, fileLine,
1117
 
                   mutexId->maxLockedDuration);
1118
 
      }
1119
 
#endif
1120
 
   }
1121
 
 
1122
 
    /* traceEvent(TRACE_ERROR, "UNLOCKED 0x%X", &(mutexId->mutex));  */
1123
 
    mutexId->isLocked = 0;
1124
 
    mutexId->numReleases++;
1125
 
    if(fileName != NULL) {
1126
 
      strcpy(mutexId->unlockFile, fileName);
1127
 
      mutexId->unlockLine = fileLine;
1128
 
    }
1129
 
  }
1130
 
 
1131
 
#ifdef SEMAPHORE_DEBUG
1132
 
  traceEvent(TRACE_INFO, "Unlocked 0x%X [%s:%d]\n",
1133
 
             &(mutexId->mutex), fileName, fileLine);
1134
 
#endif
1135
 
  return(rc);
1136
 
}
1137
 
 
1138
 
/* ************************************ */
1139
 
 
1140
 
int createCondvar(ConditionalVariable *condvarId) {
1141
 
  int rc;
1142
 
 
1143
 
  rc = pthread_mutex_init(&condvarId->mutex, NULL);
1144
 
  rc = pthread_cond_init(&condvarId->condvar, NULL);
1145
 
  condvarId->predicate = 0;
1146
 
 
1147
 
  return(rc);
1148
 
}
1149
 
 
1150
 
/* ************************************ */
1151
 
 
1152
 
void deleteCondvar(ConditionalVariable *condvarId) {
1153
 
  pthread_mutex_destroy(&condvarId->mutex);
1154
 
  pthread_cond_destroy(&condvarId->condvar);
1155
 
}
1156
 
 
1157
 
/* ************************************ */
1158
 
 
1159
 
int waitCondvar(ConditionalVariable *condvarId) {
1160
 
  int rc;
1161
 
 
1162
 
  if((rc = pthread_mutex_lock(&condvarId->mutex)) != 0)
1163
 
    return rc;
1164
 
 
1165
 
  while(condvarId->predicate <= 0) {
1166
 
    rc = pthread_cond_wait(&condvarId->condvar, &condvarId->mutex);
1167
 
  }
1168
 
 
1169
 
  condvarId->predicate--;
1170
 
 
1171
 
  rc = pthread_mutex_unlock(&condvarId->mutex);
1172
 
 
1173
 
  return rc;
1174
 
}
1175
 
 
1176
 
/* ************************************ */
1177
 
 
1178
 
int signalCondvar(ConditionalVariable *condvarId) {
1179
 
  int rc;
1180
 
 
1181
 
  rc = pthread_mutex_lock(&condvarId->mutex);
1182
 
 
1183
 
  condvarId->predicate++;
1184
 
 
1185
 
  rc = pthread_mutex_unlock(&condvarId->mutex);
1186
 
  rc = pthread_cond_signal(&condvarId->condvar);
1187
 
 
1188
 
  return rc;
1189
 
}
1190
 
 
1191
 
/* ************************************ */
1192
 
 
1193
 
#ifdef HAVE_SEMAPHORE_H
1194
 
 
1195
 
int createSem(sem_t *semId, int initialValue) {
1196
 
  int rc;
1197
 
 
1198
 
  rc = sem_init(semId, 0, initialValue);
1199
 
  return(rc);
1200
 
}
1201
 
 
1202
 
/* ************************************ */
1203
 
 
1204
 
void waitSem(sem_t *semId) {
1205
 
  sem_wait(semId);
1206
 
}
1207
 
 
1208
 
/* ************************************ */
1209
 
 
1210
 
int incrementSem(sem_t *semId) {
1211
 
  return(sem_post(semId));
1212
 
}
1213
 
 
1214
 
/* ************************************ */
1215
 
 
1216
 
int decrementSem(sem_t *semId) {
1217
 
  return(sem_trywait(semId));
1218
 
}
1219
 
 
1220
 
/* ************************************ */
1221
 
 
1222
 
int deleteSem(sem_t *semId) {
1223
 
  return(sem_destroy(semId));
1224
 
}
1225
 
#endif
1226
 
 
1227
 
#endif /* MULTITHREADED */
1228
 
#endif /* WIN32 */
1229
 
 
1230
 
/* ************************************ */
1231
 
 
1232
 
int checkCommand(char* commandName) {
1233
 
#ifdef WIN32
1234
 
  return(0);
1235
 
#else
1236
 
  FILE* fd = sec_popen(commandName, "r");
1237
 
 
1238
 
  if(fd == NULL)
1239
 
    return 0;
1240
 
  else {
1241
 
    int rc = fgetc(fd);
1242
 
    pclose(fd);
1243
 
 
1244
 
    if(rc == EOF)
1245
 
      return(0);
1246
 
    else
1247
 
      return(1);
1248
 
  }
1249
 
#endif
1250
 
}
1251
 
 
1252
 
/* ************************************ */
1253
 
 
1254
 
/*
1255
 
  #define DEBUG
1256
 
  #define USE_LSOF_DUMP
1257
 
*/
1258
 
 
1259
 
void readLsofInfo(void) {
1260
 
#ifdef WIN32
1261
 
  ;
1262
 
#else
1263
 
  char line[384];
1264
 
  FILE *fd;
1265
 
  int i, j, found, portNumber, idx, processesIdx;
1266
 
  int numLines, processSize, numRetries;
1267
 
  unsigned int fdFileno;
1268
 
  ProcessInfoList *listElement;
1269
 
  ProcessInfo **tmpProcesses;
1270
 
  fd_set mask;
1271
 
  struct timeval wait_time;
1272
 
  char fileName[NAME_MAX] = "/tmp/lsof-XXXXXX";
1273
 
  FILE *fd1;
1274
 
  time_t startTime = time(NULL);
1275
 
 
1276
 
  fd1 = getNewRandomFile(fileName, NAME_MAX);
1277
 
 
1278
 
  if(fd1 == NULL) {
1279
 
    /* The warning message is returned by getNewRandomFile() */
1280
 
    return;
1281
 
  }
1282
 
 
1283
 
  fd = sec_popen("lsof -i -n -w", "r");
1284
 
 
1285
 
  if(fd == NULL) {
1286
 
    fclose(fd);
1287
 
    isLsofPresent = 0;
1288
 
    return;
1289
 
  }
1290
 
 
1291
 
  numRetries = numLines = 0;
1292
 
  fdFileno = fileno(fd);
1293
 
  wait_time.tv_sec = 30, wait_time.tv_usec = 0;
1294
 
 
1295
 
  while(1) {
1296
 
    FD_ZERO(&mask);
1297
 
    FD_SET(fdFileno, &mask);
1298
 
 
1299
 
    if((i = select(fdFileno+1, &mask, 0, 0, &wait_time)) == 1) {
1300
 
      if(fgets(line, 383, fd) != NULL) {
1301
 
        numLines++;
1302
 
        fprintf(fd1, "%s", line);
1303
 
      } else
1304
 
        break;
1305
 
    } else {
1306
 
 
1307
 
      if((errno == 4 /* Interrupted system call */) 
1308
 
         && (numRetries < 3) /* Avoid to loop */) {
1309
 
        numRetries++;
1310
 
      } else {
1311
 
        traceEvent(TRACE_WARNING,
1312
 
                   "WARNING: lsof() timeout (select=%d)(errno=%d: %s)",
1313
 
                   i, errno, strerror(errno));
1314
 
        pclose(fd);
1315
 
        fclose(fd1);
1316
 
        unlink(fileName);
1317
 
        return;
1318
 
      }
1319
 
    }
1320
 
  } /* while */
1321
 
 
1322
 
  pclose(fd);
1323
 
  fclose(fd1);
1324
 
 
1325
 
  numLines--;
1326
 
 
1327
 
  if(numLines <= 0)
1328
 
    return; /* No processes */
1329
 
 
1330
 
  fd = fopen(fileName, "r");
1331
 
  if(fd == NULL) {
1332
 
    traceEvent(TRACE_WARNING, "WARNING: unable to read lsof dump file");
1333
 
    unlink(fileName);
1334
 
    return;
1335
 
  }
1336
 
 
1337
 
  /* ****************************************** */
1338
 
 
1339
 
#ifdef MULTITHREADED
1340
 
  accessMutex(&lsofMutex, "readLsofInfo");
1341
 
#endif
1342
 
 
1343
 
  for(i=0; i<numProcesses; i++)
1344
 
    processes[i]->marker = 0;
1345
 
 
1346
 
  for(idx=0; idx<TOP_IP_PORT; idx++) {
1347
 
    while(localPorts[idx] != NULL) {
1348
 
      listElement = localPorts[idx]->next;
1349
 
      free(localPorts[idx]);
1350
 
      localPorts[idx] = listElement;
1351
 
    }
1352
 
  }
1353
 
 
1354
 
  memset(localPorts, 0, sizeof(localPorts)); /* Just to be sure... */
1355
 
 
1356
 
  fgets(line, 383, fd); /* Ignore 1st line */
1357
 
 
1358
 
  while(fgets(line, 383, fd) != NULL) {
1359
 
    int pid, i;
1360
 
    char command[32], user[32], *portNr;
1361
 
    char *trailer, *thePort, *strtokState;
1362
 
 
1363
 
    /*traceEvent(TRACE_INFO, "%s\n", line); */
1364
 
 
1365
 
    /* Fix below courtesy of Andreas Pfaller <a.pfaller@pop.gun.de> */
1366
 
    if(3 != sscanf(line, "%31[^ \t] %d %31[^ \t]", command, &pid, user))
1367
 
      continue;
1368
 
 
1369
 
    if(strcmp(command, "lsof") == 0)
1370
 
      continue;
1371
 
 
1372
 
    /* Either UDP or TCP */
1373
 
    for(i=10; (line[i] != '\0'); i++)
1374
 
      if((line[i] == 'P') && (line[i+1] == ' '))
1375
 
        break;
1376
 
 
1377
 
    if(line[i] == '\0')
1378
 
      continue;
1379
 
    else
1380
 
      trailer = &line[i+2];
1381
 
 
1382
 
    portNr = (char*)strtok_r(trailer, ":", &strtokState);
1383
 
 
1384
 
    if(portNr[0] == '*')
1385
 
      portNr = &portNr[2];
1386
 
    else
1387
 
      portNr = (char*)strtok_r(NULL, "-", &strtokState);
1388
 
 
1389
 
    if((portNr == NULL) || (portNr[0] == '*'))
1390
 
      continue;
1391
 
 
1392
 
    for(i=0, found = 0; i<numProcesses; i++) {
1393
 
      if(processes[i]->pid == pid) {
1394
 
        found = 1;
1395
 
        processes[i]->marker = 1;
1396
 
        break;
1397
 
      }
1398
 
    }
1399
 
 
1400
 
    thePort = strtok_r(portNr, " ", &strtokState);
1401
 
 
1402
 
    for(j=0; portNr[j] != '\0'; j++)
1403
 
      if(!isalnum(portNr[j]) && portNr[j]!='-') {
1404
 
        portNr[j] = '\0';
1405
 
        break;
1406
 
      }
1407
 
 
1408
 
    if(isdigit(portNr[0])) {
1409
 
      portNumber = atoi(thePort);
1410
 
    } else {
1411
 
      portNumber = getAllPortByName(thePort);
1412
 
    }
1413
 
 
1414
 
#ifdef DEBUG
1415
 
    traceEvent(TRACE_INFO, "%s - %s - %s (%s/%d)\n", 
1416
 
               command, user, thePort, portNr, portNumber);
1417
 
#endif
1418
 
 
1419
 
    if(portNumber == -1)
1420
 
      continue;
1421
 
 
1422
 
    if(!found) {
1423
 
      int floater;
1424
 
 
1425
 
      if(numProcesses < MAX_NUM_PROCESSES) {
1426
 
        ProcessInfo **swapProcesses;
1427
 
 
1428
 
        swapProcesses = (ProcessInfo**)malloc((numProcesses+1)*sizeof(ProcessInfo*));
1429
 
        if(numProcesses > 0)
1430
 
          memcpy(swapProcesses, processes, numProcesses*sizeof(ProcessInfo*));
1431
 
        if(processes != NULL) free(processes);
1432
 
        processes = swapProcesses;
1433
 
 
1434
 
#ifdef DEBUG
1435
 
        traceEvent(TRACE_INFO, "%3d) %s %s %s/%d\n", 
1436
 
                   numProcesses, command, user, portNr, portNumber);
1437
 
#endif
1438
 
        processes[numProcesses] = (ProcessInfo*)malloc(sizeof(ProcessInfo));
1439
 
        processes[numProcesses]->command             = strdup(command);
1440
 
        processes[numProcesses]->user                = strdup(user);
1441
 
        processes[numProcesses]->pid                 = pid;
1442
 
        processes[numProcesses]->firstSeen           = actTime;
1443
 
        processes[numProcesses]->lastSeen            = actTime;
1444
 
        processes[numProcesses]->marker              = 1;
1445
 
        processes[numProcesses]->bytesSent           = 0;
1446
 
        processes[numProcesses]->bytesReceived       = 0;
1447
 
        processes[numProcesses]->contactedIpPeersIdx = 0;
1448
 
        
1449
 
        for(floater=0; floater<MAX_NUM_CONTACTED_PEERS; floater++)
1450
 
          processes[numProcesses]->contactedIpPeersIndexes[floater] = NO_PEER;
1451
 
      }
1452
 
      
1453
 
      idx = numProcesses;
1454
 
      numProcesses++;
1455
 
    } else
1456
 
      idx = i;
1457
 
 
1458
 
    listElement = (ProcessInfoList*)malloc(sizeof(ProcessInfoList));
1459
 
    listElement->element = processes[idx];
1460
 
    listElement->next = localPorts[portNumber];
1461
 
    localPorts[portNumber] = listElement;
1462
 
  }
1463
 
 
1464
 
  fclose(fd);
1465
 
  unlink(fileName);
1466
 
 
1467
 
  processSize = sizeof(ProcessInfo*)*numProcesses;
1468
 
  tmpProcesses = (ProcessInfo**)malloc(processSize);
1469
 
 
1470
 
  memcpy(tmpProcesses, processes, processSize);
1471
 
  memset(processes, 0, processSize);
1472
 
 
1473
 
  for(i=0, processesIdx=0; i<numProcesses; i++) {
1474
 
    if(tmpProcesses[i]->marker == 0) {
1475
 
      /* Free the process */
1476
 
      free(tmpProcesses[i]->command);
1477
 
      free(tmpProcesses[i]->user);
1478
 
      free(tmpProcesses[i]);
1479
 
    } else {
1480
 
      processes[processesIdx++] = tmpProcesses[i];
1481
 
    }
1482
 
  }
1483
 
 
1484
 
  numProcesses = processesIdx;
1485
 
 
1486
 
  updateLsof = 0;
1487
 
 
1488
 
#ifdef MULTITHREADED
1489
 
  releaseMutex(&lsofMutex);
1490
 
#endif
1491
 
 
1492
 
  free(tmpProcesses);
1493
 
  traceEvent(TRACE_INFO, "readLsofInfo completed (%d sec).", (int)(time(NULL)-startTime));
1494
 
#endif /* WIN32 */
1495
 
}
1496
 
 
1497
 
#ifndef WIN32
1498
 
/*
1499
 
 * An os independent signal() with BSD semantics, e.g. the signal
1500
 
 * catcher is restored following service of the signal.
1501
 
 *
1502
 
 * When sigset() is available, signal() has SYSV semantics and sigset()
1503
 
 * has BSD semantics and call interface. Unfortunately, Linux does not
1504
 
 * have sigset() so we use the more complicated sigaction() interface
1505
 
 * there.
1506
 
 *
1507
 
 * Did I mention that signals suck?
1508
 
 */
1509
 
RETSIGTYPE (*setsignal (int sig, RETSIGTYPE (*func)(int)))(int)
1510
 
{
1511
 
#ifdef HAVE_SIGACTION
1512
 
  struct sigaction old, new;
1513
 
 
1514
 
  memset(&new, 0, sizeof(new));
1515
 
  new.sa_handler = func;
1516
 
#ifdef SA_RESTART
1517
 
  new.sa_flags |= SA_RESTART;
1518
 
#endif
1519
 
  if(sigaction(sig, &new, &old) < 0)
1520
 
    return(SIG_ERR);
1521
 
  return(old.sa_handler);
1522
 
 
1523
 
#else
1524
 
  return(signal(sig, func));
1525
 
#endif
1526
 
}
1527
 
#endif /* WIN32 */
1528
 
 
1529
 
/* ************************************ */
1530
 
 
1531
 
char* decodeNBstring(char* theString, char *theBuffer) {  
1532
 
  int i=0, j = 0, len=strlen(theString);
1533
 
  
1534
 
  while((i<len) && (theString[i] != '\0')) {
1535
 
    char encodedChar, decodedChar;
1536
 
      
1537
 
    encodedChar =  theString[i++];
1538
 
    if((encodedChar < 'A') || (encodedChar > 'Z')) break; /* Wrong character */
1539
 
    
1540
 
    encodedChar -= 'A';
1541
 
    decodedChar = encodedChar << 4;
1542
 
    
1543
 
    encodedChar =  theString[i++];
1544
 
    if((encodedChar < 'A') || (encodedChar > 'Z')) break; /* Wrong character */
1545
 
    
1546
 
    encodedChar -= 'A';
1547
 
    decodedChar |= encodedChar;
1548
 
    
1549
 
    theBuffer[j++] = decodedChar;
1550
 
  }
1551
 
  
1552
 
  theBuffer[j] = '\0';
1553
 
 
1554
 
  for(i=0; i<j; i++)
1555
 
    theBuffer[i] = (char)tolower(theBuffer[i]);
1556
 
 
1557
 
  return(theBuffer);
1558
 
}
1559
 
 
1560
 
/* ************************************ */
1561
 
 
1562
 
char* getHostOS(char* ipAddr, int port _UNUSED_, char* additionalInfo) {
1563
 
#ifdef WIN32
1564
 
  return(NULL);
1565
 
#else
1566
 
  FILE *fd;
1567
 
  char line[384], *operatingSystem=NULL;
1568
 
  static char staticOsName[96];
1569
 
  int len, found=0, sockFd;
1570
 
  fd_set mask;
1571
 
  struct timeval wait_time;
1572
 
 
1573
 
  if((!isNmapPresent) || (ipAddr[0] == '\0')) {
1574
 
    return(NULL);
1575
 
  }
1576
 
 
1577
 
#ifdef DEBUG
1578
 
  traceEvent(TRACE_INFO, "getHostOS(%s:%d)\n", ipAddr, port);
1579
 
  traceEvent(TRACE_INFO, "Guessing OS of %s...\n", ipAddr);
1580
 
#endif
1581
 
 
1582
 
  /* 548 is the AFP (Apple Filing Protocol) */
1583
 
 if(snprintf(line, sizeof(line), "nmap -p 23,21,80,138,139,548 -O %s", ipAddr) < 0)
1584
 
   traceEvent(TRACE_ERROR, "Buffer overflow!");
1585
 
 
1586
 
  fd = sec_popen(line, "r");
1587
 
 
1588
 
#define OS_GUESS   "Remote operating system guess: "
1589
 
#define OS_GUESS_1 "Remote OS guesses: "
1590
 
#define OS_GUESS_2 "OS: "
1591
 
 
1592
 
  if(fd == NULL) {
1593
 
    isNmapPresent = 0;
1594
 
    return(NULL);
1595
 
  } else
1596
 
    sockFd = fileno(fd);
1597
 
 
1598
 
  if(additionalInfo != NULL) additionalInfo[0]='\0';
1599
 
 
1600
 
  while(1) {
1601
 
    FD_ZERO(&mask);
1602
 
    FD_SET(sockFd, &mask);
1603
 
    wait_time.tv_sec = PIPE_READ_TIMEOUT, wait_time.tv_usec = 0;
1604
 
 
1605
 
    if(select(sockFd+1, &mask, 0, 0, &wait_time) == 0) {
1606
 
      break; /* Timeout */
1607
 
    }
1608
 
 
1609
 
    if((operatingSystem = fgets(line, sizeof(line)-1, fd)) == NULL)
1610
 
      break;
1611
 
 
1612
 
    len = strlen(operatingSystem);
1613
 
    if ((operatingSystem[len-1] == '\n') || (operatingSystem[len-1] == '\r'))
1614
 
      operatingSystem[len-1] = '\0';    /* strip NL or CR from end-of-line */
1615
 
 
1616
 
#ifdef DEBUG
1617
 
  traceEvent(TRACE_INFO, "'%s'\n", line);
1618
 
#endif
1619
 
 
1620
 
    if(strncmp(operatingSystem, OS_GUESS, strlen(OS_GUESS)) == 0) {
1621
 
      operatingSystem = &operatingSystem[strlen(OS_GUESS)];
1622
 
      found = 1;
1623
 
      break;
1624
 
    }
1625
 
 
1626
 
    /* Patches below courtesy of
1627
 
       Valeri V. Parchine <valeri@com-con.com> */
1628
 
 
1629
 
    if((!found) &&
1630
 
       (strncmp(operatingSystem, OS_GUESS_1, strlen(OS_GUESS_1)) == 0)) {
1631
 
      operatingSystem = &operatingSystem[strlen(OS_GUESS_1)];
1632
 
      found = 1;
1633
 
      break;
1634
 
    }
1635
 
 
1636
 
    if((!found) &&
1637
 
       (strncmp(operatingSystem, OS_GUESS_2, strlen(OS_GUESS_2)) == 0)) {
1638
 
      operatingSystem = &operatingSystem[strlen(OS_GUESS_2)];
1639
 
      found = 1;
1640
 
      break;
1641
 
    }
1642
 
 
1643
 
    if(additionalInfo != NULL) {
1644
 
      if(isdigit(operatingSystem[0])) {
1645
 
        strcat(additionalInfo, operatingSystem);
1646
 
        strcat(additionalInfo, "<BR>\n");
1647
 
      }
1648
 
 
1649
 
      /*traceEvent(TRACE_INFO, "> %s\n", operatingSystem); */
1650
 
    }
1651
 
  }
1652
 
 
1653
 
  memset(staticOsName, 0, sizeof(staticOsName));
1654
 
 
1655
 
  if(found) {
1656
 
#ifdef DEBUG
1657
 
    traceEvent(TRACE_INFO, "OS is: '%s'\n", operatingSystem);
1658
 
#endif
1659
 
    len = strlen(operatingSystem);
1660
 
    strncpy(staticOsName, operatingSystem, len-1);
1661
 
  }
1662
 
 
1663
 
   memset(staticOsName, 0, sizeof(staticOsName));
1664
 
   if(found) {
1665
 
     len = strlen(operatingSystem);
1666
 
     strncpy(staticOsName, operatingSystem, len);
1667
 
     staticOsName[sizeof(staticOsName)-1] = '\0';
1668
 
#ifdef DEBUG
1669
 
     traceEvent(TRACE_INFO, "OS is: '%s'\n", operatingSystem);
1670
 
#endif
1671
 
   }
1672
 
 
1673
 
  /* Read remaining data (if any) */
1674
 
  while(1) {
1675
 
    FD_ZERO(&mask);
1676
 
    FD_SET(sockFd, &mask);
1677
 
    wait_time.tv_sec = PIPE_READ_TIMEOUT; wait_time.tv_usec = 0;
1678
 
 
1679
 
    if(select(sockFd+1, &mask, 0, 0, &wait_time) == 0) {
1680
 
      break; /* Timeout */
1681
 
    }
1682
 
 
1683
 
    if(fgets(line, sizeof(line)-1, fd) == NULL)
1684
 
      break;
1685
 
#ifdef DEBUG
1686
 
    else printf("Garbage: '%s'\n",  line);
1687
 
#endif
1688
 
  }
1689
 
  pclose(fd);
1690
 
 
1691
 
  return(staticOsName);
1692
 
#endif /* WIN32 */
1693
 
}
1694
 
 
1695
 
/* ************************************* */
1696
 
 
1697
 
void closeNwSocket(int *sockId) {
1698
 
#ifdef DEBUG
1699
 
  traceEvent(TRACE_INFO, "Closing socket %d...\n", *sockId);
1700
 
#endif
1701
 
 
1702
 
  if(*sockId == DUMMY_SOCKET_VALUE)
1703
 
    return;
1704
 
 
1705
 
#ifdef HAVE_OPENSSL
1706
 
  if(*sockId < 0)
1707
 
    term_ssl_connection(-(*sockId));
1708
 
  else
1709
 
    closesocket(*sockId);
1710
 
#else
1711
 
  closesocket(*sockId);
1712
 
#endif
1713
 
 
1714
 
  *sockId = DUMMY_SOCKET_VALUE;
1715
 
}
1716
 
 
1717
 
/* ************************************ */
1718
 
 
1719
 
char* savestr(const char *str)
1720
 
{
1721
 
  u_int size;
1722
 
  char *p;
1723
 
  static char *strptr = NULL;
1724
 
  static u_int strsize = 0;
1725
 
 
1726
 
  size = strlen(str) + 1;
1727
 
  if(size > strsize) {
1728
 
    strsize = 1024;
1729
 
    if(strsize < size)
1730
 
      strsize = size;
1731
 
    strptr = (char*)malloc(strsize);
1732
 
    if(strptr == NULL) {
1733
 
      fprintf(stderr, "savestr: malloc\n");
1734
 
      exit(1);
1735
 
    }
1736
 
  }
1737
 
  (void)strncpy(strptr, str, strsize);
1738
 
  p = strptr;
1739
 
  strptr += size;
1740
 
  strsize -= size;
1741
 
  return(p);
1742
 
}
1743
 
 
1744
 
 
1745
 
/* ************************************ */
1746
 
 
1747
 
/* The function below has been inherited by tcpdump */
1748
 
 
1749
 
 
1750
 
int name_interpret(char *in, char *out, int numBytes) {
1751
 
  int ret, len;
1752
 
  char *b;
1753
 
 
1754
 
  if(numBytes <= 0) {
1755
 
    traceEvent(TRACE_WARNING, "WARNING: name_interpret error (numBytes=%d)", numBytes);
1756
 
    return(-1);
1757
 
  }
1758
 
  
1759
 
  len = (*in++)/2;
1760
 
  b  = out;
1761
 
  *out=0;
1762
 
 
1763
 
  if(len > 30 || len < 1) {
1764
 
    traceEvent(TRACE_WARNING, "WARNING: name_interpret error (numBytes=%d)", numBytes);
1765
 
    return(-1);
1766
 
  }
1767
 
 
1768
 
  while (len--) {
1769
 
    if(in[0] < 'A' || in[0] > 'P' || in[1] < 'A' || in[1] > 'P') {
1770
 
      *out = 0;
1771
 
      return(-1);
1772
 
    }
1773
 
 
1774
 
    *out = ((in[0]-'A')<<4) + (in[1]-'A');
1775
 
    in += 2;
1776
 
    out++;
1777
 
  }
1778
 
  ret = *(--out);
1779
 
  *out = 0;
1780
 
 
1781
 
  /* Courtesy of Roberto F. De Luca <deluca@tandar.cnea.gov.ar> */
1782
 
  /* Trim trailing whitespace from the returned string */
1783
 
  for(out--; out>=b && *out==' '; out--) *out = '\0';
1784
 
 
1785
 
  return(ret);
1786
 
}
1787
 
 
1788
 
 
1789
 
/* ******************************* */
1790
 
 
1791
 
char* getNwInterfaceType(int i) {
1792
 
  switch(device[i].datalink) {
1793
 
  case DLT_NULL:        return("No&nbsp;link-layer&nbsp;encapsulation");
1794
 
  case DLT_EN10MB:      return("Ethernet");
1795
 
  case DLT_EN3MB:       return("Experimental&nbsp;Ethernet&nbsp;(3Mb)");
1796
 
  case DLT_AX25:        return("Amateur&nbsp;Radio&nbsp;AX.25");
1797
 
  case DLT_PRONET:      return("Proteon&nbsp;ProNET&nbsp;Token&nbsp;Ring");
1798
 
  case DLT_CHAOS:       return("Chaos");
1799
 
  case DLT_IEEE802:     return("IEEE&nbsp;802&nbsp;Networks");
1800
 
  case DLT_ARCNET:      return("ARCNET");
1801
 
  case DLT_SLIP:        return("SLIP");
1802
 
  case DLT_PPP:         return("PPP");
1803
 
  case DLT_FDDI:        return("FDDI");
1804
 
  case DLT_ATM_RFC1483: return("LLC/SNAP&nbsp;encapsulated&nbsp;ATM");
1805
 
  case DLT_RAW:         return("Raw&nbsp;IP");
1806
 
  case DLT_SLIP_BSDOS:  return("BSD/OS&nbsp;SLIP");
1807
 
  case DLT_PPP_BSDOS:   return("BSD/OS&nbsp;PPP");
1808
 
  }
1809
 
 
1810
 
  return(""); /* NOTREACHED (I hope) */
1811
 
}
1812
 
 
1813
 
/* ************************************ */
1814
 
 
1815
 
char* formatTime(time_t *theTime, short encodeString) {
1816
 
#define TIME_LEN    48
1817
 
  static char outStr[2][TIME_LEN];
1818
 
  static short timeBufIdx=0;
1819
 
  struct tm *locTime;
1820
 
  struct tm myLocTime;
1821
 
 
1822
 
  locTime = localtime_r(theTime, &myLocTime);
1823
 
 
1824
 
  timeBufIdx = (timeBufIdx+1)%2;
1825
 
 
1826
 
  if(encodeString)
1827
 
    strftime(outStr[timeBufIdx], TIME_LEN, "%x&nbsp;%X", locTime);
1828
 
  else
1829
 
    strftime(outStr[timeBufIdx], TIME_LEN, "%x %X", locTime);
1830
 
 
1831
 
  return(outStr[timeBufIdx]);
1832
 
#undef TIME_LEN
1833
 
}
1834
 
 
1835
 
/* ************************************ */
1836
 
 
1837
 
int getActualInterface(void) {
1838
 
  if(mergeInterfaces)
1839
 
    return(0);
1840
 
  else
1841
 
    return(deviceId);
1842
 
}
1843
 
 
1844
 
/* ************************************ */
1845
 
 
1846
 
void storeHostTrafficInstance(HostTraffic *el) {
1847
 
#ifdef HAVE_GDBM_H
1848
 
  datum key_data;
1849
 
  datum data_data;
1850
 
  char *key;
1851
 
 
1852
 
  if(broadcastHost(el))
1853
 
    return;
1854
 
 
1855
 
  if(el->ethAddressString[0] == '\0')
1856
 
    key = el->hostNumIpAddress;
1857
 
  else
1858
 
    key = el->ethAddressString;
1859
 
 
1860
 
#ifdef STORAGE_DEBUG
1861
 
  traceEvent(TRACE_INFO, "storeHostTrafficInstance(%s)\n", key);
1862
 
#endif
1863
 
 
1864
 
  /*
1865
 
    Before to store the instance all the pointers need
1866
 
    to be deleted (i.e. set to NULL)    
1867
 
  */
1868
 
  resetHostsVariables(el);
1869
 
 
1870
 
  key_data.dptr = key;
1871
 
  key_data.dsize = strlen(key_data.dptr);
1872
 
  data_data.dptr = (void*)el;
1873
 
  data_data.dsize = sizeof(HostTraffic);
1874
 
 
1875
 
#ifdef MULTITHREADED
1876
 
  accessMutex(&gdbmMutex, "storeHostTrafficInstance");
1877
 
#endif
1878
 
 
1879
 
  if(gdbm_store(hostsInfoFile, key_data, data_data, GDBM_REPLACE) == 0) {
1880
 
#ifdef STORAGE_DEBUG
1881
 
    traceEvent(TRACE_INFO, "Stored instance: '%s'\n", key);
1882
 
#endif
1883
 
    fprintf(stdout, "+"); fflush(stdout);
1884
 
  }
1885
 
 
1886
 
#ifdef MULTITHREADED
1887
 
  releaseMutex(&gdbmMutex);
1888
 
#endif
1889
 
 
1890
 
#else
1891
 
  ;
1892
 
#endif
1893
 
}
1894
 
 
1895
 
/* ************************************ */
1896
 
 
1897
 
void resetHostsVariables(HostTraffic* el) {
1898
 
 
1899
 
  FD_ZERO(&(el->flags));
1900
 
  resetUsageCounter(&el->contactedSentPeers);
1901
 
  resetUsageCounter(&el->contactedRcvdPeers);
1902
 
  resetUsageCounter(&el->contactedRouters); 
1903
 
 
1904
 
  el->fullDomainName = NULL;
1905
 
  el->dotDomainName = NULL;
1906
 
  el->hostSymIpAddress[0] = '\0';
1907
 
  el->osName = NULL;
1908
 
  el->nbHostName = NULL;
1909
 
  el->nbDomainName = NULL;
1910
 
  el->nbDescr = NULL; /* Fix courtesy of Francis Pintos <francis@arhl.com.hk> */
1911
 
  el->atNodeName = NULL;
1912
 
  memset(el->atNodeType, 0, sizeof(el->atNodeType));
1913
 
  el->routedTraffic = NULL;  
1914
 
  el->ipxHostName = NULL;
1915
 
  el->numIpxNodeTypes = 0;
1916
 
  el->portsUsage = NULL;
1917
 
  el->protoIPTrafficInfos = NULL;
1918
 
  el->tcpSessionList = NULL;
1919
 
  el->udpSessionList = NULL;
1920
 
  el->nextDBupdate = 0;
1921
 
  el->icmpInfo = NULL;
1922
 
  el->dnsStats = NULL;
1923
 
  el->httpStats = NULL;
1924
 
#ifdef ENABLE_NAPSTER
1925
 
  el->napsterStats = NULL;
1926
 
#endif
1927
 
  el->dhcpStats = NULL;
1928
 
 
1929
 
  resetUsageCounter(&el->contactedSentPeers);
1930
 
  resetUsageCounter(&el->contactedRcvdPeers);
1931
 
  resetUsageCounter(&el->contactedRouters);
1932
 
 
1933
 
  el->securityHostPkts = NULL;
1934
 
}
1935
 
 
1936
 
/* ************************************ */
1937
 
 
1938
 
HostTraffic* resurrectHostTrafficInstance(char *key) {
1939
 
#ifdef HAVE_GDBM_H
1940
 
  datum key_data;
1941
 
  datum data_data;
1942
 
 
1943
 
  key_data.dptr = key;
1944
 
  key_data.dsize = strlen(key_data.dptr);
1945
 
 
1946
 
#ifdef MULTITHREADED
1947
 
  accessMutex(&gdbmMutex, "resurrectHostTrafficInstance");
1948
 
#endif
1949
 
  data_data = gdbm_fetch(hostsInfoFile, key_data);
1950
 
 
1951
 
  if(data_data.dptr != NULL) {
1952
 
    HostTraffic *el;
1953
 
 
1954
 
    if(data_data.dsize != sizeof(HostTraffic)) {
1955
 
#ifdef STORAGE_DEBUG
1956
 
      traceEvent(TRACE_INFO,
1957
 
                 "Wrong size for '%s'[size=%d, expected=%d]. Deleted.\n",
1958
 
                 key, data_data.dsize, sizeof(HostTraffic));
1959
 
#endif
1960
 
      gdbm_delete(hostsInfoFile, key_data);
1961
 
      free(data_data.dptr);
1962
 
#ifdef MULTITHREADED
1963
 
      releaseMutex(&gdbmMutex);
1964
 
#endif
1965
 
      return(NULL);
1966
 
    }
1967
 
 
1968
 
#ifdef MULTITHREADED
1969
 
    releaseMutex(&gdbmMutex);
1970
 
#endif
1971
 
 
1972
 
#ifdef REALLOC_MEM
1973
 
    el = (HostTraffic*)malloc(sizeof(HostTraffic));
1974
 
    memcpy(el, data_data.dptr, sizeof(HostTraffic));
1975
 
    free(data_data.dptr);
1976
 
#else
1977
 
    el = (HostTraffic*)data_data.dptr;
1978
 
#endif
1979
 
 
1980
 
    if(broadcastHost(el)) {
1981
 
      /*
1982
 
        Broadcast entries should
1983
 
        NOT be stored on disk
1984
 
      */
1985
 
      free(el);
1986
 
      return(NULL);
1987
 
    } else
1988
 
      resetHostsVariables(el);
1989
 
 
1990
 
#ifdef STORAGE_DEBUG
1991
 
    traceEvent(TRACE_INFO, "\nResurrected instance: '%s/%s'\n",
1992
 
               el->ethAddressString, el->hostNumIpAddress);
1993
 
#endif
1994
 
    fprintf(stdout, "*"); fflush(stdout);
1995
 
    return(el);
1996
 
  } else {
1997
 
#ifdef STORAGE_DEBUG
1998
 
    traceEvent(TRACE_INFO, "Unable to find '%s'\n", key);
1999
 
#endif
2000
 
#ifdef MULTITHREADED
2001
 
    releaseMutex(&gdbmMutex);
2002
 
#endif
2003
 
    return(NULL);
2004
 
  }
2005
 
#else
2006
 
  return(NULL);
2007
 
#endif
2008
 
}
2009
 
 
2010
 
/* ************************************
2011
 
 *
2012
 
 * [Borrowed from tcpdump]
2013
 
 *
2014
 
 */
2015
 
u_short in_cksum(const u_short *addr, int len, u_short csum) {
2016
 
  int nleft = len;
2017
 
  const u_short *w = addr;
2018
 
  u_short answer;
2019
 
  int sum = csum;
2020
 
 
2021
 
  /*
2022
 
   *  Our algorithm is simple, using a 32 bit accumulator (sum),
2023
 
   *  we add sequential 16 bit words to it, and at the end, fold
2024
 
   *  back all the carry bits from the top 16 bits into the lower
2025
 
   *  16 bits.
2026
 
   */
2027
 
  while (nleft > 1)  {
2028
 
    sum += *w++;
2029
 
    nleft -= 2;
2030
 
  }
2031
 
  if(nleft == 1)
2032
 
    sum += htons(*(u_char *)w<<8);
2033
 
 
2034
 
  /*
2035
 
   * add back carry outs from top 16 bits to low 16 bits
2036
 
   */
2037
 
  sum = (sum >> 16) + (sum & 0xffff);   /* add hi 16 to low 16 */
2038
 
  sum += (sum >> 16);                   /* add carry */
2039
 
  answer = ~sum;                        /* truncate to 16 bits */
2040
 
  return(answer);
2041
 
}
2042
 
 
2043
 
/* ****************** */
2044
 
 
2045
 
void addTimeMapping(u_int16_t transactionId,
2046
 
                    struct timeval theTime) {
2047
 
 
2048
 
  u_int idx = transactionId % NUM_TRANSACTION_ENTRIES;
2049
 
  int i=0;
2050
 
 
2051
 
#ifdef DEBUG
2052
 
  traceEvent(TRACE_INFO, "addTimeMapping(0x%X)\n", transactionId);
2053
 
#endif
2054
 
  for(i=0; i<NUM_TRANSACTION_ENTRIES; i++) {
2055
 
    if(transTimeHash[idx].transactionId == 0) {
2056
 
      transTimeHash[idx].transactionId = transactionId;
2057
 
      transTimeHash[idx].theTime = theTime;
2058
 
      return;
2059
 
    } else if(transTimeHash[idx].transactionId == transactionId) {
2060
 
      transTimeHash[idx].theTime = theTime;
2061
 
      return;
2062
 
    }
2063
 
 
2064
 
    idx = (idx+1) % NUM_TRANSACTION_ENTRIES;
2065
 
  }
2066
 
}
2067
 
 
2068
 
/* ****************** */
2069
 
 
2070
 
/*
2071
 
 * The time difference in microseconds
2072
 
 */
2073
 
long delta_time (struct timeval * now,
2074
 
                 struct timeval * before) {
2075
 
  time_t delta_seconds;
2076
 
  time_t delta_microseconds;
2077
 
 
2078
 
  /*
2079
 
   * compute delta in second, 1/10's and 1/1000's second units
2080
 
   */
2081
 
  delta_seconds      = now -> tv_sec  - before -> tv_sec;
2082
 
  delta_microseconds = now -> tv_usec - before -> tv_usec;
2083
 
 
2084
 
  if(delta_microseconds < 0) { 
2085
 
    /* manually carry a one from the seconds field */
2086
 
    delta_microseconds += 1000000;  /* 1e6 */
2087
 
    -- delta_seconds;
2088
 
  }
2089
 
 
2090
 
  return((delta_seconds * 1000000) + delta_microseconds);
2091
 
}
2092
 
 
2093
 
/* ****************** */
2094
 
 
2095
 
time_t getTimeMapping(u_int16_t transactionId,
2096
 
                      struct timeval theTime) {
2097
 
 
2098
 
  u_int idx = transactionId % NUM_TRANSACTION_ENTRIES;
2099
 
  int i=0;
2100
 
 
2101
 
#ifdef DEBUG
2102
 
  traceEvent(TRACE_INFO, "getTimeMapping(0x%X)\n", transactionId);
2103
 
#endif
2104
 
 
2105
 
  /* ****************************************
2106
 
 
2107
 
    As  Andreas Pfaller <a.pfaller@pop.gun.de>
2108
 
    pointed out, the hash code needs to be optimised.
2109
 
    Actually the hash is scanned completely
2110
 
    if (unlikely but possible) the searched entry
2111
 
    is not present into the table.
2112
 
 
2113
 
  **************************************** */
2114
 
 
2115
 
  for(i=0; i<NUM_TRANSACTION_ENTRIES; i++) {
2116
 
    if(transTimeHash[idx].transactionId == transactionId) {
2117
 
      time_t msDiff = (time_t)delta_time(&theTime, &transTimeHash[idx].theTime);
2118
 
      transTimeHash[idx].transactionId = 0; /* Free bucket */
2119
 
#ifdef DEBUG
2120
 
      traceEvent(TRACE_INFO, "getTimeMapping(0x%X) [diff=%d]\n",
2121
 
                 transactionId, (unsigned long)msDiff);
2122
 
#endif
2123
 
      return(msDiff);
2124
 
    }
2125
 
 
2126
 
    idx = (idx+1) % NUM_TRANSACTION_ENTRIES;
2127
 
  }
2128
 
 
2129
 
#ifdef DEBUG
2130
 
  traceEvent(TRACE_INFO, "getTimeMapping(0x%X) [not found]\n", transactionId);
2131
 
#endif
2132
 
  return(0); /* Not found */
2133
 
}
2134
 
 
2135
 
/* ********************************** */
2136
 
 
2137
 
void traceEvent(int eventTraceLevel, char* file,
2138
 
                int line, char * format, ...) {
2139
 
  va_list va_ap;
2140
 
  va_start (va_ap, format);
2141
 
 
2142
 
  if(eventTraceLevel <= traceLevel) {
2143
 
    char theDate[32];
2144
 
    char buf[BUF_SIZE];  
2145
 
    time_t theTime = time(NULL);
2146
 
    struct tm t;
2147
 
 
2148
 
    if(traceLevel >= DEFAULT_TRACE_LEVEL) {
2149
 
#ifndef WIN32  
2150
 
      if(useSyslog)
2151
 
        openlog("ntop", LOG_PID, LOG_DAEMON);
2152
 
#endif
2153
 
 
2154
 
      if(!useSyslog) {
2155
 
        strftime(theDate, 32, "%d/%b/%Y %H:%M:%S", localtime_r(&theTime, &t));
2156
 
 
2157
 
        if(traceLevel == DETAIL_TRACE_LEVEL) {
2158
 
          printf("%s [%s:%d] ", theDate, file, line);
2159
 
        } else {
2160
 
          printf("%s ", theDate);
2161
 
        }
2162
 
      }
2163
 
 
2164
 
      memset(buf, 0, BUF_SIZE);
2165
 
#ifdef WIN32
2166
 
      /* Windows lacks of vsnprintf */
2167
 
      vsprintf(buf, format, va_ap);
2168
 
#else
2169
 
      vsnprintf(buf, BUF_SIZE-1, format, va_ap);
2170
 
#endif
2171
 
 
2172
 
      if(!useSyslog) {
2173
 
        printf("%s", buf);
2174
 
        if(format[strlen(format)-1] != '\n')
2175
 
          printf("\n");
2176
 
      } 
2177
 
#ifndef WIN32
2178
 
      else {
2179
 
#if 0 
2180
 
        switch(traceLevel) {
2181
 
        case 0:
2182
 
          syslog(LOG_ERR, "%s", buf);
2183
 
          break;
2184
 
        case 1:
2185
 
          syslog(LOG_WARNING, "%s", buf);
2186
 
          break;
2187
 
        case 2:
2188
 
          syslog(LOG_NOTICE, "%s", buf);
2189
 
          break;
2190
 
        default:
2191
 
          syslog(LOG_INFO, "%s", buf);
2192
 
          break;
2193
 
        }
2194
 
#else
2195
 
        syslog(LOG_ERR, "%s", buf);
2196
 
#endif
2197
 
      }
2198
 
#endif
2199
 
 
2200
 
      va_end (va_ap);
2201
 
      fflush(stdout);
2202
 
    }
2203
 
  }
2204
 
 
2205
 
#ifndef WIN32
2206
 
  if(useSyslog)
2207
 
    closelog();
2208
 
#endif
2209
 
}
2210
 
 
2211
 
/* ******************************************** */
2212
 
 
2213
 
char* _strncpy(char *dest, const char *src, size_t n) {
2214
 
  size_t len = strlen(src);
2215
 
 
2216
 
  if(len > (n-1))
2217
 
    len = n-1;
2218
 
 
2219
 
  memcpy(dest, src, len);
2220
 
  dest[len] = '\0';
2221
 
  return(dest);
2222
 
}
2223
 
 
2224
 
/* ******************************************** */
2225
 
 
2226
 
/* Courtesy of Andreas Pfaller <a.pfaller@pop.gun.de> */
2227
 
#ifndef HAVE_STRTOK_R
2228
 
/* Reentrant string tokenizer.  Generic version.
2229
 
 
2230
 
   Slightly modified from: glibc 2.1.3
2231
 
 
2232
 
   Copyright (C) 1991, 1996, 1997, 1998, 1999 Free Software Foundation, Inc.
2233
 
   This file is part of the GNU C Library.
2234
 
 
2235
 
   The GNU C Library is free software; you can redistribute it and/or
2236
 
   modify it under the terms of the GNU Library General Public License as
2237
 
   published by the Free Software Foundation; either version 2 of the
2238
 
   License, or (at your option) any later version.
2239
 
 
2240
 
   The GNU C Library is distributed in the hope that it will be useful,
2241
 
   but WITHOUT ANY WARRANTY; without even the implied warranty of
2242
 
   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
2243
 
   Library General Public License for more details.
2244
 
 
2245
 
   You should have received a copy of the GNU Library General Public
2246
 
   License along with the GNU C Library; see the file COPYING.LIB.  If not,
2247
 
   write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
2248
 
   Boston, MA 02111-1307, USA.  */
2249
 
 
2250
 
char *strtok_r(char *s, const char *delim, char **save_ptr) {
2251
 
  char *token;
2252
 
 
2253
 
  if (s == NULL)
2254
 
    s = *save_ptr;
2255
 
 
2256
 
  /* Scan leading delimiters.  */
2257
 
  s += strspn (s, delim);
2258
 
  if (*s == '\0')
2259
 
    return NULL;
2260
 
 
2261
 
  /* Find the end of the token.  */
2262
 
  token = s;
2263
 
  s = strpbrk (token, delim);
2264
 
  if (s == NULL)
2265
 
    /* This token finishes the string.  */
2266
 
    *save_ptr = "";
2267
 
  else {
2268
 
    /* Terminate the token and make *SAVE_PTR point past it.  */
2269
 
    *s = '\0';
2270
 
    *save_ptr = s + 1;
2271
 
  }
2272
 
 
2273
 
  return token;
2274
 
}
2275
 
#endif
2276
 
 
2277
 
/* ********************************** */
2278
 
 
2279
 
/* Courtesy of Andreas Pfaller <a.pfaller@pop.gun.de> */
2280
 
 
2281
 
int getSniffedDNSName(char *hostNumIpAddress, 
2282
 
                      char *name, int maxNameLen) {
2283
 
  int found = 0;
2284
 
  
2285
 
  name[0] = 0;
2286
 
 
2287
 
#ifdef HAVE_GDBM_H
2288
 
  if((hostNumIpAddress[0] != '\0') && gdbm_file) {
2289
 
    datum key;
2290
 
    datum data;
2291
 
 
2292
 
    key.dptr = hostNumIpAddress;
2293
 
    key.dsize = strlen(key.dptr)+1;
2294
 
 
2295
 
#ifdef MULTITHREADED
2296
 
    accessMutex(&gdbmMutex, "getSniffedDNSName");
2297
 
#endif
2298
 
    data = gdbm_fetch(gdbm_file, key);
2299
 
#ifdef MULTITHREADED
2300
 
    releaseMutex(&gdbmMutex);
2301
 
#endif
2302
 
 
2303
 
    if(data.dptr) {
2304
 
      int i;
2305
 
      
2306
 
      strncpy(name, data.dptr, maxNameLen-1);
2307
 
      name[maxNameLen-1] = 0;
2308
 
 
2309
 
      if((maxNameLen > 5) &&
2310
 
         (strcmp(&name[strlen(name)-5], ".arpa") == 0))
2311
 
        return(0); /* Do not return XXXX.in-addr.arpa */
2312
 
 
2313
 
      for(i=0; i<maxNameLen; i++)
2314
 
        name[i] = tolower(name[i]);
2315
 
 
2316
 
      free(data.dptr);
2317
 
      found = 1;
2318
 
    }
2319
 
  }
2320
 
#endif
2321
 
  return(found);
2322
 
}
2323
 
 
2324
 
/* *************************************** */
2325
 
 
2326
 
int strOnlyDigits(const char *s) {
2327
 
 
2328
 
  if((*s) == '\0')
2329
 
    return 0;
2330
 
 
2331
 
  while ((*s) != '\0') {
2332
 
    if(!isdigit(*s))
2333
 
      return 0;
2334
 
    s++;
2335
 
  }
2336
 
 
2337
 
  return(1);
2338
 
}
2339
 
 
2340
 
/* ****************************************************** */
2341
 
 
2342
 
FILE* getNewRandomFile(char* fileName, int len) {
2343
 
  FILE* fd;
2344
 
 
2345
 
#ifndef WIN32
2346
 
#if 0
2347
 
  int tmpfd;
2348
 
 
2349
 
  /* Patch courtesy of Thomas Biege <thomas@suse.de> */
2350
 
  if(((tmpfd = mkstemp(fileName)) < 0)
2351
 
     || (fchmod(tmpfd, 0600) < 0)
2352
 
     || ((fd = fdopen(tmpfd, "wb")) == NULL))
2353
 
    fd = NULL;
2354
 
#else
2355
 
  char tmpFileName[NAME_MAX];
2356
 
 
2357
 
  strcpy(tmpFileName, fileName);
2358
 
  sprintf(fileName, "%s-%lu", tmpFileName, numHandledHTTPrequests);
2359
 
  fd = fopen(fileName, "wb");
2360
 
#endif /* 0 */
2361
 
#else
2362
 
  tmpnam(fileName);
2363
 
  fd = fopen(fileName, "wb");
2364
 
#endif
2365
 
 
2366
 
  if(fd == NULL)
2367
 
    traceEvent(TRACE_WARNING, "Unable to create temp. file (%s). ", fileName);
2368
 
 
2369
 
  return(fd);
2370
 
}
2371
 
 
2372
 
/* ****************************************************** */
2373
 
 
2374
 
/*
2375
 
  Function added in order to catch invalid
2376
 
  strings passed on the command line.
2377
 
 
2378
 
  Thanks to Bailleux Christophe <cb@grolier.fr> for
2379
 
  pointing out the finger at the problem.
2380
 
*/
2381
 
 
2382
 
void stringSanityCheck(char* string) {
2383
 
  int i, j;
2384
 
 
2385
 
  if(string == NULL)  {
2386
 
    traceEvent(TRACE_ERROR, "FATAL ERROR: Invalid string specified.");
2387
 
    exit(-1);
2388
 
  }
2389
 
 
2390
 
  for(i=0, j=1; i<strlen(string); i++) {
2391
 
    switch(string[i]) {
2392
 
    case '%':
2393
 
    case '\\':
2394
 
      j=0;
2395
 
      break;
2396
 
    }
2397
 
  }
2398
 
 
2399
 
  if(j == 0) {
2400
 
    traceEvent(TRACE_ERROR, "FATAL ERROR: Invalid string '%s' specified.",
2401
 
               string);
2402
 
    exit(-1);
2403
 
  }
2404
 
}
2405
 
 
2406
 
/* ****************************************************** */
2407
 
 
2408
 
/*
2409
 
  Function added in order to catch invalid (too long)
2410
 
  device names specified on the command line.
2411
 
 
2412
 
  Thanks to Bailleux Christophe <cb@grolier.fr> for
2413
 
  pointing out the finger at the problem.
2414
 
*/
2415
 
 
2416
 
void deviceSanityCheck(char* string) {
2417
 
  int i, j;
2418
 
 
2419
 
  if(strlen(string) > MAX_DEVICE_NAME_LEN)
2420
 
    j = 0;
2421
 
  else {
2422
 
    for(i=0, j=1; i<strlen(string); i++) {
2423
 
      switch(string[i]) {
2424
 
      case ' ':
2425
 
      case ',':
2426
 
        j=0;
2427
 
        break;
2428
 
      }
2429
 
    }
2430
 
  }
2431
 
 
2432
 
  if(j == 0) {
2433
 
    traceEvent(TRACE_ERROR, "FATAL ERROR: Invalid device specified.");
2434
 
    exit(-1);
2435
 
  }
2436
 
}
2437
 
 
2438
 
/* ****************************************************** */
2439
 
 
2440
 
#ifndef HAVE_SNPRINTF
2441
 
int snprintf(char *string, size_t maxlen, const char *format, ...) {
2442
 
  int ret=0;
2443
 
  va_list args;
2444
 
 
2445
 
  va_start(args, format);
2446
 
  vsprintf(string,format,args);
2447
 
  va_end(args);
2448
 
  return ret;
2449
 
}
2450
 
#endif
2451
 
 
2452
 
/* ************************ */
2453
 
 
2454
 
void fillDomainName(HostTraffic *el) {
2455
 
  u_int i;
2456
 
 
2457
 
  if(theDomainHasBeenComputed(el)
2458
 
     || (el->hostSymIpAddress == NULL))
2459
 
    return;
2460
 
 
2461
 
#ifdef MULTITHREADED
2462
 
  accessMutex(&addressResolutionMutex, "fillDomainName");
2463
 
#endif
2464
 
 
2465
 
  if((el->hostSymIpAddress[0] == '*')
2466
 
     || (el->hostNumIpAddress[0] == '\0')
2467
 
     || (isdigit(el->hostSymIpAddress[strlen(el->hostSymIpAddress)-1]) &&
2468
 
         isdigit(el->hostSymIpAddress[0]))) {
2469
 
    /* NOTE: theDomainHasBeenComputed(el) = 0 */
2470
 
    el->fullDomainName = el->dotDomainName = "";
2471
 
#ifdef MULTITHREADED
2472
 
    releaseMutex(&addressResolutionMutex);
2473
 
#endif
2474
 
    return;
2475
 
  }
2476
 
 
2477
 
  FD_SET(THE_DOMAIN_HAS_BEEN_COMPUTED_FLAG, &el->flags);
2478
 
  el->fullDomainName = el->dotDomainName = ""; /* Reset values... */
2479
 
 
2480
 
  i = strlen(el->hostSymIpAddress)-1;
2481
 
 
2482
 
  while(i > 0)
2483
 
    if(el->hostSymIpAddress[i] == '.')
2484
 
      break;
2485
 
    else
2486
 
      i--;
2487
 
 
2488
 
  if((i > 0)
2489
 
     && strcmp(el->hostSymIpAddress, el->hostNumIpAddress)
2490
 
     && (strlen(el->hostSymIpAddress) > (i+1)))
2491
 
    el->dotDomainName = &el->hostSymIpAddress[i+1];
2492
 
  else {
2493
 
    /* Let's use the local domain name */
2494
 
#ifdef DEBUG
2495
 
    traceEvent(TRACE_INFO, "'%s' [%s/%s]\n",
2496
 
           el->hostSymIpAddress, domainName, shortDomainName);
2497
 
#endif
2498
 
    if((domainName[0] != '\0')
2499
 
       && (strcmp(el->hostSymIpAddress, el->hostNumIpAddress))) {
2500
 
      int len  = strlen(el->hostSymIpAddress);
2501
 
      int len1 = strlen(domainName);
2502
 
 
2503
 
      /* traceEvent(TRACE_INFO, "%s [%s]\n",
2504
 
         el->hostSymIpAddress, &el->hostSymIpAddress[len-len1]); */
2505
 
 
2506
 
      if((len > len1)
2507
 
         && (strcmp(&el->hostSymIpAddress[len-len1-1], domainName) == 0))
2508
 
        el->hostSymIpAddress[len-len1-1] = '\0';
2509
 
 
2510
 
      el->fullDomainName = domainName;
2511
 
      el->dotDomainName = shortDomainName;
2512
 
    } else {
2513
 
      el->fullDomainName = el->dotDomainName = "";
2514
 
    }
2515
 
 
2516
 
#ifdef MULTITHREADED
2517
 
    releaseMutex(&addressResolutionMutex);
2518
 
#endif
2519
 
    return;
2520
 
  }
2521
 
 
2522
 
  for(i=0; el->hostSymIpAddress[i] != '\0'; i++)
2523
 
    el->hostSymIpAddress[i] = tolower(el->hostSymIpAddress[i]);
2524
 
 
2525
 
  i = 0;
2526
 
  while(el->hostSymIpAddress[i] != '\0')
2527
 
    if(el->hostSymIpAddress[i] == '.')
2528
 
      break;
2529
 
    else
2530
 
      i++;
2531
 
 
2532
 
  if((el->hostSymIpAddress[i] == '.')
2533
 
         && (strlen(el->hostSymIpAddress) > (i+1)))
2534
 
    el->fullDomainName = &el->hostSymIpAddress[i+1];
2535
 
 
2536
 
  /* traceEvent(TRACE_INFO, "'%s'\n", el->domainName); */
2537
 
 
2538
 
#ifdef MULTITHREADED
2539
 
    releaseMutex(&addressResolutionMutex);
2540
 
#endif
2541
 
}
2542
 
 
2543
 
/* ********************************* */
2544
 
 
2545
 
/* similar to Java.String.trim() */
2546
 
void trimString(char* str) {
2547
 
  int len = strlen(str), i, idx;
2548
 
  char *out = (char *) malloc(sizeof(char) * (len+1));
2549
 
 
2550
 
  if(out == NULL) {
2551
 
    str = NULL;
2552
 
    return;
2553
 
  }
2554
 
 
2555
 
  for(i=0, idx=0; i<len; i++)
2556
 
    {
2557
 
      switch(str[i])
2558
 
        {
2559
 
        case ' ':
2560
 
        case '\t':
2561
 
          if((idx > 0)
2562
 
             && (out[idx-1] != ' ')
2563
 
             && (out[idx-1] != '\t'))
2564
 
            out[idx++] = str[i];
2565
 
          break;
2566
 
        default:
2567
 
          out[idx++] = str[i];
2568
 
          break;
2569
 
        }
2570
 
    }
2571
 
 
2572
 
  out[idx] = '\0';
2573
 
  strncpy(str, out, len);
2574
 
  free(out);
2575
 
}
2576
 
 
2577
 
/* ****************************** */
2578
 
 
2579
 
void setNBnodeNameType(HostTraffic *theHost,
2580
 
                       char nodeType, char* nbName) {
2581
 
  trimString(nbName);
2582
 
 
2583
 
  if((nbName == NULL) || (strlen(nbName) == 0))
2584
 
    return;
2585
 
 
2586
 
  if(strlen(nbName) >= (MAX_HOST_SYM_NAME_LEN-1)) /* (**) */
2587
 
    nbName[MAX_HOST_SYM_NAME_LEN-2] = '\0';
2588
 
  
2589
 
  theHost->nbNodeType = (char)nodeType;
2590
 
  /* Courtesy of Roberto F. De Luca <deluca@tandar.cnea.gov.ar> */
2591
 
 
2592
 
  theHost->nbNodeType = (char)nodeType;
2593
 
 
2594
 
  switch(nodeType) {
2595
 
  case 0x0:  /* Workstation */
2596
 
  case 0x20: /* Server */
2597
 
    if(theHost->nbHostName == NULL) {
2598
 
      theHost->nbHostName = strdup(nbName);
2599
 
      updateHostName(theHost);
2600
 
      
2601
 
      if(theHost->hostSymIpAddress[0] == '\0')
2602
 
        strcpy(theHost->hostSymIpAddress, nbName); /* See up (**) */
2603
 
            
2604
 
#ifdef DEBUG
2605
 
      printf("nbHostName=%s [0x%X]\n", nbName, nodeType);
2606
 
#endif
2607
 
    }
2608
 
    break;
2609
 
  case 0x1C: /* Domain Controller */
2610
 
  case 0x1E: /* Domain */
2611
 
  case 0x1D: /* Workgroup (I think) */
2612
 
    if(theHost->nbDomainName == NULL) {
2613
 
      if(strcmp(nbName, "__MSBROWSE__") && strncmp(&nbName[2], "__", 2)) {
2614
 
        theHost->nbDomainName = strdup(nbName);
2615
 
      }
2616
 
      break;      
2617
 
    }
2618
 
  }
2619
 
 
2620
 
  switch(nodeType) {
2621
 
  case 0x0:  /* Workstation */
2622
 
    FD_SET(HOST_TYPE_WORKSTATION, &theHost->flags);
2623
 
  case 0x20: /* Server */
2624
 
    FD_SET(HOST_TYPE_SERVER, &theHost->flags);
2625
 
  case 0x1B: /* Master Browser */
2626
 
    FD_SET(HOST_TYPE_MASTER_BROWSER, &theHost->flags);
2627
 
  }
2628
 
}
2629
 
 
2630
 
/* ******************************************* */
2631
 
 
2632
 
/* #define DEBUG  */
2633
 
 
2634
 
void addPassiveSessionInfo(u_long theHost, u_short thePort) {
2635
 
  int i;
2636
 
  time_t timeoutTime = actTime - PASSIVE_SESSION_PURGE_TIMEOUT;
2637
 
 
2638
 
#ifdef DEBUG
2639
 
  traceEvent(TRACE_INFO, "Adding %ld:%d", theHost, thePort);
2640
 
#endif
2641
 
 
2642
 
  for(i=0; i<passiveSessionsLen; i++) {
2643
 
    if((passiveSessions[i].sessionPort == 0)
2644
 
       || (passiveSessions[i].creationTime < timeoutTime)) {
2645
 
      passiveSessions[i].sessionHost.s_addr = theHost,
2646
 
        passiveSessions[i].sessionPort = thePort,
2647
 
        passiveSessions[i].creationTime = actTime;
2648
 
      break;
2649
 
    }
2650
 
  }
2651
 
 
2652
 
  if(i == passiveSessionsLen) {
2653
 
    /* Slot Not found */
2654
 
    traceEvent(TRACE_INFO, "Info: passiveSessions[size=%d] is full", passiveSessionsLen);
2655
 
 
2656
 
    /* Shift table entries */
2657
 
    for(i=1; i<passiveSessionsLen; i++) {
2658
 
      passiveSessions[i-1].sessionHost = passiveSessions[i].sessionHost,
2659
 
        passiveSessions[i-1].sessionPort = passiveSessions[i].sessionPort;
2660
 
    }
2661
 
    passiveSessions[passiveSessionsLen-1].sessionHost.s_addr = theHost,
2662
 
      passiveSessions[passiveSessionsLen-1].sessionPort = thePort;
2663
 
  }
2664
 
}
2665
 
 
2666
 
/* ******************************************* */
2667
 
 
2668
 
int isPassiveSession(u_long theHost, u_short thePort) {
2669
 
  int i;
2670
 
 
2671
 
#ifdef DEBUG
2672
 
  traceEvent(TRACE_INFO, "Searching for %ld:%d",
2673
 
             theHost, thePort);
2674
 
#endif
2675
 
 
2676
 
  for(i=0; i<passiveSessionsLen; i++) {
2677
 
    if((passiveSessions[i].sessionHost.s_addr == theHost)
2678
 
       && (passiveSessions[i].sessionPort == thePort)) {
2679
 
      passiveSessions[i].sessionHost.s_addr = 0,
2680
 
        passiveSessions[i].sessionPort = 0,
2681
 
        passiveSessions[i].creationTime = 0;
2682
 
#ifdef DEBUG
2683
 
      traceEvent(TRACE_INFO, "Found passive FTP session");
2684
 
#endif
2685
 
      return(1);
2686
 
    }
2687
 
  }
2688
 
 
2689
 
  return(0);
2690
 
}
2691
 
 
2692
 
/* ******************************************* */
2693
 
 
2694
 
void initPassiveSessions() {
2695
 
  int len;
2696
 
 
2697
 
  len = sizeof(SessionInfo)*NUM_SESSION_INFO;
2698
 
  passiveSessions = (SessionInfo*)malloc(len);
2699
 
  memset(passiveSessions, 0, len);
2700
 
  passiveSessionsLen = NUM_SESSION_INFO;
2701
 
}
2702
 
 
2703
 
/* ******************************* */
2704
 
 
2705
 
void termPassiveSessions() {
2706
 
  free(passiveSessions);
2707
 
}
2708
 
 
2709
 
/* ******************************* */
2710
 
 
2711
 
int getPortByName(ServiceEntry **theSvc, char* portName) {
2712
 
  int idx;
2713
 
 
2714
 
  for(idx=0; idx<numActServices; idx++) {
2715
 
 
2716
 
#ifdef DEBUG
2717
 
    if(theSvc[idx] != NULL)
2718
 
      traceEvent(TRACE_INFO, "%d/%s [%s]\n",
2719
 
                 theSvc[idx]->port,
2720
 
                 theSvc[idx]->name, portName);
2721
 
#endif
2722
 
 
2723
 
    if((theSvc[idx] != NULL)
2724
 
       && (strcmp(theSvc[idx]->name, portName) == 0))
2725
 
      return(theSvc[idx]->port);
2726
 
  }
2727
 
 
2728
 
  return(-1);
2729
 
}
2730
 
 
2731
 
/* ******************************* */
2732
 
 
2733
 
char* getPortByNumber(ServiceEntry **theSvc, int port) {
2734
 
  int idx = port % numActServices;
2735
 
  ServiceEntry *scan;
2736
 
 
2737
 
  for(;;) {
2738
 
    scan = theSvc[idx];
2739
 
 
2740
 
    if((scan != NULL) && (scan->port == port))
2741
 
      return(scan->name);
2742
 
    else if(scan == NULL)
2743
 
      return(NULL);
2744
 
    else
2745
 
      idx = (idx+1) % numActServices;
2746
 
  }
2747
 
}
2748
 
 
2749
 
/* ******************************* */
2750
 
 
2751
 
char* getPortByNum(int port, int type) {
2752
 
  char* rsp;
2753
 
 
2754
 
  if(type == IPPROTO_TCP) {
2755
 
    rsp = getPortByNumber(tcpSvc, port);
2756
 
  } else {
2757
 
    rsp = getPortByNumber(udpSvc, port);
2758
 
  }
2759
 
 
2760
 
  return(rsp);
2761
 
}
2762
 
 
2763
 
/* ******************************* */
2764
 
 
2765
 
char* getAllPortByNum(int port) {
2766
 
  char* rsp;
2767
 
  static char staticBuffer[2][16];
2768
 
  static short portBufIdx=0;
2769
 
 
2770
 
  rsp = getPortByNumber(tcpSvc, port); /* Try TCP first... */
2771
 
  if(rsp == NULL)
2772
 
    rsp = getPortByNumber(udpSvc, port);  /* ...then UDP */
2773
 
 
2774
 
  if(rsp != NULL)
2775
 
    return(rsp);
2776
 
  else {
2777
 
    portBufIdx = (short)((portBufIdx+1)%2);
2778
 
    if(snprintf(staticBuffer[portBufIdx], 16, "%d", port) < 0)
2779
 
      traceEvent(TRACE_ERROR, "Buffer overflow!");
2780
 
    return(staticBuffer[portBufIdx]);
2781
 
  }
2782
 
}
2783
 
 
2784
 
/* ******************************* */
2785
 
 
2786
 
int getAllPortByName(char* portName) {
2787
 
  int rsp;
2788
 
 
2789
 
  rsp = getPortByName(tcpSvc, portName); /* Try TCP first... */
2790
 
  if(rsp == -1)
2791
 
    rsp = getPortByName(udpSvc, portName);  /* ...then UDP */
2792
 
 
2793
 
  return(rsp);
2794
 
}
2795
 
 
2796
 
 
2797
 
/* ******************************* */
2798
 
 
2799
 
void addPortHashEntry(ServiceEntry **theSvc, int port, char* name) {
2800
 
  int idx = port % numActServices;
2801
 
  ServiceEntry *scan;
2802
 
 
2803
 
  for(;;) {
2804
 
    scan = theSvc[idx];
2805
 
 
2806
 
    if(scan == NULL) {
2807
 
      theSvc[idx] = (ServiceEntry*)malloc(sizeof(ServiceEntry));
2808
 
      theSvc[idx]->port = (u_short)port;
2809
 
      theSvc[idx]->name = strdup(name);
2810
 
      break;
2811
 
    } else
2812
 
      idx = (idx+1) % numActServices;
2813
 
  }
2814
 
}
2815
 
 
2816
 
/* ******************************* */
2817
 
 
2818
 
void resetUsageCounter(UsageCounter *counter) {
2819
 
  int i;
2820
 
 
2821
 
  memset(counter, 0, sizeof(UsageCounter));
2822
 
 
2823
 
  for(i=0; i<MAX_NUM_CONTACTED_PEERS; i++)
2824
 
    counter->peersIndexes[i] = NO_PEER;
2825
 
}
2826
 
 
2827
 
/* ************************************ */
2828
 
 
2829
 
/*
2830
 
  This function has to be used to reset (i.e. initialize to
2831
 
  empty values in the correct range) HostTraffic
2832
 
  instances.
2833
 
*/
2834
 
 
2835
 
void resetSecurityHostTraffic(HostTraffic *el) {
2836
 
 
2837
 
  if(el->securityHostPkts == NULL) return;
2838
 
  
2839
 
  resetUsageCounter(&el->securityHostPkts->synPktsSent);
2840
 
  resetUsageCounter(&el->securityHostPkts->rstPktsSent);
2841
 
  resetUsageCounter(&el->securityHostPkts->rstAckPktsSent);
2842
 
  resetUsageCounter(&el->securityHostPkts->synFinPktsSent);
2843
 
  resetUsageCounter(&el->securityHostPkts->finPushUrgPktsSent);
2844
 
  resetUsageCounter(&el->securityHostPkts->nullPktsSent);
2845
 
  resetUsageCounter(&el->securityHostPkts->ackScanSent);
2846
 
  resetUsageCounter(&el->securityHostPkts->xmasScanSent);
2847
 
  resetUsageCounter(&el->securityHostPkts->finScanSent);
2848
 
  resetUsageCounter(&el->securityHostPkts->nullScanSent);
2849
 
  resetUsageCounter(&el->securityHostPkts->rejectedTCPConnSent);
2850
 
  resetUsageCounter(&el->securityHostPkts->establishedTCPConnSent);
2851
 
  resetUsageCounter(&el->securityHostPkts->udpToClosedPortSent);
2852
 
  resetUsageCounter(&el->securityHostPkts->udpToDiagnosticPortSent);
2853
 
  resetUsageCounter(&el->securityHostPkts->tcpToDiagnosticPortSent);
2854
 
  resetUsageCounter(&el->securityHostPkts->tinyFragmentSent);
2855
 
  resetUsageCounter(&el->securityHostPkts->icmpFragmentSent);
2856
 
  resetUsageCounter(&el->securityHostPkts->overlappingFragmentSent);
2857
 
  resetUsageCounter(&el->securityHostPkts->closedEmptyTCPConnSent);
2858
 
  resetUsageCounter(&el->securityHostPkts->icmpPortUnreachSent);
2859
 
  resetUsageCounter(&el->securityHostPkts->icmpHostNetUnreachSent);
2860
 
  resetUsageCounter(&el->securityHostPkts->icmpProtocolUnreachSent);
2861
 
  resetUsageCounter(&el->securityHostPkts->icmpAdminProhibitedSent);
2862
 
  resetUsageCounter(&el->securityHostPkts->malformedPktsSent);
2863
 
 
2864
 
  /* ************* */
2865
 
 
2866
 
  resetUsageCounter(&el->contactedRcvdPeers);
2867
 
 
2868
 
  resetUsageCounter(&el->securityHostPkts->synPktsRcvd);
2869
 
  resetUsageCounter(&el->securityHostPkts->rstPktsRcvd);
2870
 
  resetUsageCounter(&el->securityHostPkts->rstAckPktsRcvd);
2871
 
  resetUsageCounter(&el->securityHostPkts->synFinPktsRcvd);
2872
 
  resetUsageCounter(&el->securityHostPkts->finPushUrgPktsRcvd);
2873
 
  resetUsageCounter(&el->securityHostPkts->nullPktsRcvd);
2874
 
  resetUsageCounter(&el->securityHostPkts->ackScanRcvd);
2875
 
  resetUsageCounter(&el->securityHostPkts->xmasScanRcvd);
2876
 
  resetUsageCounter(&el->securityHostPkts->finScanRcvd);
2877
 
  resetUsageCounter(&el->securityHostPkts->nullScanRcvd);
2878
 
  resetUsageCounter(&el->securityHostPkts->rejectedTCPConnRcvd);
2879
 
  resetUsageCounter(&el->securityHostPkts->establishedTCPConnRcvd);
2880
 
  resetUsageCounter(&el->securityHostPkts->udpToClosedPortRcvd);
2881
 
  resetUsageCounter(&el->securityHostPkts->udpToDiagnosticPortRcvd);
2882
 
  resetUsageCounter(&el->securityHostPkts->tcpToDiagnosticPortRcvd);
2883
 
  resetUsageCounter(&el->securityHostPkts->tinyFragmentRcvd);
2884
 
  resetUsageCounter(&el->securityHostPkts->icmpFragmentRcvd);
2885
 
  resetUsageCounter(&el->securityHostPkts->overlappingFragmentRcvd);
2886
 
  resetUsageCounter(&el->securityHostPkts->closedEmptyTCPConnRcvd);
2887
 
  resetUsageCounter(&el->securityHostPkts->icmpPortUnreachRcvd);
2888
 
  resetUsageCounter(&el->securityHostPkts->icmpHostNetUnreachRcvd);
2889
 
  resetUsageCounter(&el->securityHostPkts->icmpProtocolUnreachRcvd);
2890
 
  resetUsageCounter(&el->securityHostPkts->icmpAdminProhibitedRcvd);
2891
 
  resetUsageCounter(&el->securityHostPkts->malformedPktsRcvd); 
2892
 
 
2893
 
  resetUsageCounter(&el->contactedSentPeers);
2894
 
  resetUsageCounter(&el->contactedRcvdPeers);
2895
 
  resetUsageCounter(&el->contactedRouters);
2896
 
}
2897
 
 
2898
 
/* ********************************************* */
2899
 
 
2900
 
char* mapIcmpType(int icmpType) {
2901
 
  static char icmpString[4];
2902
 
 
2903
 
  icmpType %= ICMP_MAXTYPE; /* Just to be safe... */
2904
 
 
2905
 
  switch(icmpType) {
2906
 
  case 0: return("ECHOREPLY");
2907
 
  case 3: return("UNREACH");
2908
 
  case 4: return("SOURCEQUENCH");
2909
 
  case 5: return("REDIRECT");
2910
 
  case 8: return("ECHO");
2911
 
  case 9: return("ROUTERADVERT");
2912
 
  case 10: return("ROUTERSOLICI");
2913
 
  case 11: return("TIMXCEED");
2914
 
  case 12: return("PARAMPROB");
2915
 
  case 13: return("TIMESTAMP");
2916
 
  case 14: return("TIMESTAMPREPLY");
2917
 
  case 15: return("INFOREQ");
2918
 
  case 16: return("INFOREQREPLY");
2919
 
  case 17: return("MASKREQ");
2920
 
  case 18: return("MASKREPLY");
2921
 
  default:
2922
 
    sprintf(icmpString, "%d", icmpType);
2923
 
    return(icmpString);
2924
 
  }
2925
 
}
2926
 
 
2927
 
/* ******************************** */
2928
 
 
2929
 
#ifndef HAVE_LOCALTIME_R
2930
 
#undef localtime
2931
 
 
2932
 
#ifdef MULTITHREADED
2933
 
static PthreadMutex localtimeMutex;
2934
 
static char localtimeMutexInitialized = 0;
2935
 
#endif
2936
 
 
2937
 
struct tm *localtime_r(const time_t *t, struct tm *tp) {
2938
 
  struct tm *theTime;
2939
 
 
2940
 
#if defined(MULTITHREADED)
2941
 
  if(!localtimeMutexInitialized) {
2942
 
    createMutex(&localtimeMutex);
2943
 
    localtimeMutexInitialized = 1;
2944
 
  }
2945
 
  accessMutex(&localtimeMutex, "localtime_r");
2946
 
#endif
2947
 
 
2948
 
  theTime = localtime(t);
2949
 
 
2950
 
  if(theTime != NULL) 
2951
 
    memcpy(tp, theTime, sizeof(struct tm));
2952
 
  else
2953
 
    memset(tp, 0, sizeof(struct tm)); /* What shall I do ? */
2954
 
 
2955
 
#if defined(MULTITHREADED)
2956
 
  releaseMutex(&localtimeMutex);
2957
 
#endif
2958
 
 
2959
 
  return(tp);
2960
 
}
2961
 
#endif
2962