]> git.ipfire.org Git - thirdparty/squid.git/blame - src/icmp/Icmp4.cc
Boilerplate: update copyright blurbs on src/
[thirdparty/squid.git] / src / icmp / Icmp4.cc
CommitLineData
cc192b50 1/*
bbc27441 2 * Copyright (C) 1996-2014 The Squid Software Foundation and contributors
cc192b50 3 *
bbc27441
AJ
4 * Squid software is distributed under GPLv2+ license and includes
5 * contributions from numerous individuals and organizations.
6 * Please see the COPYING and CONTRIBUTORS files for details.
cc192b50 7 */
bbc27441
AJ
8
9/* DEBUG: section 42 ICMP Pinger program */
10
cc192b50 11//#define SQUID_HELPER 1
12
582c2af2 13#include "squid.h"
cc192b50 14
15#if USE_ICMP
16
602d9612 17#include "Debug.h"
b826ffb5
AJ
18#include "Icmp4.h"
19#include "IcmpPinger.h"
602d9612
A
20#include "leakcheck.h"
21#include "SquidTime.h"
cc192b50 22
26ac0430
AJ
23const char *icmpPktStr[] = {
24 "Echo Reply",
25 "ICMP 1",
26 "ICMP 2",
27 "Destination Unreachable",
28 "Source Quench",
29 "Redirect",
30 "ICMP 6",
31 "ICMP 7",
32 "Echo",
33 "ICMP 9",
34 "ICMP 10",
35 "Time Exceeded",
36 "Parameter Problem",
37 "Timestamp",
38 "Timestamp Reply",
39 "Info Request",
40 "Info Reply",
41 "Out of Range Type"
42};
cc192b50 43
b826ffb5 44Icmp4::Icmp4() : Icmp()
26ac0430
AJ
45{
46 ;
cc192b50 47}
48
b826ffb5 49Icmp4::~Icmp4()
cc192b50 50{
51 Close();
52}
53
54int
b826ffb5 55Icmp4::Open(void)
cc192b50 56{
57 icmp_sock = socket(PF_INET, SOCK_RAW, IPPROTO_ICMP);
58
59 if (icmp_sock < 0) {
fa84c01d 60 debugs(50, DBG_CRITICAL, HERE << " icmp_sock: " << xstrerror());
cc192b50 61 return -1;
62 }
63
64 icmp_ident = getpid() & 0xffff;
e0236918 65 debugs(42, DBG_IMPORTANT, "pinger: ICMP socket opened.");
cc192b50 66
67 return icmp_sock;
68}
69
70void
b7ac5457 71Icmp4::SendEcho(Ip::Address &to, int opcode, const char *payload, int len)
cc192b50 72{
73 int x;
74 LOCAL_ARRAY(char, pkt, MAX_PKT4_SZ);
75
76 struct icmphdr *icmp = NULL;
77 icmpEchoData *echo;
78 size_t icmp_pktsize = sizeof(struct icmphdr);
79 struct addrinfo *S = NULL;
80
81 memset(pkt, '\0', MAX_PKT4_SZ);
82
83 icmp = (struct icmphdr *) (void *) pkt;
84
85 /*
86 * cevans - beware signed/unsigned issues in untrusted data from
87 * the network!!
88 */
26ac0430 89 if (len < 0) {
cc192b50 90 len = 0;
91 }
92
93 // Construct ICMP packet header
94 icmp->icmp_type = ICMP_ECHO;
95 icmp->icmp_code = 0;
96 icmp->icmp_cksum = 0;
97 icmp->icmp_id = icmp_ident;
aec55359
FC
98 icmp->icmp_seq = (unsigned short) icmp_pkts_sent;
99 ++icmp_pkts_sent;
cc192b50 100
101 // Construct ICMP packet data content
102 echo = (icmpEchoData *) (icmp + 1);
103 echo->opcode = (unsigned char) opcode;
c3c6695b 104 memcpy(&echo->tv, &current_time, sizeof(struct timeval));
cc192b50 105
106 icmp_pktsize += sizeof(struct timeval) + sizeof(char);
107
26ac0430 108 if (payload) {
cc192b50 109 if (len > MAX_PAYLOAD)
110 len = MAX_PAYLOAD;
111
41d00cd3 112 memcpy(echo->payload, payload, len);
cc192b50 113
114 icmp_pktsize += len;
115 }
116
f45dd259 117 icmp->icmp_cksum = CheckSum((unsigned short *) icmp, icmp_pktsize);
cc192b50 118
4dd643d5 119 to.getAddrInfo(S);
cc192b50 120 ((sockaddr_in*)S->ai_addr)->sin_port = 0;
121 assert(icmp_pktsize <= MAX_PKT4_SZ);
122
30c48b1a 123 debugs(42, 5, HERE << "Send ICMP packet to " << to << ".");
cc192b50 124
125 x = sendto(icmp_sock,
26ac0430
AJ
126 (const void *) pkt,
127 icmp_pktsize,
128 0,
129 S->ai_addr,
130 S->ai_addrlen);
cc192b50 131
26ac0430 132 if (x < 0) {
e0236918 133 debugs(42, DBG_IMPORTANT, HERE << "Error sending to ICMP packet to " << to << ". ERR: " << xstrerror());
cc192b50 134 }
135
136 Log(to, ' ', NULL, 0, 0);
4dd643d5 137 Ip::Address::FreeAddrInfo(S);
cc192b50 138}
139
140void
b826ffb5 141Icmp4::Recv(void)
cc192b50 142{
143 int n;
144 struct addrinfo *from = NULL;
145 int iphdrlen = sizeof(iphdr);
146 struct iphdr *ip = NULL;
147 struct icmphdr *icmp = NULL;
148 static char *pkt = NULL;
149 struct timeval now;
150 icmpEchoData *echo;
151 static pingerReplyData preply;
152
26ac0430 153 if (icmp_sock < 0) {
fa84c01d 154 debugs(42, DBG_CRITICAL, HERE << "No socket! Recv() should not be called.");
cc192b50 155 return;
156 }
157
158 if (pkt == NULL)
159 pkt = (char *)xmalloc(MAX_PKT4_SZ);
160
4dd643d5 161 Ip::Address::InitAddrInfo(from);
cc192b50 162 n = recvfrom(icmp_sock,
163 (void *)pkt,
164 MAX_PKT4_SZ,
165 0,
166 from->ai_addr,
167 &from->ai_addrlen);
168
169 preply.from = *from;
170
171#if GETTIMEOFDAY_NO_TZP
172
173 gettimeofday(&now);
174
175#else
176
177 gettimeofday(&now, NULL);
178
179#endif
180
181 debugs(42, 8, HERE << n << " bytes from " << preply.from);
182
183 ip = (struct iphdr *) (void *) pkt;
184
185#if HAVE_STRUCT_IPHDR_IP_HL
186
187 iphdrlen = ip->ip_hl << 2;
188
189#else /* HAVE_STRUCT_IPHDR_IP_HL */
190#if WORDS_BIGENDIAN
191
192 iphdrlen = (ip->ip_vhl >> 4) << 2;
193
194#else
195
196 iphdrlen = (ip->ip_vhl & 0xF) << 2;
197
198#endif
199#endif /* HAVE_STRUCT_IPHDR_IP_HL */
200
201 icmp = (struct icmphdr *) (void *) (pkt + iphdrlen);
202
f1402d4e 203 if (icmp->icmp_type != ICMP_ECHOREPLY) {
4dd643d5 204 Ip::Address::FreeAddrInfo(from);
cc192b50 205 return;
f1402d4e 206 }
cc192b50 207
f1402d4e 208 if (icmp->icmp_id != icmp_ident) {
4dd643d5 209 Ip::Address::FreeAddrInfo(from);
cc192b50 210 return;
f1402d4e 211 }
cc192b50 212
213 echo = (icmpEchoData *) (void *) (icmp + 1);
214
215 preply.opcode = echo->opcode;
216
217 preply.hops = ipHops(ip->ip_ttl);
218
c3c6695b 219 struct timeval tv;
220 memcpy(&tv, &echo->tv, sizeof(struct timeval));
221 preply.rtt = tvSubMsec(tv, now);
cc192b50 222
223 preply.psize = n - iphdrlen - (sizeof(icmpEchoData) - MAX_PKT4_SZ);
224
225 control.SendResult(preply, (sizeof(pingerReplyData) - MAX_PKT4_SZ + preply.psize) );
226
227 Log(preply.from, icmp->icmp_type, icmpPktStr[icmp->icmp_type], preply.rtt, preply.hops);
4dd643d5 228 Ip::Address::FreeAddrInfo(from);
cc192b50 229}
230
231#endif /* USE_ICMP */