aboutsummaryrefslogtreecommitdiffstats
path: root/net/ipv4/ip_gre.c
diff options
context:
space:
mode:
Diffstat (limited to 'net/ipv4/ip_gre.c')
-rw-r--r--net/ipv4/ip_gre.c27
1 files changed, 15 insertions, 12 deletions
diff --git a/net/ipv4/ip_gre.c b/net/ipv4/ip_gre.c
index 0f9b3a31997b..f5fba051df3d 100644
--- a/net/ipv4/ip_gre.c
+++ b/net/ipv4/ip_gre.c
@@ -393,7 +393,8 @@ out:
393 int code = skb->h.icmph->code; 393 int code = skb->h.icmph->code;
394 int rel_type = 0; 394 int rel_type = 0;
395 int rel_code = 0; 395 int rel_code = 0;
396 int rel_info = 0; 396 __be32 rel_info = 0;
397 __u32 n = 0;
397 u16 flags; 398 u16 flags;
398 int grehlen = (iph->ihl<<2) + 4; 399 int grehlen = (iph->ihl<<2) + 4;
399 struct sk_buff *skb2; 400 struct sk_buff *skb2;
@@ -422,14 +423,16 @@ out:
422 default: 423 default:
423 return; 424 return;
424 case ICMP_PARAMETERPROB: 425 case ICMP_PARAMETERPROB:
425 if (skb->h.icmph->un.gateway < (iph->ihl<<2)) 426 n = ntohl(skb->h.icmph->un.gateway) >> 24;
427 if (n < (iph->ihl<<2))
426 return; 428 return;
427 429
428 /* So... This guy found something strange INSIDE encapsulated 430 /* So... This guy found something strange INSIDE encapsulated
429 packet. Well, he is fool, but what can we do ? 431 packet. Well, he is fool, but what can we do ?
430 */ 432 */
431 rel_type = ICMP_PARAMETERPROB; 433 rel_type = ICMP_PARAMETERPROB;
432 rel_info = skb->h.icmph->un.gateway - grehlen; 434 n -= grehlen;
435 rel_info = htonl(n << 24);
433 break; 436 break;
434 437
435 case ICMP_DEST_UNREACH: 438 case ICMP_DEST_UNREACH:
@@ -440,13 +443,14 @@ out:
440 return; 443 return;
441 case ICMP_FRAG_NEEDED: 444 case ICMP_FRAG_NEEDED:
442 /* And it is the only really necessary thing :-) */ 445 /* And it is the only really necessary thing :-) */
443 rel_info = ntohs(skb->h.icmph->un.frag.mtu); 446 n = ntohs(skb->h.icmph->un.frag.mtu);
444 if (rel_info < grehlen+68) 447 if (n < grehlen+68)
445 return; 448 return;
446 rel_info -= grehlen; 449 n -= grehlen;
447 /* BSD 4.2 MORE DOES NOT EXIST IN NATURE. */ 450 /* BSD 4.2 MORE DOES NOT EXIST IN NATURE. */
448 if (rel_info > ntohs(eiph->tot_len)) 451 if (n > ntohs(eiph->tot_len))
449 return; 452 return;
453 rel_info = htonl(n);
450 break; 454 break;
451 default: 455 default:
452 /* All others are translated to HOST_UNREACH. 456 /* All others are translated to HOST_UNREACH.
@@ -508,12 +512,11 @@ out:
508 512
509 /* change mtu on this route */ 513 /* change mtu on this route */
510 if (type == ICMP_DEST_UNREACH && code == ICMP_FRAG_NEEDED) { 514 if (type == ICMP_DEST_UNREACH && code == ICMP_FRAG_NEEDED) {
511 if (rel_info > dst_mtu(skb2->dst)) { 515 if (n > dst_mtu(skb2->dst)) {
512 kfree_skb(skb2); 516 kfree_skb(skb2);
513 return; 517 return;
514 } 518 }
515 skb2->dst->ops->update_pmtu(skb2->dst, rel_info); 519 skb2->dst->ops->update_pmtu(skb2->dst, n);
516 rel_info = htonl(rel_info);
517 } else if (type == ICMP_TIME_EXCEEDED) { 520 } else if (type == ICMP_TIME_EXCEEDED) {
518 struct ip_tunnel *t = netdev_priv(skb2->dev); 521 struct ip_tunnel *t = netdev_priv(skb2->dev);
519 if (t->parms.iph.ttl) { 522 if (t->parms.iph.ttl) {
@@ -576,7 +579,7 @@ static int ipgre_rcv(struct sk_buff *skb)
576 579
577 if (flags&GRE_CSUM) { 580 if (flags&GRE_CSUM) {
578 switch (skb->ip_summed) { 581 switch (skb->ip_summed) {
579 case CHECKSUM_HW: 582 case CHECKSUM_COMPLETE:
580 csum = (u16)csum_fold(skb->csum); 583 csum = (u16)csum_fold(skb->csum);
581 if (!csum) 584 if (!csum)
582 break; 585 break;
@@ -584,7 +587,7 @@ static int ipgre_rcv(struct sk_buff *skb)
584 case CHECKSUM_NONE: 587 case CHECKSUM_NONE:
585 skb->csum = 0; 588 skb->csum = 0;
586 csum = __skb_checksum_complete(skb); 589 csum = __skb_checksum_complete(skb);
587 skb->ip_summed = CHECKSUM_HW; 590 skb->ip_summed = CHECKSUM_COMPLETE;
588 } 591 }
589 offset += 4; 592 offset += 4;
590 } 593 }