/*- * Copyright (c) 2001 Hellmuth Michaelis. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * *--------------------------------------------------------------------------- * * nifmon - main * ------------- * * last edit-date: [Wed May 2 16:32:52 2001] * *---------------------------------------------------------------------------*/ #define MAIN #include "nifmon.h" #undef MAIN static pid_t pid; /*--------------------------------------------------------------------------- * Display usage and exit *---------------------------------------------------------------------------*/ static void usage() { fprintf(stderr, "\n"); fprintf(stderr, "nifmon -b -e -i -r -t (V%d.%d)\n", VERSION, RELEASE); fprintf(stderr, " -b run in background [needs -r and -t]\n"); fprintf(stderr, " -e tcpdump expression\n"); fprintf(stderr, " -i monitor interface , default lo0\n"); fprintf(stderr, " -r redirect output to device \n"); fprintf(stderr, " -t terminal type for device \n"); exit(1); } /*--------------------------------------------------------------------------- * Parse command line, startup monitor client *---------------------------------------------------------------------------*/ int main(int argc, char **argv) { int i; char *netif = "lo0"; char *expression = ""; while ((i = getopt(argc, argv, "be:i:r:t:")) != -1) { switch (i) { case 'b': background = 1; break; case 'e': expression = optarg; break; case 'i': netif = optarg; break; case 'r': rdev = optarg; has_rdev = 1; break; case 't': term = optarg; has_term = 1; break; default: usage(); break; } } if (background) { if (has_rdev == 0 || has_term == 0) { fprintf(stderr, "-b option needs both -t and -r!\n"); exit(1); } } /* only root is able to open /dev/bpfN */ if (getuid() != 0) { fprintf(stderr, "You must be superuser (root) to run this program\n"); exit(1); } sprintf(pidfile, "%s-%s%s", PIDFIL, netif, PIDPID); if (background) { check_pid(pidfile); daemonize(); write_pid(pidfile); } signal(SIGHUP, do_exit); signal(SIGINT, do_exit); signal(SIGQUIT, do_exit); signal(SIGTERM, do_exit); signal(SIGUSR1, do_exit); signal(SIGUSR2, do_exit); init_interface(netif); init_screen(netif); pfp = mpopen(netif, expression); if (pfp == NULL) { perror("mpopen"); do_exit(1); } for (;;) { fd_set set; struct timeval timeout; int ret; int high_selfd; FD_ZERO(&set); FD_SET(fileno(stdin), &set); high_selfd = fileno(stdin); FD_SET(fileno(pfp), &set); high_selfd = fileno(pfp); timeout.tv_sec = 1; timeout.tv_usec = 0; ret = select(high_selfd + 1, &set, NULL, NULL, &timeout); if (ret > 0) { if (FD_ISSET(fileno(stdin), &set)) kbdrdhdl(); if (FD_ISSET(fileno(pfp), &set)) loghdl(pfp); } update_interface(netif); } } /*---------------------------------------------------------------------------* * program exit *---------------------------------------------------------------------------*/ void do_exit(int exitval) { mpclose(pfp); if (curses_ready) endwin(); unlink(pidfile); exit(exitval); } /*---------------------------------------------------------------------------* * open pipe to tcpdump *---------------------------------------------------------------------------*/ FILE * mpopen(char *interface, char *expression) { FILE *fp; int pdes[2]; char *argv[5]; if (pipe(pdes) < 0) return (NULL); argv[0] = TCPDUMP; argv[1] = TCPDUMPFLAGS; argv[2] = interface; argv[3] = expression; argv[4] = NULL; switch (pid = vfork()) { case -1: /* Error. */ (void) close(pdes[0]); (void) close(pdes[1]); return (NULL); case 0: /* Child. */ (void) close(pdes[0]); if (pdes[1] != STDOUT_FILENO) { (void) dup2(pdes[1], STDOUT_FILENO); (void) close(pdes[1]); } /*XXX*/ close(STDERR_FILENO); execv(TCPDUMPPATH, argv); _exit(127); } /* Parent */ fp = fdopen(pdes[0], "r"); (void) close(pdes[1]); return (fp); } /*---------------------------------------------------------------------------* * close pipe and terminate tcpdump *---------------------------------------------------------------------------*/ int mpclose(FILE * fp) { int pstat; pid_t mpid; (void) fclose(fp); kill(pid, SIGTERM); do { mpid = wait4(pid, &pstat, 0, (struct rusage *) 0); } while (mpid == -1 && errno == EINTR); return (mpid == -1 ? -1 : pstat); }