/* pdumpq - Pcap Dump for Linux/Netfilter QUEUE * * Copyright (C) 2001 Ian Jones * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #include void cmdline (int argc, char **argv) { #ifdef MAIL static char opts[] = "j:p:kr:Rm:e:t:q:"; #else static char opts[] = "p:kr:Rm:"; #endif /* MAIL */ int ch, i; char *ep; int klr = 0; int rotateflag = 0; pid_t pid; while ((ch = getopt (argc, argv, opts)) != -1) switch (ch) { case 'm': /* marks */ if (v.mcount == 0) { v.marks = malloc (sizeof (unsigned long)); v.verdicts = malloc (sizeof (unsigned int)); if (v.marks == NULL || v.verdicts == NULL) crash ("malloc:pdumpq"); } else { if (realloc (v.marks, sizeof (unsigned long) * (v.mcount + 1)) == NULL) crash ("realloc:pdumpq"); if (realloc (v.verdicts, sizeof (unsigned int) * (v.mcount + 1)) == NULL) crash ("realloc:pdumpq"); } errno = 0; v.marks[v.mcount] = strtoul (optarg, &ep, 0); if (v.marks[v.mcount] == ULONG_MAX && errno == ERANGE) { fprintf (stderr, "Invalid MARK specification in %s\n", optarg); usage (argv[0]); } if (ep == optarg) { fprintf (stderr, "Invalid MARK specification in %s\n", optarg); usage (argv[0]); } /* no verdict specified with -m */ if (*ep == 0) { v.verdicts[v.mcount] = -1; } else { if (*ep != ',') { fprintf (stderr, "Invalid MARK verdict: %s\n", ep); usage (argv[0]); } switch (ep[1]) { case '0': fprintf (stderr, "Invalid MARK verdict: %s\n", ep); usage (argv[0]); break; case 'a': case 'A': v.verdicts[v.mcount] = NF_ACCEPT; break; case 'd': case 'D': v.verdicts[v.mcount] = NF_DROP; break; default: fprintf (stderr, "Invalid MARK verdict: %s\n", ep); usage (argv[0]); } } v.mcount++; break; case 'p': /* default policy */ switch (optarg[0]) { case 'a': case 'A': v.policy = NF_ACCEPT; break; case 'd': case 'D': v.policy = NF_DROP; break; default: printf ("Valid policy flags are [Aa]CCEPT and [Dd]ROP\n"); usage (argv[0]); } break; case 'k': /* kill running process */ klr = 1; if (pid = is_running ()) { kill (pid, SIGTERM); sleep (1); /* give dying process time to clean up */ } break; case 'r': /* number of rotations */ if (rotateflag) { fprintf (stderr, "The 'r' and 'R' flags can not be used together.\n"); usage (argv[0]); } errno = 0; v.rotate = strtoul (optarg, &ep, 0); if (*ep != 0 || ep == optarg || (v.rotate == ULONG_MAX && errno == ERANGE)) { fprintf (stderr, "Invalid string for rotate - %s: %s\n", optarg, ep); usage (argv[0]); } break; case 'C': case 'R': /* Clobber, don't rotate */ if (rotateflag) { fprintf (stderr, "The 'r' and 'R' flags can not be used together.\n"); usage (argv[0]); } v.rotate = 0; break; #ifdef MAIL case 'e': mail_init (); v.mail = 1; v.email = strdup (optarg); break; case 't': /* email queue timer */ if (!v.mail) v.mail = -1; v.timer = strtoul (optarg, &ep, 0); if (*ep != 0 || ep == optarg || (v.timer == ULONG_MAX && errno == ERANGE)) { fprintf (stderr, "Invalid string for timer - %s: %s\n", optarg, ep); usage (argv[0]); } break; case 'q': /* email queue size */ if (!v.mail) v.mail = -1; v.maxq = strtoul (optarg, &ep, 0); if (*ep != 0 || ep == optarg || (v.maxq == ULONG_MAX && errno == ERANGE)) { fprintf (stderr, "Invalid string for queue size - %s: %s\n", optarg, ep); usage (argv[0]); } break; #endif /* MAIL */ default: usage (argv[0]); } /* after all switches the only thing that should be left is */ if (!(optind + 1 == argc)) { if (klr) { if (pid) printf ("Killed process [%d], no dumpfile specified...exiting.\n", pid); else printf ("Process not running, no dumpfile specified...exiting.\n"); exit (0); } usage (argv[0]); } #ifdef MAIL if (v.mail == -1) { fprintf (stderr, "(-t)ime or (-q)ueue requires (-e)mail\n"); usage (argv[0]); } #endif /* MAIL */ /* if a verdict wasn't specified for mark, set as per policy */ for (i = 0; i < v.mcount; i++) { if (v.verdicts[i] == -1) v.verdicts[i] = v.policy; } /* standard output mode (don't detach) */ if (argv[optind][0] == '-' && argv[optind][1] == '\0') { if (!klr && (pid = is_running ())) { fprintf (stderr, "Process [%d] already running, use '-k' to kill.\n", pid); exit (1); } v.daemon = 0; v.dumpfile = strdup ("stdout"); } else { v.daemon = 1; v.dumpfile = strdup (argv[optind]); } } void usage (char *app) { fprintf (stderr, "\n Pcap Dump for Linux/Netfilter QUEUE - v%s\n Ian Jones \n", VERSION); fprintf (stderr, " %s -[kRC][r][p][m,(a|d)]", app); #ifdef MAIL fprintf (stderr, "[e][tq]"); #endif /* MAIL */ fprintf (stderr, " \n\n"); fprintf (stderr, " -k\t\tKill daemon (if running)\n"); fprintf (stderr, " -R|C\t\tDon't Rotate (clobber if existing)\n"); fprintf (stderr, " -r \tMax number of file rotations (default is %d), oldest is deleted\n", MAX_ROTATE); fprintf (stderr, " -p \tDefault policy: [Aa]CCEPT or [Dd]ROP, compiled as %s\n", v.policy == NF_DROP ? "NF_DROP" : "NF_ACCEPT"); fprintf (stderr, " -m \tOnly capture packets with firewall (multiples allowed)\n"); fprintf (stderr, " ,[Aa|Dd] Optional Mark Verdict (eg.: -m 666,a -m 123,D )\n\n"); #ifdef MAIL fprintf (stderr, " -e \tSend packet dumps to \n"); fprintf (stderr, " -t