]> git.ipfire.org Git - thirdparty/squid.git/blobdiff - src/icmp/Icmp6.cc
SourceFormat Enforcement
[thirdparty/squid.git] / src / icmp / Icmp6.cc
index 7b4bde6ec739fc0748af88f3cc3e45dc0040257f..a84f2b8c2de0d3f5275ecd443b02462fcdecbd6e 100644 (file)
@@ -1,45 +1,24 @@
 /*
- * DEBUG: section 42    ICMP Pinger program
- * AUTHOR: Duane Wessels, Amos Jeffries
- *
- * SQUID Web Proxy Cache          http://www.squid-cache.org/
- * ----------------------------------------------------------
- *
- *  Squid is the result of efforts by numerous individuals from
- *  the Internet community; see the CONTRIBUTORS file for full
- *  details.   Many organizations have provided support for Squid's
- *  development; see the SPONSORS file for full details.  Squid is
- *  Copyrighted (C) 2001 by the Regents of the University of
- *  California; see the COPYRIGHT file for full details.  Squid
- *  incorporates software developed and/or copyrighted by other
- *  sources; see the CREDITS file for full details.
- *
- *  This program is free software; you can redistribute it and/or modify
- *  it under the terms of the GNU General Public License as published by
- *  the Free Software Foundation; either version 2 of the License, or
- *  (at your option) any later version.
- *
- *  This program is distributed in the hope that it will be useful,
- *  but WITHOUT ANY WARRANTY; without even the implied warranty of
- *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- *  GNU General Public License for more details.
- *
- *  You should have received a copy of the GNU General Public License
- *  along with this program; if not, write to the Free Software
- *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111, USA.
+ * Copyright (C) 1996-2017 The Squid Software Foundation and contributors
  *
+ * Squid software is distributed under GPLv2+ license and includes
+ * contributions from numerous individuals and organizations.
+ * Please see the COPYING and CONTRIBUTORS files for details.
  */
+
+/* DEBUG: section 42    ICMP Pinger program */
+
 //#define SQUID_HELPER 1
 
 #include "squid.h"
 
 #if USE_ICMP
 
-#include "leakcheck.h"
-#include "SquidTime.h"
 #include "Debug.h"
 #include "Icmp6.h"
 #include "IcmpPinger.h"
+#include "leakcheck.h"
+#include "SquidTime.h"
 
 // Some system headers are only neeed internally here.
 // They should not be included via the header.
 
 // Icmp6 OP-Codes
 // see http://www.iana.org/assignments/icmpv6-parameters
