1
0
mirror of https://git.FreeBSD.org/src.git synced 2024-12-15 10:17:20 +00:00

Add an ICMP protocol handler, partly based on LBL's traceroute 1.4 .

Submitted by:	dcs
This commit is contained in:
Bill Fenner 2002-07-22 23:01:11 +00:00
parent 88c39af35f
commit 290006640b
Notes: svn2git 2020-12-20 02:59:44 +00:00
svn path=/head/; revision=100535
2 changed files with 57 additions and 4 deletions

View File

@ -109,7 +109,7 @@ path).
.TP .TP
.B \-P .B \-P
Send packets of specified IP protocol. The currently supported protocols Send packets of specified IP protocol. The currently supported protocols
are: UDP, TCP and GRE. Other protocols may also be specified (either by are: UDP, TCP, GRE and ICMP. Other protocols may also be specified (either by
name or by number), though name or by number), though
.I traceroute .I traceroute
does not implement any special knowledge of their packet formats. This does not implement any special knowledge of their packet formats. This

View File

@ -275,6 +275,7 @@ struct outdata {
u_char seq; /* sequence number of this packet */ u_char seq; /* sequence number of this packet */
u_char ttl; /* ttl packet left with */ u_char ttl; /* ttl packet left with */
struct timeval tv; /* time packet left */ struct timeval tv; /* time packet left */
int optlen; /* length of ip options */
}; };
/* Descriptor structure for each outgoing protocol we support */ /* Descriptor structure for each outgoing protocol we support */
@ -326,6 +327,7 @@ extern char *optarg;
/* Forwards */ /* Forwards */
double deltaT(struct timeval *, struct timeval *); double deltaT(struct timeval *, struct timeval *);
u_short in_cksum(u_short *, int);
char *inetname(struct in_addr); char *inetname(struct in_addr);
int main(int, char **); int main(int, char **);
int packet_ok(u_char *, int, struct sockaddr_in *, int); int packet_ok(u_char *, int, struct sockaddr_in *, int);
@ -350,6 +352,8 @@ void gre_prep(struct outdata *);
int gre_check(const u_char *, int); int gre_check(const u_char *, int);
void gen_prep(struct outdata *); void gen_prep(struct outdata *);
int gen_check(const u_char *, int); int gen_check(const u_char *, int);
void icmp_prep(struct outdata *);
int icmp_check(const u_char *, int);
/* List of supported protocols. The first one is the default. The last /* List of supported protocols. The first one is the default. The last
one is the handler for generic protocols not explicitly listed. */ one is the handler for generic protocols not explicitly listed. */
@ -378,6 +382,14 @@ struct outproto protos[] = {
gre_prep, gre_prep,
gre_check gre_check
}, },
{
"icmp",
IPPROTO_ICMP,
sizeof(struct icmp),
0,
icmp_prep,
icmp_check
},
{ {
NULL, NULL,
0, 0,
@ -785,6 +797,7 @@ main(int argc, char **argv)
/* Prepare outgoing data */ /* Prepare outgoing data */
outdata.seq = ++seq; outdata.seq = ++seq;
outdata.ttl = ttl; outdata.ttl = ttl;
outdata.optlen = optlen;
/* Avoid alignment problems by copying bytewise: */ /* Avoid alignment problems by copying bytewise: */
(void)gettimeofday(&t1, &tz); (void)gettimeofday(&t1, &tz);
@ -820,9 +833,21 @@ main(int argc, char **argv)
#endif #endif
precis = 3; precis = 3;
Printf(" %.*f ms", precis, T); Printf(" %.*f ms", precis, T);
if (i == -2) {
#ifdef ARCHAIC
ip = (struct ip *)packet;
if (ip->ip_ttl <= 1)
Printf(" !");
#endif
++got_there;
break;
}
/* time exceeded in transit */ /* time exceeded in transit */
if (i == -1) if (i == -1)
break; break;
code = i - 1; code = i - 1;
switch (code) { switch (code) {
@ -1030,6 +1055,10 @@ packet_ok(register u_char *buf, int cc, register struct sockaddr_in *from,
#endif #endif
type = icp->icmp_type; type = icp->icmp_type;
code = icp->icmp_code; code = icp->icmp_code;
if (type == ICMP_ECHOREPLY
&& proto->num == IPPROTO_ICMP
&& (*proto->check)((u_char *)icp,seq))
return -2;
if ((type == ICMP_TIMXCEED && code == ICMP_TIMXCEED_INTRANS) || if ((type == ICMP_TIMXCEED && code == ICMP_TIMXCEED_INTRANS) ||
type == ICMP_UNREACH) { type == ICMP_UNREACH) {
struct ip *hip; struct ip *hip;
@ -1058,6 +1087,32 @@ packet_ok(register u_char *buf, int cc, register struct sockaddr_in *from,
return(0); return(0);
} }
void
icmp_prep(struct outdata *outdata)
{
struct icmp *const icmpheader = (struct icmp *) outprot;
icmpheader->icmp_type = ICMP_ECHO;
icmpheader->icmp_id = htons(ident);
icmpheader->icmp_seq = htons(outdata->seq);
icmpheader->icmp_cksum = 0;
icmpheader->icmp_cksum = in_cksum((u_short *)icmpheader,
packlen - (sizeof(*outip) + outdata->optlen));
if (icmpheader->icmp_cksum == 0)
icmpheader->icmp_cksum = 0xffff;
}
int
icmp_check(const u_char *data, int seq)
{
struct icmp *const icmpheader = (struct icmp *) data;
return (icmpheader->icmp_id == htons(ident)
&& icmpheader->icmp_seq == htons(seq));
}
void void
udp_prep(struct outdata *outdata) udp_prep(struct outdata *outdata)
{ {
@ -1157,11 +1212,10 @@ print(register u_char *buf, register int cc, register struct sockaddr_in *from)
Printf(" %d bytes to %s", cc, inet_ntoa (ip->ip_dst)); Printf(" %d bytes to %s", cc, inet_ntoa (ip->ip_dst));
} }
#ifdef notyet
/* /*
* Checksum routine for Internet Protocol family headers (C Version) * Checksum routine for Internet Protocol family headers (C Version)
*/ */
u_short
in_cksum(register u_short *addr, register int len) in_cksum(register u_short *addr, register int len)
{ {
register int nleft = len; register int nleft = len;
@ -1192,7 +1246,6 @@ in_cksum(register u_short *addr, register int len)
answer = ~sum; /* truncate to 16 bits */ answer = ~sum; /* truncate to 16 bits */
return (answer); return (answer);
} }
#endif
/* /*
* Subtract 2 timeval structs: out = out - in. * Subtract 2 timeval structs: out = out - in.