Revision: 14918
Author:   adrian.chadd
Date:     Thu Jul 14 06:11:23 2011
Log:      Break out the ICMPv4 receive side code.

pinger now handles the ICMP payload; libpinger just handles the ICMPv4
(and soon IPv6) encode/decode.


http://code.google.com/p/lusca-cache/source/detail?r=14918

Modified:
 /playpen/LUSCA_HEAD_ipv6/libpinger/icmp_v4.c
 /playpen/LUSCA_HEAD_ipv6/libpinger/icmp_v4.h
 /playpen/LUSCA_HEAD_ipv6/src/pinger.c

=======================================
--- /playpen/LUSCA_HEAD_ipv6/libpinger/icmp_v4.c        Thu Jul 14 04:10:35 2011
+++ /playpen/LUSCA_HEAD_ipv6/libpinger/icmp_v4.c        Thu Jul 14 06:11:23 2011
@@ -38,6 +38,7 @@
 #include <stdlib.h>
 #include <unistd.h>
 #include <string.h>
+#include <arpa/inet.h>

 #if !defined(_SQUID_WIN32_)

@@ -134,6 +135,22 @@
     answer = (unsigned short) ~sum;
     return (answer);
 }
+
+static int
+ipHops(int ttl)
+{
+    if (ttl < 33)
+        return 33 - ttl;
+    if (ttl < 63)
+        return 63 - ttl;        /* 62 = (64+60)/2 */
+    if (ttl < 65)
+        return 65 - ttl;        /* 62 = (64+60)/2 */
+    if (ttl < 129)
+        return 129 - ttl;
+    if (ttl < 193)
+        return 193 - ttl;
+    return 256 - ttl;
+}

 /*
  * Assemble an IPv4 ICMP Echo packet.
@@ -192,3 +209,74 @@
       sizeof(struct sockaddr_in));
 }

+/*
+ * Receive an ICMP packet.
+ *
+ * If NULL is returned, the packet isn't valid or is the wrong type.
+ *
+ * If non-NULL is returned, the pointer refers to the beginning of
+ * the ICMP response payload; *len is set to the payload length.
+ */
+char *
+pingerv4RecvEcho(int icmp_sock, int *icmp_type, int *payload_len,
+  struct in_addr *src, int *hops)
+{
+    int n;
+    socklen_t fromlen;
+    struct sockaddr_in from;
+    int iphdrlen = 20;
+    struct iphdr *ip = NULL;
+    struct icmphdr *icmp = NULL;
+    static char *pkt = NULL;
+
+    (*icmp_type = -1);
+
+    if (pkt == NULL)
+        pkt = xmalloc(MAX_PKT_SZ);
+    fromlen = sizeof(from);
+
+    n = recvfrom(icmp_sock,
+      pkt,
+      MAX_PKT_SZ,
+      0,
+      (struct sockaddr *) &from,
+      &fromlen);
+
+    debug(42, 9) ("pingerRecv: %d bytes from %s\n", n,
+      inet_ntoa(from.sin_addr));
+    ip = (struct iphdr *) (void *) pkt;
+    (*src) = from.sin_addr;
+
+#if HAVE_IP_HL
+    iphdrlen = ip->ip_hl << 2;
+#else /* HAVE_IP_HL */
+#if WORDS_BIGENDIAN
+    iphdrlen = (ip->ip_vhl >> 4) << 2;
+#else
+    iphdrlen = (ip->ip_vhl & 0xF) << 2;
+#endif
+#endif /* HAVE_IP_HL */
+    icmp = (struct icmphdr *) (void *) (pkt + iphdrlen);
+
+    if (icmp->icmp_type != ICMP_ECHOREPLY) {
+        debug(42, 9) ("%s: icmp_type=%d\n", __func__, icmp->icmp_type);
+        return NULL;
+    }
+    if (icmp->icmp_id != icmp_ident) {
+        debug(42, 9) ("%s: icmp_id=%d, ident should be %d\n", __func__,
+          icmp->icmp_id, icmp_ident);
+        return NULL;
+    }
+
+    /* record the ICMP results */
+    (*hops) = ipHops(ip->ip_ttl);
+    (*payload_len) = n - iphdrlen - sizeof(struct icmphdr);
+    if (*payload_len < 0)
+        return NULL;
+
+    debug(42, 9) ("%s: hops=%d, len=%d\n", __func__, ipHops(ip->ip_ttl),
+      n - iphdrlen);
+
+    /* There may be no payload; the caller should check len first */
+    return (pkt + iphdrlen + sizeof(struct icmphdr));
+}
=======================================
--- /playpen/LUSCA_HEAD_ipv6/libpinger/icmp_v4.h        Thu Jul 14 04:10:35 2011
+++ /playpen/LUSCA_HEAD_ipv6/libpinger/icmp_v4.h        Thu Jul 14 06:11:23 2011
@@ -96,4 +96,7 @@
 extern void pingerv4SendEcho(int sock, struct in_addr to, int opcode,
   char *payload, int len);