-// NP: LowPktStr is for codes 0-127
-static const char *icmp6LowPktStr[] = {
-    "ICMP 0",                  // 0
-    "Destination Unreachable", // 1 - RFC2463
-    "Packet Too Big",          // 2 - RFC2463
-    "Time Exceeded",           // 3 - RFC2463
-    "Parameter Problem",               // 4 - RFC2463
-    "ICMP 5",                  // 5
-    "ICMP 6",                  // 6
-    "ICMP 7",                  // 7
-    "ICMP 8",                  // 8
-    "ICMP 9",                  // 9
-    "ICMP 10"                  // 10
-};
-
-// NP: HighPktStr is for codes 128-255
-static const char *icmp6HighPktStr[] = {
-    "Echo Request",                                    // 128 - RFC2463
-    "Echo Reply",                                      // 129 - RFC2463
-    "Multicast Listener Query",                        // 130 - RFC2710
-    "Multicast Listener Report",                       // 131 - RFC2710
-    "Multicast Listener Done",                 // 132 - RFC2710
-    "Router Solicitation",                             // 133 - RFC4861
-    "Router Advertisement",                            // 134 - RFC4861
-    "Neighbor Solicitation",                   // 135 - RFC4861
-    "Neighbor Advertisement",                  // 136 - RFC4861
-    "Redirect Message",                                // 137 - RFC4861
-    "Router Renumbering",                              // 138 - Crawford
-    "ICMP Node Information Query",                     // 139 - RFC4620
-    "ICMP Node Information Response",          // 140 - RFC4620
-    "Inverse Neighbor Discovery Solicitation", // 141 - RFC3122
-    "Inverse Neighbor Discovery Advertisement",        // 142 - RFC3122
-    "Version 2 Multicast Listener Report",             // 143 - RFC3810
-    "Home Agent Address Discovery Request",            // 144 - RFC3775
-    "Home Agent Address Discovery Reply",              // 145 - RFC3775
-    "Mobile Prefix Solicitation",                      // 146 - RFC3775
-    "Mobile Prefix Advertisement",                     // 147 - RFC3775
-    "Certification Path Solicitation",         // 148 - RFC3971
-    "Certification Path Advertisement",                // 149 - RFC3971
-    "ICMP Experimental (150)",                 // 150 - RFC4065
-    "Multicast Router Advertisement",          // 151 - RFC4286
-    "Multicast Router Solicitation",           // 152 - RFC4286
-    "Multicast Router Termination",                    // 153 - [RFC4286]
-    "ICMP 154",
-    "ICMP 155",
-    "ICMP 156",
-    "ICMP 157",
-    "ICMP 158",
-    "ICMP 159",
-    "ICMP 160"
-};
+static const char *
+IcmpPacketType(uint8_t v)
+{
+    // NP: LowPktStr is for codes 0-127
+    static const char *icmp6LowPktStr[] = {
+        "ICMPv6 0",         // 0
+        "Destination Unreachable",  // 1 - RFC2463
+        "Packet Too Big",       // 2 - RFC2463
+        "Time Exceeded",        // 3 - RFC2463
+        "Parameter Problem",        // 4 - RFC2463
+    };
+
+    // low codes 1-4 registered
+    if (0 < v && v < 5)
+        return icmp6LowPktStr[(int)(v&0x7f)];
+
+    // NP: HighPktStr is for codes 128-255
+    static const char *icmp6HighPktStr[] = {
+        "Echo Request",                 // 128 - RFC2463
+        "Echo Reply",                   // 129 - RFC2463
+        "Multicast Listener Query",         // 130 - RFC2710
+        "Multicast Listener Report",            // 131 - RFC2710
+        "Multicast Listener Done",          // 132 - RFC2710
+        "Router Solicitation",              // 133 - RFC4861
+        "Router Advertisement",             // 134 - RFC4861
+        "Neighbor Solicitation",            // 135 - RFC4861
+        "Neighbor Advertisement",           // 136 - RFC4861
+        "Redirect Message",             // 137 - RFC4861
+        "Router Renumbering",               // 138 - Crawford
+        "ICMP Node Information Query",          // 139 - RFC4620
+        "ICMP Node Information Response",       // 140 - RFC4620
+        "Inverse Neighbor Discovery Solicitation",  // 141 - RFC3122
+        "Inverse Neighbor Discovery Advertisement", // 142 - RFC3122
+        "Version 2 Multicast Listener Report",      // 143 - RFC3810
+        "Home Agent Address Discovery Request",     // 144 - RFC3775
+        "Home Agent Address Discovery Reply",       // 145 - RFC3775
+        "Mobile Prefix Solicitation",           // 146 - RFC3775
+        "Mobile Prefix Advertisement",          // 147 - RFC3775
+        "Certification Path Solicitation",      // 148 - RFC3971
+        "Certification Path Advertisement",     // 149 - RFC3971
+        "ICMP Experimental (150)",          // 150 - RFC4065
+        "Multicast Router Advertisement",       // 151 - RFC4286
+        "Multicast Router Solicitation",        // 152 - RFC4286
+        "Multicast Router Termination",         // 153 - [RFC4286]
+    };
+
+    // high codes 127-153 registered
+    if (127 < v && v < 154)
+        return icmp6HighPktStr[(int)(v&0x7f)];
+
+    // give all others a generic display
+    static char buf[50];
+    snprintf(buf, sizeof(buf), "ICMPv6 %u", v);
+    return buf;
+}
 
 Icmp6::Icmp6() : Icmp()
 {
@@ -118,7 +101,8 @@ Icmp6::Open(void)
     icmp_sock = socket(PF_INET6, SOCK_RAW, IPPROTO_ICMPV6);
 
     if (icmp_sock < 0) {
-        debugs(50, DBG_CRITICAL, HERE << " icmp_sock: " << xstrerror());
+        int xerrno = errno;
+        debugs(50, DBG_CRITICAL, MYNAME << " icmp_sock: " << xstrerr(xerrno));
         return -1;
     }
 
@@ -195,12 +179,13 @@ Icmp6::SendEcho(Ip::Address &to, int opcode, const char *payload, int len)
                S->ai_addrlen);
 
     if (x < 0) {
-        debugs(42, DBG_IMPORTANT, HERE << "Error sending to ICMPv6 packet to " << to << ". ERR: " << xstrerror());
+        int xerrno = errno;
+        debugs(42, DBG_IMPORTANT, MYNAME << "ERROR: sending to ICMPv6 packet to " << to << ": " << xstrerr(xerrno));
     }
     debugs(42,9, HERE << "x=" << x);
 
     Log(to, 0, NULL, 0, 0);
