Jindrich Makovicka 16 rokov pred
rodič
commit
89129e18ac
1 zmenil súbory, kde vykonal 109 pridanie a 112 odobranie
  1. 109 112
      pinger.c

+ 109 - 112
pinger.c

@@ -84,7 +84,7 @@ typedef struct _host_data {
     union {
         struct icmp v4;
         struct icmp6_hdr v6;
-    } icp;
+    } icmp;
     char rcvd_tbl[MAX_DUP_CHK / 8];
     int phase;
     int counter;
@@ -127,7 +127,7 @@ static void host_free(host_data * h)
 
 static gint compare_nhost(gconstpointer a, gconstpointer b)
 {
-    return ((host_data *) a)->nhost - *(int *) b;
+    return ((host_data *) a)->nhost - *(int32_t *) b;
 }
 
 static gint compare_nhost2(gconstpointer a, gconstpointer b)
@@ -180,6 +180,47 @@ static void write_result(host_data * h, gchar * msg, gchar * shortmsg)
     g_string_assign(h->shortmsg, shortmsg);
 }
 
+static void host_check_dup(host_data * h, int seq)
+{
+    if (TST(seq % MAX_DUP_CHK)) {
+        ++h->rep;
+        ++h->tmp_rep;
+        --h->recv;
+        --h->tmp_recv;
+        h->dupflag = 1;
+    } else {
+        SET(seq % MAX_DUP_CHK);
+        h->dupflag = 0;
+    }
+}
+
+static void set_packet_data(u_char *buf, host_data *h)
+{
+    (void) gettimeofday((struct timeval *) buf,
+                        (struct timezone *) NULL);
+
+    *(int32_t *) (buf + sizeof(struct timeval)) = h->nhost;
+}
+
+static host_data * get_packet_data(u_char *buf, host_data **h, struct timeval *tv)
+{
+    GList *l;
+    int32_t *hidp = (int32_t *) (buf + sizeof(struct timeval));
+
+    *tv = *(struct timeval *) buf;
+
+    l = g_list_find_custom(hosts, hidp, compare_nhost);
+
+    if (l) {
+        *h = (host_data *) l->data;
+    } else {
+        *h = 0;
+        fprintf(stderr, "Unknown host ID (%" PRIi32 ")\n", *hidp);
+    }
+
+    return *h;
+}
+
 /*
  * pinger --
  *      Compose and transmit an ICMP ECHO REQUEST packet.  The IP packet
@@ -192,31 +233,27 @@ static void write_result(host_data * h, gchar * msg, gchar * shortmsg)
  */
 static void pinger4(host_data * h)
 {
-    struct icmphdr *icp;
+    struct icmp *icp;
     int i;
 
     has_pinged = 1;
 
-    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 */
+    icp = (struct icmp *) outpack;
+    icp->icmp_type = ICMP_ECHO;
+    icp->icmp_code = 0;
+    icp->icmp_cksum = 0;
+    icp->icmp_seq = htons(ntransmitted++);
+    icp->icmp_id = ident;       /* ID */
 
     h->sent++;
     h->tmp_sent++;
 
-    CLR(icp->un.echo.sequence % MAX_DUP_CHK);
+    CLR(icp->icmp_seq % MAX_DUP_CHK);
 
-    (void) gettimeofday((struct timeval *) &outpack[sizeof(*icp)],
-                        (struct timezone *) NULL);
-
-    *(int *) &outpack[sizeof(*icp)
-                      + sizeof(struct timeval)] = h->nhost;
+    set_packet_data(icp->icmp_data, h);
 
     /* compute ICMP checksum here */
-    icp->checksum = in_cksum((u_short *) icp, sizeof(outpack));
+    icp->icmp_cksum = in_cksum((u_short *) icp, sizeof(outpack));
 
     i = sendto(icmp_socket, (char *) outpack, sizeof(outpack), 0,
                (struct sockaddr *)&h->addr, sizeof(h->addr));
@@ -229,28 +266,24 @@ static void pinger4(host_data * h)
 
 static void pinger6(host_data * h)
 {
-    struct icmp6_hdr *icp;
+    struct icmp6_hdr *icmp;
     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 */
+    icmp = (struct icmp6_hdr *) outpack;
+    icmp->icmp6_type = ICMP6_ECHO_REQUEST;
+    icmp->icmp6_code = 0;
+    icmp->icmp6_cksum = 0;
+    icmp->icmp6_seq = htons(ntransmitted++);
+    icmp->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);
+    CLR(icmp->icmp6_seq % MAX_DUP_CHK);
 
-    *(int32_t *) &outpack[sizeof(*icp)
-                          + sizeof(struct timeval)] = h->nhost;
+    set_packet_data(outpack + sizeof(*icmp), h);
 
     i = sendto(icmp6_socket, (char *) outpack, sizeof(outpack), 0,
                &h->addr.addr, sizeof(struct sockaddr_in6));
@@ -425,18 +458,18 @@ static gchar *pr_icmph(struct icmp *icp)
  * pr_icmph --
  *      Print a descriptive string about an ICMPv6 header.
  */
-static gchar *pr_icmph6(struct icmp6_hdr *icp)
+static gchar *pr_icmph6(struct icmp6_hdr *icmp)
 {
     GString *s = g_string_new(NULL);
     gchar *c;
 
-    switch (icp->icmp6_type) {
+    switch (icmp->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) {
+        switch (icmp->icmp6_code) {
         case ICMP6_DST_UNREACH_NOROUTE:
             g_string_assign(s, "No route to destination");
             break;
@@ -454,7 +487,7 @@ static gchar *pr_icmph6(struct icmp6_hdr *icp)
             break;
         default:
             g_string_sprintf(s, "Dest Unreachable, Unknown Code: %d",
-                             icp->icmp6_code);
+                             icmp->icmp6_code);
             break;
         }
         break;
@@ -463,7 +496,7 @@ static gchar *pr_icmph6(struct icmp6_hdr *icp)
         /* XXX ID + Seq + Data */
         break;
     case ICMP6_TIME_EXCEEDED:
-        switch (icp->icmp6_code) {
+        switch (icmp->icmp6_code) {
         case ICMP6_TIME_EXCEED_TRANSIT:
             g_string_assign(s, "Hop Limit == 0 in transit");
             break;
@@ -472,12 +505,12 @@ static gchar *pr_icmph6(struct icmp6_hdr *icp)
             break;
         default:
             g_string_sprintf(s, "Time exceeded, Bad Code: %d",
-                             icp->icmp6_code);
+                             icmp->icmp6_code);
             break;
         }
         break;
     case ICMP_PARAMETERPROB:
-        switch (icp->icmp6_code) {
+        switch (icmp->icmp6_code) {
         case ICMP6_PARAMPROB_HEADER:
             g_string_assign(s, "Erroneous header field");
             break;
@@ -489,16 +522,16 @@ static gchar *pr_icmph6(struct icmp6_hdr *icp)
             break;
         default:
             g_string_sprintf(s, "Parameter problem, Unknown Code: %d",
-                             icp->icmp6_code);
+                             icmp->icmp6_code);
             break;
         }
         break;
     case ICMP6_PACKET_TOO_BIG:
         g_string_sprintf(s, "Packet too big, Bad Code: %d",
-                         icp->icmp6_code);
+                         icmp->icmp6_code);
         break;
     default:
-        g_string_sprintf(s, "Bad ICMP type: %d", icp->icmp6_type);
+        g_string_sprintf(s, "Bad ICMP type: %d", icmp->icmp6_type);
     }
 
     c = s->str;
@@ -525,7 +558,7 @@ void pr_pack(char *buf, int cc, struct sockaddr_in *from)
 {
     struct icmp *icp;
     struct ip *ip;
-    struct timeval tv, *tp;
+    struct timeval tv, tvs;
     long triptime = 0;
     int hlen;
     host_data *h;
@@ -547,65 +580,43 @@ void pr_pack(char *buf, int cc, struct sockaddr_in *from)
         if (icp->icmp_id != ident)
             return;             /* 'Twas not our ECHO */
 
-        h = (host_data *) g_list_find_custom(hosts,
-                                             (int *) &icp->
-                                             icmp_data[sizeof(struct timeval)],
-                                             compare_nhost)->data;
-        if (h == NULL) return; /* host not found */
+        if (!get_packet_data(icp->icmp_data, &h, &tvs))
+            return;
 
         ++h->recv;
         ++h->tmp_recv;
 
-        tp = (struct timeval *) icp->icmp_data;
-        tvsub(&tv, tp);
+        tvsub(&tv, &tvs);
         triptime = tv.tv_sec * 1000000 + tv.tv_usec;
         h->tsum += triptime;
         h->tmp_tsum += triptime;
 
-        if (TST(ntohs(icp->icmp_seq) % MAX_DUP_CHK)) {
-            ++h->rep;
-            ++h->tmp_rep;
-            --h->recv;
-            --h->tmp_recv;
-            h->dupflag = 1;
-        } else {
-            SET(ntohs(icp->icmp_seq) % MAX_DUP_CHK);
-            h->dupflag = 0;
-        }
+        host_check_dup(h, ntohs(icp->icmp_seq));
     } else {
         switch (icp->icmp_type) {
         case ICMP_ECHO:
             return;
-        case ICMP_SOURCE_QUENCH:
-        case ICMP_REDIRECT:
         case ICMP_DEST_UNREACH:
         case ICMP_TIME_EXCEEDED:
         case ICMP_PARAMETERPROB:
             {
                 struct ip *iph = (struct ip *) (&icp->icmp_data);
                 struct icmp *icp1 =
-                    (struct icmp *) ((unsigned char *) iph +
+                    (struct icmp *) ((u_char *) iph +
                                      iph->ip_hl * 4);
-                int error_pkt;
 
                 if (icp1->icmp_type != ICMP_ECHO ||
                     iph->ip_src.s_addr != ip->ip_dst.s_addr ||
                     icp1->icmp_id != ident)
+                {
                     return;
-                error_pkt = (icp->icmp_type != ICMP_REDIRECT &&
-                             icp->icmp_type != ICMP_SOURCE_QUENCH);
-
-                h = (host_data *) g_list_find_custom(hosts,
-                                                     (int *) &icp1->
-                                                     icmp_data[sizeof
-                                                               (struct
-                                                                timeval)],
-                                                     compare_nhost)->data;
-                if (h) {
-                    h->icp.v4 = *icp;
-                    h->error_flag = 1;
                 }
 
+                if (!get_packet_data(icp1->icmp_data, &h, &tvs))
+                    return;
+
+                h->icmp.v4 = *icp;
+                h->error_flag = 1;
             }
         }
     }
@@ -614,8 +625,9 @@ void pr_pack(char *buf, int cc, struct sockaddr_in *from)
 // process a received packet
 void pr_pack6(char *buf, int cc, struct sockaddr_in6 *from)
 {
-    struct icmp6_hdr *icp;
-    struct timeval tv, *tp;
+    struct icmp6_hdr *icmp;
+    u_char *data;
+    struct timeval tv, tvs;
     long triptime = 0;
     host_data *h;
 
@@ -625,39 +637,27 @@ void pr_pack6(char *buf, int cc, struct sockaddr_in6 *from)
         return;
 
     /* Now the ICMP part */
-    icp = (struct icmp6_hdr *) buf;
+    icmp = (struct icmp6_hdr *) buf;
+    data = (u_char *)(icmp + 1);
 
-    if (icp->icmp6_type == ICMP6_ECHO_REPLY) {
-        if (icp->icmp6_id != ident)
+    if (icmp->icmp6_type == ICMP6_ECHO_REPLY) {
+        if (icmp->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 */
+        if (!get_packet_data(data, &h, &tvs))
+            return;
 
         ++h->recv;
         ++h->tmp_recv;
 
-        tp = (struct timeval *) &buf[sizeof(*icp)];
-        tvsub(&tv, tp);
+        tvsub(&tv, &tvs);
         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;
-        }
+        host_check_dup(h, ntohs(icmp->icmp6_seq));
     } else {
-        switch (icp->icmp6_type) {
+        switch (icmp->icmp6_type) {
         case ICMP6_ECHO_REPLY:
             return;
         case ICMP6_PACKET_TOO_BIG:
@@ -665,27 +665,24 @@ void pr_pack6(char *buf, int cc, struct sockaddr_in6 *from)
         case ICMP6_TIME_EXCEEDED:
         case ICMP6_PARAM_PROB:
             {
-                struct ip6_hdr *orig_ip = (struct ip6_hdr *) (icp + 1);
+                struct ip6_hdr *orig_ip = (struct ip6_hdr *) (icmp + 1);
                 struct icmp6_hdr *orig_icmp = (struct icmp6_hdr *) (orig_ip + 1);
+                u_char *orig_data = (u_char *)(orig_icmp + 1);
 
-                char *data = (char *)(orig_icmp + 1);
-
-                h = (host_data *) g_list_find_custom(
-                    hosts,
-                    (int *)&data[sizeof(struct timeval)],
-                    compare_nhost)->data;
-
-                if (h == NULL) return;
-
-                if (!IN6_ARE_ADDR_EQUAL (&orig_ip->ip6_dst, &h->addr.in6.sin6_addr)
+                if (orig_icmp->icmp6_id != ident
                     || orig_ip->ip6_nxt != IPPROTO_ICMPV6
-                    || orig_icmp->icmp6_type != ICMP6_ECHO_REQUEST
-                    || orig_icmp->icmp6_id != ident)
+                    || orig_icmp->icmp6_type != ICMP6_ECHO_REQUEST)
                 {
                     return;
                 }
 
-                h->icp.v6 = *icp;
+                if (!get_packet_data(orig_data, &h, &tvs))
+                    return;
+
+                if (!IN6_ARE_ADDR_EQUAL (&orig_ip->ip6_dst, &h->addr.in6.sin6_addr))
+                    return;
+
+                h->icmp.v6 = *icmp;
                 h->error_flag = 1;
 
             }
@@ -789,9 +786,9 @@ void ping_host(host_data * h)
 
     if (h->error_flag) {
         if (h->addr.addr.sa_family == AF_INET)
-            msg = pr_icmph(&h->icp.v4);
+            msg = pr_icmph(&h->icmp.v4);
         else
-            msg = pr_icmph6(&h->icp.v6);
+            msg = pr_icmph6(&h->icmp.v6);
         write_result(h, msg, "Err");
         g_free(msg);
     }