Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- #include <stdio.h>
- #include <stdarg.h>
- #include <stdlib.h>
- #include <string.h>
- #include <unistd.h>
- #include <ctype.h>
- #include <syslog.h>
- #include <signal.h>
- #include <poll.h>
- #include <pcap.h>
- #include <errno.h>
- #include <time.h>
- #include <sys/time.h>
- #include <sys/types.h>
- #include <stdint.h> /* Definition of uint64_t */
- #define MAXBUF 2048 /* Length of log message buffer */
- #define SNAP_LEN 1518 /* Packet capture snaplength */
- #define INTV_MIN 1ULL /* milliseconds */
- #define INTV_MAX 18446744073709ULL /* milliseconds */
- #define TSTAMPFMT "%Y-%m-%dT%H:%M:%S"
- char *iface = NULL;
- char *bpf = NULL;
- int i, daemonize = 1;
- uint64_t interval = 1000ULL;
- int log_facility = LOG_DAEMON;
- /* Signal handler flags */
- static int exit_request = 0;
- /* from tcpdump.c */
- char *copy_argv(register char **argv)
- {
- register char **p;
- register u_int len = 0;
- char *buf;
- char *src, *dst;
- p = argv;
- if (*p == 0)
- return 0;
- while (*p)
- len += strlen(*p++) + 1;
- buf = (char *)malloc(len);
- if (buf == NULL)
- fprintf(stderr, "copy_argv: malloc\n");
- p = argv;
- dst = buf;
- while ((src = *p++) != NULL) {
- while ((*dst++ = *src++) != '\0')
- ;
- dst[-1] = ' ';
- }
- dst[-1] = '\0';
- return buf;
- }
- /* from Pound */
- void logmsg(const int priority, const char *fmt, ...)
- {
- char buf[MAXBUF + 1];
- va_list ap;
- buf[MAXBUF] = '\0';
- va_start(ap, fmt);
- vsnprintf(buf, MAXBUF, fmt, ap);
- va_end(ap);
- if(daemonize)
- syslog(log_facility | priority, "%s", buf);
- else
- fprintf(stderr, "%s\n", buf);
- return;
- }
- void usage(char* prog)
- {
- printf("Usage: %s -i <iface> [options]\n", prog);
- printf("Options:\n");
- printf(" -w n Set deadline to n milliseconds.\n");
- printf(" -D Run in foreground. Log to stderr.\n");
- }
- /* from
- * http://www.gnu.org/software/libc/manual/html_node/Example-of-Getopt.html
- */
- int getcmdline(int argc, char **argv)
- {
- int c;
- opterr = 0;
- while((c = getopt(argc, argv, "hi:w:fD")) != -1)
- switch (c)
- {
- case 'h':
- usage(argv[0]);
- exit(EXIT_SUCCESS);
- case 'i':
- iface = optarg;
- break;
- case 'w':
- /* milliseconds */
- interval = strtoll(optarg, NULL, 10);
- if(interval < INTV_MIN)
- {
- fprintf(stderr, "Fatal: Interval must be >= %lld ms\n", INTV_MIN);
- usage(argv[0]);
- exit(EXIT_FAILURE);
- }
- break;
- case 'D':
- daemonize = 0;
- break;
- case '?':
- if(optopt == 'i' || optopt == 'w')
- fprintf(stderr, "Option -%c requires an argument.\n", optopt);
- else if(isprint (optopt))
- fprintf(stderr, "Fatal: Unknown option `-%c'.\n", optopt);
- else
- fprintf(stderr, "Fatal: Unknown option character `\\x%x'.\n", optopt);
- usage(argv[0]);
- exit(EXIT_FAILURE);
- default:
- usage(argv[0]);
- exit(EXIT_FAILURE);
- }
- /* iface arg is required */
- if(iface == NULL)
- {
- fprintf(stderr, "Fatal: No interface specified.\n");
- usage(argv[0]);
- exit(EXIT_FAILURE);
- }
- /* the rest is the bpf, even if empty */
- bpf = copy_argv(&argv[optind]);
- return 0;
- }
- void got_packet(u_char *args, const struct pcap_pkthdr *header, const u_char *packet)
- {
- (void) args; /* avoid warning about unused parameter */
- (void) header; /* avoid warning about unused parameter */
- (void) packet; /* avoid warning about unused parameter */
- }
- static void sighand_exit(int signum)
- {
- (void) signum;
- logmsg(LOG_WARNING, "Received SIGTERM; scheduling exit.");
- exit_request = 1;
- }
- int main (int argc, char **argv)
- {
- char errbuf[PCAP_ERRBUF_SIZE];
- pcap_t *descr;
- struct bpf_program fp;
- struct timeval tstart, tend;
- uint64_t tdiff;
- time_t ttmp;
- char tstamp[20];
- suseconds_t ustmp;
- pid_t pid;
- getcmdline(argc, argv);
- /* open capture device */
- descr = pcap_open_live(iface, SNAP_LEN, 1, 0, errbuf);
- if (descr == NULL) {
- fprintf(stderr, "pcap_open_live failed (%s): %s\n", iface, errbuf);
- exit(EXIT_FAILURE);
- }
- /* apply the filter */
- if (pcap_compile(descr, &fp, bpf, 0, 0) == -1) {
- fprintf(stderr, "pcap_compile failed (%s): %s\n", iface, pcap_geterr(descr));
- exit(EXIT_FAILURE);
- }
- if (pcap_setfilter(descr, &fp) == -1) {
- fprintf(stderr, "pcap_setfilter failed (%s): %s\n", iface, pcap_geterr(descr));
- exit(EXIT_FAILURE);
- }
- signal(SIGTERM, sighand_exit);
- signal(SIGINT, sighand_exit);
- /* prepare for poll loop */
- int inoutage = 0; /* state switch */
- char errmsg[1024]; /* XXX - arbitrary size */
- int error = 0;
- int nfds;
- struct pollfd pfd[1];
- /* stuff to poll */
- pfd[0].fd = pcap_fileno(descr);
- pfd[0].events = POLLIN;
- pfd[0].revents = 0;
- if (daemonize && daemon(0, 0))
- fprintf(stderr, "daemon() failed. Staying in foreground.\n");
- /* Get pid after forking. The pid is simply used to identify
- * instances of the program running simultaneously.
- */
- pid = getpid();
- if (daemonize)
- openlog("tcpwatch", LOG_CONS, LOG_DAEMON);
- logmsg(LOG_NOTICE, "Starting with %llums deadline and filter: `%s'", interval, bpf);
- /* Main loop */
- for(;;)
- {
- nfds = poll(pfd, 1, interval);
- if (nfds == -1 || (pfd[0].revents & (POLLERR|POLLHUP|POLLNVAL))) {
- if (errno != EINTR)
- {
- logmsg(LOG_ERR, "Poll error: %s", strerror(errno));
- exit(EXIT_FAILURE);
- }
- }
- /* Handle packet arrivals */
- if (pfd[0].revents) {
- /* Reading a packet from the fd is tricky, so
- * we leave all that work to pcap_dispatch
- * (which in turn calls pcap_read_packet to do
- * the actual reading).
- */
- (void)pcap_dispatch(descr, -1, (pcap_handler)got_packet, NULL);
- if(inoutage)
- {
- if (gettimeofday(&tend, NULL) == -1)
- {
- logmsg(LOG_ERR, "gettimeofday failed: %s", strerror(errno));
- exit_request = 1;
- }
- ttmp = time(NULL);
- strftime(tstamp, sizeof(tstamp), TSTAMPFMT, localtime(&ttmp));
- ustmp = tend.tv_usec;
- /* Calculate timediff */
- tend.tv_sec -= tstart.tv_sec;
- tend.tv_usec -= tstart.tv_usec;
- if(tend.tv_usec < 0)
- {
- tend.tv_sec--;
- tend.tv_usec += 1000000;
- }
- tdiff = tend.tv_sec * 1000 + tend.tv_usec / 1000;
- logmsg(LOG_INFO, "(PID %d) %s.%03ld Outage recovered (%llu ms downtime).",
- pid,
- tstamp,
- ustmp/1000,
- tdiff);
- inoutage = 0;
- }
- }
- /* Handle poll timeout */
- if(!nfds)
- {
- if(!inoutage)
- {
- if (gettimeofday(&tstart, NULL) == -1)
- {
- logmsg(LOG_ERR, "gettimeofday failed: %s", strerror(errno));
- exit_request = 1;
- }
- ttmp = time(NULL);
- strftime(tstamp, sizeof(tstamp), TSTAMPFMT, localtime(&ttmp));
- logmsg(LOG_DEBUG, "(PID %d) %s.%03ld Outage detected (%llu ms deadline).",
- pid,
- tstamp,
- tstart.tv_usec/1000,
- interval);
- inoutage = 1;
- }
- }
- if (error)
- logmsg(LOG_WARNING, errmsg);
- if (exit_request)
- {
- logmsg(LOG_WARNING, "Exiting on system/user request.");
- break;
- }
- }
- logmsg(LOG_DEBUG, "Closing packet capture device.");
- pcap_close(descr);
- exit(EXIT_SUCCESS);
- return 0;
- }
Add Comment
Please, Sign In to add comment