/* * Copyright (c) 1999 RISS-Telecom Networking Center * * Copyright (c) 1993 The CAD lab of the * Novosibirsk Institute of Broadcasting and Telecommunication * * BPFT $Id: main.c,v 1.2 1993/10/30 10:15:30 bob Exp $ * * $Log: main.c,v $ * Revision 1.2 1993/10/30 10:15:30 bob * Modify access method to daemon * * Revision 1.1 1993/10/20 16:05:35 bob * Initial revision * * * Redistribution and use in source forms, with and without modification, * are permitted provided that this entire comment appears intact. * Redistribution in binary form may occur without any restrictions. * * THIS SOFTWARE IS PROVIDED ``AS IS'' WITHOUT ANY WARRANTIES OF ANY KIND. */ /* main.c - tcp/udp data traffic daemon statistics */ #include #include #include #include #include #include #include #ifdef USE_PIPE #include #else /* Unix Domain */ #include #endif #include #include #include #include #include #include #include #include #include "interface.h" #include "addrtoname.h" #define PORT 150 #define WAIT_DAEMON 5 #define MAX_RETRY 5 /* * Command line switches. */ int bflag; /* binary output */ int fflag; /* convert addresses to names only for local hosts */ int nflag; /* don't convert addresses to host names */ int Nflag; /* output host names without domain */ char *device_name = 0; char *program_name; char *host; static char file_fifo[40]; extern int errno; extern int h_errno; extern int traf_get(); extern void traf_put(); extern void traf_print(); static jmp_buf after_alarm; void main(argc, argv) int argc; char **argv; { register FILE *fd; register int ifd, op, pid; struct sockaddr_in server, client; #ifndef USE_PIPE struct sockaddr_un un; #endif struct hostent *hp; char buf[40]; extern char *optarg; extern int optind, opterr; char ebuf[PCAP_ERRBUF_SIZE]; bpf_u_int32 localnet, netmask; void cleanup(), /* onpipe(), */ onterm(), onalarm(), usage(); program_name = stripdir(argv[0]); opterr = 0; while ((op = getopt(argc, argv, "bfi:nN")) != EOF) switch (op) { case 'b': ++bflag; break; case 'f': ++fflag; break; case 'i': device_name = optarg; break; case 'n': ++nflag; break; case 'N': ++Nflag; break; default: usage(); } if (device_name == 0) if ((device_name = getenv("IFF_LISTEN")) == NULL) if ((device_name = pcap_lookupdev(ebuf)) == 0) error("%s", ebuf); if (pcap_lookupnet(device_name, &localnet, &netmask, ebuf) < 0) { localnet =0; netmask = 0; warning("%s", ebuf); } init_addrtoname(localnet, netmask); file_fifo[0] = 0; signal(SIGTERM, onterm); /* signal(SIGPIPE, onpipe); */ signal(SIGIO, SIG_IGN); signal(SIGURG, SIG_IGN); if (signal(SIGINT, SIG_IGN) != SIG_IGN) signal(SIGINT, cleanup); if ((host = argv[optind]) != NULL) { if (atoi(host) > 0) { server.sin_family = AF_INET; server.sin_addr.s_addr = inet_addr(host); } else { if ((hp = gethostbyname(host)) == NULL) { sprintf(buf, "%s: gethostbyname", program_name); herror(buf); exit(1); } server.sin_family = hp->h_addrtype; bcopy(hp->h_addr, (char *)&server.sin_addr, hp->h_length); host = hp->h_name; } ++optind; server.sin_port = htons(argv[optind] ? atoi(argv[optind]) : PORT); if ((ifd = socket(AF_INET, SOCK_STREAM, 0)) < 0) error("can't open stream socket"); fprintf(stderr, "Trying...\n"); if (connect(ifd, (struct sockaddr *)&server, sizeof(server)) < 0) { sprintf(buf, "%s: connect", program_name); perror(buf); exit(1); } fprintf(stderr, "Connected to %s.\n", host); sprintf(buf, "-i %s -b\n", device_name); write(ifd, buf, strlen(buf)); } else { int i, sigusr; sprintf(buf, "%strafd.%s", _PATH_VARRUN, device_name); if ((fd = fopen(buf, "r")) == NULL) error("interface %s don't listen", device_name); fgets(buf, sizeof(buf), fd); fclose(fd); pid = atoi(buf); if (kill((pid_t)pid, 0) < 0) error("permission denied"); sprintf(file_fifo, "%strafd.%s", _PATH_TMP, device_name); unlink(file_fifo); signal(SIGALRM, onalarm); #ifdef USE_PIPE if (mkfifo(file_fifo, 0666) < 0) error("can't creat named pipe"); for (i = SIGUSR1; i <= SIGUSR2; i++) { alarm(WAIT_DAEMON); kill((pid_t)pid, i); if ((ifd = open(file_fifo, O_RDONLY)) >= 0) break; else if (errno != EINTR) error("can't open named pipe"); } #else /* Use UNIX IPC Domain */ if ((op = socket(AF_UNIX, SOCK_STREAM, 0)) < 0) error("can't open Unix domain socket"); un.sun_family = AF_UNIX; strcpy(un.sun_path, file_fifo); if (bind(op, (struct sockaddr *)&un, sizeof(struct sockaddr_un)) < 0) error("can't bind Unix domain socket"); listen(op, 0); /* for (i = SIGUSR1; i <= SIGUSR2; i++) { alarm(WAIT_DAEMON); kill((pid_t)pid, i); if ((ifd = accept(op, 0, 0)) >= 0) break; else if (errno != EINTR) error("can't accept Unix domain connection"); } */ i = 0; alarm(WAIT_DAEMON); if (setjmp(after_alarm)) { if (++i >= MAX_RETRY) error("hmm... daemon not response"); sigusr = SIGUSR2; } else sigusr = SIGUSR1; kill((pid_t)pid, sigusr); if ((ifd = accept(op, 0, 0)) < 0) error("can't accept Unix domain connection"); #endif alarm(0); signal(SIGALRM, SIG_IGN); } pid = traf_get(ifd); /* signal(SIGPIPE, SIG_IGN); */ if (host != NULL) { shutdown(ifd, 2); close(ifd); } else { close(ifd); #ifndef USE_PIPE close(op); #endif unlink(file_fifo); } if (pid) { if (bflag) traf_put(1); else traf_print(); } else error("can't obtain or empty traffic table"); exit(0); } void cleanup() { if (file_fifo[0]) unlink(file_fifo); fprintf(stderr, " ...%s: interrupted\n", program_name); exit(1); } /* void onpipe() { fprintf(stderr, "%s: broken pipe\n", program_name); cleanup(); } */ void onterm() { fprintf(stderr, "%s: terminated\n", program_name); cleanup(); } void onalarm() { longjmp(after_alarm, 1); } void usage() { extern char version[]; fprintf(stderr, "trafstat v%s - tcp/udp data traffic daemon statistics\n", version); fprintf(stderr, "Usage: %s [-i iface] [-b | -fnN] [host] [port]\n", program_name); exit(-1); }