summaryrefslogtreecommitdiff
path: root/networking/traceroute.c
diff options
context:
space:
mode:
authorEric Andersen <andersen@codepoet.org>2001-07-12 20:26:32 +0000
committerEric Andersen <andersen@codepoet.org>2001-07-12 20:26:32 +0000
commit7467c8d3b6a50e2cbd8db750963d40b420ad38d1 (patch)
tree10dcece1e0bb88e35aa95c3a68896ad426e43f7a /networking/traceroute.c
parentf69bfc76fa7acb0c87fa3f3b319fde361a8315a8 (diff)
downloadbusybox-w32-7467c8d3b6a50e2cbd8db750963d40b420ad38d1.tar.gz
busybox-w32-7467c8d3b6a50e2cbd8db750963d40b420ad38d1.tar.bz2
busybox-w32-7467c8d3b6a50e2cbd8db750963d40b420ad38d1.zip
Patch from vodz:
Changed email address cmdedit API change optimizations for traceroute and md5sum added a new shared create_icmp_socket() function
Diffstat (limited to 'networking/traceroute.c')
-rw-r--r--networking/traceroute.c511
1 files changed, 242 insertions, 269 deletions
diff --git a/networking/traceroute.c b/networking/traceroute.c
index a02be8a9e..106cf043b 100644
--- a/networking/traceroute.c
+++ b/networking/traceroute.c
@@ -5,6 +5,7 @@
5 * This code is derived from software contributed to Berkeley by 5 * This code is derived from software contributed to Berkeley by
6 * Van Jacobson. 6 * Van Jacobson.
7 * 7 *
8 * Special for busybox ported by Vladimir Oleynik <dzo@simtreas.ru> 2001
8 * Redistribution and use in source and binary forms, with or without 9 * Redistribution and use in source and binary forms, with or without
9 * modification, are permitted provided that the following conditions 10 * modification, are permitted provided that the following conditions
10 * are met: 11 * are met:
@@ -61,6 +62,10 @@
61 * Tue Dec 20 03:50:13 PST 1988 62 * Tue Dec 20 03:50:13 PST 1988
62 */ 63 */
63 64
65#undef BB_FEATURE_TRACEROUTE_VERBOSE
66//#define BB_FEATURE_TRACEROUTE_VERBOSE
67#undef BB_FEATURE_TRACEROUTE_SO_DEBUG /* not in documentation man */
68
64#include <stdio.h> 69#include <stdio.h>
65#include <errno.h> 70#include <errno.h>
66#include <stdlib.h> 71#include <stdlib.h>
@@ -100,13 +105,6 @@ struct opacket {
100 105
101#include "busybox.h" 106#include "busybox.h"
102 107
103static int wait_for_reply (int, struct sockaddr_in *, int);
104static void send_probe (int, int);
105static double deltaT (struct timeval *, struct timeval *);
106static int packet_ok (u_char *, int, struct sockaddr_in *, int);
107static void print (u_char *, int, struct sockaddr_in *);
108static char *inetname (struct in_addr);
109
110static u_char packet[512]; /* last inbound (icmp) packet */ 108static u_char packet[512]; /* last inbound (icmp) packet */
111static struct opacket *outpacket; /* last output (udp) packet */ 109static struct opacket *outpacket; /* last output (udp) packet */
112 110
@@ -122,10 +120,229 @@ static int max_ttl = 30;
122static u_short ident; 120static u_short ident;
123static u_short port = 32768+666; /* start udp dest port # for probe packets */ 121static u_short port = 32768+666; /* start udp dest port # for probe packets */
124 122
123#ifdef BB_FEATURE_TRACEROUTE_VERBOSE
125static int verbose; 124static int verbose;
125#endif
126static int waittime = 5; /* time to wait for response (in seconds) */ 126static int waittime = 5; /* time to wait for response (in seconds) */
127static int nflag; /* print addresses numerically */ 127static int nflag; /* print addresses numerically */
128 128
129/*
130 * Construct an Internet address representation.
131 * If the nflag has been supplied, give
132 * numeric value, otherwise try for symbolic name.
133 */
134static inline char *
135inetname(struct in_addr in)
136{
137 char *cp;
138 static char line[50];
139 struct hostent *hp;
140 static char domain[MAXHOSTNAMELEN + 1];
141 static int first = 1;
142
143 if (first && !nflag) {
144 first = 0;
145 if (gethostname(domain, MAXHOSTNAMELEN) == 0 &&
146 (cp = index(domain, '.')))
147 (void) strcpy(domain, cp + 1);
148 else
149 domain[0] = 0;
150 }
151 cp = 0;
152 if (!nflag && in.s_addr != INADDR_ANY) {
153 hp = gethostbyaddr((char *)&in, sizeof (in), AF_INET);
154 if (hp) {
155 if ((cp = index(hp->h_name, '.')) &&
156 !strcmp(cp + 1, domain))
157 *cp = 0;
158 cp = (char *)hp->h_name;
159 }
160 }
161 if (cp)
162 (void) strcpy(line, cp);
163 else {
164 in.s_addr = ntohl(in.s_addr);
165 strcpy(line, inet_ntoa(in));
166 }
167 return (line);
168}
169
170static inline void
171print(u_char *buf, int cc, struct sockaddr_in *from)
172{
173 struct ip *ip;
174 int hlen;
175
176 ip = (struct ip *) buf;
177 hlen = ip->ip_hl << 2;
178 cc -= hlen;
179
180 if (nflag)
181 printf(" %s", inet_ntoa(from->sin_addr));
182 else
183 printf(" %s (%s)", inetname(from->sin_addr),
184 inet_ntoa(from->sin_addr));
185
186#ifdef BB_FEATURE_TRACEROUTE_VERBOSE
187 if (verbose)
188 printf (" %d bytes to %s", cc, inet_ntoa (ip->ip_dst));
189#endif
190}
191
192static inline double
193deltaT(struct timeval *t1p, struct timeval *t2p)
194{
195 double dt;
196
197 dt = (double)(t2p->tv_sec - t1p->tv_sec) * 1000.0 +
198 (double)(t2p->tv_usec - t1p->tv_usec) / 1000.0;
199 return (dt);
200}
201
202static inline int
203wait_for_reply(int sock, struct sockaddr_in *from, int reset_timer)
204{
205 fd_set fds;
206 static struct timeval wait;
207 int cc = 0;
208 int fromlen = sizeof (*from);
209
210 FD_ZERO(&fds);
211 FD_SET(sock, &fds);
212 if (reset_timer) {
213 /*
214 * traceroute could hang if someone else has a ping
215 * running and our ICMP reply gets dropped but we don't
216 * realize it because we keep waking up to handle those
217 * other ICMP packets that keep coming in. To fix this,
218 * "reset_timer" will only be true if the last packet that
219 * came in was for us or if this is the first time we're
220 * waiting for a reply since sending out a probe. Note
221 * that this takes advantage of the select() feature on
222 * Linux where the remaining timeout is written to the
223 * struct timeval area.
224 */
225 wait.tv_sec = waittime;
226 wait.tv_usec = 0;
227 }
228
229 if (select(sock+1, &fds, (fd_set *)0, (fd_set *)0, &wait) > 0)
230 cc=recvfrom(s, (char *)packet, sizeof(packet), 0,
231 (struct sockaddr *)from, &fromlen);
232
233 return(cc);
234}
235
236#ifdef BB_FEATURE_TRACEROUTE_VERBOSE
237/*
238 * Convert an ICMP "type" field to a printable string.
239 */
240static inline const char *
241pr_type(t)
242 u_char t;
243{
244 static const char * const ttab[] = {
245 "Echo Reply", "ICMP 1", "ICMP 2", "Dest Unreachable",
246 "Source Quench", "Redirect", "ICMP 6", "ICMP 7",
247 "Echo", "ICMP 9", "ICMP 10", "Time Exceeded",
248 "Param Problem", "Timestamp", "Timestamp Reply", "Info Request",
249 "Info Reply"
250 };
251
252 if(t > 16)
253 return("OUT-OF-RANGE");
254
255 return(ttab[t]);
256}
257#endif
258
259static inline int
260packet_ok(u_char *buf, int cc, struct sockaddr_in *from, int seq)
261{
262 struct icmp *icp;
263 u_char type, code;
264 int hlen;
265 struct ip *ip;
266
267 ip = (struct ip *) buf;
268 hlen = ip->ip_hl << 2;
269 if (cc < hlen + ICMP_MINLEN) {
270#ifdef BB_FEATURE_TRACEROUTE_VERBOSE
271 if (verbose)
272 printf("packet too short (%d bytes) from %s\n", cc,
273 inet_ntoa(from->sin_addr));
274#endif
275 return (0);
276 }
277 cc -= hlen;
278 icp = (struct icmp *)(buf + hlen);
279 type = icp->icmp_type; code = icp->icmp_code;
280 if ((type == ICMP_TIMXCEED && code == ICMP_TIMXCEED_INTRANS) ||
281 type == ICMP_UNREACH) {
282 struct ip *hip;
283 struct udphdr *up;
284
285 hip = &icp->icmp_ip;
286 hlen = hip->ip_hl << 2;
287 up = (struct udphdr *)((u_char *)hip + hlen);
288 if (hlen + 12 <= cc && hip->ip_p == IPPROTO_UDP &&
289 up->source == htons(ident) &&
290 up->dest == htons(port+seq))
291 return (type == ICMP_TIMXCEED? -1 : code+1);
292 }
293#ifdef BB_FEATURE_TRACEROUTE_VERBOSE
294 if (verbose) {
295 int i;
296 u_long *lp = (u_long *)&icp->icmp_ip;
297
298 printf("\n%d bytes from %s to %s: icmp type %d (%s) code %d\n",
299 cc, inet_ntoa(from->sin_addr), inet_ntoa(ip->ip_dst),
300 type, pr_type(type), icp->icmp_code);
301 for (i = 4; i < cc ; i += sizeof(long))
302 printf("%2d: x%8.8lx\n", i, *lp++);
303 }
304#endif
305 return(0);
306}
307
308static void /* not inline */
309send_probe(int seq, int ttl)
310{
311 struct opacket *op = outpacket;
312 struct ip *ip = &op->ip;
313 struct udphdr *up = &op->udp;
314 int i;
315 struct timezone tz;
316
317 ip->ip_off = 0;
318 ip->ip_hl = sizeof(*ip) >> 2;
319 ip->ip_p = IPPROTO_UDP;
320 ip->ip_len = datalen;
321 ip->ip_ttl = ttl;
322 ip->ip_v = IPVERSION;
323 ip->ip_id = htons(ident+seq);
324
325 up->source = htons(ident);
326 up->dest = htons(port+seq);
327 up->len = htons((u_short)(datalen - sizeof(struct ip)));
328 up->check = 0;
329
330 op->seq = seq;
331 op->ttl = ttl;
332 (void) gettimeofday(&op->tv, &tz);
333
334 i = sendto(sndsock, (char *)outpacket, datalen, 0, &whereto,
335 sizeof(struct sockaddr));
336 if (i < 0 || i != datalen) {
337 if (i<0)
338 perror("sendto");
339 printf("traceroute: wrote %s %d chars, ret=%d\n", hostname,
340 datalen, i);
341 (void) fflush(stdout);
342 }
343}
344
345
129int 346int
130#ifndef BB_TRACEROUTE 347#ifndef BB_TRACEROUTE
131main(argc, argv) 348main(argc, argv)
@@ -138,7 +355,6 @@ traceroute_main(argc, argv)
138 extern char *optarg; 355 extern char *optarg;
139 extern int optind; 356 extern int optind;
140 struct hostent *hp; 357 struct hostent *hp;
141 struct protoent *pe;
142 struct sockaddr_in from, *to; 358 struct sockaddr_in from, *to;
143 int ch, i, on, probe, seq, tos, ttl; 359 int ch, i, on, probe, seq, tos, ttl;
144 360
@@ -152,7 +368,9 @@ traceroute_main(argc, argv)
152 while ((ch = getopt(argc, argv, "dm:np:q:rs:t:w:v")) != EOF) 368 while ((ch = getopt(argc, argv, "dm:np:q:rs:t:w:v")) != EOF)
153 switch(ch) { 369 switch(ch) {
154 case 'd': 370 case 'd':
371#ifdef BB_FEATURE_TRACEROUTE_SO_DEBUG
155 options |= SO_DEBUG; 372 options |= SO_DEBUG;
373#endif
156 break; 374 break;
157 case 'm': 375 case 'm':
158 max_ttl = atoi(optarg); 376 max_ttl = atoi(optarg);
@@ -188,7 +406,9 @@ traceroute_main(argc, argv)
188 error_msg_and_die("tos must be 0 to 255."); 406 error_msg_and_die("tos must be 0 to 255.");
189 break; 407 break;
190 case 'v': 408 case 'v':
409#ifdef BB_FEATURE_TRACEROUTE_VERBOSE
191 verbose++; 410 verbose++;
411#endif
192 break; 412 break;
193 case 'w': 413 case 'w':
194 waittime = atoi(optarg); 414 waittime = atoi(optarg);
@@ -206,21 +426,11 @@ traceroute_main(argc, argv)
206 426
207 setlinebuf (stdout); 427 setlinebuf (stdout);
208 428
209 (void) bzero((char *)&whereto, sizeof(struct sockaddr)); 429 memset(&whereto, 0, sizeof(struct sockaddr));
210 to->sin_family = AF_INET; 430 hp = xgethostbyname(*argv);
211 to->sin_addr.s_addr = inet_addr(*argv);
212 if (to->sin_addr.s_addr != -1)
213 hostname = *argv;
214 else {
215 hp = gethostbyname(*argv);
216 if (hp) {
217 to->sin_family = hp->h_addrtype; 431 to->sin_family = hp->h_addrtype;
218 bcopy(hp->h_addr, (caddr_t)&to->sin_addr, hp->h_length); 432 memcpy(&to->sin_addr, hp->h_addr, hp->h_length);
219 hostname = (char *)hp->h_name; 433 hostname = (char *)hp->h_name;
220 } else {
221 error_msg_and_die("unknown host %s", *argv);
222 }
223 }
224 if (*++argv) 434 if (*++argv)
225 datalen = atoi(*argv); 435 datalen = atoi(*argv);
226 if (datalen < 0 || datalen >= MAXPACKET - sizeof(struct opacket)) 436 if (datalen < 0 || datalen >= MAXPACKET - sizeof(struct opacket))
@@ -228,7 +438,7 @@ traceroute_main(argc, argv)
228 MAXPACKET - sizeof(struct opacket)); 438 MAXPACKET - sizeof(struct opacket));
229 datalen += sizeof(struct opacket); 439 datalen += sizeof(struct opacket);
230 outpacket = (struct opacket *)xmalloc((unsigned)datalen); 440 outpacket = (struct opacket *)xmalloc((unsigned)datalen);
231 (void) bzero((char *)outpacket, datalen); 441 memset(outpacket, 0, datalen);
232 outpacket->ip.ip_dst = to->sin_addr; 442 outpacket->ip.ip_dst = to->sin_addr;
233 outpacket->ip.ip_tos = tos; 443 outpacket->ip.ip_tos = tos;
234 outpacket->ip.ip_v = IPVERSION; 444 outpacket->ip.ip_v = IPVERSION;
@@ -236,19 +446,19 @@ traceroute_main(argc, argv)
236 446
237 ident = (getpid() & 0xffff) | 0x8000; 447 ident = (getpid() & 0xffff) | 0x8000;
238 448
239 if ((pe = getprotobyname("icmp")) == NULL) 449 if ((sndsock = socket(AF_INET, SOCK_RAW, IPPROTO_RAW)) < 0)
240 error_msg_and_die("icmp: unknown protocol"); 450 perror_msg_and_die(can_not_create_raw_socket);
241 if ((s = socket(AF_INET, SOCK_RAW, pe->p_proto)) < 0) 451
242 perror_msg_and_die("icmp socket"); 452 s = create_icmp_socket();
453
454#ifdef BB_FEATURE_TRACEROUTE_SO_DEBUG
243 if (options & SO_DEBUG) 455 if (options & SO_DEBUG)
244 (void) setsockopt(s, SOL_SOCKET, SO_DEBUG, 456 (void) setsockopt(s, SOL_SOCKET, SO_DEBUG,
245 (char *)&on, sizeof(on)); 457 (char *)&on, sizeof(on));
458#endif
246 if (options & SO_DONTROUTE) 459 if (options & SO_DONTROUTE)
247 (void) setsockopt(s, SOL_SOCKET, SO_DONTROUTE, 460 (void) setsockopt(s, SOL_SOCKET, SO_DONTROUTE,
248 (char *)&on, sizeof(on)); 461 (char *)&on, sizeof(on));
249
250 if ((sndsock = socket(AF_INET, SOCK_RAW, IPPROTO_RAW)) < 0)
251 perror_msg_and_die("raw socket");
252#ifdef SO_SNDBUF 462#ifdef SO_SNDBUF
253 if (setsockopt(sndsock, SOL_SOCKET, SO_SNDBUF, (char *)&datalen, 463 if (setsockopt(sndsock, SOL_SOCKET, SO_SNDBUF, (char *)&datalen,
254 sizeof(datalen)) < 0) 464 sizeof(datalen)) < 0)
@@ -259,15 +469,17 @@ traceroute_main(argc, argv)
259 sizeof(on)) < 0) 469 sizeof(on)) < 0)
260 perror_msg_and_die("IP_HDRINCL"); 470 perror_msg_and_die("IP_HDRINCL");
261#endif IP_HDRINCL 471#endif IP_HDRINCL
472#ifdef BB_FEATURE_TRACEROUTE_SO_DEBUG
262 if (options & SO_DEBUG) 473 if (options & SO_DEBUG)
263 (void) setsockopt(sndsock, SOL_SOCKET, SO_DEBUG, 474 (void) setsockopt(sndsock, SOL_SOCKET, SO_DEBUG,
264 (char *)&on, sizeof(on)); 475 (char *)&on, sizeof(on));
476#endif
265 if (options & SO_DONTROUTE) 477 if (options & SO_DONTROUTE)
266 (void) setsockopt(sndsock, SOL_SOCKET, SO_DONTROUTE, 478 (void) setsockopt(sndsock, SOL_SOCKET, SO_DONTROUTE,
267 (char *)&on, sizeof(on)); 479 (char *)&on, sizeof(on));
268 480
269 if (source) { 481 if (source) {
270 (void) bzero((char *)&from, sizeof(struct sockaddr)); 482 memset(&from, 0, sizeof(struct sockaddr));
271 from.sin_family = AF_INET; 483 from.sin_family = AF_INET;
272 from.sin_addr.s_addr = inet_addr(source); 484 from.sin_addr.s_addr = inet_addr(source);
273 if (from.sin_addr.s_addr == -1) 485 if (from.sin_addr.s_addr == -1)
@@ -284,7 +496,6 @@ traceroute_main(argc, argv)
284 if (source) 496 if (source)
285 fprintf(stderr, " from %s", source); 497 fprintf(stderr, " from %s", source);
286 fprintf(stderr, ", %d hops max, %d byte packets\n", max_ttl, datalen); 498 fprintf(stderr, ", %d hops max, %d byte packets\n", max_ttl, datalen);
287 (void) fflush(stderr);
288 499
289 for (ttl = 1; ttl <= max_ttl; ++ttl) { 500 for (ttl = 1; ttl <= max_ttl; ++ttl) {
290 u_long lastaddr = 0; 501 u_long lastaddr = 0;
@@ -312,11 +523,9 @@ traceroute_main(argc, argv)
312 printf(" %g ms", deltaT(&t1, &t2)); 523 printf(" %g ms", deltaT(&t1, &t2));
313 switch(i - 1) { 524 switch(i - 1) {
314 case ICMP_UNREACH_PORT: 525 case ICMP_UNREACH_PORT:
315#ifndef ARCHAIC
316 ip = (struct ip *)packet; 526 ip = (struct ip *)packet;
317 if (ip->ip_ttl <= 1) 527 if (ip->ip_ttl <= 1)
318 printf(" !"); 528 printf(" !");
319#endif ARCHAIC
320 ++got_there; 529 ++got_there;
321 break; 530 break;
322 case ICMP_UNREACH_NET: 531 case ICMP_UNREACH_NET:
@@ -355,239 +564,3 @@ traceroute_main(argc, argv)
355 564
356 return 0; 565 return 0;
357} 566}
358
359static int
360wait_for_reply(sock, from, reset_timer)
361 int sock;
362 struct sockaddr_in *from;
363 int reset_timer;
364{
365 fd_set fds;
366 static struct timeval wait;
367 int cc = 0;
368 int fromlen = sizeof (*from);
369
370 FD_ZERO(&fds);
371 FD_SET(sock, &fds);
372 if (reset_timer) {
373 /*
374 * traceroute could hang if someone else has a ping
375 * running and our ICMP reply gets dropped but we don't
376 * realize it because we keep waking up to handle those
377 * other ICMP packets that keep coming in. To fix this,
378 * "reset_timer" will only be true if the last packet that
379 * came in was for us or if this is the first time we're
380 * waiting for a reply since sending out a probe. Note
381 * that this takes advantage of the select() feature on
382 * Linux where the remaining timeout is written to the
383 * struct timeval area.
384 */
385 wait.tv_sec = waittime;
386 wait.tv_usec = 0;
387 }
388
389 if (select(sock+1, &fds, (fd_set *)0, (fd_set *)0, &wait) > 0)
390 cc=recvfrom(s, (char *)packet, sizeof(packet), 0,
391 (struct sockaddr *)from, &fromlen);
392
393 return(cc);
394}
395
396
397static void
398send_probe(seq, ttl)
399 int seq, ttl;
400{
401 struct opacket *op = outpacket;
402 struct ip *ip = &op->ip;
403 struct udphdr *up = &op->udp;
404 int i;
405 struct timezone tz;
406
407 ip->ip_off = 0;
408 ip->ip_hl = sizeof(*ip) >> 2;
409 ip->ip_p = IPPROTO_UDP;
410 ip->ip_len = datalen;
411 ip->ip_ttl = ttl;
412 ip->ip_v = IPVERSION;
413 ip->ip_id = htons(ident+seq);
414
415 up->source = htons(ident);
416 up->dest = htons(port+seq);
417 up->len = htons((u_short)(datalen - sizeof(struct ip)));
418 up->check = 0;
419
420 op->seq = seq;
421 op->ttl = ttl;
422 (void) gettimeofday(&op->tv, &tz);
423
424 i = sendto(sndsock, (char *)outpacket, datalen, 0, &whereto,
425 sizeof(struct sockaddr));
426 if (i < 0 || i != datalen) {
427 if (i<0)
428 perror("sendto");
429 printf("traceroute: wrote %s %d chars, ret=%d\n", hostname,
430 datalen, i);
431 (void) fflush(stdout);
432 }
433}
434
435
436static double
437deltaT(t1p, t2p)
438 struct timeval *t1p, *t2p;
439{
440 register double dt;
441
442 dt = (double)(t2p->tv_sec - t1p->tv_sec) * 1000.0 +
443 (double)(t2p->tv_usec - t1p->tv_usec) / 1000.0;
444 return (dt);
445}
446
447
448/*
449 * Convert an ICMP "type" field to a printable string.
450 */
451static const char *
452pr_type(t)
453 u_char t;
454{
455 static const char * const ttab[] = {
456 "Echo Reply", "ICMP 1", "ICMP 2", "Dest Unreachable",
457 "Source Quench", "Redirect", "ICMP 6", "ICMP 7",
458 "Echo", "ICMP 9", "ICMP 10", "Time Exceeded",
459 "Param Problem", "Timestamp", "Timestamp Reply", "Info Request",
460 "Info Reply"
461 };
462
463 if(t > 16)
464 return("OUT-OF-RANGE");
465
466 return(ttab[t]);
467}
468
469
470static int
471packet_ok(buf, cc, from, seq)
472 u_char *buf;
473 int cc;
474 struct sockaddr_in *from;
475 int seq;
476{
477 register struct icmp *icp;
478 u_char type, code;
479 int hlen;
480#ifndef ARCHAIC
481 struct ip *ip;
482
483 ip = (struct ip *) buf;
484 hlen = ip->ip_hl << 2;
485 if (cc < hlen + ICMP_MINLEN) {
486 if (verbose)
487 printf("packet too short (%d bytes) from %s\n", cc,
488 inet_ntoa(from->sin_addr));
489 return (0);
490 }
491 cc -= hlen;
492 icp = (struct icmp *)(buf + hlen);
493#else
494 icp = (struct icmp *)buf;
495#endif ARCHAIC
496 type = icp->icmp_type; code = icp->icmp_code;
497 if ((type == ICMP_TIMXCEED && code == ICMP_TIMXCEED_INTRANS) ||
498 type == ICMP_UNREACH) {
499 struct ip *hip;
500 struct udphdr *up;
501
502 hip = &icp->icmp_ip;
503 hlen = hip->ip_hl << 2;
504 up = (struct udphdr *)((u_char *)hip + hlen);
505 if (hlen + 12 <= cc && hip->ip_p == IPPROTO_UDP &&
506 up->source == htons(ident) &&
507 up->dest == htons(port+seq))
508 return (type == ICMP_TIMXCEED? -1 : code+1);
509 }
510#ifndef ARCHAIC
511 if (verbose) {
512 int i;
513 u_long *lp = (u_long *)&icp->icmp_ip;
514
515 printf("\n%d bytes from %s to %s", cc,
516 inet_ntoa(from->sin_addr), inet_ntoa(ip->ip_dst));
517 printf(": icmp type %d (%s) code %d\n", type, pr_type(type),
518 icp->icmp_code);
519 for (i = 4; i < cc ; i += sizeof(long))
520 printf("%2d: x%8.8lx\n", i, *lp++);
521 }
522#endif ARCHAIC
523 return(0);
524}
525
526
527static void
528print(buf, cc, from)
529 u_char *buf;
530 int cc;
531 struct sockaddr_in *from;
532{
533 struct ip *ip;
534 int hlen;
535
536 ip = (struct ip *) buf;
537 hlen = ip->ip_hl << 2;
538 cc -= hlen;
539
540 if (nflag)
541 printf(" %s", inet_ntoa(from->sin_addr));
542 else
543 printf(" %s (%s)", inetname(from->sin_addr),
544 inet_ntoa(from->sin_addr));
545
546 if (verbose)
547 printf (" %d bytes to %s", cc, inet_ntoa (ip->ip_dst));
548}
549
550
551/*
552 * Construct an Internet address representation.
553 * If the nflag has been supplied, give
554 * numeric value, otherwise try for symbolic name.
555 */
556static char *
557inetname(in)
558 struct in_addr in;
559{
560 register char *cp;
561 static char line[50];
562 struct hostent *hp;
563 static char domain[MAXHOSTNAMELEN + 1];
564 static int first = 1;
565
566 if (first && !nflag) {
567 first = 0;
568 if (gethostname(domain, MAXHOSTNAMELEN) == 0 &&
569 (cp = index(domain, '.')))
570 (void) strcpy(domain, cp + 1);
571 else
572 domain[0] = 0;
573 }
574 cp = 0;
575 if (!nflag && in.s_addr != INADDR_ANY) {
576 hp = gethostbyaddr((char *)&in, sizeof (in), AF_INET);
577 if (hp) {
578 if ((cp = index(hp->h_name, '.')) &&
579 !strcmp(cp + 1, domain))
580 *cp = 0;
581 cp = (char *)hp->h_name;
582 }
583 }
584 if (cp)
585 (void) strcpy(line, cp);
586 else {
587 in.s_addr = ntohl(in.s_addr);
588#define C(x) ((x) & 0xff)
589 sprintf(line, "%u.%u.%u.%u", C(in.s_addr >> 24),
590 C(in.s_addr >> 16), C(in.s_addr >> 8), C(in.s_addr));
591 }
592 return (line);
593}