X-Git-Url: http://git.tdb.fi/?a=blobdiff_plain;f=main.c;h=00b26de58677ed0e6f844bc89710e0916af3980a;hb=ec0ee88d13987e2953b7c532c2e8e1e5506967ac;hp=1b123858edba619a3b71e1f764260dfbd4535bf1;hpb=a0232882b0b537a4c065c70039972785afba743d;p=netmon.git diff --git a/main.c b/main.c index 1b12385..00b26de 100644 --- a/main.c +++ b/main.c @@ -6,22 +6,23 @@ Distributed under the GPL #include #include -#include +#include +#include +#include #include #include #include +#include +#include +#include +#include +#include +#include #include +#include #include -#include -#include #include -#include -#include -#include -#include #include -#include -#include typedef unsigned long long Time; @@ -43,6 +44,16 @@ typedef struct Time connection_down_time; } Monitor; +typedef struct +{ + Monitor *monitor; + Time delay; + Time interval; + const char *command; + Time next; + pid_t child_pid; +} Trigger; + typedef struct { const char *target_name; @@ -61,6 +72,8 @@ Time current_time(); int monitor_init(Monitor *); void monitor_check(Monitor *, Time); void capture_handler(uint8_t *, const struct pcap_pkthdr *, const uint8_t *); +int trigger_init(Trigger *); +void trigger_check(Trigger *, Time); int get_inet_scope(uint32_t, const Address *); int get_inet6_scope(const struct in6_addr *, const Address *); int pinger_init(Pinger *); @@ -75,17 +88,18 @@ int verbose; int main(int argc, char **argv) { Monitor monitor; + Trigger trigger; Pinger pinger; int o; char *endp; Time stats_interval = 1800000000ULL; - Time trigger_delay = 60000000ULL; - Time trigger_interval = 600000000ULL; - const char *trigger_cmd = NULL; no_daemon = 0; verbose = 0; monitor.interface_name = NULL; + trigger.monitor = &monitor; + trigger.delay = 60000000ULL; + trigger.interval = 600000000ULL; pinger.target_name = NULL; /* Parse options */ @@ -102,14 +116,14 @@ int main(int argc, char **argv) stats_interval = strtoul(optarg, NULL, 10)*1000000; break; case 't': - trigger_delay = strtoul(optarg, &endp, 10)*1000000; + trigger.delay = strtoul(optarg, &endp, 10)*1000000; if(*endp==',') - trigger_interval = strtoul(endp+1, NULL, 10)*1000000; + trigger.interval = strtoul(endp+1, NULL, 10)*1000000; else - trigger_interval = trigger_delay; + trigger.interval = trigger.delay; break; case 'c': - trigger_cmd = optarg; + trigger.command = optarg; break; case 'i': monitor.interface_name = strdup(optarg); @@ -120,8 +134,13 @@ int main(int argc, char **argv) } if(monitor.interface_name) + { monitor_init(&monitor); + if(trigger.command) + trigger_init(&trigger); + } + if(pinger.target_name) pinger_init(&pinger); @@ -131,8 +150,6 @@ int main(int argc, char **argv) openlog("netmon", 0, LOG_LOCAL7); Time next_stats = current_time()+stats_interval; - Time next_trigger = trigger_delay; - pid_t child_pid = 0; while(1) { Time time = current_time(); @@ -141,17 +158,8 @@ int main(int argc, char **argv) { monitor_check(&monitor, time); - if(monitor.connection_status) - next_trigger = trigger_delay; - else if(time>=monitor.last_receive+next_trigger) - { - if(no_daemon) - printf("Running %s\n", trigger_cmd); - else - syslog(LOG_INFO, "Running %s", trigger_cmd); - child_pid = run_command(trigger_cmd); - next_trigger += trigger_interval; - } + if(trigger.command) + trigger_check(&trigger, time); } if(pinger.target_name) @@ -174,13 +182,6 @@ int main(int argc, char **argv) next_stats += stats_interval; } } - - /* Reap any finished child process */ - if(child_pid) - { - if(waitpid(child_pid, NULL, WNOHANG)==child_pid) - child_pid = 0; - } } closelog(); @@ -275,30 +276,30 @@ void monitor_check(Monitor *monitor, Time timestamp) void capture_handler(uint8_t *user, const struct pcap_pkthdr *header, const uint8_t *data) { Monitor *monitor = (Monitor *)user; - const struct ethhdr *eth = (const struct ethhdr *)(data); + const struct ether_header *eth = (const struct ether_header *)(data); int src_scope = 0; int dst_scope = 0; - int proto = ntohs(eth->h_proto); - if(proto==ETH_P_IP) + int proto = ntohs(eth->ether_type); + if(proto==ETHERTYPE_IP) { - const struct iphdr *ip = (const struct iphdr *)(eth+1); - if(ntohl(ip->daddr)>>28==14) + const struct ip *ip = (const struct ip *)(eth+1); + if(ntohl(ip->ip_dst.s_addr)>>28==14) dst_scope = 3; for(unsigned i=0; in_addresses; ++i) if(monitor->addresses[i].address.ss_family==AF_INET) { - int s = get_inet_scope(ip->saddr, &monitor->addresses[i]); + int s = get_inet_scope(ip->ip_src.s_addr, &monitor->addresses[i]); if(s>src_scope) src_scope = s; - s = get_inet_scope(ip->daddr, &monitor->addresses[i]); + s = get_inet_scope(ip->ip_dst.s_addr, &monitor->addresses[i]); if(s>dst_scope) dst_scope = s; } } - else if(proto==ETH_P_IPV6) + else if(proto==ETHERTYPE_IPV6) { const struct ip6_hdr *ip6 = (const struct ip6_hdr *)(eth+1); for(unsigned i=0; in_addresses; ++i) @@ -321,6 +322,38 @@ void capture_handler(uint8_t *user, const struct pcap_pkthdr *header, const uint monitor->last_transmit = timestamp; } +int trigger_init(Trigger *trigger) +{ + trigger->next = trigger->delay; + trigger->child_pid = 0; + + return 0; +} + +void trigger_check(Trigger *trigger, Time time) +{ + Monitor *monitor = trigger->monitor; + + if(monitor->connection_status) + trigger->next = trigger->delay; + else if(time>=monitor->last_receive+trigger->next) + { + if(no_daemon) + printf("Running %s\n", trigger->command); + else + syslog(LOG_INFO, "Running %s", trigger->command); + trigger->child_pid = run_command(trigger->command); + trigger->next += trigger->interval; + } + + /* Reap any finished child process */ + if(trigger->child_pid) + { + if(waitpid(trigger->child_pid, NULL, WNOHANG)==trigger->child_pid) + trigger->child_pid = 0; + } +} + int get_inet_scope(uint32_t addr, const Address *local_addr) { uint32_t diff = addr^((struct sockaddr_in *)&local_addr->address)->sin_addr.s_addr; @@ -415,11 +448,11 @@ void pinger_check(Pinger *pinger, Time time) fprintf(stderr, "recvfrom error: %s\n", strerror(errno)); else { - struct iphdr *ip = (struct iphdr *)data; - if(ip->protocol==IPPROTO_ICMP) + struct ip *ip = (struct ip *)data; + if(ip->ip_p==IPPROTO_ICMP) { - struct icmphdr *icmp = (struct icmphdr *)(ip+1); - if(icmp->type==ICMP_ECHOREPLY && icmp->un.echo.id==pinger->id) + struct icmp *icmp = (struct icmp *)(ip+1); + if(icmp->icmp_type==ICMP_ECHOREPLY && icmp->icmp_id==pinger->id) { /* It's an ICMP echo reply and ours, process it */ if(verbose) @@ -429,10 +462,10 @@ void pinger_check(Pinger *pinger, Time time) printf("Ping reply from %s\n", buf); } - if(icmp->un.echo.sequence==pinger->pending) + if(icmp->icmp_seq==pinger->pending) pinger->pending = 0; else if(verbose) - printf("Sequence %d, expected %d\n", icmp->un.echo.sequence, pinger->pending); + printf("Sequence %d, expected %d\n", icmp->icmp_seq, pinger->pending); } } } @@ -469,13 +502,13 @@ void send_ping(Pinger *pinger) for(unsigned i=0; itype = ICMP_ECHO; - hdr->code = 0; - hdr->checksum = 0; - hdr->un.echo.id = pinger->id; - hdr->un.echo.sequence = pinger->seq; - hdr->checksum = checksum(data, sizeof(data)); + struct icmp *hdr = (struct icmp *)data; + hdr->icmp_type = ICMP_ECHO; + hdr->icmp_code = 0; + hdr->icmp_cksum = 0; + hdr->icmp_id = pinger->id; + hdr->icmp_seq = pinger->seq; + hdr->icmp_cksum = checksum(data, sizeof(data)); if(sendto(pinger->socket, data, sizeof(data), 0, (struct sockaddr *)&pinger->target_addr, sizeof(struct sockaddr_in))==-1) fprintf(stderr, "sendto error: %s\n", strerror(errno));