]>
git.ipfire.org Git - thirdparty/squid.git/blob - src/pinger.cc
3 * $Id: pinger.cc,v 1.28 1997/10/31 05:15:08 wessels Exp $
5 * DEBUG: section 42 ICMP Pinger program
6 * AUTHOR: Duane Wessels
8 * SQUID Internet Object Cache http://squid.nlanr.net/Squid/
9 * --------------------------------------------------------
11 * Squid is the result of efforts by numerous individuals from the
12 * Internet community. Development is led by Duane Wessels of the
13 * National Laboratory for Applied Network Research and funded by
14 * the National Science Foundation.
16 * This program is free software; you can redistribute it and/or modify
17 * it under the terms of the GNU General Public License as published by
18 * the Free Software Foundation; either version 2 of the License, or
19 * (at your option) any later version.
21 * This program is distributed in the hope that it will be useful,
22 * but WITHOUT ANY WARRANTY; without even the implied warranty of
23 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
24 * GNU General Public License for more details.
26 * You should have received a copy of the GNU General Public License
27 * along with this program; if not, write to the Free Software
28 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
36 #include <netinet/in_systm.h>
37 #include <netinet/in.h>
38 #include <netinet/ip.h>
39 #include <netinet/ip_icmp.h>
47 #define icmp_type type
48 #define icmp_code code
49 #define icmp_cksum checksum
50 #define icmp_id un.echo.id
51 #define icmp_seq un.echo.sequence
52 #define icmp_gwaddr un.gateway
56 #define ip_len tot_len
58 #define ip_off frag_off
66 #define MAX_PKT_SZ 8192
67 #define MAX_PAYLOAD (MAX_PKT_SZ - sizeof(struct icmphdr) - sizeof (char) - sizeof(struct timeval) - 1)
72 char payload
[MAX_PAYLOAD
];
76 int icmp_pkts_sent
= 0;
78 static const char *icmpPktStr
[] =
83 "Destination Unreachable",
100 static int in_cksum(unsigned short *ptr
, int size
);
101 static void pingerRecv(void);
102 static void pingerLog(struct icmphdr
*, struct in_addr
, int, int);
103 static int ipHops(int ttl
);
104 static void pingerSendtoSquid(pingerReplyData
* preply
);
109 struct protoent
*proto
= NULL
;
110 if ((proto
= getprotobyname("icmp")) == 0) {
111 debug(42, 0) ("pingerOpen: unknown protocol: icmp\n");
114 icmp_sock
= socket(PF_INET
, SOCK_RAW
, proto
->p_proto
);
116 debug(50, 0) ("pingerOpen: icmp_sock: %s\n", xstrerror());
119 icmp_ident
= getpid() & 0xffff;
120 debug(42, 0) ("ICMP socket opened\n", icmp_sock
);
132 pingerSendEcho(struct in_addr to
, int opcode
, char *payload
, int len
)
134 LOCAL_ARRAY(char, pkt
, MAX_PKT_SZ
);
135 struct icmphdr
*icmp
= NULL
;
137 int icmp_pktsize
= sizeof(struct icmphdr
);
139 struct sockaddr_in S
;
140 memset(pkt
, '\0', MAX_PKT_SZ
);
141 icmp
= (struct icmphdr
*) (void *) pkt
;
142 icmp
->icmp_type
= ICMP_ECHO
;
144 icmp
->icmp_cksum
= 0;
145 icmp
->icmp_id
= icmp_ident
;
146 icmp
->icmp_seq
= icmp_pkts_sent
++;
147 echo
= (icmpEchoData
*) (icmp
+ 1);
148 echo
->opcode
= (unsigned char) opcode
;
149 echo
->tv
= current_time
;
150 icmp_pktsize
+= sizeof(icmpEchoData
) - MAX_PAYLOAD
;
152 if (len
> MAX_PAYLOAD
)
154 xmemcpy(echo
->payload
, payload
, len
);
157 icmp
->icmp_cksum
= in_cksum((u_short
*) icmp
, icmp_pktsize
);
158 S
.sin_family
= AF_INET
;
161 x
= sendto(icmp_sock
,
165 (struct sockaddr
*) &S
,
166 sizeof(struct sockaddr_in
));
167 pingerLog(icmp
, to
, 0, 0);
175 struct sockaddr_in from
;
177 struct iphdr
*ip
= NULL
;
178 struct icmphdr
*icmp
= NULL
;
179 LOCAL_ARRAY(char, pkt
, MAX_PKT_SZ
);
182 static pingerReplyData preply
;
184 fromlen
= sizeof(from
);
185 n
= recvfrom(icmp_sock
,
189 (struct sockaddr
*) &from
,
191 gettimeofday(&now
, NULL
);
192 debug(42, 9) ("pingerRecv: %d bytes from %s\n", n
, inet_ntoa(from
.sin_addr
));
193 ip
= (struct iphdr
*) (void *) pkt
;
195 iphdrlen
= ip
->ip_hl
<< 2;
196 #else /* HAVE_IP_HL */
198 iphdrlen
= (ip
->ip_vhl
>> 4) << 2;
200 iphdrlen
= (ip
->ip_vhl
& 0xF) << 2;
202 #endif /* HAVE_IP_HL */
203 icmp
= (struct icmphdr
*) (void *) (pkt
+ iphdrlen
);
204 if (icmp
->icmp_type
!= ICMP_ECHOREPLY
)
206 if (icmp
->icmp_id
!= icmp_ident
)
208 echo
= (icmpEchoData
*) (void *) (icmp
+ 1);
209 preply
.from
= from
.sin_addr
;
210 preply
.opcode
= echo
->opcode
;
211 preply
.hops
= ipHops(ip
->ip_ttl
);
212 preply
.rtt
= tvSubMsec(echo
->tv
, now
);
213 preply
.psize
= n
- iphdrlen
- (sizeof(icmpEchoData
) - MAX_PKT_SZ
);
214 pingerSendtoSquid(&preply
);
215 pingerLog(icmp
, from
.sin_addr
, preply
.rtt
, preply
.hops
);
220 in_cksum(unsigned short *ptr
, int size
)
223 unsigned short oddbyte
;
224 unsigned short answer
;
232 *((unsigned char *) &oddbyte
) = *(unsigned char *) ptr
;
235 sum
= (sum
>> 16) + (sum
& 0xffff);
242 pingerLog(struct icmphdr
*icmp
, struct in_addr addr
, int rtt
, int hops
)
244 debug(42, 2) ("pingerLog: %9d.%06d %-16s %d %-15.15s %dms %d hops\n",
245 (int) current_time
.tv_sec
,
246 (int) current_time
.tv_usec
,
248 (int) icmp
->icmp_type
,
249 icmpPktStr
[icmp
->icmp_type
],
260 return 63 - ttl
; /* 62 = (64+60)/2 */
262 return 65 - ttl
; /* 62 = (64+60)/2 */
271 pingerReadRequest(void)
273 static pingerEchoData pecho
;
276 memset(&pecho
, '\0', sizeof(pecho
));
277 n
= recv(0, (char *) &pecho
, sizeof(pecho
), 0);
280 guess_size
= n
- (sizeof(pingerEchoData
) - MAX_PKT_SZ
);
281 if (guess_size
!= pecho
.psize
)
282 fprintf(stderr
, "size mismatch, guess=%d psize=%d\n",
283 guess_size
, pecho
.psize
);
284 pingerSendEcho(pecho
.to
,
292 pingerSendtoSquid(pingerReplyData
* preply
)
294 int len
= sizeof(pingerReplyData
) - MAX_PKT_SZ
+ preply
->psize
;
295 if (send(1, (char *) preply
, len
, 0) < 0) {
296 debug(50, 0) ("pinger: send: %s\n", xstrerror());
304 #if GETTIMEOFDAY_NO_TZP
305 gettimeofday(¤t_time
);
307 gettimeofday(¤t_time
, NULL
);
309 return squid_curtime
= current_time
.tv_sec
;
314 main(int argc
, char *argv
[])
319 const char *debug_args
= "ALL,1";
321 time_t last_check_time
= 0;
323 if ((t
= getenv("SQUID_DEBUG")))
324 debug_args
= xstrdup(t
);
326 _db_init(NULL
, debug_args
);
334 FD_SET(icmp_sock
, &R
);
335 x
= select(icmp_sock
+ 1, &R
, NULL
, NULL
, &tv
);
340 if (pingerReadRequest() < 0) {
341 debug(42, 0) ("Pinger exiting.\n");
344 if (FD_ISSET(icmp_sock
, &R
))
346 if (10 + last_check_time
< squid_curtime
) {
347 if (send(1, (char *) &tv
, 0, 0) < 0)
349 last_check_time
= squid_curtime
;
358 main(int argc
, char *argv
[])
360 fprintf(stderr
, "%s: ICMP support not compiled in.\n", argv
[0]);
363 #endif /* USE_ICMP */