diff options
author | Ralf Baechle <ralf@linux-mips.org> | 1999-01-04 16:03:48 +0000 |
---|---|---|
committer | Ralf Baechle <ralf@linux-mips.org> | 1999-01-04 16:03:48 +0000 |
commit | 78c388aed2b7184182c08428db1de6c872d815f5 (patch) | |
tree | 4b2003b1b4ceb241a17faa995da8dd1004bb8e45 /net/ipv4/ip_options.c | |
parent | eb7a5bf93aaa4be1d7c6181100ab7639e74d67f7 (diff) |
Merge with Linux 2.1.131 and more MIPS goodies.
(Did I mention that CVS is buggy ...)
Diffstat (limited to 'net/ipv4/ip_options.c')
-rw-r--r-- | net/ipv4/ip_options.c | 74 |
1 files changed, 37 insertions, 37 deletions
diff --git a/net/ipv4/ip_options.c b/net/ipv4/ip_options.c index 153c7a391..92502239c 100644 --- a/net/ipv4/ip_options.c +++ b/net/ipv4/ip_options.c @@ -5,7 +5,7 @@ * * The options processing module for ip.c * - * Version: $Id: ip_options.c,v 1.14 1998/08/26 12:03:51 davem Exp $ + * Version: $Id: ip_options.c,v 1.15 1998/10/03 09:37:27 davem Exp $ * * Authors: A.N.Kuznetsov * @@ -89,12 +89,6 @@ int ip_options_echo(struct ip_options * dopt, struct sk_buff * skb) int optlen; u32 daddr; -#if 111 - if (skb == NULL) { - printk(KERN_DEBUG "no skb in ip_options_echo\n"); - return -EINVAL; - } -#endif memset(dopt, 0, sizeof(struct ip_options)); dopt->is_data = 1; @@ -145,14 +139,19 @@ int ip_options_echo(struct ip_options * dopt, struct sk_buff * skb) return -EINVAL; dopt->ts_needtime = 1; soffset += 4; - } - if (((struct timestamp*)(dptr+1))->flags == IPOPT_TS_PRESPEC) { - __u32 addr; - memcpy(&addr, sptr+soffset-9, 4); - if (inet_addr_type(addr) == RTN_UNICAST) { - dopt->ts_needtime = 0; - dopt->ts_needaddr = 0; - soffset -= 8; + if ((dptr[3]&0xF) == IPOPT_TS_PRESPEC) { + __u32 addr; + if (soffset + 3 > optlen) + return -EINVAL; + soffset += 4; + if (soffset + 8 <= optlen) { + dopt->ts_needtime = 0; + memcpy(&addr, sptr+soffset-1, 4); + if (inet_addr_type(addr) != RTN_UNICAST) { + dopt->ts_needtime = 1; + soffset += 8; + } + } } } dptr[2] = soffset; @@ -353,55 +352,56 @@ int ip_options_compile(struct ip_options * opt, struct sk_buff * skb) goto error; } if (optptr[2] <= optlen) { - struct timestamp * ts = (struct timestamp*)(optptr+1); __u32 * timeptr = NULL; - if (ts->ptr+3 > ts->len) { + if (optptr[2]+3 > optptr[1]) { pp_ptr = optptr + 2; goto error; } - switch (ts->flags) { + switch (optptr[3]&0xF) { case IPOPT_TS_TSONLY: opt->ts = optptr - iph; if (skb) - timeptr = (__u32*)&optptr[ts->ptr-1]; + timeptr = (__u32*)&optptr[optptr[2]-1]; opt->ts_needtime = 1; - ts->ptr += 4; + optptr[2] += 4; break; case IPOPT_TS_TSANDADDR: - if (ts->ptr+7 > ts->len) { + if (optptr[2]+7 > optptr[1]) { pp_ptr = optptr + 2; goto error; } opt->ts = optptr - iph; if (skb) { - memcpy(&optptr[ts->ptr-1], &rt->rt_spec_dst, 4); - timeptr = (__u32*)&optptr[ts->ptr+3]; + memcpy(&optptr[optptr[2]-1], &rt->rt_spec_dst, 4); + timeptr = (__u32*)&optptr[optptr[2]+3]; } opt->ts_needaddr = 1; opt->ts_needtime = 1; - ts->ptr += 8; + optptr[2] += 8; break; case IPOPT_TS_PRESPEC: - if (ts->ptr+7 > ts->len) { + if (optptr[2]+7 > optptr[1]) { pp_ptr = optptr + 2; goto error; } opt->ts = optptr - iph; { u32 addr; - memcpy(&addr, &optptr[ts->ptr-1], 4); + memcpy(&addr, &optptr[optptr[2]-1], 4); if (inet_addr_type(addr) == RTN_UNICAST) break; if (skb) - timeptr = (__u32*)&optptr[ts->ptr+3]; + timeptr = (__u32*)&optptr[optptr[2]+3]; } - opt->ts_needaddr = 1; opt->ts_needtime = 1; - ts->ptr += 8; + optptr[2] += 8; break; default: - pp_ptr = optptr + 3; - goto error; + if (!skb && !capable(CAP_NET_RAW)) { + pp_ptr = optptr + 3; + goto error; + } + break; } if (timeptr) { struct timeval tv; @@ -412,14 +412,14 @@ int ip_options_compile(struct ip_options * opt, struct sk_buff * skb) opt->is_changed = 1; } } else { - struct timestamp * ts = (struct timestamp*)(optptr+1); - if (ts->overflow == 15) { + unsigned overflow = optptr[3]>>4; + if (overflow == 15) { pp_ptr = optptr + 3; goto error; } opt->ts = optptr - iph; if (skb) { - ts->overflow++; + optptr[3] = (optptr[3]&0xF)|((overflow+1)<<4); opt->is_changed = 1; } } @@ -435,7 +435,7 @@ int ip_options_compile(struct ip_options * opt, struct sk_buff * skb) case IPOPT_SEC: case IPOPT_SID: default: - if (!skb) { + if (!skb && !capable(CAP_NET_RAW)) { pp_ptr = optptr; goto error; } @@ -480,10 +480,10 @@ void ip_options_undo(struct ip_options * opt) memset(&optptr[optptr[2]-1], 0, 4); optptr[2] -= 4; } - if (opt->ts_needaddr) { + if (opt->ts_needaddr) memset(&optptr[optptr[2]-1], 0, 4); + if ((optptr[3]&0xF) != IPOPT_TS_PRESPEC) optptr[2] -= 4; - } } } |