Jindrich Makovicka 16 vuotta sitten
vanhempi
sitoutus
269e8c2725
1 muutettua tiedostoa jossa 333 lisäystä ja 55 poistoa
  1. 333 55
      pinger.c

+ 333 - 55
pinger.c

@@ -28,12 +28,15 @@ ____________________________________________________________________________*/
 #include <netinet/in.h>
 #include <netinet/in.h>
 #include <netinet/ip.h>
 #include <netinet/ip.h>
 #include <netinet/ip_icmp.h>
 #include <netinet/ip_icmp.h>
+#include <netinet/ip6.h>
+#include <netinet/icmp6.h>
 #include <arpa/inet.h>
 #include <arpa/inet.h>
 #include <netdb.h>
 #include <netdb.h>
 
 
 #include <stdio.h>
 #include <stdio.h>
 #include <stdlib.h>
 #include <stdlib.h>
 #include <string.h>
 #include <string.h>
+#include <assert.h>
 #include <signal.h>
 #include <signal.h>
 #include <fcntl.h>
 #include <fcntl.h>
 #include <unistd.h>
 #include <unistd.h>
@@ -45,7 +48,7 @@ ____________________________________________________________________________*/
 #define STORM_PHASE 0
 #define STORM_PHASE 0
 #define STANDBY_PHASE 1
 #define STANDBY_PHASE 1
 
 
-#define         DEFDATALEN      (64 - 8)        /* default data length */
+#define         DEFDATALEN      (64 - 16)        /* default data length */
 #define         MAXIPLEN        60
 #define         MAXIPLEN        60
 #define         MAXICMPLEN      76
 #define         MAXICMPLEN      76
 #define         MAXPACKET       (65536 - 60 - 8)        /* max packet size */
 #define         MAXPACKET       (65536 - 60 - 8)        /* max packet size */
@@ -58,7 +61,7 @@ ____________________________________________________________________________*/
 #define         CLR(bit)        (A(bit) &= (~B(bit)))
 #define         CLR(bit)        (A(bit) &= (~B(bit)))
 #define         TST(bit)        (A(bit) & B(bit))
 #define         TST(bit)        (A(bit) & B(bit))
 
 
-int icmp_socket;
+int icmp_socket, icmp6_socket;
 static int ident;               /* process id to identify our packets */
 static int ident;               /* process id to identify our packets */
 static int datalen = DEFDATALEN;
 static int datalen = DEFDATALEN;
 static long ntransmitted = 0;   /* sequence # for outbound packets = #sent */
 static long ntransmitted = 0;   /* sequence # for outbound packets = #sent */
