~ubuntu-branches/ubuntu/maverick/ntop/maverick

« back to all changes in this revision

Viewing changes to ntop/main.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
#include "ntop.h"
 
44
#include "globals-report.h"
 
45
 
 
46
#if defined(WIN32) && defined(__GNUC__) /* mingw compiler */
 
47
 /* we're using the winpcap getopt() implementation
 
48
  * which has the globals inside the dll, so a simple
 
49
  * extern declaration is insufficient on win32
 
50
  *
 
51
  * Scott Renfro <scott@renfro.org>
 
52
  *
 
53
  */
 
54
extern __attribute__((dllimport)) char *optarg;
 
55
#else  /* !WIN32 */
 
56
extern char *optarg;
 
57
#endif
 
58
 
 
59
#if defined(NEED_INET_ATON)
 
60
/*
 
61
 * Minimal implementation of inet_aton.
 
62
 * Cannot distinguish between failure and a local broadcast address.
 
63
 */
 
64
 
 
65
#ifndef INADDR_NONE
 
66
#define INADDR_NONE 0xffffffff
 
67
#endif
 
68
 
 
69
 
 
70
static int inet_aton(const char *cp, struct in_addr *addr)
 
71
{
 
72
  addr->s_addr = inet_addr(cp);
 
73
  return (addr->s_addr == INADDR_NONE) ? 0 : 1;
 
74
}
 
75
 
 
76
#endif
 
77
 
 
78
/* That's the meat */
 
