|
@@ -372,22 +372,13 @@ static int ipv6_rthdr_rcv(struct sk_buff **skbp)
|
|
|
struct rt0_hdr *rthdr;
|
|
|
int accept_source_route = ipv6_devconf.accept_source_route;
|
|
|
|
|
|
- if (accept_source_route < 0 ||
|
|
|
- ((idev = in6_dev_get(skb->dev)) == NULL)) {
|
|
|
- kfree_skb(skb);
|
|
|
- return -1;
|
|
|
- }
|
|
|
- if (idev->cnf.accept_source_route < 0) {
|
|
|
+ idev = in6_dev_get(skb->dev);
|
|
|
+ if (idev) {
|
|
|
+ if (accept_source_route > idev->cnf.accept_source_route)
|
|
|
+ accept_source_route = idev->cnf.accept_source_route;
|
|
|
in6_dev_put(idev);
|
|
|
- kfree_skb(skb);
|
|
|
- return -1;
|
|
|
}
|
|
|
|
|
|
- if (accept_source_route > idev->cnf.accept_source_route)
|
|
|
- accept_source_route = idev->cnf.accept_source_route;
|
|
|
-
|
|
|
- in6_dev_put(idev);
|
|
|
-
|
|
|
if (!pskb_may_pull(skb, skb_transport_offset(skb) + 8) ||
|
|
|
!pskb_may_pull(skb, (skb_transport_offset(skb) +
|
|
|
((skb_transport_header(skb)[1] + 1) << 3)))) {
|
|
@@ -399,24 +390,6 @@ static int ipv6_rthdr_rcv(struct sk_buff **skbp)
|
|
|
|
|
|
hdr = (struct ipv6_rt_hdr *)skb_transport_header(skb);
|
|
|
|
|
|
- switch (hdr->type) {
|
|
|
-#ifdef CONFIG_IPV6_MIP6
|
|
|
- case IPV6_SRCRT_TYPE_2:
|
|
|
- break;
|
|
|
-#endif
|
|
|
- case IPV6_SRCRT_TYPE_0:
|
|
|
- if (accept_source_route > 0)
|
|
|
- break;
|
|
|
- kfree_skb(skb);
|
|
|
- return -1;
|
|
|
- default:
|
|
|
- IP6_INC_STATS_BH(ip6_dst_idev(skb->dst),
|
|
|
- IPSTATS_MIB_INHDRERRORS);
|
|
|
- icmpv6_param_prob(skb, ICMPV6_HDR_FIELD,
|
|
|
- (&hdr->type) - skb_network_header(skb));
|
|
|
- return -1;
|
|
|
- }
|
|
|
-
|
|
|
if (ipv6_addr_is_multicast(&ipv6_hdr(skb)->daddr) ||
|
|
|
skb->pkt_type != PACKET_HOST) {
|
|
|
IP6_INC_STATS_BH(ip6_dst_idev(skb->dst),
|
|
@@ -455,6 +428,8 @@ looped_back:
|
|
|
|
|
|
switch (hdr->type) {
|
|
|
case IPV6_SRCRT_TYPE_0:
|
|
|
+ if (accept_source_route <= 0)
|
|
|
+ goto unknown_rh;
|
|
|
if (hdr->hdrlen & 0x01) {
|
|
|
IP6_INC_STATS_BH(ip6_dst_idev(skb->dst),
|
|
|
IPSTATS_MIB_INHDRERRORS);
|
|
@@ -466,6 +441,8 @@ looped_back:
|
|
|
break;
|
|
|
#if defined(CONFIG_IPV6_MIP6) || defined(CONFIG_IPV6_MIP6_MODULE)
|
|
|
case IPV6_SRCRT_TYPE_2:
|
|
|
+ if (accept_source_route < 0)
|
|
|
+ goto unknown_rh;
|
|
|
/* Silently discard invalid RTH type 2 */
|
|
|
if (hdr->hdrlen != 2 || hdr->segments_left != 1) {
|
|
|
IP6_INC_STATS_BH(ip6_dst_idev(skb->dst),
|
|
@@ -475,6 +452,8 @@ looped_back:
|
|
|
}
|
|
|
break;
|
|
|
#endif
|
|
|
+ default:
|
|
|
+ goto unknown_rh;
|
|
|
}
|
|
|
|
|
|
/*
|
|
@@ -578,6 +557,12 @@ looped_back:
|
|
|
skb_push(skb, skb->data - skb_network_header(skb));
|
|
|
dst_input(skb);
|
|
|
return -1;
|
|
|
+
|
|
|
+unknown_rh:
|
|
|
+ IP6_INC_STATS_BH(ip6_dst_idev(skb->dst), IPSTATS_MIB_INHDRERRORS);
|
|
|
+ icmpv6_param_prob(skb, ICMPV6_HDR_FIELD,
|
|
|
+ (&hdr->type) - skb_network_header(skb));
|
|
|
+ return -1;
|
|
|
}
|
|
|
|
|
|
static struct inet6_protocol rthdr_protocol = {
|