]>
git.ipfire.org Git - thirdparty/squid.git/blob - src/icmp/Icmp6.cc
4 * DEBUG: section 42 ICMP Pinger program
5 * AUTHOR: Duane Wessels, Amos Jeffries
7 * SQUID Web Proxy Cache http://www.squid-cache.org/
8 * ----------------------------------------------------------
10 * Squid is the result of efforts by numerous individuals from
11 * the Internet community; see the CONTRIBUTORS file for full
12 * details. Many organizations have provided support for Squid's
13 * development; see the SPONSORS file for full details. Squid is
14 * Copyrighted (C) 2001 by the Regents of the University of
15 * California; see the COPYRIGHT file for full details. Squid
16 * incorporates software developed and/or copyrighted by other
17 * sources; see the CREDITS file for full details.
19 * This program is free software; you can redistribute it and/or modify
20 * it under the terms of the GNU General Public License as published by
21 * the Free Software Foundation; either version 2 of the License, or
22 * (at your option) any later version.
24 * This program is distributed in the hope that it will be useful,
25 * but WITHOUT ANY WARRANTY; without even the implied warranty of
26 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
27 * GNU General Public License for more details.
29 * You should have received a copy of the GNU General Public License
30 * along with this program; if not, write to the Free Software
31 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111, USA.
34 //#define SQUID_HELPER 1
38 #if USE_ICMP && USE_IPV6
40 #include "SquidTime.h"
43 #include "IcmpPinger.h"
45 // Some system headers are only neeed internally here.
46 // They should not be included via the header.
48 #if HAVE_NETINET_IP6_H
49 #include <netinet/ip6.h>
53 // see http://www.iana.org/assignments/icmpv6-parameters
54 // NP: LowPktStr is for codes 0-127
55 static const char *icmp6LowPktStr
[] = {
57 "Destination Unreachable", // 1 - RFC2463
58 "Packet Too Big", // 2 - RFC2463
59 "Time Exceeded", // 3 - RFC2463
60 "Parameter Problem", // 4 - RFC2463
69 // NP: HighPktStr is for codes 128-255
70 static const char *icmp6HighPktStr
[] = {
71 "Echo Request", // 128 - RFC2463
72 "Echo Reply", // 129 - RFC2463
73 "Multicast Listener Query", // 130 - RFC2710
74 "Multicast Listener Report", // 131 - RFC2710
75 "Multicast Listener Done", // 132 - RFC2710
76 "Router Solicitation", // 133 - RFC4861
77 "Router Advertisement", // 134 - RFC4861
78 "Neighbor Solicitation", // 135 - RFC4861
79 "Neighbor Advertisement", // 136 - RFC4861
80 "Redirect Message", // 137 - RFC4861
81 "Router Renumbering", // 138 - Crawford
82 "ICMP Node Information Query", // 139 - RFC4620
83 "ICMP Node Information Response", // 140 - RFC4620
84 "Inverse Neighbor Discovery Solicitation", // 141 - RFC3122
85 "Inverse Neighbor Discovery Advertisement", // 142 - RFC3122
86 "Version 2 Multicast Listener Report", // 143 - RFC3810
87 "Home Agent Address Discovery Request", // 144 - RFC3775
88 "Home Agent Address Discovery Reply", // 145 - RFC3775
89 "Mobile Prefix Solicitation", // 146 - RFC3775
90 "Mobile Prefix Advertisement", // 147 - RFC3775
91 "Certification Path Solicitation", // 148 - RFC3971
92 "Certification Path Advertisement", // 149 - RFC3971
93 "ICMP Experimental (150)", // 150 - RFC4065
94 "Multicast Router Advertisement", // 151 - RFC4286
95 "Multicast Router Solicitation", // 152 - RFC4286
96 "Multicast Router Termination", // 153 - [RFC4286]
106 Icmp6::Icmp6() : Icmp()
119 icmp_sock
= socket(PF_INET6
, SOCK_RAW
, IPPROTO_ICMPV6
);
122 debugs(50, 0, HERE
<< " icmp_sock: " << xstrerror());
126 icmp_ident
= getpid() & 0xffff;
127 debugs(42, 1, "pinger: ICMPv6 socket opened");
133 * Generates an RFC 4443 Icmp6 ECHO Packet and sends into the network.
136 Icmp6::SendEcho(IpAddress
&to
, int opcode
, const char *payload
, int len
)
139 LOCAL_ARRAY(char, pkt
, MAX_PKT6_SZ
);
140 struct icmp6_hdr
*icmp
= NULL
;
141 icmpEchoData
*echo
= NULL
;
142 struct addrinfo
*S
= NULL
;
143 size_t icmp6_pktsize
= 0;
145 memset(pkt
, '\0', MAX_PKT6_SZ
);
146 icmp
= (struct icmp6_hdr
*)pkt
;
149 * cevans - beware signed/unsigned issues in untrusted data from
156 // Construct Icmp6 ECHO header
157 icmp
->icmp6_type
= ICMP6_ECHO_REQUEST
;
158 icmp
->icmp6_code
= 0;
159 icmp
->icmp6_cksum
= 0;
160 icmp
->icmp6_id
= icmp_ident
;
161 icmp
->icmp6_seq
= (u_short
) icmp_pkts_sent
++;
163 icmp6_pktsize
= sizeof(struct icmp6_hdr
);
166 // Fill Icmp6 ECHO data content
167 echo
= (icmpEchoData
*) (pkt
+ sizeof(icmp6_hdr
));
168 echo
->opcode
= (unsigned char) opcode
;
169 memcpy(&echo
->tv
, ¤t_time
, sizeof(struct timeval
));
171 icmp6_pktsize
+= sizeof(struct timeval
) + sizeof(char);
174 if (len
> MAX_PAYLOAD
)
177 xmemcpy(echo
->payload
, payload
, len
);
179 icmp6_pktsize
+= len
;
182 icmp
->icmp6_cksum
= CheckSum((u_short
*) icmp
, icmp6_pktsize
);
185 ((sockaddr_in6
*)S
->ai_addr
)->sin6_port
= 0;
187 assert(icmp6_pktsize
<= MAX_PKT6_SZ
);
189 debugs(42, 5, HERE
<< "Send Icmp6 packet to " << to
<< ".");
191 x
= sendto(icmp_sock
,
199 debugs(42, 1, HERE
<< "Error sending to ICMPv6 packet to " << to
<< ". ERR: " << xstrerror());
201 debugs(42,9, HERE
<< "x=" << x
);
203 Log(to
, 0, NULL
, 0, 0);
207 * Reads an RFC 4443 Icmp6 ECHO-REPLY Packet from the network.
213 struct addrinfo
*from
= NULL
;
214 // struct ip6_hdr *ip = NULL;
215 static char *pkt
= NULL
;
216 struct icmp6_hdr
*icmp6
= NULL
;
217 icmpEchoData
*echo
= NULL
;
219 static pingerReplyData preply
;
222 debugs(42,0, HERE
<< "dropping ICMPv6 read. No socket!?");
227 pkt
= (char *)xmalloc(MAX_PKT6_SZ
);
230 preply
.from
.InitAddrInfo(from
);
232 n
= recvfrom(icmp_sock
,
241 #if GETTIMEOFDAY_NO_TZP
247 gettimeofday(&now
, NULL
);
251 debugs(42, 8, HERE
<< n
<< " bytes from " << preply
.from
);
253 // FIXME INET6 : The IPv6 Header (ip6_hdr) is not availble directly >:-(
255 // TTL still has to come from the IP header somewhere.
256 // still need to strip and process it properly.
257 // probably have to rely on RTT as given by timestamp in data sent and current.
258 /* IPv6 Header Structures (linux)
261 // fields (via simple define)
262 #define ip6_vfc // N.A
263 #define ip6_flow // N/A
264 #define ip6_plen // payload length.
265 #define ip6_nxt // expect to be type 0x3a - ICMPv6
266 #define ip6_hlim // MAX hops (always 64, but no guarantee)
267 #define ip6_hops // HOPS!!! (can it be true??)
270 ip = (struct ip6_hdr *) pkt;
271 pkt += sizeof(ip6_hdr);
273 debugs(42,0, HERE << "ip6_nxt=" << ip->ip6_nxt <<
274 ", ip6_plen=" << ip->ip6_plen <<
275 ", ip6_hlim=" << ip->ip6_hlim <<
276 ", ip6_hops=" << ip->ip6_hops <<
277 " ::: 40 == sizef(ip6_hdr) == " << sizeof(ip6_hdr)
281 icmp6
= (struct icmp6_hdr
*) pkt
;
282 pkt
+= sizeof(icmp6_hdr
);
284 if (icmp6
->icmp6_type
!= ICMP6_ECHO_REPLY
) {
286 switch (icmp6
->icmp6_type
) {
290 /* ignore Router/Neighbour Advertisements */
294 debugs(42, 8, HERE
<< preply
.from
<< " said: " << icmp6
->icmp6_type
<< "/" << (int)icmp6
->icmp6_code
<< " " <<
295 ( icmp6
->icmp6_type
&0x80 ? icmp6HighPktStr
[(int)(icmp6
->icmp6_type
&0x7f)] : icmp6LowPktStr
[(int)(icmp6
->icmp6_type
&0x7f)] )
301 if (icmp6
->icmp6_id
!= icmp_ident
) {
302 debugs(42, 8, HERE
<< "dropping Icmp6 read. IDENT check failed. ident=='" << icmp_ident
<< "'=='" << icmp6
->icmp6_id
<< "'");
306 echo
= (icmpEchoData
*) pkt
;
308 preply
.opcode
= echo
->opcode
;
311 memcpy(&tv
, &echo
->tv
, sizeof(struct timeval
));
312 preply
.rtt
= tvSubMsec(tv
, now
);
315 * FIXME INET6: Without access to the IPv6-Hops header we must rely on the total RTT
316 * and could caculate the hops from that, but it produces some weird value mappings using ipHops
317 * for now everything is 1 v6 hop away with variant RTT
318 * WANT: preply.hops = ip->ip6_hops; // ipHops(ip->ip_hops);
322 preply
.psize
= n
- /* sizeof(ip6_hdr) - */ sizeof(icmp6_hdr
) - (sizeof(icmpEchoData
) - MAX_PKT6_SZ
);
324 /* Ensure the response packet has safe payload size */
325 if ( preply
.psize
> (unsigned short) MAX_PKT6_SZ
) {
326 preply
.psize
= MAX_PKT6_SZ
;
327 } else if ( preply
.psize
< (unsigned short)0) {
333 ( icmp6
->icmp6_type
&0x80 ? icmp6HighPktStr
[(int)(icmp6
->icmp6_type
&0x7f)] : icmp6LowPktStr
[(int)(icmp6
->icmp6_type
&0x7f)] ),
337 /* send results of the lookup back to squid.*/
338 control
.SendResult(preply
, (sizeof(pingerReplyData
) - PINGER_PAYLOAD_SZ
+ preply
.psize
) );
341 #endif /* USE_ICMP && USE_IPV6 */