~ubuntu-branches/ubuntu/wily/ntop/wily-proposed

« back to all changes in this revision

Viewing changes to ntop/util.c

  • Committer: Bazaar Package Importer
  • Author(s): Dennis Schoen
  • Date: 2002-04-12 11:38:47 UTC
  • Revision ID: james.westby@ubuntu.com-20020412113847-4k4yydw0pzybc6g8
Tags: upstream-2.0.0
ImportĀ upstreamĀ versionĀ 2.0.0

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(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, buf);
 
2183
          break;
 
2184
        case 1:
 
2185
          syslog(LOG_WARNING, buf);
 
2186
          break;
 
2187
        case 2:
 
2188
          syslog(LOG_NOTICE, buf);
 
2189
          break;
 
2190
        default:
 
2191
          syslog(LOG_INFO, buf);
 
2192
          break;
 
2193
        }
 
2194
#else
 
2195
        syslog(LOG_ERR, 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