-    Ip::Address::FreeAddrInfo(S);
+    Ip::Address::FreeAddr(S);
 }
 
 /**
@@ -227,7 +212,7 @@ Icmp6::Recv(void)
         pkt = (char *)xmalloc(MAX_PKT6_SZ);
     }
 
-    Ip::Address::InitAddrInfo(from);
+    Ip::Address::InitAddr(from);
 
     n = recvfrom(icmp_sock,
                  (void *)pkt,
@@ -236,6 +221,12 @@ Icmp6::Recv(void)
                  from->ai_addr,
                  &from->ai_addrlen);
 
+    if (n <= 0) {
+        debugs(42, DBG_CRITICAL, HERE << "Error when calling recvfrom() on ICMPv6 socket.");
+        Ip::Address::FreeAddr(from);
+        return;
+    }
+
     preply.from = *from;
 
 #if GETTIMEOFDAY_NO_TZP
@@ -253,32 +244,31 @@ Icmp6::Recv(void)
 // FIXME INET6 : The IPv6 Header (ip6_hdr) is not availble directly >:-(
 //
 // TTL still has to come from the IP header somewhere.
-//     still need to strip and process it properly.
-//     probably have to rely on RTT as given by timestamp in data sent and current.
+//  still need to strip and process it properly.
+//  probably have to rely on RTT as given by timestamp in data sent and current.
     /* IPv6 Header Structures (linux)
     struct ip6_hdr
 
     // fields (via simple define)
-    #define ip6_vfc            // N.A
-    #define ip6_flow   // N/A
-    #define ip6_plen   // payload length.
-    #define ip6_nxt            // expect to be type 0x3a - ICMPv6
-    #define ip6_hlim   // MAX hops  (always 64, but no guarantee)
-    #define ip6_hops   // HOPS!!!  (can it be true??)
+    #define ip6_vfc     // N.A
+    #define ip6_flow    // N/A
+    #define ip6_plen    // payload length.
+    #define ip6_nxt     // expect to be type 0x3a - ICMPv6
+    #define ip6_hlim    // MAX hops  (always 64, but no guarantee)
+    #define ip6_hops    // HOPS!!!  (can it be true??)
 
         ip = (struct ip6_hdr *) pkt;
-        pkt += sizeof(ip6_hdr);
+        FIXME  += sizeof(ip6_hdr);
 
     debugs(42, DBG_CRITICAL, HERE << "ip6_nxt=" << ip->ip6_nxt <<
-               ", ip6_plen=" << ip->ip6_plen <<
-               ", ip6_hlim=" << ip->ip6_hlim <<
-               ", ip6_hops=" << ip->ip6_hops   <<
-               " ::: 40 == sizef(ip6_hdr) == " << sizeof(ip6_hdr)
+            ", ip6_plen=" << ip->ip6_plen <<
+            ", ip6_hlim=" << ip->ip6_hlim <<
+            ", ip6_hops=" << ip->ip6_hops   <<
+            " ::: 40 == sizef(ip6_hdr) == " << sizeof(ip6_hdr)
     );
     */
 
     icmp6header = (struct icmp6_hdr *) pkt;
-    pkt += sizeof(icmp6_hdr);
 
     if (icmp6header->icmp6_type != ICMP6_ECHO_REPLY) {
 
@@ -291,20 +281,19 @@ Icmp6::Recv(void)
 
         default:
             debugs(42, 8, HERE << preply.from << " said: " << icmp6header->icmp6_type << "/" << (int)icmp6header->icmp6_code << " " <<
-                   ( icmp6header->icmp6_type&0x80 ? icmp6HighPktStr[(int)(icmp6header->icmp6_type&0x7f)] : icmp6LowPktStr[(int)(icmp6header->icmp6_type&0x7f)] )
-                  );
+                   IcmpPacketType(icmp6header->icmp6_type));
         }
-        Ip::Address::FreeAddrInfo(from);
+        Ip::Address::FreeAddr(from);
         return;
     }
 
     if (icmp6header->icmp6_id != icmp_ident) {
         debugs(42, 8, HERE << "dropping Icmp6 read. IDENT check failed. ident=='" << icmp_ident << "'=='" << icmp6header->icmp6_id << "'");
-        Ip::Address::FreeAddrInfo(from);
+        Ip::Address::FreeAddr(from);
         return;
     }
 
-    echo = (icmpEchoData *) pkt;
+    echo = (icmpEchoData *) (pkt + sizeof(icmp6_hdr));
 
     preply.opcode = echo->opcode;
 
@@ -315,7 +304,7 @@ Icmp6::Recv(void)
     /*
      * FIXME INET6: Without access to the IPv6-Hops header we must rely on the total RTT
      *      and could caculate the hops from that, but it produces some weird value mappings using ipHops
-     * for now everything is 1 v6 hop away with variant RTT
+     *  for now everything is 1 v6 hop away with variant RTT
      * WANT:    preply.hops = ip->ip6_hops; // ipHops(ip->ip_hops);
      */
     preply.hops = 1;
@@ -331,13 +320,14 @@ Icmp6::Recv(void)
 
     Log(preply.from,
         icmp6header->icmp6_type,
-        ( icmp6header->icmp6_type&0x80 ? icmp6HighPktStr[(int)(icmp6header->icmp6_type&0x7f)] : icmp6LowPktStr[(int)(icmp6header->icmp6_type&0x7f)] ),
+        IcmpPacketType(icmp6header->icmp6_type),
         preply.rtt,
         preply.hops);
 
     /* send results of the lookup back to squid.*/
     control.SendResult(preply, (sizeof(pingerReplyData) - PINGER_PAYLOAD_SZ + preply.psize) );
-    Ip::Address::FreeAddrInfo(from);
+    Ip::Address::FreeAddr(from);
 }
 
 #endif /* USE_ICMP */
+