+extern char * pingerv4RecvEcho(int icmp_sock, int *icmp_type, int *payload_len,
+  struct in_addr *src, int *hops);
+
 #endif /* __LIBPINGER_ICMP_V4_H__ */
=======================================
--- /playpen/LUSCA_HEAD_ipv6/src/pinger.c       Thu Jul 14 04:10:35 2011
+++ /playpen/LUSCA_HEAD_ipv6/src/pinger.c       Thu Jul 14 06:11:23 2011
@@ -99,7 +99,6 @@

 static void pingerRecv(void);
 static void pingerLog(int, struct in_addr, int, int);
-static int ipHops(int ttl);
 static void pingerSendtoSquid(pingerReplyData * preply);
 static void pingerOpen(void);
 static void pingerClose(void);
@@ -231,70 +230,54 @@
     pingerLog(ICMP_ECHO, to, 0, 0);
 }

+/*
+ * This is an IPv4-specific function for now.
+ */
 static void
 pingerRecv(void)
 {
-    int n;
-    socklen_t fromlen;
-    struct sockaddr_in from;
-    int iphdrlen = 20;
-    struct iphdr *ip = NULL;
-    struct icmphdr *icmp = NULL;
-    static char *pkt = NULL;
+    char *pkt;
     struct timeval now;
     icmpEchoData *echo;
     static pingerReplyData preply;
     struct timeval tv;
     struct sockaddr_in *v4;

+    int icmp_type, payload_len, hops;
+    struct in_addr from;
+
+    debug(42, 9) ("%s: called\n", __func__);
+
+    pkt = pingerv4RecvEcho(icmp_sock, &icmp_type, &payload_len,
+      &from, &hops);
+    debug(42, 9) ("%s: returned %p\n", __func__, pkt);
+
     if (pkt == NULL)
-       pkt = xmalloc(MAX_PKT_SZ);
-    fromlen = sizeof(from);
-    n = recvfrom(icmp_sock,
-       pkt,
-       MAX_PKT_SZ,
-       0,
-       (struct sockaddr *) &from,
-       &fromlen);
+        return;
+
 #if GETTIMEOFDAY_NO_TZP
     gettimeofday(&now);
 #else
     gettimeofday(&now, NULL);
 #endif
- debug(42, 9) ("pingerRecv: %d bytes from %s\n", n, inet_ntoa(from.sin_addr));
-    ip = (struct iphdr *) (void *) pkt;
-#if HAVE_IP_HL
-    iphdrlen = ip->ip_hl << 2;
-#else /* HAVE_IP_HL */
-#if WORDS_BIGENDIAN
-    iphdrlen = (ip->ip_vhl >> 4) << 2;
-#else
-    iphdrlen = (ip->ip_vhl & 0xF) << 2;
-#endif
-#endif /* HAVE_IP_HL */
-    icmp = (struct icmphdr *) (void *) (pkt + iphdrlen);
-    if (icmp->icmp_type != ICMP_ECHOREPLY)
-       return;
-    if (icmp->icmp_id != icmp_ident)
-       return;
-    echo = (icmpEchoData *) (void *) (icmp + 1);
-
-    /* Assign IPv4 address */
-#warning IPv6-ify this!
-
+
+    debug(42, 9) ("pingerRecv: %d payload bytes from %s\n", payload_len,
+      inet_ntoa(from));
+    echo = (icmpEchoData *) pkt;
+
+    /* Set V4 address in preply */
     v4 = (struct sockaddr_in *) &preply.from;
-    /* This should also match ss_family */
     v4->sin_family = AF_INET;
     v4->sin_port = 0;
-    v4->sin_addr = from.sin_addr;
+    v4->sin_addr = from;

     preply.opcode = echo->opcode;
-    preply.hops = ipHops(ip->ip_ttl);
+    preply.hops = hops;
     memcpy(&tv, &echo->tv, sizeof(tv));
     preply.rtt = tvSubMsec(tv, now);
-    preply.psize = n - iphdrlen - (sizeof(icmpEchoData) - MAX_PKT_SZ);
+    preply.psize = payload_len;
     pingerSendtoSquid(&preply);
-    pingerLog(icmp->icmp_type, from.sin_addr, preply.rtt, preply.hops);
+    pingerLog(icmp_type, from, preply.rtt, preply.hops);
 }

 static void
@@ -309,22 +292,6 @@
        rtt,
        hops);
 }
-
-static int
-ipHops(int ttl)
-{
-    if (ttl < 33)
-       return 33 - ttl;
-    if (ttl < 63)
-       return 63 - ttl;        /* 62 = (64+60)/2 */
-    if (ttl < 65)
-       return 65 - ttl;        /* 62 = (64+60)/2 */
-    if (ttl < 129)
-       return 129 - ttl;
-    if (ttl < 193)
-       return 193 - ttl;
-    return 256 - ttl;
-}

 static int
 pingerReadRequest(void)

--
You received this message because you are subscribed to the Google Groups 
"lusca-commit" group.
To post to this group, send email to [email protected].
To unsubscribe from this group, send email to 
[email protected].
For more options, visit this group at 
http://groups.google.com/group/lusca-commit?hl=en.

Reply via email to