Replace kfree_skb() which is used in ip6_forward() and ip_forward() with kfree_skb_reason(). The new drop reason 'SKB_DROP_REASON_PKT_TOO_BIG' is introduced for the case that the length of the packet exceeds MTU and can't fragment.
Unified · Split
| @@ -453,6 +453,9 @@ enum skb_drop_reason { · 452 unmodified lines | |||
| 453 | SKB_DROP_REASON_IP_INNOROUTES, /* network unreachable, corresponding | 453 | SKB_DROP_REASON_IP_INNOROUTES, /* network unreachable, corresponding |
| 454 | * to IPSTATS_MIB_INADDRERRORS | 454 | * to IPSTATS_MIB_INADDRERRORS |
| 455 | */ | 455 | */ |
| 456 | SKB_DROP_REASON_PKT_TOO_BIG, /* packet size is too big (maybe exceed | ||
| 457 | * the MTU) | ||
| 458 | */ | ||
| 456 | SKB_DROP_REASON_MAX, | 459 | SKB_DROP_REASON_MAX, |
| 457 | }; | 460 | }; |
| 458 | 461 | ||
| @@ -65,6 +65,7 @@ · 64 unmodified lines | |||
| 65 | EM(SKB_DROP_REASON_INVALID_PROTO, INVALID_PROTO) \ | 65 | EM(SKB_DROP_REASON_INVALID_PROTO, INVALID_PROTO) \ |
| 66 | EM(SKB_DROP_REASON_IP_INADDRERRORS, IP_INADDRERRORS) \ | 66 | EM(SKB_DROP_REASON_IP_INADDRERRORS, IP_INADDRERRORS) \ |
| 67 | EM(SKB_DROP_REASON_IP_INNOROUTES, IP_INNOROUTES) \ | 67 | EM(SKB_DROP_REASON_IP_INNOROUTES, IP_INNOROUTES) \ |
| 68 | EM(SKB_DROP_REASON_PKT_TOO_BIG, PKT_TOO_BIG) \ | ||
| 68 | EMe(SKB_DROP_REASON_MAX, MAX) | 69 | EMe(SKB_DROP_REASON_MAX, MAX) |
| 69 | 70 | ||
| 70 | #undef EM | 71 | #undef EM |
| @@ -90,6 +90,7 @@ int ip_forward(struct sk_buff *skb) · 89 unmodified lines | |||
| 90 | struct rtable *rt; /* Route we use */ | 90 | struct rtable *rt; /* Route we use */ |
| 91 | struct ip_options *opt = &(IPCB(skb)->opt); | 91 | struct ip_options *opt = &(IPCB(skb)->opt); |
| 92 | struct net *net; | 92 | struct net *net; |
| 93 | SKB_DR(reason); | ||
| 93 | 94 | ||
| 94 | /* that should never happen */ | 95 | /* that should never happen */ |
| 95 | if (skb->pkt_type != PACKET_HOST) | 96 | if (skb->pkt_type != PACKET_HOST) |
| @@ -101,8 +102,10 @@ int ip_forward(struct sk_buff *skb) · 5 unmodified lines | |||
| 101 | if (skb_warn_if_lro(skb)) | 102 | if (skb_warn_if_lro(skb)) |
| 102 | goto drop; | 103 | goto drop; |
| 103 | 104 | ||
| 104 | if (!xfrm4_policy_check(NULL, XFRM_POLICY_FWD, skb)) | 105 | if (!xfrm4_policy_check(NULL, XFRM_POLICY_FWD, skb)) { |
| 106 | SKB_DR_SET(reason, XFRM_POLICY); | ||
| 105 | goto drop; | 107 | goto drop; |
| 108 | } | ||
| 106 | 109 | ||
| 107 | if (IPCB(skb)->opt.router_alert && ip_call_ra_chain(skb)) | 110 | if (IPCB(skb)->opt.router_alert && ip_call_ra_chain(skb)) |
| 108 | return NET_RX_SUCCESS; | 111 | return NET_RX_SUCCESS; |
| @@ -118,8 +121,10 @@ int ip_forward(struct sk_buff *skb) · 9 unmodified lines | |||
| 118 | if (ip_hdr(skb)->ttl <= 1) | 121 | if (ip_hdr(skb)->ttl <= 1) |
| 119 | goto too_many_hops; | 122 | goto too_many_hops; |
| 120 | 123 | ||
| 121 | if (!xfrm4_route_forward(skb)) | 124 | if (!xfrm4_route_forward(skb)) { |
| 125 | SKB_DR_SET(reason, XFRM_POLICY); | ||
| 122 | goto drop; | 126 | goto drop; |
| 127 | } | ||
| 123 | 128 | ||
| 124 | rt = skb_rtable(skb); | 129 | rt = skb_rtable(skb); |
| 125 | 130 | ||
| @@ -132,6 +137,7 @@ int ip_forward(struct sk_buff *skb) · 6 unmodified lines | |||
| 132 | IP_INC_STATS(net, IPSTATS_MIB_FRAGFAILS); | 137 | IP_INC_STATS(net, IPSTATS_MIB_FRAGFAILS); |
| 133 | icmp_send(skb, ICMP_DEST_UNREACH, ICMP_FRAG_NEEDED, | 138 | icmp_send(skb, ICMP_DEST_UNREACH, ICMP_FRAG_NEEDED, |
| 134 | htonl(mtu)); | 139 | htonl(mtu)); |
| 140 | SKB_DR_SET(reason, PKT_TOO_BIG); | ||
| 135 | goto drop; | 141 | goto drop; |
| 136 | } | 142 | } |
| 137 | 143 | ||
| @@ -169,7 +175,8 @@ too_many_hops: · 31 unmodified lines | |||
| 169 | /* Tell the sender its packet died... */ | 175 | /* Tell the sender its packet died... */ |
| 170 | __IP_INC_STATS(net, IPSTATS_MIB_INHDRERRORS); | 176 | __IP_INC_STATS(net, IPSTATS_MIB_INHDRERRORS); |
| 171 | icmp_send(skb, ICMP_TIME_EXCEEDED, ICMP_EXC_TTL, 0); | 177 | icmp_send(skb, ICMP_TIME_EXCEEDED, ICMP_EXC_TTL, 0); |
| 178 | SKB_DR_SET(reason, IP_INHDR); | ||
| 172 | drop: | 179 | drop: |
| 173 | kfree_skb(skb); | 180 | kfree_skb_reason(skb, reason); |
| 174 | return NET_RX_DROP; | 181 | return NET_RX_DROP; |
| 175 | } | 182 | } |
| @@ -469,6 +469,7 @@ int ip6_forward(struct sk_buff *skb) · 468 unmodified lines | |||
| 469 | struct inet6_skb_parm *opt = IP6CB(skb); | 469 | struct inet6_skb_parm *opt = IP6CB(skb); |
| 470 | struct net *net = dev_net(dst->dev); | 470 | struct net *net = dev_net(dst->dev); |
| 471 | struct inet6_dev *idev; | 471 | struct inet6_dev *idev; |
| 472 | SKB_DR(reason); | ||
| 472 | u32 mtu; | 473 | u32 mtu; |
| 473 | 474 | ||
| 474 | idev = __in6_dev_get_safely(dev_get_by_index_rcu(net, IP6CB(skb)->iif)); | 475 | idev = __in6_dev_get_safely(dev_get_by_index_rcu(net, IP6CB(skb)->iif)); |
| @@ -518,7 +519,7 @@ int ip6_forward(struct sk_buff *skb) · 43 unmodified lines | |||
| 518 | icmpv6_send(skb, ICMPV6_TIME_EXCEED, ICMPV6_EXC_HOPLIMIT, 0); | 519 | icmpv6_send(skb, ICMPV6_TIME_EXCEED, ICMPV6_EXC_HOPLIMIT, 0); |
| 519 | __IP6_INC_STATS(net, idev, IPSTATS_MIB_INHDRERRORS); | 520 | __IP6_INC_STATS(net, idev, IPSTATS_MIB_INHDRERRORS); |
| 520 | 521 | ||
| 521 | kfree_skb(skb); | 522 | kfree_skb_reason(skb, SKB_DROP_REASON_IP_INHDR); |
| 522 | return -ETIMEDOUT; | 523 | return -ETIMEDOUT; |
| 523 | } | 524 | } |
| 524 | 525 | ||
| @@ -537,6 +538,7 @@ int ip6_forward(struct sk_buff *skb) · 12 unmodified lines | |||
| 537 | 538 | ||
| 538 | if (!xfrm6_route_forward(skb)) { | 539 | if (!xfrm6_route_forward(skb)) { |
| 539 | __IP6_INC_STATS(net, idev, IPSTATS_MIB_INDISCARDS); | 540 | __IP6_INC_STATS(net, idev, IPSTATS_MIB_INDISCARDS); |
| 541 | SKB_DR_SET(reason, XFRM_POLICY); | ||
| 540 | goto drop; | 542 | goto drop; |
| 541 | } | 543 | } |
| 542 | dst = skb_dst(skb); | 544 | dst = skb_dst(skb); |
| @@ -596,7 +598,7 @@ int ip6_forward(struct sk_buff *skb) · 53 unmodified lines | |||
| 596 | __IP6_INC_STATS(net, idev, IPSTATS_MIB_INTOOBIGERRORS); | 598 | __IP6_INC_STATS(net, idev, IPSTATS_MIB_INTOOBIGERRORS); |
| 597 | __IP6_INC_STATS(net, ip6_dst_idev(dst), | 599 | __IP6_INC_STATS(net, ip6_dst_idev(dst), |
| 598 | IPSTATS_MIB_FRAGFAILS); | 600 | IPSTATS_MIB_FRAGFAILS); |
| 599 | kfree_skb(skb); | 601 | kfree_skb_reason(skb, SKB_DROP_REASON_PKT_TOO_BIG); |
| 600 | return -EMSGSIZE; | 602 | return -EMSGSIZE; |
| 601 | } | 603 | } |
| 602 | 604 | ||
| @@ -618,8 +620,9 @@ int ip6_forward(struct sk_buff *skb) · 15 unmodified lines | |||
| 618 | 620 | ||
| 619 | error: | 621 | error: |
| 620 | __IP6_INC_STATS(net, idev, IPSTATS_MIB_INADDRERRORS); | 622 | __IP6_INC_STATS(net, idev, IPSTATS_MIB_INADDRERRORS); |
| 623 | SKB_DR_SET(reason, IP_INADDRERRORS); | ||
| 621 | drop: | 624 | drop: |
| 622 | kfree_skb(skb); | 625 | kfree_skb_reason(skb, reason); |
| 623 | return -EINVAL; | 626 | return -EINVAL; |
| 624 | } | 627 | } |
| 625 | 628 | ||