diff options
author | jlemon <jlemon@FreeBSD.org> | 2001-10-25 06:27:51 +0000 |
---|---|---|
committer | jlemon <jlemon@FreeBSD.org> | 2001-10-25 06:27:51 +0000 |
commit | db827296e43acae577fb6732dd460639567beb4b (patch) | |
tree | 2cb280061d8abc916e190da298f21c64828aa5b6 /sys | |
parent | 669cd5c6d78c0056da6450671a852cb7ef1a663e (diff) | |
download | FreeBSD-src-db827296e43acae577fb6732dd460639567beb4b.zip FreeBSD-src-db827296e43acae577fb6732dd460639567beb4b.tar.gz |
Don't use the ip_timestamp structure to access timestamp options, as the
compiler may cause an unaligned access to be generated in some cases.
PR: 30982
Diffstat (limited to 'sys')
-rw-r--r-- | sys/netinet/ip_input.c | 51 |
1 files changed, 22 insertions, 29 deletions
diff --git a/sys/netinet/ip_input.c b/sys/netinet/ip_input.c index c09bb48..f529a7e 100644 --- a/sys/netinet/ip_input.c +++ b/sys/netinet/ip_input.c @@ -1161,7 +1161,6 @@ ip_dooptions(m) { register struct ip *ip = mtod(m, struct ip *); register u_char *cp; - register struct ip_timestamp *ipt; register struct in_ifaddr *ia; int opt, optlen, cnt, off, code, type = ICMP_PARAMPROB, forward = 0; struct in_addr *sin, dst; @@ -1325,35 +1324,33 @@ nosourcerouting: case IPOPT_TS: code = cp - (u_char *)ip; - ipt = (struct ip_timestamp *)cp; - if (ipt->ipt_len < 4 || ipt->ipt_len > 40) { - code = (u_char *)&ipt->ipt_len - (u_char *)ip; + if (optlen < 4 || optlen > 40) { + code = &cp[IPOPT_OLEN] - (u_char *)ip; goto bad; } - if (ipt->ipt_ptr < 5) { - code = (u_char *)&ipt->ipt_ptr - (u_char *)ip; + if ((off = cp[IPOPT_OFFSET]) < 5) { + code = &cp[IPOPT_OLEN] - (u_char *)ip; goto bad; } - if (ipt->ipt_ptr > - ipt->ipt_len - (int)sizeof(int32_t)) { - if (++ipt->ipt_oflw == 0) { - code = (u_char *)&ipt->ipt_ptr - - (u_char *)ip; + if (off > optlen - (int)sizeof(int32_t)) { + cp[IPOPT_OFFSET + 1] += (1 << 4); + if ((cp[IPOPT_OFFSET + 1] & 0xf0) == 0) { + code = &cp[IPOPT_OFFSET] - (u_char *)ip; goto bad; } break; } - sin = (struct in_addr *)(cp + ipt->ipt_ptr - 1); - switch (ipt->ipt_flg) { + off--; /* 0 origin */ + sin = (struct in_addr *)(cp + off); + switch (cp[IPOPT_OFFSET + 1] & 0x0f) { case IPOPT_TS_TSONLY: break; case IPOPT_TS_TSANDADDR: - if (ipt->ipt_ptr - 1 + sizeof(n_time) + - sizeof(struct in_addr) > ipt->ipt_len) { - code = (u_char *)&ipt->ipt_ptr - - (u_char *)ip; + if (off + sizeof(n_time) + + sizeof(struct in_addr) > optlen) { + code = &cp[IPOPT_OFFSET] - (u_char *)ip; goto bad; } ipaddr.sin_addr = dst; @@ -1363,33 +1360,29 @@ nosourcerouting: continue; (void)memcpy(sin, &IA_SIN(ia)->sin_addr, sizeof(struct in_addr)); - ipt->ipt_ptr += sizeof(struct in_addr); + cp[IPOPT_OFFSET] += sizeof(struct in_addr); break; case IPOPT_TS_PRESPEC: - if (ipt->ipt_ptr - 1 + sizeof(n_time) + - sizeof(struct in_addr) > ipt->ipt_len) { - code = (u_char *)&ipt->ipt_ptr - - (u_char *)ip; + if (off + sizeof(n_time) + + sizeof(struct in_addr) > optlen) { + code = &cp[IPOPT_OFFSET] - (u_char *)ip; goto bad; } (void)memcpy(&ipaddr.sin_addr, sin, sizeof(struct in_addr)); if (ifa_ifwithaddr((SA)&ipaddr) == 0) continue; - ipt->ipt_ptr += sizeof(struct in_addr); + cp[IPOPT_OFFSET] += sizeof(struct in_addr); break; default: - /* XXX can't take &ipt->ipt_flg */ - code = (u_char *)&ipt->ipt_ptr - - (u_char *)ip + 1; + code = &cp[IPOPT_OFFSET + 1] - (u_char *)ip; goto bad; } ntime = iptime(); - (void)memcpy(cp + ipt->ipt_ptr - 1, &ntime, - sizeof(n_time)); - ipt->ipt_ptr += sizeof(n_time); + (void)memcpy(cp + off, &ntime, sizeof(n_time)); + cp[IPOPT_OFFSET] += sizeof(n_time); } } if (forward && ipforwarding) { |