]> git.tdb.fi Git - netmon.git/blobdiff - main.c
Request default POSIX features from system headers
[netmon.git] / main.c
diff --git a/main.c b/main.c
index 1b123858edba619a3b71e1f764260dfbd4535bf1..e22dbbe2f3c1670da6095938ba4a254e32f682fc 100644 (file)
--- a/main.c
+++ b/main.c
@@ -4,24 +4,26 @@ Copyright © 2008-2016 Mikko Rasa, Mikkosoft Productions
 Distributed under the GPL
 */
 
+#define _DEFAULT_SOURCE
 #include <stdint.h>
 #include <stdio.h>
-#include <getopt.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
 #include <errno.h>
 #include <syslog.h>
 #include <sys/poll.h>
+#include <sys/socket.h>
+#include <sys/time.h>
+#include <sys/wait.h>
+#include <net/ethernet.h>
+#include <netinet/in.h>
+#include <netinet/ip.h>
 #include <netinet/ip_icmp.h>
+#include <netinet/ip6.h>
 #include <netdb.h>
-#include <sys/wait.h>
-#include <stdlib.h>
 #include <arpa/inet.h>
-#include <fcntl.h>
-#include <unistd.h>
-#include <sys/time.h>
-#include <string.h>
 #include <pcap/pcap.h>
-#include <netinet/ether.h>
-#include <netinet/ip6.h>
 
 typedef unsigned long long Time;
 
@@ -43,6 +45,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 +73,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 +89,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 +117,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,19 +135,28 @@ int main(int argc, char **argv)
                }
 
        if(monitor.interface_name)
-               monitor_init(&monitor);
+       {
+               if(monitor_init(&monitor))
+                       return 1;
+
+               if(trigger.command)
+                       if(trigger_init(&trigger))
+                               return 1;
+       }
 
        if(pinger.target_name)
-               pinger_init(&pinger);
+               if(pinger_init(&pinger))
+                       return 1;
 
        if(!no_daemon && daemon(1, 0)==-1)
+       {
                perror("daemon");
+               return 1;
+       }
 
        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 +165,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 +189,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 +283,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; i<monitor->n_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; i<monitor->n_addresses; ++i)
@@ -321,6 +329,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;
@@ -384,7 +424,7 @@ int pinger_init(Pinger *pinger)
        pinger->socket = socket(PF_INET, SOCK_RAW, IPPROTO_ICMP);
        if(pinger->socket==-1)
        {
-               perror("socket");
+               perror("socket(SOCK_RAW)");
                return -1;
        }
 
@@ -415,11 +455,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 +469,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 +509,13 @@ void send_ping(Pinger *pinger)
        for(unsigned i=0; i<sizeof(data); ++i)
                data[i] = i;
 
-       struct icmphdr *hdr = (struct icmphdr *)data;
-       hdr->type = 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));