转:http://blog.csdn.net/nerdx/article/details/12452149
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
1.1 int ip_options_compile(struct ip_options * opt, struct sk_buff * skb)
-
{
-
int l;
-
unsigned char * iph;
-
unsigned char * optptr;
-
int optlen;
-
unsigned char * pp_ptr = NULL;
-
struct rtable *rt = skb ? (struct rtable*)skb->dst : NULL;
-
-
if (!opt) {
-
opt = &(IPCB(skb)->opt);
-
memset(opt, 0, sizeof(struct ip_options));
-
iph = skb->nh.raw;
-
opt->optlen = ((struct iphdr *)iph)->ihl*4 - sizeof(struct iphdr);
-
optptr = iph + sizeof(struct iphdr);
-
opt->is_data = 0;
-
} else {
-
optptr = opt->is_data ? opt->__data : (unsigned char*)&(skb->nh.iph[1]);
-
iph = optptr - sizeof(struct iphdr);
-
}
-
-
for (l = opt->optlen; l > 0; ) {
-
switch (*optptr) {
-
case IPOPT_END:
-
for (optptr++, l--; l>0; optptr++, l--) {
-
if (*optptr != IPOPT_END) {
-
*optptr = IPOPT_END;
-
opt->is_changed = 1;
-
}
-
}
-
goto eol;
-
case IPOPT_NOOP:
-
l--;
-
optptr++;
-
continue;
-
}
-
-
-
-
optlen = optptr[1];
-
if (optlen<2 || optlen>l) {
-
pp_ptr = optptr;
-
goto error;
-
}
-
switch (*optptr) {
-
case IPOPT_SSRR:
-
case IPOPT_LSRR:
-
if (optlen < 3) {
-
pp_ptr = optptr + 1;
-
goto error;
-
}
-
if (optptr[2] < 4) {
-
pp_ptr = optptr + 2;
-
goto error;
-
}
-
-
if (opt->srr) {
-
pp_ptr = optptr;
-
goto error;
-
}
-
-
if (!skb) {
-
if (optptr[2] != 4 || optlen < 7 || ((optlen-3) & 3)) {
-
pp_ptr = optptr + 1;
-
goto error;
-
}
-
memcpy(&opt->faddr, &optptr[3], 4);
-
if (optlen > 7)
-
memmove(&optptr[3], &optptr[7], optlen-7);
-
}
-
opt->is_strictroute = (optptr[0] == IPOPT_SSRR);
-
opt->srr = optptr - iph;
-
break;
-
case IPOPT_RR:
-
if (opt->rr) {
-
pp_ptr = optptr;
-
goto error;
-
}
-
if (optlen < 3) {
-
pp_ptr = optptr + 1;
-
goto error;
-
}
-
if (optptr[2] < 4) {
-
pp_ptr = optptr + 2;
-
goto error;
-
}
-
if (optptr[2] <= optlen) {
-
if (optptr[2]+3 > optlen) {
-
pp_ptr = optptr + 2;
-
goto error;
-
}
-
if (skb) {
-
memcpy(&optptr[optptr[2]-1], &rt->rt_spec_dst, 4);
-
opt->is_changed = 1;
-
}
-
optptr[2] += 4;
-
opt->rr_needaddr = 1;
-
}
-
opt->rr = optptr - iph;
-
break;
-
case IPOPT_TIMESTAMP:
-
if (opt->ts) {
-
pp_ptr = optptr;
-
goto error;
-
}
-
if (optlen < 4) {
-
pp_ptr = optptr + 1;
-
goto error;
-
}
-
if (optptr[2] < 5) {
-
pp_ptr = optptr + 2;
-
goto error;
-
}
-
if (optptr[2] <= optlen) {
-
__u32 * timeptr = NULL;
-
if (optptr[2]+3 > optptr[1]) {
-
pp_ptr = optptr + 2;
-
goto error;
-
}
-
-
switch (optptr[3]&0xF) {
-
case IPOPT_TS_TSONLY:
-
opt->ts = optptr - iph;
-
if (skb)
-
timeptr = (__u32*)&optptr[optptr[2]-1];
-
opt->ts_needtime = 1;
-
optptr[2] += 4;
-
break;
-
case IPOPT_TS_TSANDADDR:
-
if (optptr[2]+7 > optptr[1]) {
-
pp_ptr = optptr + 2;
-
goto error;
-
}
-
opt->ts = optptr - iph;
-
if (skb) {
-
memcpy(&optptr[optptr[2]-1], &rt->rt_spec_dst, 4);
-
timeptr = (__u32*)&optptr[optptr[2]+3];
-
}
-
opt->ts_needaddr = 1;
-
opt->ts_needtime = 1;
-
optptr[2] += 8;
-
break;
-
case IPOPT_TS_PRESPEC:
-
if (optptr[2]+7 > optptr[1]) {
-
pp_ptr = optptr + 2;
-
goto error;
-
}
-
opt->ts = optptr - iph;
-
{
-
u32 addr;
-
memcpy(&addr, &optptr[optptr[2]-1], 4);
-
if (inet_addr_type(addr) == RTN_UNICAST)
-
break;
-
if (skb)
-
timeptr = (__u32*)&optptr[optptr[2]+3];
-
}
-
opt->ts_needtime = 1;
-
optptr[2] += 8;
-
break;
-
default:
-
if (!skb && !capable(CAP_NET_RAW)) {
-
pp_ptr = optptr + 3;
-
goto error;
-
}
-
break;
-
}
-
if (timeptr) {
-
struct timeval tv;
-
__u32 midtime;
-
do_gettimeofday(&tv);
-
midtime = htonl((tv.tv_sec % 86400) * 1000 + tv.tv_usec / 1000);
-
memcpy(timeptr, &midtime, sizeof(__u32));
-
opt->is_changed = 1;
-
}
-
} else {
-
unsigned overflow = optptr[3]>>4;
-
if (overflow == 15) {
-
pp_ptr = optptr + 3;
-
goto error;
-
}
-
opt->ts = optptr - iph;
-
if (skb) {
-
optptr[3] = (optptr[3]&0xF)|((overflow+1)<<4);
-
opt->is_changed = 1;
-
}
-
}
-
break;
-
case IPOPT_RA:
-
if (optlen < 4) {
-
pp_ptr = optptr + 1;
-
goto error;
-
}
-
if (optptr[2] == 0 && optptr[3] == 0)
-
opt->router_alert = optptr - iph;
-
break;
-
case IPOPT_SEC:
-
case IPOPT_SID:
-
default:
-
if (!skb && !capable(CAP_NET_RAW)) {
-
pp_ptr = optptr;
-
goto error;
-
}
-
break;
-
}
-
l -= optlen;
-
optptr += optlen;
-
}
-
-
eol:
-
if (!pp_ptr)
-
return 0;
-
-
error:
-
if (skb) {
-
icmp_send(skb, ICMP_PARAMETERPROB, 0, htonl((pp_ptr-iph)<<24));
-
}
-
return -EINVAL;
-
}
-
阅读(1134) | 评论(0) | 转发(0) |