summaryrefslogtreecommitdiffstats
path: root/contrib
diff options
context:
space:
mode:
authorfenner <fenner@FreeBSD.org>2002-07-28 02:34:39 +0000
committerfenner <fenner@FreeBSD.org>2002-07-28 02:34:39 +0000
commitb61bd3d17427fa3e9868bc373fd6a88600e450a2 (patch)
tree51ee46b91443a6b1e7b8fe49c1e897098cf4ce12 /contrib
parent0e3f6f62f9320678710cb80a7afb4105152ddcea (diff)
downloadFreeBSD-src-b61bd3d17427fa3e9868bc373fd6a88600e450a2.zip
FreeBSD-src-b61bd3d17427fa3e9868bc373fd6a88600e450a2.tar.gz
Calculate checksums correctly when LSRR is in effect by passing the
IP header and protocol header seperately. Also calculate TCP checksums. Submitted by: orion
Diffstat (limited to 'contrib')
-rw-r--r--contrib/traceroute/traceroute.c60
1 files changed, 36 insertions, 24 deletions
diff --git a/contrib/traceroute/traceroute.c b/contrib/traceroute/traceroute.c
index 666d570..2c91466 100644
--- a/contrib/traceroute/traceroute.c
+++ b/contrib/traceroute/traceroute.c
@@ -222,6 +222,7 @@ static const char rcsid[] =
#include <netinet/udp.h>
#include <netinet/udp_var.h>
#include <netinet/tcp.h>
+#include <netinet/tcpip.h>
#include <arpa/inet.h>
@@ -300,7 +301,6 @@ 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 */
};
#ifndef HAVE_ICMP_NEXTMTU
@@ -366,6 +366,7 @@ struct hostinfo *gethostinfo(char *);
u_short in_cksum(u_short *, int);
char *inetname(struct in_addr);
int main(int, char **);
+u_short p_cksum(struct ip *, u_short *, int);
int packet_ok(u_char *, int, struct sockaddr_in *, int);
char *pr_type(u_char);
void print(u_char *, int, struct sockaddr_in *);
@@ -470,7 +471,6 @@ main(int argc, char **argv)
register u_short off = 0;
struct ifaddrlist *al;
char errbuf[132];
- register int optlen = 0;
int requestPort = -1;
int sump = 0;
int sockerrno;
@@ -924,7 +924,6 @@ 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);
@@ -1269,13 +1268,10 @@ icmp_prep(struct outdata *outdata)
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));
+ icmpheader->icmp_cksum = in_cksum((u_short *)icmpheader, protlen);
if (icmpheader->icmp_cksum == 0)
icmpheader->icmp_cksum = 0xffff;
-
}
int
@@ -1291,29 +1287,17 @@ void
udp_prep(struct outdata *outdata)
{
struct udphdr *const outudp = (struct udphdr *) outp;
- struct ip tip;
- struct udpiphdr *ui, *oui;
outudp->uh_sport = htons(ident);
outudp->uh_dport = htons(port + outdata->seq);
outudp->uh_ulen = htons((u_short)protlen);
+ outudp->uh_sum = 0;
if (doipcksum) {
- /* Checksum (we must save and restore ip header) */
- tip = *outip;
- ui = (struct udpiphdr *)outip;
- oui = (struct udpiphdr *)&tip;
- /* Easier to zero and put back things that are ok */
- memset((char *)ui, 0, sizeof(ui->ui_i));
- ui->ui_src = oui->ui_src;
- ui->ui_dst = oui->ui_dst;
- ui->ui_pr = oui->ui_pr;
- ui->ui_len = outudp->uh_ulen;
- outudp->uh_sum = 0;
- outudp->uh_sum = in_cksum((u_short *)ui, packlen);
- if (outudp->uh_sum == 0)
- outudp->uh_sum = 0xffff;
- *outip = tip;
+ u_short sum = p_cksum(outip, (u_short*)outudp, protlen);
+ outudp->uh_sum = (sum) ? sum : 0xffff;
}
+
+ return;
}
int
@@ -1336,6 +1320,12 @@ tcp_prep(struct outdata *outdata)
tcp->th_ack = 0;
tcp->th_off = 5;
tcp->th_flags = TH_SYN;
+ tcp->th_sum = 0;
+
+ if (doipcksum) {
+ u_short sum = p_cksum(outip, (u_short*)tcp, protlen);
+ tcp->th_sum = (sum) ? sum : 0xffff;
+ }
}
int
@@ -1406,6 +1396,28 @@ print(register u_char *buf, register int cc, register struct sockaddr_in *from)
}
/*
+ * Checksum routine for UDP and TCP headers.
+ */
+u_short
+p_cksum(struct ip *ip, u_short *data, int len)
+{
+ static struct ipovly ipo;
+ u_short sumh, sumd;
+ u_long sumt;
+
+ ipo.ih_pr = ip->ip_p;
+ ipo.ih_len = htons(len);
+ ipo.ih_src = ip->ip_src;
+ ipo.ih_dst = ip->ip_dst;
+
+ sumh = in_cksum((u_short*)&ipo, sizeof(ipo)); /* pseudo ip hdr cksum */
+ sumd = in_cksum((u_short*)data, len); /* payload data cksum */
+ sumt = (sumh << 16) | (sumd);
+
+ return ~in_cksum((u_short*)&sumt, sizeof(sumt));
+}
+
+/*
* Checksum routine for Internet Protocol family headers (C Version)
*/
u_short
OpenPOWER on IntegriCloud