/* angst - main.c * by Patroklos Argyroudis * * Main control of the program. * * $Id: main.c,v 1.20 2001/02/06 19:17:54 argp Exp $ */ #include "angst.h" static char version[] = "0.4b"; int main(int argc, char *argv[]) { int c; int datalink = 0; /* link layer type */ int promisc_flag = 1; /* default to set promiscuous mode */ int flood_flag = 0; /* default to passive sniffing */ int f_flag = 1; /* enable IP forwarding flag */ int e_flag = 0; /* user supplied filter expression flag */ char expr[BUFSIZE]; /* user supplied filter expression buffer */ char filter_expr[BUFSIZE]; /* final filter expression */ bpf_u_int32 localnet, netmask; /* network number, associated netmask */ struct bpf_program filter; /* filter program */ char errbuf[PCAP_ERRBUF_SIZE]; /* libpcap error handling buffer */ /* default values */ device = NULL; arp_flag = 0; resolve_flag = LIBNET_DONT_RESOLVE; /* don't resolve IP addresses */ seconds = 0; pktcount = MACPKTS; /* flood MACPKTS number of packets */ logfile = LOGFILE; head = NULL; tail = NULL; opterr = 0; /* don't let getopt() write to stderr */ while((c = getopt(argc, argv, "ade:fhprvc:i:l:s:")) != EOF) { switch(c) { case 'a': arp_flag = 1; break; case 'd': f_flag = 0; break; case 'e': e_flag = 1; strlcpy(expr, build_expression(optarg), sizeof(expr)); fprintf(stderr, "warning: the filter expression is %s\n", expr); break; case 'f': flood_flag = 1; break; case 'h': usage(argv[0]); exit(EXIT_SUCCESS); case 'p': promisc_flag = 0; break; case 'r': resolve_flag = LIBNET_RESOLVE; break; case 'v': display_version(version); exit(EXIT_SUCCESS); case 'c': pktcount = atoi(optarg); break; case 'i': device = optarg; break; case 'l': logfile = optarg; break; case 's': seconds = atoi(optarg); break; default: usage(argv[0]); exit(EXIT_SUCCESS); } } /* while */ /* maybe in the next version */ if(flood_flag == 1 && arp_flag == 1) xprintf("error: you cannot use both active sniffing methods simultaneously\n"); if(arp_flag == 1) { #ifdef LINUX if(f_flag == 1) linux_enable_ip_forwarding(); #else /* {Free,Net,Open}BSD */ if(f_flag == 1) bsd_enable_ip_forwarding(); #endif /* LINUX */ } if(arp_flag == 1 && f_flag == 0) fprintf(stderr, "warning: in order for the man-in-the-middle ARP method to work, IP forwarding must be enabled on the local host, I trust you enabled it yourself\n"); if(arp_flag == 0 && flood_flag == 0) fprintf(stderr, "warning: no active sniffing method was specified\n"); init_buf(buffer, sizeof(buffer)); /* set the callback function */ callback = (pcap_handler)dissect; /* choose packet capturing device */ if(device == NULL) { if((device = pcap_lookupdev(errbuf)) == NULL) xprintf("pcap_lookupdev error: %s\n", errbuf); } #ifdef DEBUG fprintf(stderr, "device: %s\n", device); #endif /* DEBUG */ /* open the device */ if((pd = pcap_open_live(device, SNAPLEN, promisc_flag, TIMEOUT, errbuf)) == NULL) xprintf("pcap_open_live error: %s\n", errbuf); /* determine link layer type */ if((datalink = pcap_datalink(pd)) < 0) xprintf("pcap_datalink error: %s\n", pcap_geterr(pd)); /* determine the header length of the link layer encapsulation */ hdrlen = find_header_length(datalink); /* get network address and subnet mask */ if((pcap_lookupnet(device, &localnet, &netmask, errbuf)) < 0) { localnet = netmask = 0; xprintf("pcap_lookupnet error: %s\n", errbuf); } if(e_flag == 1) strlcpy(filter_expr, expr, sizeof(filter_expr)); else strlcpy(filter_expr, FILTER, sizeof(filter_expr)); /* compile the filter program */ if((pcap_compile(pd, &filter, filter_expr, 1, netmask)) < 0) xprintf("pcap_compile error: %s\n", pcap_geterr(pd)); /* set the filter program */ if((pcap_setfilter(pd, &filter)) < 0) xprintf("pcap_setfilter error: %s\n", pcap_geterr(pd)); /* catch some signals in order to keep things tidy */ if((signal(SIGTERM, catcher)) == SIG_ERR) xprintf("signal error\n"); if((signal(SIGINT, catcher)) == SIG_ERR) xprintf("signal error\n"); if((signal(SIGQUIT, catcher)) == SIG_ERR) xprintf("signal error\n"); /* become a daemon */ if((daemonize(".")) == -1) xprintf("fork error\n"); /* setup the fake ARP replies active sniffing method */ if(arp_flag == 1) { if(seconds == 0) seconds = WAKETIME; if((signal(SIGALRM, sig_arp)) == SIG_ERR) xprintf("signal error\n"); /* send them for the first time */ sig_arp(SIGALRM); } /* setup the flooder, for active sniffing */ if(flood_flag == 1) { if(seconds == 0) seconds = WAKETIME; if((signal(SIGALRM, sig_flood)) == SIG_ERR) xprintf("signal error\n"); /* flood for the first time */ sig_flood(SIGALRM); } /* open the log file in append mode */ if((fp = fopen(logfile, "a+")) == NULL) xprintf("fopen error: %s\n", strerror(errno)); /* change the mode of the log file */ if((chmod(logfile, (S_IRUSR | S_IWUSR))) == -1) xprintf("chmod error: %s\n", strerror(errno)); /* collect and process packets infinite loop */ if((pcap_loop(pd, -1, callback, NULL))) xprintf("pcap_loop error: %s\n", pcap_geterr(pd)); /* this should not be reached */ if((fflush(fp)) == EOF) xprintf("fflush error: %s\n", strerror(errno)); if((fclose(fp)) == EOF) xprintf("fclose error: %s\n", strerror(errno)); pcap_close(pd); return(EXIT_SUCCESS); } /* EOF */