ip_options.c (57b8628bb0ac4e47c806e45c5bbd89282e93869b) | ip_options.c (e87cc4728f0e2fb663e592a1141742b1d6c63256) |
---|---|
1/* 2 * INET An implementation of the TCP/IP protocol suite for the LINUX 3 * operating system. INET is implemented using the BSD Socket 4 * interface as the means of communication with the user level. 5 * 6 * The options processing module for ip.c 7 * 8 * Authors: A.N.Kuznetsov --- 196 unchanged lines hidden (view full) --- 205} 206 207/* 208 * Options "fragmenting", just fill options not 209 * allowed in fragments with NOOPs. 210 * Simple and stupid 8), but the most efficient way. 211 */ 212 | 1/* 2 * INET An implementation of the TCP/IP protocol suite for the LINUX 3 * operating system. INET is implemented using the BSD Socket 4 * interface as the means of communication with the user level. 5 * 6 * The options processing module for ip.c 7 * 8 * Authors: A.N.Kuznetsov --- 196 unchanged lines hidden (view full) --- 205} 206 207/* 208 * Options "fragmenting", just fill options not 209 * allowed in fragments with NOOPs. 210 * Simple and stupid 8), but the most efficient way. 211 */ 212 |
213void ip_options_fragment(struct sk_buff * skb) | 213void ip_options_fragment(struct sk_buff *skb) |
214{ 215 unsigned char *optptr = skb_network_header(skb) + sizeof(struct iphdr); | 214{ 215 unsigned char *optptr = skb_network_header(skb) + sizeof(struct iphdr); |
216 struct ip_options * opt = &(IPCB(skb)->opt); | 216 struct ip_options *opt = &(IPCB(skb)->opt); |
217 int l = opt->optlen; 218 int optlen; 219 220 while (l > 0) { 221 switch (*optptr) { 222 case IPOPT_END: 223 return; 224 case IPOPT_NOOP: --- 18 unchanged lines hidden (view full) --- 243 244/* 245 * Verify options and fill pointers in struct options. 246 * Caller should clear *opt, and set opt->data. 247 * If opt == NULL, then skb->data should point to IP header. 248 */ 249 250int ip_options_compile(struct net *net, | 217 int l = opt->optlen; 218 int optlen; 219 220 while (l > 0) { 221 switch (*optptr) { 222 case IPOPT_END: 223 return; 224 case IPOPT_NOOP: --- 18 unchanged lines hidden (view full) --- 243 244/* 245 * Verify options and fill pointers in struct options. 246 * Caller should clear *opt, and set opt->data. 247 * If opt == NULL, then skb->data should point to IP header. 248 */ 249 250int ip_options_compile(struct net *net, |
251 struct ip_options * opt, struct sk_buff * skb) | 251 struct ip_options *opt, struct sk_buff *skb) |
252{ 253 int l; | 252{ 253 int l; |
254 unsigned char * iph; 255 unsigned char * optptr; | 254 unsigned char *iph; 255 unsigned char *optptr; |
256 int optlen; | 256 int optlen; |
257 unsigned char * pp_ptr = NULL; | 257 unsigned char *pp_ptr = NULL; |
258 struct rtable *rt = NULL; 259 260 if (skb != NULL) { 261 rt = skb_rtable(skb); 262 optptr = (unsigned char *)&(ip_hdr(skb)[1]); 263 } else 264 optptr = opt->__data; 265 iph = optptr - sizeof(struct iphdr); --- 142 unchanged lines hidden (view full) --- 408 struct timespec tv; 409 u32 midtime; 410 getnstimeofday(&tv); 411 midtime = (tv.tv_sec % 86400) * MSEC_PER_SEC + tv.tv_nsec / NSEC_PER_MSEC; 412 put_unaligned_be32(midtime, timeptr); 413 opt->is_changed = 1; 414 } 415 } else { | 258 struct rtable *rt = NULL; 259 260 if (skb != NULL) { 261 rt = skb_rtable(skb); 262 optptr = (unsigned char *)&(ip_hdr(skb)[1]); 263 } else 264 optptr = opt->__data; 265 iph = optptr - sizeof(struct iphdr); --- 142 unchanged lines hidden (view full) --- 408 struct timespec tv; 409 u32 midtime; 410 getnstimeofday(&tv); 411 midtime = (tv.tv_sec % 86400) * MSEC_PER_SEC + tv.tv_nsec / NSEC_PER_MSEC; 412 put_unaligned_be32(midtime, timeptr); 413 opt->is_changed = 1; 414 } 415 } else { |
416 unsigned overflow = optptr[3]>>4; | 416 unsigned int overflow = optptr[3]>>4; |
417 if (overflow == 15) { 418 pp_ptr = optptr + 3; 419 goto error; 420 } 421 opt->ts = optptr - iph; 422 if (skb) { 423 optptr[3] = (optptr[3]&0xF)|((overflow+1)<<4); 424 opt->is_changed = 1; --- 43 unchanged lines hidden (view full) --- 468 return -EINVAL; 469} 470EXPORT_SYMBOL(ip_options_compile); 471 472/* 473 * Undo all the changes done by ip_options_compile(). 474 */ 475 | 417 if (overflow == 15) { 418 pp_ptr = optptr + 3; 419 goto error; 420 } 421 opt->ts = optptr - iph; 422 if (skb) { 423 optptr[3] = (optptr[3]&0xF)|((overflow+1)<<4); 424 opt->is_changed = 1; --- 43 unchanged lines hidden (view full) --- 468 return -EINVAL; 469} 470EXPORT_SYMBOL(ip_options_compile); 471 472/* 473 * Undo all the changes done by ip_options_compile(). 474 */ 475 |
476void ip_options_undo(struct ip_options * opt) | 476void ip_options_undo(struct ip_options *opt) |
477{ 478 if (opt->srr) { | 477{ 478 if (opt->srr) { |
479 unsigned char * optptr = opt->__data+opt->srr-sizeof(struct iphdr); | 479 unsigned char *optptr = opt->__data+opt->srr-sizeof(struct iphdr); |
480 memmove(optptr+7, optptr+3, optptr[1]-7); 481 memcpy(optptr+3, &opt->faddr, 4); 482 } 483 if (opt->rr_needaddr) { | 480 memmove(optptr+7, optptr+3, optptr[1]-7); 481 memcpy(optptr+3, &opt->faddr, 4); 482 } 483 if (opt->rr_needaddr) { |
484 unsigned char * optptr = opt->__data+opt->rr-sizeof(struct iphdr); | 484 unsigned char *optptr = opt->__data+opt->rr-sizeof(struct iphdr); |
485 optptr[2] -= 4; 486 memset(&optptr[optptr[2]-1], 0, 4); 487 } 488 if (opt->ts) { | 485 optptr[2] -= 4; 486 memset(&optptr[optptr[2]-1], 0, 4); 487 } 488 if (opt->ts) { |
489 unsigned char * optptr = opt->__data+opt->ts-sizeof(struct iphdr); | 489 unsigned char *optptr = opt->__data+opt->ts-sizeof(struct iphdr); |
490 if (opt->ts_needtime) { 491 optptr[2] -= 4; 492 memset(&optptr[optptr[2]-1], 0, 4); 493 if ((optptr[3]&0xF) == IPOPT_TS_PRESPEC) 494 optptr[2] -= 4; 495 } 496 if (opt->ts_needaddr) { 497 optptr[2] -= 4; --- 46 unchanged lines hidden (view full) --- 544 return -ENOMEM; 545 if (optlen) 546 memcpy(opt->opt.__data, data, optlen); 547 return ip_options_get_finish(net, optp, opt, optlen); 548} 549 550void ip_forward_options(struct sk_buff *skb) 551{ | 490 if (opt->ts_needtime) { 491 optptr[2] -= 4; 492 memset(&optptr[optptr[2]-1], 0, 4); 493 if ((optptr[3]&0xF) == IPOPT_TS_PRESPEC) 494 optptr[2] -= 4; 495 } 496 if (opt->ts_needaddr) { 497 optptr[2] -= 4; --- 46 unchanged lines hidden (view full) --- 544 return -ENOMEM; 545 if (optlen) 546 memcpy(opt->opt.__data, data, optlen); 547 return ip_options_get_finish(net, optp, opt, optlen); 548} 549 550void ip_forward_options(struct sk_buff *skb) 551{ |
552 struct ip_options * opt = &(IPCB(skb)->opt); 553 unsigned char * optptr; | 552 struct ip_options *opt = &(IPCB(skb)->opt); 553 unsigned char *optptr; |
554 struct rtable *rt = skb_rtable(skb); 555 unsigned char *raw = skb_network_header(skb); 556 557 if (opt->rr_needaddr) { 558 optptr = (unsigned char *)raw + opt->rr; 559 ip_rt_get_source(&optptr[optptr[2]-5], skb, rt); 560 opt->is_changed = 1; 561 } --- 11 unchanged lines hidden (view full) --- 573 if (memcmp(&opt->nexthop, &optptr[srrptr-1], 4) == 0) 574 break; 575 } 576 if (srrptr + 3 <= srrspace) { 577 opt->is_changed = 1; 578 ip_hdr(skb)->daddr = opt->nexthop; 579 ip_rt_get_source(&optptr[srrptr-1], skb, rt); 580 optptr[2] = srrptr+4; | 554 struct rtable *rt = skb_rtable(skb); 555 unsigned char *raw = skb_network_header(skb); 556 557 if (opt->rr_needaddr) { 558 optptr = (unsigned char *)raw + opt->rr; 559 ip_rt_get_source(&optptr[optptr[2]-5], skb, rt); 560 opt->is_changed = 1; 561 } --- 11 unchanged lines hidden (view full) --- 573 if (memcmp(&opt->nexthop, &optptr[srrptr-1], 4) == 0) 574 break; 575 } 576 if (srrptr + 3 <= srrspace) { 577 opt->is_changed = 1; 578 ip_hdr(skb)->daddr = opt->nexthop; 579 ip_rt_get_source(&optptr[srrptr-1], skb, rt); 580 optptr[2] = srrptr+4; |
581 } else if (net_ratelimit()) 582 pr_crit("%s(): Argh! Destination lost!\n", __func__); | 581 } else { 582 net_crit_ratelimited("%s(): Argh! Destination lost!\n", 583 __func__); 584 } |
583 if (opt->ts_needaddr) { 584 optptr = raw + opt->ts; 585 ip_rt_get_source(&optptr[optptr[2]-9], skb, rt); 586 opt->is_changed = 1; 587 } 588 } 589 if (opt->is_changed) { 590 opt->is_changed = 0; --- 61 unchanged lines hidden --- | 585 if (opt->ts_needaddr) { 586 optptr = raw + opt->ts; 587 ip_rt_get_source(&optptr[optptr[2]-9], skb, rt); 588 opt->is_changed = 1; 589 } 590 } 591 if (opt->is_changed) { 592 opt->is_changed = 0; --- 61 unchanged lines hidden --- |