patch-2.1.124 linux/net/ipv4/ip_options.c
Next file: linux/net/ipv4/ip_output.c
Previous file: linux/net/ipv4/ip_nat_dumb.c
Back to the patch index
Back to the overall index
- Lines: 163
- Date:
Sun Oct 4 10:19:39 1998
- Orig file:
v2.1.123/linux/net/ipv4/ip_options.c
- Orig date:
Sat Sep 5 16:46:42 1998
diff -u --recursive --new-file v2.1.123/linux/net/ipv4/ip_options.c linux/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 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 @@
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 @@
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 @@
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 @@
case IPOPT_SEC:
case IPOPT_SID:
default:
- if (!skb) {
+ if (!skb && !capable(CAP_NET_RAW)) {
pp_ptr = optptr;
goto error;
}
@@ -480,10 +480,10 @@
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;
- }
}
}
FUNET's LINUX-ADM group, linux-adm@nic.funet.fi
TCL-scripts by Sam Shen, slshen@lbl.gov