@@ -76,12 +79,19 @@ typedef struct _host_data {
     GString *hostname, *percentage, *sent_str, *recv_str, *msg, *shortmsg;
     GString *hostname, *percentage, *sent_str, *recv_str, *msg, *shortmsg;
     int dynamic;
     int dynamic;
     int dummy;
     int dummy;
-    struct sockaddr addr;
+    union {
+        struct sockaddr addr;
+        struct sockaddr_in in4;
+        struct sockaddr_in6 in6;
+    } addr;
     int sent, recv, rep;
     int sent, recv, rep;
     int tmp_sent, tmp_recv, tmp_rep;
     int tmp_sent, tmp_recv, tmp_rep;
     int dupflag, error_flag;
     int dupflag, error_flag;
     long tsum, tmp_tsum;
     long tsum, tmp_tsum;
-    struct icmp icp;
+    union {
+        struct icmp v4;
+        struct icmp6_hdr v6;
+    } icp;
     char rcvd_tbl[MAX_DUP_CHK / 8];
     char rcvd_tbl[MAX_DUP_CHK / 8];
     int phase;
     int phase;
     int counter;
     int counter;
@@ -187,46 +197,91 @@ static void write_result(host_data * h, gchar * msg, gchar * shortmsg)
  *
  *
  * Another 4 bytes are the index of the host being pinged -JM
  * Another 4 bytes are the index of the host being pinged -JM
  */
  */
-static void pinger(host_data * h)
+static void pinger4(host_data * h)
 {
 {
-    struct icmp *icp;
+    struct icmphdr *icp;
     int cc;
     int cc;
     int i;
     int i;
 
 
     has_pinged = 1;
     has_pinged = 1;
 
 
-//    fprintf(stderr, "pinger: pinging host No. %d\n", h->nhost);
-
-    icp = (struct icmp *) outpack;
-    icp->icmp_type = ICMP_ECHO;
-    icp->icmp_code = 0;
-    icp->icmp_cksum = 0;
-    icp->icmp_seq = ntransmitted++;
-    icp->icmp_id = ident;       /* ID */
+    icp = (struct icmphdr *) outpack;
+    icp->type = ICMP_ECHO;
+    icp->code = 0;
+    icp->checksum = 0;
+    icp->un.echo.sequence = htons(ntransmitted++);
+    icp->un.echo.id = ident;       /* ID */
 
 
     h->sent++;
     h->sent++;
     h->tmp_sent++;
     h->tmp_sent++;
 
 
-    CLR(icp->icmp_seq % MAX_DUP_CHK);
+    CLR(icp->un.echo.sequence % MAX_DUP_CHK);
 
 
-    (void) gettimeofday((struct timeval *) &outpack[8],
+    (void) gettimeofday((struct timeval *) &outpack[sizeof(*icp)],
                         (struct timezone *) NULL);
                         (struct timezone *) NULL);
 
 
-    *(int *) &outpack[8 + sizeof(struct timeval)] = h->nhost;
+    *(int *) &outpack[sizeof(*icp)
+                      + sizeof(struct timeval)] = h->nhost;
 
 
     cc = datalen + 8;           /* skips ICMP portion */
     cc = datalen + 8;           /* skips ICMP portion */
 
 
     /* compute ICMP checksum here */
     /* compute ICMP checksum here */
-    icp->icmp_cksum = in_cksum((u_short *) icp, cc);
+    icp->checksum = in_cksum((u_short *) icp, cc);
 
 
-    i = sendto(icmp_socket, (char *) outpack, cc, 0, &h->addr,
-               sizeof(struct sockaddr));
+    i = sendto(icmp_socket, (char *) outpack, cc, 0,
+               (struct sockaddr *)&h->addr, sizeof(h->addr));
 
 
     if (i < 0 || i != cc) {
     if (i < 0 || i != cc) {
+        perror("pinger: sendto");
         write_result(h, "Error sending packet", "Err");
         write_result(h, "Error sending packet", "Err");
     }
     }
 }
 }
 
 
+static void pinger6(host_data * h)
+{
+    struct icmp6_hdr *icp;
+    int cc;
+    int i;
+
+    has_pinged = 1;
+
+    icp = (struct icmp6_hdr *) outpack;
+    icp->icmp6_type = ICMP6_ECHO_REQUEST;
+    icp->icmp6_code = 0;
+    icp->icmp6_cksum = 0;
+    icp->icmp6_seq = htons(ntransmitted++);
+    icp->icmp6_id = ident;       /* ID */
+
+    h->sent++;
+    h->tmp_sent++;
+
+    CLR(icp->icmp6_seq % MAX_DUP_CHK);
+
+    (void) gettimeofday((struct timeval *) &outpack[sizeof(*icp)],
+                        (struct timezone *) NULL);
+
+    *(int32_t *) &outpack[sizeof(*icp)
+                          + sizeof(struct timeval)] = h->nhost;
+
+    cc = datalen + 8;           /* skips ICMP portion */
+
+    i = sendto(icmp6_socket, (char *) outpack, cc, 0,
+               &h->addr.addr, sizeof(struct sockaddr_in6));
+
+    if (i < 0 || i != cc) {
+        perror("pinger: sendto");
+        write_result(h, "Error sending packet", "Err");
+    }
+}
+
+static void pinger(host_data * h)
+{
+    if (h->addr.addr.sa_family == AF_INET)
+        pinger4(h);
+    else if (h->addr.addr.sa_family == AF_INET6)
+        pinger6(h);
+}
+
 /*
 /*
  * pr_icmph --
  * pr_icmph --
  *      Print a descriptive string about an ICMP header.
  *      Print a descriptive string about an ICMP header.
@@ -379,6 +434,91 @@ static gchar *pr_icmph(struct icmp *icp)
     return c;
     return c;
 }
 }
 
 
+/*
+ * pr_icmph --
+ *      Print a descriptive string about an ICMPv6 header.
+ */
+static gchar *pr_icmph6(struct icmp6_hdr *icp)
+{
+    GString *s = g_string_new(NULL);
+    gchar *c;
+
+    switch (icp->icmp6_type) {
+    case ICMP6_ECHO_REPLY:
+        g_string_assign(s, "Echo Reply");
+        /* XXX ID + Seq + Data */
+        break;
+    case ICMP6_DST_UNREACH:
+        switch (icp->icmp6_code) {
+        case ICMP6_DST_UNREACH_NOROUTE:
+            g_string_assign(s, "No route to destination");
+            break;
+        case ICMP6_DST_UNREACH_ADMIN:
+            g_string_assign(s, "Communication with destination administratively prohibited");
+            break;
+        case ICMP6_DST_UNREACH_BEYONDSCOPE:
+            g_string_assign(s, "Beyond scope of source address");
+            break;
+        case ICMP6_DST_UNREACH_ADDR:
+            g_string_assign(s, "Address unreachable");
+            break;
+        case ICMP6_DST_UNREACH_NOPORT:
+            g_string_assign(s, "Bad port");
+            break;
+        default:
+            g_string_sprintf(s, "Dest Unreachable, Unknown Code: %d",
+                             icp->icmp6_code);
+            break;
+        }
+        break;
+    case ICMP6_ECHO_REQUEST:
+        g_string_assign(s, "Echo Request");
+        /* XXX ID + Seq + Data */
+        break;
+    case ICMP6_TIME_EXCEEDED:
+        switch (icp->icmp6_code) {
+        case ICMP6_TIME_EXCEED_TRANSIT:
+            g_string_assign(s, "Hop Limit == 0 in transit");
+            break;
+        case ICMP6_TIME_EXCEED_REASSEMBLY:
+            g_string_assign(s, "Frag reassembly time exceeded");
+            break;
+        default:
+            g_string_sprintf(s, "Time exceeded, Bad Code: %d",
+                             icp->icmp6_code);
+            break;
+        }
+        break;
+    case ICMP_PARAMETERPROB:
+        switch (icp->icmp6_code) {
+        case ICMP6_PARAMPROB_HEADER:
+            g_string_assign(s, "Erroneous header field");
+            break;
+        case ICMP6_PARAMPROB_NEXTHEADER:
+            g_string_assign(s, "Unrecognized Next Header");
+            break;
+        case ICMP6_PARAMPROB_OPTION:
+            g_string_assign(s, "Unrecognized IPv6 option");
+            break;
+        default:
+            g_string_sprintf(s, "Parameter problem, Unknown Code: %d",
+                             icp->icmp6_code);
+            break;
+        }
+        break;
+    case ICMP6_PACKET_TOO_BIG:
+        g_string_sprintf(s, "Packet too big, Bad Code: %d",
+                         icp->icmp6_code);
+        break;
+    default:
+        g_string_sprintf(s, "Bad ICMP type: %d", icp->icmp6_type);
+    }
+
+    c = s->str;
+    g_string_free(s, FALSE);
+    return c;
+}
+
 /*
 /*
  * tvsub --
  * tvsub --
  *      Subtract 2 timeval structs:  out = out - in.  Out is assumed to
  *      Subtract 2 timeval structs:  out = out - in.  Out is assumed to
@@ -422,8 +562,7 @@ void pr_pack(char *buf, int cc, struct sockaddr_in *from)
 
 
         h = (host_data *) g_list_find_custom(hosts,
         h = (host_data *) g_list_find_custom(hosts,
                                              (int *) &icp->
                                              (int *) &icp->
-                                             icmp_data[sizeof
-                                                       (struct timeval)],
+                                             icmp_data[sizeof(struct timeval)],
                                              compare_nhost)->data;
                                              compare_nhost)->data;
         if (h == NULL) return; /* host not found */
         if (h == NULL) return; /* host not found */
 
 
@@ -436,14 +575,14 @@ void pr_pack(char *buf, int cc, struct sockaddr_in *from)
         h->tsum += triptime;
         h->tsum += triptime;
         h->tmp_tsum += triptime;
         h->tmp_tsum += triptime;
 
 
-        if (TST(icp->icmp_seq % MAX_DUP_CHK)) {
+        if (TST(ntohs(icp->icmp_seq) % MAX_DUP_CHK)) {
             ++h->rep;
             ++h->rep;
             ++h->tmp_rep;
             ++h->tmp_rep;
             --h->recv;
             --h->recv;
             --h->tmp_recv;
             --h->tmp_recv;
             h->dupflag = 1;
             h->dupflag = 1;
         } else {
         } else {
-            SET(icp->icmp_seq % MAX_DUP_CHK);
+            SET(ntohs(icp->icmp_seq) % MAX_DUP_CHK);
             h->dupflag = 0;
             h->dupflag = 0;
         }
         }
     } else {
     } else {
@@ -476,7 +615,87 @@ void pr_pack(char *buf, int cc, struct sockaddr_in *from)
                                                                 timeval)],
                                                                 timeval)],
                                                      compare_nhost)->data;
                                                      compare_nhost)->data;
                 if (h) {
                 if (h) {
-                    h->icp = *icp;
+                    h->icp.v4 = *icp;
+                    h->error_flag = 1;
+                }
+
+            }
+        }
+    }
+}
+
+// process a received packet
+void pr_pack6(char *buf, int cc, struct sockaddr_in6 *from)
+{
+    struct icmp6_hdr *icp;
+    struct timeval tv, *tp;
+    long triptime = 0;
+    host_data *h;
+
+    (void) gettimeofday(&tv, (struct timezone *) NULL);
+
+    if (cc < datalen + ICMP_MINLEN)
+        return;
+
+    /* Now the ICMP part */
+    icp = (struct icmp6_hdr *) buf;
+
+    if (icp->icmp6_type == ICMP6_ECHO_REPLY) {
+        if (icp->icmp6_id != ident)
+            return;             /* 'Twas not our ECHO */
+
+        h = (host_data *) g_list_find_custom(
+            hosts,
+            (int *)&buf[sizeof(*icp) + sizeof(struct timeval)],
+            compare_nhost)->data;
+        if (h == NULL) return; /* host not found */
+
+        ++h->recv;
+        ++h->tmp_recv;
+
+        tp = (struct timeval *) &buf[sizeof(*icp)];
+        tvsub(&tv, tp);
+        triptime = tv.tv_sec * 1000000 + tv.tv_usec;
+        h->tsum += triptime;
+        h->tmp_tsum += triptime;
+
+        if (TST(ntohs(icp->icmp6_seq) % MAX_DUP_CHK)) {
+            ++h->rep;
+            ++h->tmp_rep;
+            --h->recv;
+            --h->tmp_recv;
+            h->dupflag = 1;
+        } else {
+            SET(ntohs(icp->icmp6_seq) % MAX_DUP_CHK);
+            h->dupflag = 0;
+        }
+    } else {
+        switch (icp->icmp6_type) {
+        case ICMP6_ECHO_REPLY:
+            return;
+        case ICMP6_PACKET_TOO_BIG:
+        case ICMP6_DST_UNREACH:
+        case ICMP6_TIME_EXCEEDED:
+        case ICMP6_PARAM_PROB:
+            {
+                struct ip6_hdr *orig_ip = (struct ip6_hdr *) (icp + 1);
+                struct icmp6_hdr *orig_icmp = (struct icmp6_hdr *) (orig_ip + 1);
+
+                if (!IN6_ARE_ADDR_EQUAL (&orig_ip->ip6_dst, &h->addr.in6)
+                    || orig_ip->ip6_nxt != IPPROTO_ICMPV6
+                    || orig_icmp->icmp6_type != ICMP6_ECHO_REQUEST
+                    || orig_icmp->icmp6_id != ident)
+                {
+                    return;
+                }
+
+                char *data = (char *)(orig_icmp + 1);
+                h = (host_data *) g_list_find_custom(
+                    hosts,
+                    (int *) &data[sizeof(struct timeval)],
+                    compare_nhost)->data;
+                if (h) {
+                    h->icp.v6 = *icp;
                     h->error_flag = 1;
                     h->error_flag = 1;
                 }
                 }
 
 
@@ -497,7 +716,6 @@ void clear_tmp_flags(host_data * h)
 
 
 void dump_host(host_data * h)
 void dump_host(host_data * h)
 {
 {
-//    fprintf(stderr, "dump_host: %d\n", h->nhost);
     printf("%s\n", h->percentage->str);
     printf("%s\n", h->percentage->str);
     printf("%s\n", h->sent_str->str);
     printf("%s\n", h->sent_str->str);
     printf("%s\n", h->recv_str->str);
     printf("%s\n", h->recv_str->str);
@@ -512,7 +730,7 @@ int hostname_to_addr(const char *hostname, struct sockaddr *addr)
     int s, ret = -1;
     int s, ret = -1;
 
 
     memset(&hints, 0, sizeof(struct addrinfo));
     memset(&hints, 0, sizeof(struct addrinfo));
-    hints.ai_family = AF_INET;      /* Allow IPv4 */
+    hints.ai_family = AF_UNSPEC;
     hints.ai_socktype = 0;
     hints.ai_socktype = 0;
     hints.ai_flags = 0;
     hints.ai_flags = 0;
     hints.ai_protocol = 0;          /* Any protocol */
     hints.ai_protocol = 0;          /* Any protocol */
@@ -527,8 +745,16 @@ int hostname_to_addr(const char *hostname, struct sockaddr *addr)
     }
     }
 
 
     for (rp = result; rp != NULL; rp = rp->ai_next) {
     for (rp = result; rp != NULL; rp = rp->ai_next) {
-        if (rp->ai_addr->sa_family == AF_INET) {
-            *addr = *rp->ai_addr;
+        if (rp->ai_addr->sa_family == AF_INET
+            || rp->ai_addr->sa_family == AF_INET6)
+        {
+            if (rp->ai_addr->sa_family == AF_INET) {
+                assert(rp->ai_addrlen == sizeof(struct sockaddr_in));
+            }
+            if (rp->ai_addr->sa_family == AF_INET6) {
+                assert(rp->ai_addrlen == sizeof(struct sockaddr_in6));
+            }
+            memcpy(addr, rp->ai_addr, rp->ai_addrlen);
             ret = 0;
             ret = 0;
             break;
             break;
         }
         }
@@ -542,16 +768,7 @@ int hostname_to_addr(const char *hostname, struct sockaddr *addr)
 // recheck the dns (needed for dialup users or dynamic DNS)
 // recheck the dns (needed for dialup users or dynamic DNS)
 int update_dns(host_data *h)
 int update_dns(host_data *h)
 {
 {
-    int res;
-    struct sockaddr addr;
-
-    res = hostname_to_addr(h->hostname->str, &addr);
-    if (res == 0) {
-        h->addr  = addr;
-        return 0;
-    }
-
-    return 1;
+    return hostname_to_addr(h->hostname->str, &h->addr.addr);
 }
 }
 
 
 
 
@@ -582,7 +799,10 @@ void ping_host(host_data * h)
     }
     }
 
 
     if (h->error_flag) {
     if (h->error_flag) {
-        msg = pr_icmph(&h->icp);
+        if (h->addr.addr.sa_family == AF_INET)
+            msg = pr_icmph(&h->icp.v4);
+        else
+            msg = pr_icmph6(&h->icp.v6);
         write_result(h, msg, "Err");
         write_result(h, msg, "Err");
         g_free(msg);
         g_free(msg);
     }
     }
@@ -650,7 +870,6 @@ gint timeout_callback()
 void receiver()
 void receiver()
 {
 {
     int cc;
     int cc;
-    struct sockaddr_in from;
     socklen_t fromlen;
     socklen_t fromlen;
     struct timeval tv,tv_old,tv_new;
     struct timeval tv,tv_old,tv_new;
     fd_set rfds;
     fd_set rfds;
@@ -658,27 +877,41 @@ void receiver()
 
 
     FD_ZERO(&rfds);
     FD_ZERO(&rfds);
     FD_SET(icmp_socket, &rfds);
     FD_SET(icmp_socket, &rfds);
+    FD_SET(icmp6_socket, &rfds);
 
 
     tv.tv_usec = 500000;
     tv.tv_usec = 500000;
     tv.tv_sec = 0;
     tv.tv_sec = 0;
 
 
     gettimeofday(&tv_old, NULL);
     gettimeofday(&tv_old, NULL);
-    fromlen = sizeof(from);
     for (;!terminated;) {
     for (;!terminated;) {
         FD_ZERO(&rfds);
         FD_ZERO(&rfds);
         FD_SET(icmp_socket, &rfds);
         FD_SET(icmp_socket, &rfds);
+        FD_SET(icmp6_socket, &rfds);
 
 
         tv.tv_usec = 100000;
         tv.tv_usec = 100000;
         tv.tv_sec = 0;
         tv.tv_sec = 0;
 
 
-        avail = select(icmp_socket + 1, &rfds, NULL, NULL, &tv);
+        avail = select(icmp6_socket + 1, &rfds, NULL, NULL, &tv);
 
 
         if (avail) {
         if (avail) {
-            if ((cc = recvfrom(icmp_socket, (char *) packet, packlen, 0,
-                               (struct sockaddr *) &from, &fromlen)) < 0) {
-                perror("ping: recvfrom");
-            } else {
-                pr_pack((char *) packet, cc, &from);
+            if (FD_ISSET(icmp_socket, &rfds)) {
+                struct sockaddr_in from;
+                fromlen = sizeof(from);
+                if ((cc = recvfrom(icmp_socket, (char *) packet, packlen, 0,
+                                   (struct sockaddr *) &from, &fromlen)) < 0) {
+                    perror("pinger: recvfrom");
+                } else {
+                    pr_pack((char *) packet, cc, &from);
+                }
+            } else if (FD_ISSET(icmp6_socket, &rfds)) {
+                struct sockaddr_in6 from;
+                fromlen = sizeof(from);
+                if ((cc = recvfrom(icmp6_socket, (char *) packet, packlen, 0,
+                                   (struct sockaddr *) &from, &fromlen)) < 0) {
+                    perror("pinger: recvfrom");
+                } else {
+                    pr_pack6((char *) packet, cc, &from);
+                }
             }
             }
         }
         }
         gettimeofday(&tv_new, NULL);
         gettimeofday(&tv_new, NULL);
@@ -745,11 +978,14 @@ void update_host_stats(host_data * h)
 }
 }
 
 
 
 
-void append_host(struct sockaddr addr, char * hostname, char * updatefreq, char * dynamic, int dummy)
+void append_host(struct sockaddr *addr, char * hostname, char * updatefreq, char * dynamic, int dummy)
 {
 {
     host_data *h = host_malloc();
     host_data *h = host_malloc();
 
 
-    h->addr = addr;
+    if (addr->sa_family == AF_INET)
+        h->addr.in4 = *(struct sockaddr_in *)addr;
+    else if (addr->sa_family == AF_INET6)
+        h->addr.in6 = *(struct sockaddr_in6 *)addr;
 
 
     g_string_assign(h->hostname, hostname);
     g_string_assign(h->hostname, hostname);
 
 
@@ -822,22 +1058,62 @@ int main(int argc, char **argv)
         exit(2);
         exit(2);
     }
     }
 
 
+    struct icmp6_filter filter;
+    const int on = 1;
+    int err;
+    if ((icmp6_socket = socket(PF_INET6, SOCK_RAW, IPPROTO_ICMPV6)) < 0) {
+        if (errno == EPERM) {
+            fprintf(stderr, "pinger: must run as root\n");
+        } else
+            perror("pinger: socket");
+        exit(2);
+    }
+
+    /* Tell which ICMPs we are interested in.  */
+    ICMP6_FILTER_SETBLOCKALL (&filter);
+    ICMP6_FILTER_SETPASS (ICMP6_ECHO_REPLY, &filter);
+    ICMP6_FILTER_SETPASS (ICMP6_DST_UNREACH, &filter);
+    ICMP6_FILTER_SETPASS (ICMP6_PACKET_TOO_BIG, &filter);
+    ICMP6_FILTER_SETPASS (ICMP6_TIME_EXCEEDED, &filter);
+    ICMP6_FILTER_SETPASS (ICMP6_PARAM_PROB, &filter);
+
+    err = setsockopt (icmp6_socket, IPPROTO_ICMPV6, ICMP6_FILTER,
+                      &filter, sizeof (filter));
+    if (err)
+    {
+        close (icmp6_socket);
+        exit(2);
+    }
+
+    err = setsockopt (icmp6_socket, IPPROTO_IPV6, IPV6_RECVHOPLIMIT,
+                      &on, sizeof (on));
+    if (err)
+    {
+        close (icmp6_socket);
+        exit(2);
+    }
+
     setuid(getuid());
     setuid(getuid());
 
 
     fcntl(icmp_socket, F_SETFL, O_NONBLOCK);
     fcntl(icmp_socket, F_SETFL, O_NONBLOCK);
+    fcntl(icmp6_socket, F_SETFL, O_NONBLOCK);
     ident = getpid() & 0xFFFF;
     ident = getpid() & 0xFFFF;
 
 
     for (i = 1; i < argc - 2; i += 3) {
     for (i = 1; i < argc - 2; i += 3) {
-        struct sockaddr addr;
+        union {
+            struct sockaddr addr;
+            struct sockaddr_in in4;
+            struct sockaddr_in6 in6;
+        } addr;
         int res;
         int res;
 
 
-        res = hostname_to_addr(argv[i], &addr);
+        res = hostname_to_addr(argv[i], &addr.addr);
         if (res == 0) {
         if (res == 0) {
-            append_host(addr, argv[i], argv[i+1], argv[i+2], 0);
+            append_host(&addr.addr, argv[i], argv[i+1], argv[i+2], 0);
         } else if (i <= argc-3) {
         } else if (i <= argc-3) {
             memset(&addr, 0, sizeof(addr));
             memset(&addr, 0, sizeof(addr));
-            addr.sa_family = AF_INET;
-            append_host(addr, argv[i], argv[i+1], argv[i+2], 1); // dummy host
+            addr.addr.sa_family = AF_INET;
+            append_host(&addr.addr, argv[i], argv[i+1], argv[i+2], 1); // dummy host
         }
         }
     }
     }
 
 
@@ -853,5 +1129,7 @@ int main(int argc, char **argv)
     receiver();
     receiver();
 
 
     free_hosts();
     free_hosts();
+    close(icmp_socket);
+    close(icmp6_socket);
     return 0;
     return 0;
 }
 }