summaryrefslogtreecommitdiffstats
path: root/contrib/traceroute
diff options
context:
space:
mode:
authorfenner <fenner@FreeBSD.org>2002-07-22 23:01:11 +0000
committerfenner <fenner@FreeBSD.org>2002-07-22 23:01:11 +0000
commitc9f6925854845df524541d066473b45091e6042b (patch)
tree7593c805d3120c3c78d8bfba1110ddf9359bc0fb /contrib/traceroute
parentcb7f1cefec456220dc1b02513d3740517addc49d (diff)
downloadFreeBSD-src-c9f6925854845df524541d066473b45091e6042b.zip
FreeBSD-src-c9f6925854845df524541d066473b45091e6042b.tar.gz
Add an ICMP protocol handler, partly based on LBL's traceroute 1.4 .
Submitted by: dcs
Diffstat (limited to 'contrib/traceroute')
-rw-r--r--contrib/traceroute/traceroute.82
-rw-r--r--contrib/traceroute/traceroute.c59
2 files changed, 57 insertions, 4 deletions
diff --git a/contrib/traceroute/traceroute.8 b/contrib/traceroute/traceroute.8
index 24bae14..003025c 100644
--- a/contrib/traceroute/traceroute.8
+++ b/contrib/traceroute/traceroute.8
@@ -109,7 +109,7 @@ path).
.TP
.B \-P
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
.I traceroute
does not implement any special knowledge of their packet formats. This
diff --git a/contrib/traceroute/traceroute.c b/contrib/traceroute/traceroute.c
index 90add90..ad4a1ba 100644
--- a/contrib/traceroute/traceroute.c
+++ b/contrib/traceroute/traceroute.c
@@ -275,6 +275,7 @@ struct outdata {
u_char seq; /* sequence number of this packet */
u_char ttl; /* ttl packet left with */
struct timeval tv; /* time packet left */
+ int optlen; /* length of ip options */
};
/* Descriptor structure for each outgoing protocol we support */
@@ -326,6 +327,7 @@ extern char *optarg;
/* Forwards */
double deltaT(struct timeval *, struct timeval *);
+u_short in_cksum(u_short *, int);
char *inetname(struct in_addr);
int main(int, char **);
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);
void gen_prep(struct outdata *);
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
one is the handler for generic protocols not explicitly listed. */
@@ -379,6 +383,14 @@ struct outproto protos[] = {
gre_check
},
{
+ "icmp",
+ IPPROTO_ICMP,
+ sizeof(struct icmp),
+ 0,
+ icmp_prep,
+ icmp_check
+ },
+ {
NULL,
0,
2 * sizeof(u_short),
@@ -785,6 +797,7 @@ main(int argc, char **argv)
/* Prepare outgoing data */
outdata.seq = ++seq;
outdata.ttl = ttl;
+ outdata.optlen = optlen;
/* Avoid alignment problems by copying bytewise: */
(void)gettimeofday(&t1, &tz);
@@ -820,9 +833,21 @@ main(int argc, char **argv)
#endif
precis = 3;
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 */
if (i == -1)
break;
+
code = i - 1;
switch (code) {
@@ -1030,6 +1055,10 @@ packet_ok(register u_char *buf, int cc, register struct sockaddr_in *from,
#endif
type = icp->icmp_type;
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) ||
type == ICMP_UNREACH) {
struct ip *hip;
@@ -1059,6 +1088,32 @@ packet_ok(register u_char *buf, int cc, register struct sockaddr_in *from,
}
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
udp_prep(struct outdata *outdata)
{
struct udphdr *const udp = (struct udphdr *) outprot;
@@ -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));
}
-
-#ifdef notyet
/*
* Checksum routine for Internet Protocol family headers (C Version)
*/
+u_short
in_cksum(register u_short *addr, register int len)
{
register int nleft = len;
@@ -1192,7 +1246,6 @@ in_cksum(register u_short *addr, register int len)
answer = ~sum; /* truncate to 16 bits */
return (answer);
}
-#endif
/*
* Subtract 2 timeval structs: out = out - in.
OpenPOWER on IntegriCloud