79
int main(int argc, char *argv[]) {
 
80
  int pflag, i, len;
 
81
#ifdef WIN32
 
82
  int optind=0;
 
83
#else
 
84
  int userId=0, groupId=0;
 
85
#endif
 
86
  int op, mergeInterfaces=1;
 
87
  int enableDBsupport=0;
 
88
  int enableThUpdate=1;
 
89
  int enableIdleHosts=1;
 
90
  char *cp, *localAddresses=NULL, *webAddr=NULL, *devices, *sslAddr=NULL;
 
91
  char *flowSpecs, *protoSpecs, rulesFile[128], ifStr[196], *theOpts;
 
92
  time_t lastTime;
 
93
 
 
94
  printf("Wait please: ntop is coming up...\n");
 
95
 
 
96
  ntop_argc = argc;
 
97
  ntop_argv = argv;
 
98
 
 
99
#ifndef WIN32
 
100
  if (freopen("/dev/null", "w", stderr) == NULL) {
 
101
    traceEvent(TRACE_WARNING,
 
102
               "ntop: unable to replace stderr with /dev/null: %s\n",
 
103
               strerror(errno));
 
104
  }
 
105
#endif
 
106
 
 
107
#ifdef MEMORY_DEBUG
 
108
  initLeaks();
 
109
#endif
 
110
 
 
111
  webPort = NTOP_DEFAULT_WEB_PORT;
 
112
#ifdef HAVE_OPENSSL
 
113
  sslPort = 0; /* Disabled: it can enabled using -W <SSL port> */
 
114
#endif
 
115
 
 
116
  enableSuspiciousPacketDump = 0;
 
117
  usePersistentStorage = 0;
 
118
  stickyHosts = 0;
 
119
  enableNetFlowSupport = 0;
 
120
 
 
121
  /* Initialization of local variables */
 
122
  isLsofPresent = isNmapPresent = filterExpressionInExtraFrame = 0;
 
123
 
 
124
  rulesFile[0] = '\0';
 
125
  flowSpecs = NULL;
 
126
  protoSpecs = NULL;
 
127
  flowsList = NULL;
 
128
  localAddrFlag = 1;
 
129
  logTimeout = 0;
 
130
  tcpChain = NULL, udpChain = NULL, icmpChain = NULL;
 
131
  devices = NULL;
 
132
  daemonMode = pflag = numericFlag = debugMode = 0;
 
133
 
 
134
#ifndef WIN32
 
135
  useSyslog = 0;
 
136
#endif
 
137
 
 
138
  refreshRate = 0;
 
139
  rFileName = NULL;
 
140
  maxHashSize = MAX_HASH_SIZE;
 
141
  traceLevel = DEFAULT_TRACE_LEVEL;
 
142
  accuracyLevel = HIGH_ACCURACY_LEVEL;
 
143
  domainName[0] = '\0';
 
144
  /*
 
145
    If you need a good mapper look at this
 
146
    http://jake.ntop.org/cgi-bin/mapper.pl
 
147
  */
 
148
  mapperURL[0] = '\0';
 
149
  pcapLog = NULL;
 
150
  actTime = time(NULL);
 
151
  strncpy(dbPath, DBFILE_DIR, sizeof(dbPath));
 
152
 
 
153
  if ((cp = strrchr(argv[0], '/')) != NULL)
 
154
    program_name = cp + 1;
 
155
  else
 
156
    program_name = argv[0];
 
157
 
 
158
  if(strcmp(program_name, "ntopd") == 0) {
 
159
    daemonMode++;
 
160
  }
 
161
 
 
162
#ifdef WIN32
 
163
  theOpts = "ce:f:F:hr:p:i:nw:m:b:B:D:s:P:R:S:g:t:a:W:12l:qU:kA:";
 
164
#else
 
165
  theOpts = "cIdEe:f:F:hr:i:p:nNw:m:b:v:D:s:P:R:MS:g:t:a:u:W:12l:qU:kKLA:";
 
166
#endif
 
167
 
 
168
  while((op = getopt(argc, argv, theOpts)) != EOF) {
 
169
    switch (op) {
 
170
      /* Courtesy of Ralf Amandi <Ralf.Amandi@accordata.net> */
 
171
 
 
172
    case 'c': /* Sticky hosts = hosts that are not purged
 
173
                 when idle */
 
174
      stickyHosts = 1;
 
175
      break;
 
176
 
 
177
    case 'P': /* DB-Path */
 
178
      stringSanityCheck(optarg);
 
179
      strncpy(dbPath, optarg, sizeof(dbPath)-1)[sizeof(dbPath)-1] = '\0';
 
180
      break;
 
181
 
 
182
    case 'a': /* ntop access log path */
 
183
      stringSanityCheck(optarg);
 
184
      strncpy(accessLogPath, optarg,
 
185
              sizeof(accessLogPath)-1)[sizeof(accessLogPath)-1] = '\0';
 
186
      break;
 
187
 
 
188
#ifndef WIN32
 
189
    case 'd':
 
190
      daemonMode=1;
 
191
      break;
 
192
 
 
193
    case 'I': /* Interactive mode */
 
194
      printf("intop provides you curses support. "
 
195
             "ntop -I is no longer used.\n");
 
196
      return(-1);
 
197
#endif
 
198
 
 
199
    case 'q': /* allow ntop to save suspicious packets
 
200
                 in a file in pcap (tcpdump) format */
 
201
      enableSuspiciousPacketDump=1;
 
202
      break;
 
203
 
 
204
    case '1': /* disable throughput update */
 
205
      enableThUpdate=0;
 
206
      break;
 
207
 
 
208
    case '2': /* disable purging of idle hosts */
 
209
      enableIdleHosts=0;
 
210
      break;
 
211
 
 
212
    case 'l':
 
213
      stringSanityCheck(optarg);
 
214
      pcapLog = optarg;
 
215
      break;
 
216
 
 
217
    case 'b': /* host:port */
 
218
      stringSanityCheck(optarg);
 
219
      handleDbSupport(optarg, &enableDBsupport);
 
220
      break;
 
221
 
 
222
    case 'g': /* host:port */
 
223
      stringSanityCheck(optarg);
 
224
      handleNetFlowSupport(optarg);
 
225
      break;
 
226
 
 
227
#ifdef HAVE_MYSQL
 
228
    case 'v': /* username:password:dbname:host */
 
229
      stringSanityCheck(optarg);
 
230
      handlemySQLSupport(optarg, &enableDBsupport);
 
231
      break;
 
232
#endif
 
233
 
 
234
    case 'D': /* domain */
 
235
      stringSanityCheck(optarg);
 
236
      strncpy(domainName, optarg,
 
237
              sizeof(domainName)-1)[sizeof(domainName)-1] = '\0';
 
238
      break;
 
239
        
 
240
    case 'f':
 
241
      isLsofPresent = 0; /* Don't make debugging too complex */
 
242
      rFileName = optarg;
 
243
      break;
 
244
        
 
245
    case 'r':
 
246
      if(!isdigit(optarg[0])) {
 
247
        printf("FATAL ERROR: flag -r expects a numeric argument.\n");
 
248
        exit(-1);
 
249
      }
 
250
      refreshRate = atoi(optarg);
 
251
      break;
 
252
 
 
253
#ifndef MICRO_NTOP
 
254
    case 'e':
 
255
      maxNumLines = atoi(optarg);
 
256
      break;
 
257
#endif
 
258
 
 
259
    case 'E':
 
260
      isLsofPresent  = checkCommand("lsof");
 
261
      isNmapPresent  = checkCommand("nmap");
 
262
      break;
 
263
 
 
264
    case 's':
 
265
      maxHashSize = atoi(optarg);
 
266
      if(maxHashSize < 64) {
 
267
        maxHashSize = 64;
 
268
        traceEvent(TRACE_INFO, "Max hash size set to 64 (minimum hash size)");
 
269
      }
 
270
      break;
 
271
 
 
272
    case 'i':
 
273
      stringSanityCheck(optarg);
 
274
      devices = optarg;
 
275
      break;
 
276
 
 
277
    case 'p':
 
278
      stringSanityCheck(optarg);
 
279
      len = strlen(optarg);
 
280
      if(len > 2048) len = 2048;
 
281
      protoSpecs = (char*)malloc(len+1);
 
282
      memset(protoSpecs, 0, len+1);
 
283
      strncpy(protoSpecs, optarg, len);
 
284
      break;
 
285
 
 
286
    case 'F':
 
287
      stringSanityCheck(optarg);
 
288
      len = strlen(optarg);
 
289
      if(len > 2048) len = 2048;
 
290
      flowSpecs = (char*)malloc(len+1);
 
291
      memset(flowSpecs, 0, len+1);
 
292
      strncpy(flowSpecs, optarg, len);
 
293
      break;
 
294
 
 
295
    case 'm':
 
296
      stringSanityCheck(optarg);
 
297
      localAddresses = strdup(optarg);
 
298
      break;
 
299
 
 
300
    case 'n':
 
301
      numericFlag++;
 
302
      break;
 
303
 
 
304
    case 'N':
 
305
      isNmapPresent = 0;
 
306
      break;
 
307
 
 
308
    case 'w':
 
309
      stringSanityCheck(optarg);
 
310
      if(!isdigit(optarg[0])) {
 
311
        printf("FATAL ERROR: flag -w expects a numeric argument.\n");
 
312
        exit(-1);
 
313
      }
 
314
 
 
315
      /* Courtesy of Daniel Savard <daniel.savard@gespro.com> */
 
316
      if ((webAddr = strchr(optarg,':'))) {
 
317
        /* DS: Search for : to find xxx.xxx.xxx.xxx:port */
 
318
        /* This code is to be able to bind to a particular interface */
 
319
        *webAddr = '\0';
 
320
        webPort = atoi(webAddr+1);
 
321
        webAddr = optarg;
 
322
      } else {
 
323
        webPort = atoi(optarg);
 
324
      }
 
325
      break;
 
326
 
 
327
#ifdef HAVE_OPENSSL
 
328
    case 'W':
 
329
      stringSanityCheck(optarg);
 
330
      if(!isdigit(optarg[0])) {
 
331
        printf("FATAL ERROR: flag -W expects a numeric argument.\n");
 
332
        exit(-1);
 
333
      }
 
334
 
 
335
      /*
 
336
        lets swipe the same address binding code from -w above
 
337
        Curtis Doty <Curtis@GreenKey.net>
 
338
      */
 
339
      if((sslAddr = strchr(optarg,':'))) {
 
340
        *sslAddr = '\0';
 
341
        sslPort = atoi(sslAddr+1);
 
342
        sslAddr = optarg;
 
343
      } else {
 
344
        sslPort = atoi(optarg);
 
345
      }
 
346
 
 
347
      break;
 
348
#endif
 
349
 
 
350
    case 'R':
 
351
      stringSanityCheck(optarg);
 
352
      strncpy(rulesFile, optarg,
 
353
              sizeof(rulesFile)-1)[sizeof(rulesFile)-1] = '\0';
 
354
      break;
 
355
 
 
356
    case 'M':
 
357
      mergeInterfaces = 0;
 
358
      break;
 
359
 
 
360
    case 'S':
 
361
      /*
 
362
        Persitent storage only for 'local' machines
 
363
        Courtesy of Joel Crisp <jcrisp@dyn21-126.trilogy.com>
 
364
 
 
365
        0 = no storage
 
366
        1 = store all hosts
 
367
        2 = store only local hosts
 
368
      */
 
369
      usePersistentStorage = atoi(optarg);
 
370
      if((usePersistentStorage > 2)
 
371
         || (usePersistentStorage < 0)){
 
372
        printf("FATAL ERROR: -S flag accepts value in the 0-2 range.\n");
 
373
        exit(-1);
 
374
      }
 
375
      break;
 
376
 
 
377
    case 't':
 
378
      /* Trace Level Initialization */
 
379
      traceLevel = atoi(optarg);
 
380
      if(traceLevel > DETAIL_TRACE_LEVEL)
 
381
        traceLevel = DETAIL_TRACE_LEVEL;
 
382
      break;
 
383
 
 
384
    case 'A':
 
385
      /* Accuracy Level */
 
386
      accuracyLevel = atoi(optarg);
 
387
      if(accuracyLevel > HIGH_ACCURACY_LEVEL)
 
388
        accuracyLevel = HIGH_ACCURACY_LEVEL;
 
389
      break;
 
390
 
 
391
#ifndef WIN32
 
392
    case 'u':
 
393
      stringSanityCheck(optarg);
 
394
      if(strOnlyDigits(optarg))
 
395
        userId = atoi(optarg);
 
396
      else {
 
397
        struct passwd *pw;
 
398
        pw = getpwnam(optarg);
 
399
        if(pw == NULL) {
 
400
          printf("FATAL ERROR: Unknown user %s.\n", optarg);
 
401
          exit(-1);
 
402
        }
 
403
        userId = pw->pw_uid;
 
404
        groupId = pw->pw_gid;
 
405
        endpwent();
 
406
      }
 
407
      break;
 
408
#endif /* WIN32 */
 
409
 
 
410
    case 'U': /* host:port */
 
411
      if(strlen(optarg) >= (sizeof(mapperURL)-1)) {
 
412
        strncpy(mapperURL, optarg, sizeof(mapperURL)-2);
 
413
        mapperURL[sizeof(mapperURL)-1] = '\0';
 
414
      } else
 
415
        strcpy(mapperURL, optarg);
 
416
      break;
 
417
        
 
418
    case 'k':
 
419
      /* update info of used kernel filter expression in extra frame */
 
420
      filterExpressionInExtraFrame=1;
 
421
      break;
 
422
 
 
423
#ifndef WIN32   
 
424
    case 'K':
 
425
      debugMode = 1;
 
426
      break;
 
427
 
 
428
    case 'L':
 
429
      useSyslog = 1;
 
430
      break;
 
431
#endif
 
432
 
 
433
    default:
 
434
      usage();
 
435
      exit(-1);
 
436
      /* NOTREACHED */
 
437
    }
 
438
  }  
 
439
 
 
440
  if(webPort == 0) {
 
441
#ifdef HAVE_OPENSSL
 
442
    if(sslPort == 0) {
 
443
      traceEvent(TRACE_ERROR,
 
444
                 "FATAL ERROR: both -W and -w can't be set to 0.\n");
 
445
      exit(-1);
 
446
    }
 
447
#else
 
448
    traceEvent(TRACE_ERROR,
 
449
               "FATAL ERROR: -w can't be set to 0.\n");
 
450
    exit(-1);
 
451
#endif
 
452
  }
 
453
 
 
454
  /* ***************************** */
 
455
 
 
456
#ifdef HAVE_OPENSSL
 
457
  if(sslPort == 0)
 
458
    traceEvent(TRACE_INFO, "SSL is present but https is disabled: "
 
459
               "use -W <https port> for enabling it\n");
 
460
#endif
 
461
 
 
462
  initIPServices();
 
463
 
 
464
  snprintf(accessLogPath, sizeof(accessLogPath), "%s/%s",
 
465
           dbPath, DETAIL_ACCESS_LOG_FILE_PATH);
 
466
 
 
467
  initLogger(); /* Do not call this function before dbPath
 
468
                   is initialized */
 
469
 
 
470
  initGlobalValues();
 
471
 
 
472
#ifndef MICRO_NTOP
 
473
  reportValues(&lastTime);
 
474
#endif /* MICRO_NTOP */
 
475
  postCommandLineArgumentsInitialization(&lastTime);
 
476
  initGdbm();
 
477
 
 
478
  initDevices(devices);
 
479
 
 
480
  traceEvent(TRACE_INFO, "ntop v.%s %s [%s] (%s build)",
 
481
             version, THREAD_MODE, osName, buildDate);
 
482
 
 
483
  ifStr[0] = '\0';
 
484
  if(rFileName != NULL)
 
485
    strncpy(ifStr, PCAP_NW_INTERFACE, sizeof(ifStr));
 
486
  else
 
487
    for(i=0; i<numDevices; i++) {
 
488
      char tmpBuf[48];
 
489
 
 
490
      if(i>0) {
 
491
        if(snprintf(tmpBuf, sizeof(tmpBuf), ",%s", device[i].name)  < 0)
 
492
          traceEvent(TRACE_ERROR, "Buffer overflow!");
 
493
      } else {
 
494
        if(snprintf(tmpBuf, sizeof(tmpBuf), "%s", device[i].name) < 0)
 
495
          traceEvent(TRACE_ERROR, "Buffer overflow!");
 
496
      }
 
497
      strncat(ifStr, tmpBuf, sizeof(ifStr)-strlen(ifStr)-1)[sizeof(ifStr)-1] = '\0';
 
498
    }
 
499
 
 
500
  traceEvent(TRACE_INFO, "Listening on [%s]", ifStr);
 
501
  traceEvent(TRACE_INFO, "Copyright 1998-2001 by %s\n", author);
 
502
  traceEvent(TRACE_INFO, "Get the freshest ntop from http://www.ntop.org/\n");
 
503
  traceEvent(TRACE_INFO, "Initializing...\n");
 
504
 
 
505
  initLibpcap(rulesFile, numDevices);
 
506
#ifndef MICRO_NTOP
 
507
  loadPlugins();
 
508
#endif
 
509
 
 
510
  /*
 
511
    Code fragment below courtesy of
 
512
    Andreas Pfaller <a.pfaller@pop.gun.de>
 
513
  */
 
514
 
 
515
#ifndef WIN32
 
516
  if((getuid() != geteuid()) || (getgid() != getegid())) {
 
517
    /* setuid binary, drop privileges */
 
518
    if (setgid(getgid())!=0 || setuid(getuid())!=0) {
 
519
      traceEvent(TRACE_ERROR,
 
520
                 "FATAL ERROR: Unable to drop privileges.\n");
 
521
      exit(-1);
 
522
    }
 
523
  }
 
524
 
 
525
  if((userId != 0) || (groupId != 0)){
 
526
    /* user id specified on commandline */
 
527
    if ((setgid(groupId) != 0) || (setuid(userId) != 0)) {
 
528
      traceEvent(TRACE_ERROR, "FATAL ERROR: Unable to change user ID.\n");
 
529
      exit(-1);
 
530
    }
 
531
  }
 
532
 
 
533
  if((geteuid() == 0) || (getegid() == 0)) {
 
534
    traceEvent(TRACE_INFO, "WARNING: For security reasons it is STRONGLY recommended to");
 
535
    traceEvent(TRACE_INFO, "WARNING: run ntop as unprivileged user by using the -u option!");
 
536
  }
 
537
#endif
 
538
 
 
539
  if(localAddresses != NULL) {
 
540
    handleLocalAddresses(localAddresses);
 
541
    free(localAddresses);
 
542
    localAddresses = NULL;
 
543
  }
 
544
 
 
545
  initDeviceDatalink();
 
546
  parseTrafficFilter(argv, optind);
 
547
 
 
548
  /* Handle flows (if any) */
 
549
  if(flowSpecs != NULL) {
 
550
    if(flowSpecs[0] != '\0')
 
551
      handleFlowsSpecs(flowSpecs);
 
552
    free(flowSpecs);
 
553
  }
 
554
 
 
555
  /* Patch courtesy of Burton M. Strauss III <BStrauss3@attbi.com> */
 
556
  if(protoSpecs != NULL) {
 
557
    if(protoSpecs[0] != '\0')
 
558
      handleProtocols(protoSpecs);
 
559
    free(protoSpecs);
 
560
  }
 
561
 
 
562
  initCounters(mergeInterfaces);
 
563
  initApps();
 
564
  initSignals();
 
565
 
 
566
  initThreads(enableThUpdate, enableIdleHosts, enableDBsupport);
 
567
#ifndef MICRO_NTOP
 
568
  startPlugins();
 
569
#endif
 
570
  initWeb(webPort, webAddr, sslAddr);
 
571
 
 
572
  traceEvent(TRACE_INFO, "Sniffying...\n");
 
573
 
 
574
#ifdef MEMORY_DEBUG
 
575
  resetLeaks();
 
576
#endif
 
577
 
 
578
  /*
 
579
    In multithread mode, a separate thread handles
 
580
    packet sniffing
 
581
  */
 
582
#ifndef MULTITHREADED
 
583
  packetCaptureLoop(&lastTime, refreshRate);
 
584
#else
 
585
  startSniffer();
 
586
#endif
 
587
 
 
588
#ifndef WIN32
 
589
  pause();
 
590
#endif
 
591
  while(!endNtop) 
 
592
    sleep(30);
 
593
 
 
594
  return(0);
 
595
}