diff options
Diffstat (limited to 'net/ipv6')
-rw-r--r-- | net/ipv6/addrconf.c | 55 | ||||
-rw-r--r-- | net/ipv6/addrlabel.c | 9 | ||||
-rw-r--r-- | net/ipv6/af_inet6.c | 2 | ||||
-rw-r--r-- | net/ipv6/ip6_fib.c | 5 | ||||
-rw-r--r-- | net/ipv6/ip6_output.c | 58 | ||||
-rw-r--r-- | net/ipv6/ip6mr.c | 3 | ||||
-rw-r--r-- | net/ipv6/ndisc.c | 16 | ||||
-rw-r--r-- | net/ipv6/raw.c | 145 | ||||
-rw-r--r-- | net/ipv6/route.c | 110 | ||||
-rw-r--r-- | net/ipv6/sit.c | 4 | ||||
-rw-r--r-- | net/ipv6/syncookies.c | 1 | ||||
-rw-r--r-- | net/ipv6/tcp_ipv6.c | 5 | ||||
-rw-r--r-- | net/ipv6/udp.c | 7 |
13 files changed, 250 insertions, 170 deletions
diff --git a/net/ipv6/addrconf.c b/net/ipv6/addrconf.c index 498b927f68be..a06c53c14d84 100644 --- a/net/ipv6/addrconf.c +++ b/net/ipv6/addrconf.c | |||
@@ -656,7 +656,7 @@ ipv6_add_addr(struct inet6_dev *idev, const struct in6_addr *addr, int pfxlen, | |||
656 | * layer address of our nexhop router | 656 | * layer address of our nexhop router |
657 | */ | 657 | */ |
658 | 658 | ||
659 | if (rt->rt6i_nexthop == NULL) | 659 | if (dst_get_neighbour(&rt->dst) == NULL) |
660 | ifa->flags &= ~IFA_F_OPTIMISTIC; | 660 | ifa->flags &= ~IFA_F_OPTIMISTIC; |
661 | 661 | ||
662 | ifa->idev = idev; | 662 | ifa->idev = idev; |
@@ -1470,6 +1470,8 @@ void addrconf_leave_solict(struct inet6_dev *idev, const struct in6_addr *addr) | |||
1470 | static void addrconf_join_anycast(struct inet6_ifaddr *ifp) | 1470 | static void addrconf_join_anycast(struct inet6_ifaddr *ifp) |
1471 | { | 1471 | { |
1472 | struct in6_addr addr; | 1472 | struct in6_addr addr; |
1473 | if (ifp->prefix_len == 127) /* RFC 6164 */ | ||
1474 | return; | ||
1473 | ipv6_addr_prefix(&addr, &ifp->addr, ifp->prefix_len); | 1475 | ipv6_addr_prefix(&addr, &ifp->addr, ifp->prefix_len); |
1474 | if (ipv6_addr_any(&addr)) | 1476 | if (ipv6_addr_any(&addr)) |
1475 | return; | 1477 | return; |
@@ -1559,6 +1561,11 @@ static int addrconf_ifid_sit(u8 *eui, struct net_device *dev) | |||
1559 | return -1; | 1561 | return -1; |
1560 | } | 1562 | } |
1561 | 1563 | ||
1564 | static int addrconf_ifid_gre(u8 *eui, struct net_device *dev) | ||
1565 | { | ||
1566 | return __ipv6_isatap_ifid(eui, *(__be32 *)dev->dev_addr); | ||
1567 | } | ||
1568 | |||
1562 | static int ipv6_generate_eui64(u8 *eui, struct net_device *dev) | 1569 | static int ipv6_generate_eui64(u8 *eui, struct net_device *dev) |
1563 | { | 1570 | { |
1564 | switch (dev->type) { | 1571 | switch (dev->type) { |
@@ -1572,6 +1579,8 @@ static int ipv6_generate_eui64(u8 *eui, struct net_device *dev) | |||
1572 | return addrconf_ifid_infiniband(eui, dev); | 1579 | return addrconf_ifid_infiniband(eui, dev); |
1573 | case ARPHRD_SIT: | 1580 | case ARPHRD_SIT: |
1574 | return addrconf_ifid_sit(eui, dev); | 1581 | return addrconf_ifid_sit(eui, dev); |
1582 | case ARPHRD_IPGRE: | ||
1583 | return addrconf_ifid_gre(eui, dev); | ||
1575 | } | 1584 | } |
1576 | return -1; | 1585 | return -1; |
1577 | } | 1586 | } |
@@ -2423,6 +2432,29 @@ static void addrconf_sit_config(struct net_device *dev) | |||
2423 | } | 2432 | } |
2424 | #endif | 2433 | #endif |
2425 | 2434 | ||
2435 | #if defined(CONFIG_NET_IPGRE) || defined(CONFIG_NET_IPGRE_MODULE) | ||
2436 | static void addrconf_gre_config(struct net_device *dev) | ||
2437 | { | ||
2438 | struct inet6_dev *idev; | ||
2439 | struct in6_addr addr; | ||
2440 | |||
2441 | pr_info("ipv6: addrconf_gre_config(%s)\n", dev->name); | ||
2442 | |||
2443 | ASSERT_RTNL(); | ||
2444 | |||
2445 | if ((idev = ipv6_find_idev(dev)) == NULL) { | ||
2446 | printk(KERN_DEBUG "init gre: add_dev failed\n"); | ||
2447 | return; | ||
2448 | } | ||
2449 | |||
2450 | ipv6_addr_set(&addr, htonl(0xFE800000), 0, 0, 0); | ||
2451 | addrconf_prefix_route(&addr, 64, dev, 0, 0); | ||
2452 | |||
2453 | if (!ipv6_generate_eui64(addr.s6_addr + 8, dev)) | ||
2454 | addrconf_add_linklocal(idev, &addr); | ||
2455 | } | ||
2456 | #endif | ||
2457 | |||
2426 | static inline int | 2458 | static inline int |
2427 | ipv6_inherit_linklocal(struct inet6_dev *idev, struct net_device *link_dev) | 2459 | ipv6_inherit_linklocal(struct inet6_dev *idev, struct net_device *link_dev) |
2428 | { | 2460 | { |
@@ -2539,6 +2571,11 @@ static int addrconf_notify(struct notifier_block *this, unsigned long event, | |||
2539 | addrconf_sit_config(dev); | 2571 | addrconf_sit_config(dev); |
2540 | break; | 2572 | break; |
2541 | #endif | 2573 | #endif |
2574 | #if defined(CONFIG_NET_IPGRE) || defined(CONFIG_NET_IPGRE_MODULE) | ||
2575 | case ARPHRD_IPGRE: | ||
2576 | addrconf_gre_config(dev); | ||
2577 | break; | ||
2578 | #endif | ||
2542 | case ARPHRD_TUNNEL6: | 2579 | case ARPHRD_TUNNEL6: |
2543 | addrconf_ip6_tnl_config(dev); | 2580 | addrconf_ip6_tnl_config(dev); |
2544 | break; | 2581 | break; |
@@ -4692,16 +4729,20 @@ int __init addrconf_init(void) | |||
4692 | if (err < 0) | 4729 | if (err < 0) |
4693 | goto errout_af; | 4730 | goto errout_af; |
4694 | 4731 | ||
4695 | err = __rtnl_register(PF_INET6, RTM_GETLINK, NULL, inet6_dump_ifinfo); | 4732 | err = __rtnl_register(PF_INET6, RTM_GETLINK, NULL, inet6_dump_ifinfo, |
4733 | NULL); | ||
4696 | if (err < 0) | 4734 | if (err < 0) |
4697 | goto errout; | 4735 | goto errout; |
4698 | 4736 | ||
4699 | /* Only the first call to __rtnl_register can fail */ | 4737 | /* Only the first call to __rtnl_register can fail */ |
4700 | __rtnl_register(PF_INET6, RTM_NEWADDR, inet6_rtm_newaddr, NULL); | 4738 | __rtnl_register(PF_INET6, RTM_NEWADDR, inet6_rtm_newaddr, NULL, NULL); |
4701 | __rtnl_register(PF_INET6, RTM_DELADDR, inet6_rtm_deladdr, NULL); | 4739 | __rtnl_register(PF_INET6, RTM_DELADDR, inet6_rtm_deladdr, NULL, NULL); |
4702 | __rtnl_register(PF_INET6, RTM_GETADDR, inet6_rtm_getaddr, inet6_dump_ifaddr); | 4740 | __rtnl_register(PF_INET6, RTM_GETADDR, inet6_rtm_getaddr, |
4703 | __rtnl_register(PF_INET6, RTM_GETMULTICAST, NULL, inet6_dump_ifmcaddr); | 4741 | inet6_dump_ifaddr, NULL); |
4704 | __rtnl_register(PF_INET6, RTM_GETANYCAST, NULL, inet6_dump_ifacaddr); | 4742 | __rtnl_register(PF_INET6, RTM_GETMULTICAST, NULL, |
4743 | inet6_dump_ifmcaddr, NULL); | ||
4744 | __rtnl_register(PF_INET6, RTM_GETANYCAST, NULL, | ||
4745 | inet6_dump_ifacaddr, NULL); | ||
4705 | 4746 | ||
4706 | ipv6_addr_label_rtnl_register(); | 4747 | ipv6_addr_label_rtnl_register(); |
4707 | 4748 | ||
diff --git a/net/ipv6/addrlabel.c b/net/ipv6/addrlabel.c index c8993e5a337c..2d8ddba9ee58 100644 --- a/net/ipv6/addrlabel.c +++ b/net/ipv6/addrlabel.c | |||
@@ -592,8 +592,11 @@ out: | |||
592 | 592 | ||
593 | void __init ipv6_addr_label_rtnl_register(void) | 593 | void __init ipv6_addr_label_rtnl_register(void) |
594 | { | 594 | { |
595 | __rtnl_register(PF_INET6, RTM_NEWADDRLABEL, ip6addrlbl_newdel, NULL); | 595 | __rtnl_register(PF_INET6, RTM_NEWADDRLABEL, ip6addrlbl_newdel, |
596 | __rtnl_register(PF_INET6, RTM_DELADDRLABEL, ip6addrlbl_newdel, NULL); | 596 | NULL, NULL); |
597 | __rtnl_register(PF_INET6, RTM_GETADDRLABEL, ip6addrlbl_get, ip6addrlbl_dump); | 597 | __rtnl_register(PF_INET6, RTM_DELADDRLABEL, ip6addrlbl_newdel, |
598 | NULL, NULL); | ||
599 | __rtnl_register(PF_INET6, RTM_GETADDRLABEL, ip6addrlbl_get, | ||
600 | ip6addrlbl_dump, NULL); | ||
598 | } | 601 | } |
599 | 602 | ||
diff --git a/net/ipv6/af_inet6.c b/net/ipv6/af_inet6.c index d450a2f9fc06..3b5669a2582d 100644 --- a/net/ipv6/af_inet6.c +++ b/net/ipv6/af_inet6.c | |||
@@ -274,7 +274,7 @@ int inet6_bind(struct socket *sock, struct sockaddr *uaddr, int addr_len) | |||
274 | return -EINVAL; | 274 | return -EINVAL; |
275 | 275 | ||
276 | if (addr->sin6_family != AF_INET6) | 276 | if (addr->sin6_family != AF_INET6) |
277 | return -EINVAL; | 277 | return -EAFNOSUPPORT; |
278 | 278 | ||
279 | addr_type = ipv6_addr_type(&addr->sin6_addr); | 279 | addr_type = ipv6_addr_type(&addr->sin6_addr); |
280 | if ((addr_type & IPV6_ADDR_MULTICAST) && sock->type == SOCK_STREAM) | 280 | if ((addr_type & IPV6_ADDR_MULTICAST) && sock->type == SOCK_STREAM) |
diff --git a/net/ipv6/ip6_fib.c b/net/ipv6/ip6_fib.c index 4076a0b14b20..54a4678955bf 100644 --- a/net/ipv6/ip6_fib.c +++ b/net/ipv6/ip6_fib.c | |||
@@ -1455,7 +1455,7 @@ static int fib6_age(struct rt6_info *rt, void *arg) | |||
1455 | RT6_TRACE("aging clone %p\n", rt); | 1455 | RT6_TRACE("aging clone %p\n", rt); |
1456 | return -1; | 1456 | return -1; |
1457 | } else if ((rt->rt6i_flags & RTF_GATEWAY) && | 1457 | } else if ((rt->rt6i_flags & RTF_GATEWAY) && |
1458 | (!(rt->rt6i_nexthop->flags & NTF_ROUTER))) { | 1458 | (!(dst_get_neighbour(&rt->dst)->flags & NTF_ROUTER))) { |
1459 | RT6_TRACE("purging route %p via non-router but gateway\n", | 1459 | RT6_TRACE("purging route %p via non-router but gateway\n", |
1460 | rt); | 1460 | rt); |
1461 | return -1; | 1461 | return -1; |
@@ -1586,7 +1586,8 @@ int __init fib6_init(void) | |||
1586 | if (ret) | 1586 | if (ret) |
1587 | goto out_kmem_cache_create; | 1587 | goto out_kmem_cache_create; |
1588 | 1588 | ||
1589 | ret = __rtnl_register(PF_INET6, RTM_GETROUTE, NULL, inet6_dump_fib); | 1589 | ret = __rtnl_register(PF_INET6, RTM_GETROUTE, NULL, inet6_dump_fib, |
1590 | NULL); | ||
1590 | if (ret) | 1591 | if (ret) |
1591 | goto out_unregister_subsys; | 1592 | goto out_unregister_subsys; |
1592 | out: | 1593 | out: |
diff --git a/net/ipv6/ip6_output.c b/net/ipv6/ip6_output.c index 9d4b165837d6..32e5339db0c8 100644 --- a/net/ipv6/ip6_output.c +++ b/net/ipv6/ip6_output.c | |||
@@ -100,6 +100,7 @@ static int ip6_finish_output2(struct sk_buff *skb) | |||
100 | { | 100 | { |
101 | struct dst_entry *dst = skb_dst(skb); | 101 | struct dst_entry *dst = skb_dst(skb); |
102 | struct net_device *dev = dst->dev; | 102 | struct net_device *dev = dst->dev; |
103 | struct neighbour *neigh; | ||
103 | 104 | ||
104 | skb->protocol = htons(ETH_P_IPV6); | 105 | skb->protocol = htons(ETH_P_IPV6); |
105 | skb->dev = dev; | 106 | skb->dev = dev; |
@@ -134,10 +135,9 @@ static int ip6_finish_output2(struct sk_buff *skb) | |||
134 | skb->len); | 135 | skb->len); |
135 | } | 136 | } |
136 | 137 | ||
137 | if (dst->hh) | 138 | neigh = dst_get_neighbour(dst); |
138 | return neigh_hh_output(dst->hh, skb); | 139 | if (neigh) |
139 | else if (dst->neighbour) | 140 | return neigh_output(neigh, skb); |
140 | return dst->neighbour->output(skb); | ||
141 | 141 | ||
142 | IP6_INC_STATS_BH(dev_net(dst->dev), | 142 | IP6_INC_STATS_BH(dev_net(dst->dev), |
143 | ip6_dst_idev(dst), IPSTATS_MIB_OUTNOROUTES); | 143 | ip6_dst_idev(dst), IPSTATS_MIB_OUTNOROUTES); |
@@ -385,6 +385,7 @@ int ip6_forward(struct sk_buff *skb) | |||
385 | struct ipv6hdr *hdr = ipv6_hdr(skb); | 385 | struct ipv6hdr *hdr = ipv6_hdr(skb); |
386 | struct inet6_skb_parm *opt = IP6CB(skb); | 386 | struct inet6_skb_parm *opt = IP6CB(skb); |
387 | struct net *net = dev_net(dst->dev); | 387 | struct net *net = dev_net(dst->dev); |
388 | struct neighbour *n; | ||
388 | u32 mtu; | 389 | u32 mtu; |
389 | 390 | ||
390 | if (net->ipv6.devconf_all->forwarding == 0) | 391 | if (net->ipv6.devconf_all->forwarding == 0) |
@@ -459,11 +460,10 @@ int ip6_forward(struct sk_buff *skb) | |||
459 | send redirects to source routed frames. | 460 | send redirects to source routed frames. |
460 | We don't send redirects to frames decapsulated from IPsec. | 461 | We don't send redirects to frames decapsulated from IPsec. |
461 | */ | 462 | */ |
462 | if (skb->dev == dst->dev && dst->neighbour && opt->srcrt == 0 && | 463 | n = dst_get_neighbour(dst); |
463 | !skb_sec_path(skb)) { | 464 | if (skb->dev == dst->dev && n && opt->srcrt == 0 && !skb_sec_path(skb)) { |
464 | struct in6_addr *target = NULL; | 465 | struct in6_addr *target = NULL; |
465 | struct rt6_info *rt; | 466 | struct rt6_info *rt; |
466 | struct neighbour *n = dst->neighbour; | ||
467 | 467 | ||
468 | /* | 468 | /* |
469 | * incoming and outgoing devices are the same | 469 | * incoming and outgoing devices are the same |
@@ -596,6 +596,31 @@ int ip6_find_1stfragopt(struct sk_buff *skb, u8 **nexthdr) | |||
596 | return offset; | 596 | return offset; |
597 | } | 597 | } |
598 | 598 | ||
599 | void ipv6_select_ident(struct frag_hdr *fhdr, struct rt6_info *rt) | ||
600 | { | ||
601 | static atomic_t ipv6_fragmentation_id; | ||
602 | int old, new; | ||
603 | |||
604 | if (rt) { | ||
605 | struct inet_peer *peer; | ||
606 | |||
607 | if (!rt->rt6i_peer) | ||
608 | rt6_bind_peer(rt, 1); | ||
609 | peer = rt->rt6i_peer; | ||
610 | if (peer) { | ||
611 | fhdr->identification = htonl(inet_getid(peer, 0)); | ||
612 | return; | ||
613 | } | ||
614 | } | ||
615 | do { | ||
616 | old = atomic_read(&ipv6_fragmentation_id); | ||
617 | new = old + 1; | ||
618 | if (!new) | ||
619 | new = 1; | ||
620 | } while (atomic_cmpxchg(&ipv6_fragmentation_id, old, new) != old); | ||
621 | fhdr->identification = htonl(new); | ||
622 | } | ||
623 | |||
599 | int ip6_fragment(struct sk_buff *skb, int (*output)(struct sk_buff *)) | 624 | int ip6_fragment(struct sk_buff *skb, int (*output)(struct sk_buff *)) |
600 | { | 625 | { |
601 | struct sk_buff *frag; | 626 | struct sk_buff *frag; |
@@ -680,7 +705,7 @@ int ip6_fragment(struct sk_buff *skb, int (*output)(struct sk_buff *)) | |||
680 | skb_reset_network_header(skb); | 705 | skb_reset_network_header(skb); |
681 | memcpy(skb_network_header(skb), tmp_hdr, hlen); | 706 | memcpy(skb_network_header(skb), tmp_hdr, hlen); |
682 | 707 | ||
683 | ipv6_select_ident(fh); | 708 | ipv6_select_ident(fh, rt); |
684 | fh->nexthdr = nexthdr; | 709 | fh->nexthdr = nexthdr; |
685 | fh->reserved = 0; | 710 | fh->reserved = 0; |
686 | fh->frag_off = htons(IP6_MF); | 711 | fh->frag_off = htons(IP6_MF); |
@@ -826,7 +851,7 @@ slow_path: | |||
826 | fh->nexthdr = nexthdr; | 851 | fh->nexthdr = nexthdr; |
827 | fh->reserved = 0; | 852 | fh->reserved = 0; |
828 | if (!frag_id) { | 853 | if (!frag_id) { |
829 | ipv6_select_ident(fh); | 854 | ipv6_select_ident(fh, rt); |
830 | frag_id = fh->identification; | 855 | frag_id = fh->identification; |
831 | } else | 856 | } else |
832 | fh->identification = frag_id; | 857 | fh->identification = frag_id; |
@@ -920,8 +945,11 @@ out: | |||
920 | static int ip6_dst_lookup_tail(struct sock *sk, | 945 | static int ip6_dst_lookup_tail(struct sock *sk, |
921 | struct dst_entry **dst, struct flowi6 *fl6) | 946 | struct dst_entry **dst, struct flowi6 *fl6) |
922 | { | 947 | { |
923 | int err; | ||
924 | struct net *net = sock_net(sk); | 948 | struct net *net = sock_net(sk); |
949 | #ifdef CONFIG_IPV6_OPTIMISTIC_DAD | ||
950 | struct neighbour *n; | ||
951 | #endif | ||
952 | int err; | ||
925 | 953 | ||
926 | if (*dst == NULL) | 954 | if (*dst == NULL) |
927 | *dst = ip6_route_output(net, sk, fl6); | 955 | *dst = ip6_route_output(net, sk, fl6); |
@@ -947,7 +975,8 @@ static int ip6_dst_lookup_tail(struct sock *sk, | |||
947 | * dst entry and replace it instead with the | 975 | * dst entry and replace it instead with the |
948 | * dst entry of the nexthop router | 976 | * dst entry of the nexthop router |
949 | */ | 977 | */ |
950 | if ((*dst)->neighbour && !((*dst)->neighbour->nud_state & NUD_VALID)) { | 978 | n = dst_get_neighbour(*dst); |
979 | if (n && !(n->nud_state & NUD_VALID)) { | ||
951 | struct inet6_ifaddr *ifp; | 980 | struct inet6_ifaddr *ifp; |
952 | struct flowi6 fl_gw6; | 981 | struct flowi6 fl_gw6; |
953 | int redirect; | 982 | int redirect; |
@@ -1072,7 +1101,8 @@ static inline int ip6_ufo_append_data(struct sock *sk, | |||
1072 | int getfrag(void *from, char *to, int offset, int len, | 1101 | int getfrag(void *from, char *to, int offset, int len, |
1073 | int odd, struct sk_buff *skb), | 1102 | int odd, struct sk_buff *skb), |
1074 | void *from, int length, int hh_len, int fragheaderlen, | 1103 | void *from, int length, int hh_len, int fragheaderlen, |
1075 | int transhdrlen, int mtu,unsigned int flags) | 1104 | int transhdrlen, int mtu,unsigned int flags, |
1105 | struct rt6_info *rt) | ||
1076 | 1106 | ||
1077 | { | 1107 | { |
1078 | struct sk_buff *skb; | 1108 | struct sk_buff *skb; |
@@ -1116,7 +1146,7 @@ static inline int ip6_ufo_append_data(struct sock *sk, | |||
1116 | skb_shinfo(skb)->gso_size = (mtu - fragheaderlen - | 1146 | skb_shinfo(skb)->gso_size = (mtu - fragheaderlen - |
1117 | sizeof(struct frag_hdr)) & ~7; | 1147 | sizeof(struct frag_hdr)) & ~7; |
1118 | skb_shinfo(skb)->gso_type = SKB_GSO_UDP; | 1148 | skb_shinfo(skb)->gso_type = SKB_GSO_UDP; |
1119 | ipv6_select_ident(&fhdr); | 1149 | ipv6_select_ident(&fhdr, rt); |
1120 | skb_shinfo(skb)->ip6_frag_id = fhdr.identification; | 1150 | skb_shinfo(skb)->ip6_frag_id = fhdr.identification; |
1121 | __skb_queue_tail(&sk->sk_write_queue, skb); | 1151 | __skb_queue_tail(&sk->sk_write_queue, skb); |
1122 | 1152 | ||
@@ -1282,7 +1312,7 @@ int ip6_append_data(struct sock *sk, int getfrag(void *from, char *to, | |||
1282 | 1312 | ||
1283 | err = ip6_ufo_append_data(sk, getfrag, from, length, | 1313 | err = ip6_ufo_append_data(sk, getfrag, from, length, |
1284 | hh_len, fragheaderlen, | 1314 | hh_len, fragheaderlen, |
1285 | transhdrlen, mtu, flags); | 1315 | transhdrlen, mtu, flags, rt); |
1286 | if (err) | 1316 | if (err) |
1287 | goto error; | 1317 | goto error; |
1288 | return 0; | 1318 | return 0; |
diff --git a/net/ipv6/ip6mr.c b/net/ipv6/ip6mr.c index 82a809901f8e..705c82886281 100644 --- a/net/ipv6/ip6mr.c +++ b/net/ipv6/ip6mr.c | |||
@@ -1354,7 +1354,8 @@ int __init ip6_mr_init(void) | |||
1354 | goto add_proto_fail; | 1354 | goto add_proto_fail; |
1355 | } | 1355 | } |
1356 | #endif | 1356 | #endif |
1357 | rtnl_register(RTNL_FAMILY_IP6MR, RTM_GETROUTE, NULL, ip6mr_rtm_dumproute); | 1357 | rtnl_register(RTNL_FAMILY_IP6MR, RTM_GETROUTE, NULL, |
1358 | ip6mr_rtm_dumproute, NULL); | ||
1358 | return 0; | 1359 | return 0; |
1359 | #ifdef CONFIG_IPV6_PIMSM_V2 | 1360 | #ifdef CONFIG_IPV6_PIMSM_V2 |
1360 | add_proto_fail: | 1361 | add_proto_fail: |
diff --git a/net/ipv6/ndisc.c b/net/ipv6/ndisc.c index 7596f071d308..9da6e02eaaeb 100644 --- a/net/ipv6/ndisc.c +++ b/net/ipv6/ndisc.c | |||
@@ -107,8 +107,6 @@ static const struct neigh_ops ndisc_generic_ops = { | |||
107 | .error_report = ndisc_error_report, | 107 | .error_report = ndisc_error_report, |
108 | .output = neigh_resolve_output, | 108 | .output = neigh_resolve_output, |
109 | .connected_output = neigh_connected_output, | 109 | .connected_output = neigh_connected_output, |
110 | .hh_output = dev_queue_xmit, | ||
111 | .queue_xmit = dev_queue_xmit, | ||
112 | }; | 110 | }; |
113 | 111 | ||
114 | static const struct neigh_ops ndisc_hh_ops = { | 112 | static const struct neigh_ops ndisc_hh_ops = { |
@@ -117,17 +115,13 @@ static const struct neigh_ops ndisc_hh_ops = { | |||
117 | .error_report = ndisc_error_report, | 115 | .error_report = ndisc_error_report, |
118 | .output = neigh_resolve_output, | 116 | .output = neigh_resolve_output, |
119 | .connected_output = neigh_resolve_output, | 117 | .connected_output = neigh_resolve_output, |
120 | .hh_output = dev_queue_xmit, | ||
121 | .queue_xmit = dev_queue_xmit, | ||
122 | }; | 118 | }; |
123 | 119 | ||
124 | 120 | ||
125 | static const struct neigh_ops ndisc_direct_ops = { | 121 | static const struct neigh_ops ndisc_direct_ops = { |
126 | .family = AF_INET6, | 122 | .family = AF_INET6, |
127 | .output = dev_queue_xmit, | 123 | .output = neigh_direct_output, |
128 | .connected_output = dev_queue_xmit, | 124 | .connected_output = neigh_direct_output, |
129 | .hh_output = dev_queue_xmit, | ||
130 | .queue_xmit = dev_queue_xmit, | ||
131 | }; | 125 | }; |
132 | 126 | ||
133 | struct neigh_table nd_tbl = { | 127 | struct neigh_table nd_tbl = { |
@@ -392,7 +386,7 @@ static int ndisc_constructor(struct neighbour *neigh) | |||
392 | if (!dev->header_ops) { | 386 | if (!dev->header_ops) { |
393 | neigh->nud_state = NUD_NOARP; | 387 | neigh->nud_state = NUD_NOARP; |
394 | neigh->ops = &ndisc_direct_ops; | 388 | neigh->ops = &ndisc_direct_ops; |
395 | neigh->output = neigh->ops->queue_xmit; | 389 | neigh->output = neigh_direct_output; |
396 | } else { | 390 | } else { |
397 | if (is_multicast) { | 391 | if (is_multicast) { |
398 | neigh->nud_state = NUD_NOARP; | 392 | neigh->nud_state = NUD_NOARP; |
@@ -1244,7 +1238,7 @@ static void ndisc_router_discovery(struct sk_buff *skb) | |||
1244 | rt = rt6_get_dflt_router(&ipv6_hdr(skb)->saddr, skb->dev); | 1238 | rt = rt6_get_dflt_router(&ipv6_hdr(skb)->saddr, skb->dev); |
1245 | 1239 | ||
1246 | if (rt) | 1240 | if (rt) |
1247 | neigh = rt->rt6i_nexthop; | 1241 | neigh = dst_get_neighbour(&rt->dst); |
1248 | 1242 | ||
1249 | if (rt && lifetime == 0) { | 1243 | if (rt && lifetime == 0) { |
1250 | neigh_clone(neigh); | 1244 | neigh_clone(neigh); |
@@ -1265,7 +1259,7 @@ static void ndisc_router_discovery(struct sk_buff *skb) | |||
1265 | return; | 1259 | return; |
1266 | } | 1260 | } |
1267 | 1261 | ||
1268 | neigh = rt->rt6i_nexthop; | 1262 | neigh = dst_get_neighbour(&rt->dst); |
1269 | if (neigh == NULL) { | 1263 | if (neigh == NULL) { |
1270 | ND_PRINTK0(KERN_ERR | 1264 | ND_PRINTK0(KERN_ERR |
1271 | "ICMPv6 RA: %s() got default router without neighbour.\n", | 1265 | "ICMPv6 RA: %s() got default router without neighbour.\n", |
diff --git a/net/ipv6/raw.c b/net/ipv6/raw.c index cc7313b8f7ea..6a79f3081bdb 100644 --- a/net/ipv6/raw.c +++ b/net/ipv6/raw.c | |||
@@ -959,57 +959,54 @@ static int do_rawv6_setsockopt(struct sock *sk, int level, int optname, | |||
959 | return -EFAULT; | 959 | return -EFAULT; |
960 | 960 | ||
961 | switch (optname) { | 961 | switch (optname) { |
962 | case IPV6_CHECKSUM: | 962 | case IPV6_CHECKSUM: |
963 | if (inet_sk(sk)->inet_num == IPPROTO_ICMPV6 && | 963 | if (inet_sk(sk)->inet_num == IPPROTO_ICMPV6 && |
964 | level == IPPROTO_IPV6) { | 964 | level == IPPROTO_IPV6) { |
965 | /* | 965 | /* |
966 | * RFC3542 tells that IPV6_CHECKSUM socket | 966 | * RFC3542 tells that IPV6_CHECKSUM socket |
967 | * option in the IPPROTO_IPV6 level is not | 967 | * option in the IPPROTO_IPV6 level is not |
968 | * allowed on ICMPv6 sockets. | 968 | * allowed on ICMPv6 sockets. |
969 | * If you want to set it, use IPPROTO_RAW | 969 | * If you want to set it, use IPPROTO_RAW |
970 | * level IPV6_CHECKSUM socket option | 970 | * level IPV6_CHECKSUM socket option |
971 | * (Linux extension). | 971 | * (Linux extension). |
972 | */ | 972 | */ |
973 | return -EINVAL; | 973 | return -EINVAL; |
974 | } | 974 | } |
975 | 975 | ||
976 | /* You may get strange result with a positive odd offset; | 976 | /* You may get strange result with a positive odd offset; |
977 | RFC2292bis agrees with me. */ | 977 | RFC2292bis agrees with me. */ |
978 | if (val > 0 && (val&1)) | 978 | if (val > 0 && (val&1)) |
979 | return -EINVAL; | 979 | return -EINVAL; |
980 | if (val < 0) { | 980 | if (val < 0) { |
981 | rp->checksum = 0; | 981 | rp->checksum = 0; |
982 | } else { | 982 | } else { |
983 | rp->checksum = 1; | 983 | rp->checksum = 1; |
984 | rp->offset = val; | 984 | rp->offset = val; |
985 | } | 985 | } |
986 | 986 | ||
987 | return 0; | 987 | return 0; |
988 | break; | ||
989 | 988 | ||
990 | default: | 989 | default: |
991 | return -ENOPROTOOPT; | 990 | return -ENOPROTOOPT; |
992 | } | 991 | } |
993 | } | 992 | } |
994 | 993 | ||
995 | static int rawv6_setsockopt(struct sock *sk, int level, int optname, | 994 | static int rawv6_setsockopt(struct sock *sk, int level, int optname, |
996 | char __user *optval, unsigned int optlen) | 995 | char __user *optval, unsigned int optlen) |
997 | { | 996 | { |
998 | switch(level) { | 997 | switch (level) { |
999 | case SOL_RAW: | 998 | case SOL_RAW: |
1000 | break; | 999 | break; |
1001 | 1000 | ||
1002 | case SOL_ICMPV6: | 1001 | case SOL_ICMPV6: |
1003 | if (inet_sk(sk)->inet_num != IPPROTO_ICMPV6) | 1002 | if (inet_sk(sk)->inet_num != IPPROTO_ICMPV6) |
1004 | return -EOPNOTSUPP; | 1003 | return -EOPNOTSUPP; |
1005 | return rawv6_seticmpfilter(sk, level, optname, optval, | 1004 | return rawv6_seticmpfilter(sk, level, optname, optval, optlen); |
1006 | optlen); | 1005 | case SOL_IPV6: |
1007 | case SOL_IPV6: | 1006 | if (optname == IPV6_CHECKSUM) |
1008 | if (optname == IPV6_CHECKSUM) | 1007 | break; |
1009 | break; | 1008 | default: |
1010 | default: | 1009 | return ipv6_setsockopt(sk, level, optname, optval, optlen); |
1011 | return ipv6_setsockopt(sk, level, optname, optval, | ||
1012 | optlen); | ||
1013 | } | 1010 | } |
1014 | 1011 | ||
1015 | return do_rawv6_setsockopt(sk, level, optname, optval, optlen); | 1012 | return do_rawv6_setsockopt(sk, level, optname, optval, optlen); |
@@ -1075,21 +1072,19 @@ static int do_rawv6_getsockopt(struct sock *sk, int level, int optname, | |||
1075 | static int rawv6_getsockopt(struct sock *sk, int level, int optname, | 1072 | static int rawv6_getsockopt(struct sock *sk, int level, int optname, |
1076 | char __user *optval, int __user *optlen) | 1073 | char __user *optval, int __user *optlen) |
1077 | { | 1074 | { |
1078 | switch(level) { | 1075 | switch (level) { |
1079 | case SOL_RAW: | 1076 | case SOL_RAW: |
1080 | break; | 1077 | break; |
1081 | 1078 | ||
1082 | case SOL_ICMPV6: | 1079 | case SOL_ICMPV6: |
1083 | if (inet_sk(sk)->inet_num != IPPROTO_ICMPV6) | 1080 | if (inet_sk(sk)->inet_num != IPPROTO_ICMPV6) |
1084 | return -EOPNOTSUPP; | 1081 | return -EOPNOTSUPP; |
1085 | return rawv6_geticmpfilter(sk, level, optname, optval, | 1082 | return rawv6_geticmpfilter(sk, level, optname, optval, optlen); |
1086 | optlen); | 1083 | case SOL_IPV6: |
1087 | case SOL_IPV6: | 1084 | if (optname == IPV6_CHECKSUM) |
1088 | if (optname == IPV6_CHECKSUM) | 1085 | break; |
1089 | break; | 1086 | default: |
1090 | default: | 1087 | return ipv6_getsockopt(sk, level, optname, optval, optlen); |
1091 | return ipv6_getsockopt(sk, level, optname, optval, | ||
1092 | optlen); | ||
1093 | } | 1088 | } |
1094 | 1089 | ||
1095 | return do_rawv6_getsockopt(sk, level, optname, optval, optlen); | 1090 | return do_rawv6_getsockopt(sk, level, optname, optval, optlen); |
@@ -1119,31 +1114,29 @@ static int compat_rawv6_getsockopt(struct sock *sk, int level, int optname, | |||
1119 | 1114 | ||
1120 | static int rawv6_ioctl(struct sock *sk, int cmd, unsigned long arg) | 1115 | static int rawv6_ioctl(struct sock *sk, int cmd, unsigned long arg) |
1121 | { | 1116 | { |
1122 | switch(cmd) { | 1117 | switch (cmd) { |
1123 | case SIOCOUTQ: | 1118 | case SIOCOUTQ: { |
1124 | { | 1119 | int amount = sk_wmem_alloc_get(sk); |
1125 | int amount = sk_wmem_alloc_get(sk); | ||
1126 | 1120 | ||
1127 | return put_user(amount, (int __user *)arg); | 1121 | return put_user(amount, (int __user *)arg); |
1128 | } | 1122 | } |
1129 | case SIOCINQ: | 1123 | case SIOCINQ: { |
1130 | { | 1124 | struct sk_buff *skb; |
1131 | struct sk_buff *skb; | 1125 | int amount = 0; |
1132 | int amount = 0; | 1126 | |
1133 | 1127 | spin_lock_bh(&sk->sk_receive_queue.lock); | |
1134 | spin_lock_bh(&sk->sk_receive_queue.lock); | 1128 | skb = skb_peek(&sk->sk_receive_queue); |
1135 | skb = skb_peek(&sk->sk_receive_queue); | 1129 | if (skb != NULL) |
1136 | if (skb != NULL) | 1130 | amount = skb->tail - skb->transport_header; |
1137 | amount = skb->tail - skb->transport_header; | 1131 | spin_unlock_bh(&sk->sk_receive_queue.lock); |
1138 | spin_unlock_bh(&sk->sk_receive_queue.lock); | 1132 | return put_user(amount, (int __user *)arg); |
1139 | return put_user(amount, (int __user *)arg); | 1133 | } |
1140 | } | ||
1141 | 1134 | ||
1142 | default: | 1135 | default: |
1143 | #ifdef CONFIG_IPV6_MROUTE | 1136 | #ifdef CONFIG_IPV6_MROUTE |
1144 | return ip6mr_ioctl(sk, cmd, (void __user *)arg); | 1137 | return ip6mr_ioctl(sk, cmd, (void __user *)arg); |
1145 | #else | 1138 | #else |
1146 | return -ENOIOCTLCMD; | 1139 | return -ENOIOCTLCMD; |
1147 | #endif | 1140 | #endif |
1148 | } | 1141 | } |
1149 | } | 1142 | } |
diff --git a/net/ipv6/route.c b/net/ipv6/route.c index de2b1decd786..e8987da06667 100644 --- a/net/ipv6/route.c +++ b/net/ipv6/route.c | |||
@@ -72,7 +72,8 @@ | |||
72 | #define RT6_TRACE(x...) do { ; } while (0) | 72 | #define RT6_TRACE(x...) do { ; } while (0) |
73 | #endif | 73 | #endif |
74 | 74 | ||
75 | static struct rt6_info * ip6_rt_copy(struct rt6_info *ort); | 75 | static struct rt6_info *ip6_rt_copy(const struct rt6_info *ort, |
76 | const struct in6_addr *dest); | ||
76 | static struct dst_entry *ip6_dst_check(struct dst_entry *dst, u32 cookie); | 77 | static struct dst_entry *ip6_dst_check(struct dst_entry *dst, u32 cookie); |
77 | static unsigned int ip6_default_advmss(const struct dst_entry *dst); | 78 | static unsigned int ip6_default_advmss(const struct dst_entry *dst); |
78 | static unsigned int ip6_default_mtu(const struct dst_entry *dst); | 79 | static unsigned int ip6_default_mtu(const struct dst_entry *dst); |
@@ -127,6 +128,11 @@ static u32 *ipv6_cow_metrics(struct dst_entry *dst, unsigned long old) | |||
127 | return p; | 128 | return p; |
128 | } | 129 | } |
129 | 130 | ||
131 | static struct neighbour *ip6_neigh_lookup(const struct dst_entry *dst, const void *daddr) | ||
132 | { | ||
133 | return __neigh_lookup_errno(&nd_tbl, daddr, dst->dev); | ||
134 | } | ||
135 | |||
130 | static struct dst_ops ip6_dst_ops_template = { | 136 | static struct dst_ops ip6_dst_ops_template = { |
131 | .family = AF_INET6, | 137 | .family = AF_INET6, |
132 | .protocol = cpu_to_be16(ETH_P_IPV6), | 138 | .protocol = cpu_to_be16(ETH_P_IPV6), |
@@ -142,6 +148,7 @@ static struct dst_ops ip6_dst_ops_template = { | |||
142 | .link_failure = ip6_link_failure, | 148 | .link_failure = ip6_link_failure, |
143 | .update_pmtu = ip6_rt_update_pmtu, | 149 | .update_pmtu = ip6_rt_update_pmtu, |
144 | .local_out = __ip6_local_out, | 150 | .local_out = __ip6_local_out, |
151 | .neigh_lookup = ip6_neigh_lookup, | ||
145 | }; | 152 | }; |
146 | 153 | ||
147 | static unsigned int ip6_blackhole_default_mtu(const struct dst_entry *dst) | 154 | static unsigned int ip6_blackhole_default_mtu(const struct dst_entry *dst) |
@@ -168,6 +175,7 @@ static struct dst_ops ip6_dst_blackhole_ops = { | |||
168 | .default_advmss = ip6_default_advmss, | 175 | .default_advmss = ip6_default_advmss, |
169 | .update_pmtu = ip6_rt_blackhole_update_pmtu, | 176 | .update_pmtu = ip6_rt_blackhole_update_pmtu, |
170 | .cow_metrics = ip6_rt_blackhole_cow_metrics, | 177 | .cow_metrics = ip6_rt_blackhole_cow_metrics, |
178 | .neigh_lookup = ip6_neigh_lookup, | ||
171 | }; | 179 | }; |
172 | 180 | ||
173 | static const u32 ip6_template_metrics[RTAX_MAX] = { | 181 | static const u32 ip6_template_metrics[RTAX_MAX] = { |
@@ -228,9 +236,10 @@ static struct rt6_info ip6_blk_hole_entry_template = { | |||
228 | 236 | ||
229 | /* allocate dst with ip6_dst_ops */ | 237 | /* allocate dst with ip6_dst_ops */ |
230 | static inline struct rt6_info *ip6_dst_alloc(struct dst_ops *ops, | 238 | static inline struct rt6_info *ip6_dst_alloc(struct dst_ops *ops, |
231 | struct net_device *dev) | 239 | struct net_device *dev, |
240 | int flags) | ||
232 | { | 241 | { |
233 | struct rt6_info *rt = dst_alloc(ops, dev, 0, 0, 0); | 242 | struct rt6_info *rt = dst_alloc(ops, dev, 0, 0, flags); |
234 | 243 | ||
235 | memset(&rt->rt6i_table, 0, sizeof(*rt) - sizeof(struct dst_entry)); | 244 | memset(&rt->rt6i_table, 0, sizeof(*rt) - sizeof(struct dst_entry)); |
236 | 245 | ||
@@ -355,7 +364,7 @@ out: | |||
355 | #ifdef CONFIG_IPV6_ROUTER_PREF | 364 | #ifdef CONFIG_IPV6_ROUTER_PREF |
356 | static void rt6_probe(struct rt6_info *rt) | 365 | static void rt6_probe(struct rt6_info *rt) |
357 | { | 366 | { |
358 | struct neighbour *neigh = rt ? rt->rt6i_nexthop : NULL; | 367 | struct neighbour *neigh = rt ? dst_get_neighbour(&rt->dst) : NULL; |
359 | /* | 368 | /* |
360 | * Okay, this does not seem to be appropriate | 369 | * Okay, this does not seem to be appropriate |
361 | * for now, however, we need to check if it | 370 | * for now, however, we need to check if it |
@@ -403,7 +412,7 @@ static inline int rt6_check_dev(struct rt6_info *rt, int oif) | |||
403 | 412 | ||
404 | static inline int rt6_check_neigh(struct rt6_info *rt) | 413 | static inline int rt6_check_neigh(struct rt6_info *rt) |
405 | { | 414 | { |
406 | struct neighbour *neigh = rt->rt6i_nexthop; | 415 | struct neighbour *neigh = dst_get_neighbour(&rt->dst); |
407 | int m; | 416 | int m; |
408 | if (rt->rt6i_flags & RTF_NONEXTHOP || | 417 | if (rt->rt6i_flags & RTF_NONEXTHOP || |
409 | !(rt->rt6i_flags & RTF_GATEWAY)) | 418 | !(rt->rt6i_flags & RTF_GATEWAY)) |
@@ -682,7 +691,8 @@ int ip6_ins_rt(struct rt6_info *rt) | |||
682 | return __ip6_ins_rt(rt, &info); | 691 | return __ip6_ins_rt(rt, &info); |
683 | } | 692 | } |
684 | 693 | ||
685 | static struct rt6_info *rt6_alloc_cow(struct rt6_info *ort, const struct in6_addr *daddr, | 694 | static struct rt6_info *rt6_alloc_cow(const struct rt6_info *ort, |
695 | const struct in6_addr *daddr, | ||
686 | const struct in6_addr *saddr) | 696 | const struct in6_addr *saddr) |
687 | { | 697 | { |
688 | struct rt6_info *rt; | 698 | struct rt6_info *rt; |
@@ -691,7 +701,7 @@ static struct rt6_info *rt6_alloc_cow(struct rt6_info *ort, const struct in6_add | |||
691 | * Clone the route. | 701 | * Clone the route. |
692 | */ | 702 | */ |
693 | 703 | ||
694 | rt = ip6_rt_copy(ort); | 704 | rt = ip6_rt_copy(ort, daddr); |
695 | 705 | ||
696 | if (rt) { | 706 | if (rt) { |
697 | struct neighbour *neigh; | 707 | struct neighbour *neigh; |
@@ -699,12 +709,11 @@ static struct rt6_info *rt6_alloc_cow(struct rt6_info *ort, const struct in6_add | |||
699 | 709 | ||
700 | if (!(rt->rt6i_flags&RTF_GATEWAY)) { | 710 | if (!(rt->rt6i_flags&RTF_GATEWAY)) { |
701 | if (rt->rt6i_dst.plen != 128 && | 711 | if (rt->rt6i_dst.plen != 128 && |
702 | ipv6_addr_equal(&rt->rt6i_dst.addr, daddr)) | 712 | ipv6_addr_equal(&ort->rt6i_dst.addr, daddr)) |
703 | rt->rt6i_flags |= RTF_ANYCAST; | 713 | rt->rt6i_flags |= RTF_ANYCAST; |
704 | ipv6_addr_copy(&rt->rt6i_gateway, daddr); | 714 | ipv6_addr_copy(&rt->rt6i_gateway, daddr); |
705 | } | 715 | } |
706 | 716 | ||
707 | ipv6_addr_copy(&rt->rt6i_dst.addr, daddr); | ||
708 | rt->rt6i_dst.plen = 128; | 717 | rt->rt6i_dst.plen = 128; |
709 | rt->rt6i_flags |= RTF_CACHE; | 718 | rt->rt6i_flags |= RTF_CACHE; |
710 | rt->dst.flags |= DST_HOST; | 719 | rt->dst.flags |= DST_HOST; |
@@ -744,22 +753,23 @@ static struct rt6_info *rt6_alloc_cow(struct rt6_info *ort, const struct in6_add | |||
744 | dst_free(&rt->dst); | 753 | dst_free(&rt->dst); |
745 | return NULL; | 754 | return NULL; |
746 | } | 755 | } |
747 | rt->rt6i_nexthop = neigh; | 756 | dst_set_neighbour(&rt->dst, neigh); |
748 | 757 | ||
749 | } | 758 | } |
750 | 759 | ||
751 | return rt; | 760 | return rt; |
752 | } | 761 | } |
753 | 762 | ||
754 | static struct rt6_info *rt6_alloc_clone(struct rt6_info *ort, const struct in6_addr *daddr) | 763 | static struct rt6_info *rt6_alloc_clone(struct rt6_info *ort, |
764 | const struct in6_addr *daddr) | ||
755 | { | 765 | { |
756 | struct rt6_info *rt = ip6_rt_copy(ort); | 766 | struct rt6_info *rt = ip6_rt_copy(ort, daddr); |
767 | |||
757 | if (rt) { | 768 | if (rt) { |
758 | ipv6_addr_copy(&rt->rt6i_dst.addr, daddr); | ||
759 | rt->rt6i_dst.plen = 128; | 769 | rt->rt6i_dst.plen = 128; |
760 | rt->rt6i_flags |= RTF_CACHE; | 770 | rt->rt6i_flags |= RTF_CACHE; |
761 | rt->dst.flags |= DST_HOST; | 771 | rt->dst.flags |= DST_HOST; |
762 | rt->rt6i_nexthop = neigh_clone(ort->rt6i_nexthop); | 772 | dst_set_neighbour(&rt->dst, neigh_clone(dst_get_neighbour(&ort->dst))); |
763 | } | 773 | } |
764 | return rt; | 774 | return rt; |
765 | } | 775 | } |
@@ -793,7 +803,7 @@ restart: | |||
793 | dst_hold(&rt->dst); | 803 | dst_hold(&rt->dst); |
794 | read_unlock_bh(&table->tb6_lock); | 804 | read_unlock_bh(&table->tb6_lock); |
795 | 805 | ||
796 | if (!rt->rt6i_nexthop && !(rt->rt6i_flags & RTF_NONEXTHOP)) | 806 | if (!dst_get_neighbour(&rt->dst) && !(rt->rt6i_flags & RTF_NONEXTHOP)) |
797 | nrt = rt6_alloc_cow(rt, &fl6->daddr, &fl6->saddr); | 807 | nrt = rt6_alloc_cow(rt, &fl6->daddr, &fl6->saddr); |
798 | else if (!(rt->dst.flags & DST_HOST)) | 808 | else if (!(rt->dst.flags & DST_HOST)) |
799 | nrt = rt6_alloc_clone(rt, &fl6->daddr); | 809 | nrt = rt6_alloc_clone(rt, &fl6->daddr); |
@@ -899,7 +909,10 @@ struct dst_entry *ip6_blackhole_route(struct net *net, struct dst_entry *dst_ori | |||
899 | new->input = dst_discard; | 909 | new->input = dst_discard; |
900 | new->output = dst_discard; | 910 | new->output = dst_discard; |
901 | 911 | ||
902 | dst_copy_metrics(new, &ort->dst); | 912 | if (dst_metrics_read_only(&ort->dst)) |
913 | new->_metrics = ort->dst._metrics; | ||
914 | else | ||
915 | dst_copy_metrics(new, &ort->dst); | ||
903 | rt->rt6i_idev = ort->rt6i_idev; | 916 | rt->rt6i_idev = ort->rt6i_idev; |
904 | if (rt->rt6i_idev) | 917 | if (rt->rt6i_idev) |
905 | in6_dev_hold(rt->rt6i_idev); | 918 | in6_dev_hold(rt->rt6i_idev); |
@@ -1042,7 +1055,7 @@ struct dst_entry *icmp6_dst_alloc(struct net_device *dev, | |||
1042 | if (unlikely(idev == NULL)) | 1055 | if (unlikely(idev == NULL)) |
1043 | return NULL; | 1056 | return NULL; |
1044 | 1057 | ||
1045 | rt = ip6_dst_alloc(&net->ipv6.ip6_dst_ops, dev); | 1058 | rt = ip6_dst_alloc(&net->ipv6.ip6_dst_ops, dev, 0); |
1046 | if (unlikely(rt == NULL)) { | 1059 | if (unlikely(rt == NULL)) { |
1047 | in6_dev_put(idev); | 1060 | in6_dev_put(idev); |
1048 | goto out; | 1061 | goto out; |
@@ -1057,19 +1070,12 @@ struct dst_entry *icmp6_dst_alloc(struct net_device *dev, | |||
1057 | } | 1070 | } |
1058 | 1071 | ||
1059 | rt->rt6i_idev = idev; | 1072 | rt->rt6i_idev = idev; |
1060 | rt->rt6i_nexthop = neigh; | 1073 | dst_set_neighbour(&rt->dst, neigh); |
1061 | atomic_set(&rt->dst.__refcnt, 1); | 1074 | atomic_set(&rt->dst.__refcnt, 1); |
1075 | ipv6_addr_copy(&rt->rt6i_dst.addr, addr); | ||
1062 | dst_metric_set(&rt->dst, RTAX_HOPLIMIT, 255); | 1076 | dst_metric_set(&rt->dst, RTAX_HOPLIMIT, 255); |
1063 | rt->dst.output = ip6_output; | 1077 | rt->dst.output = ip6_output; |
1064 | 1078 | ||
1065 | #if 0 /* there's no chance to use these for ndisc */ | ||
1066 | rt->dst.flags = ipv6_addr_type(addr) & IPV6_ADDR_UNICAST | ||
1067 | ? DST_HOST | ||
1068 | : 0; | ||
1069 | ipv6_addr_copy(&rt->rt6i_dst.addr, addr); | ||
1070 | rt->rt6i_dst.plen = 128; | ||
1071 | #endif | ||
1072 | |||
1073 | spin_lock_bh(&icmp6_dst_lock); | 1079 | spin_lock_bh(&icmp6_dst_lock); |
1074 | rt->dst.next = icmp6_dst_gc_list; | 1080 | rt->dst.next = icmp6_dst_gc_list; |
1075 | icmp6_dst_gc_list = &rt->dst; | 1081 | icmp6_dst_gc_list = &rt->dst; |
@@ -1214,7 +1220,7 @@ int ip6_route_add(struct fib6_config *cfg) | |||
1214 | goto out; | 1220 | goto out; |
1215 | } | 1221 | } |
1216 | 1222 | ||
1217 | rt = ip6_dst_alloc(&net->ipv6.ip6_dst_ops, NULL); | 1223 | rt = ip6_dst_alloc(&net->ipv6.ip6_dst_ops, NULL, DST_NOCOUNT); |
1218 | 1224 | ||
1219 | if (rt == NULL) { | 1225 | if (rt == NULL) { |
1220 | err = -ENOMEM; | 1226 | err = -ENOMEM; |
@@ -1244,7 +1250,7 @@ int ip6_route_add(struct fib6_config *cfg) | |||
1244 | ipv6_addr_prefix(&rt->rt6i_dst.addr, &cfg->fc_dst, cfg->fc_dst_len); | 1250 | ipv6_addr_prefix(&rt->rt6i_dst.addr, &cfg->fc_dst, cfg->fc_dst_len); |
1245 | rt->rt6i_dst.plen = cfg->fc_dst_len; | 1251 | rt->rt6i_dst.plen = cfg->fc_dst_len; |
1246 | if (rt->rt6i_dst.plen == 128) | 1252 | if (rt->rt6i_dst.plen == 128) |
1247 | rt->dst.flags = DST_HOST; | 1253 | rt->dst.flags |= DST_HOST; |
1248 | 1254 | ||
1249 | #ifdef CONFIG_IPV6_SUBTREES | 1255 | #ifdef CONFIG_IPV6_SUBTREES |
1250 | ipv6_addr_prefix(&rt->rt6i_src.addr, &cfg->fc_src, cfg->fc_src_len); | 1256 | ipv6_addr_prefix(&rt->rt6i_src.addr, &cfg->fc_src, cfg->fc_src_len); |
@@ -1345,12 +1351,12 @@ int ip6_route_add(struct fib6_config *cfg) | |||
1345 | rt->rt6i_prefsrc.plen = 0; | 1351 | rt->rt6i_prefsrc.plen = 0; |
1346 | 1352 | ||
1347 | if (cfg->fc_flags & (RTF_GATEWAY | RTF_NONEXTHOP)) { | 1353 | if (cfg->fc_flags & (RTF_GATEWAY | RTF_NONEXTHOP)) { |
1348 | rt->rt6i_nexthop = __neigh_lookup_errno(&nd_tbl, &rt->rt6i_gateway, dev); | 1354 | struct neighbour *n = __neigh_lookup_errno(&nd_tbl, &rt->rt6i_gateway, dev); |
1349 | if (IS_ERR(rt->rt6i_nexthop)) { | 1355 | if (IS_ERR(n)) { |
1350 | err = PTR_ERR(rt->rt6i_nexthop); | 1356 | err = PTR_ERR(n); |
1351 | rt->rt6i_nexthop = NULL; | ||
1352 | goto out; | 1357 | goto out; |
1353 | } | 1358 | } |
1359 | dst_set_neighbour(&rt->dst, n); | ||
1354 | } | 1360 | } |
1355 | 1361 | ||
1356 | rt->rt6i_flags = cfg->fc_flags; | 1362 | rt->rt6i_flags = cfg->fc_flags; |
@@ -1581,10 +1587,10 @@ void rt6_redirect(const struct in6_addr *dest, const struct in6_addr *src, | |||
1581 | dst_confirm(&rt->dst); | 1587 | dst_confirm(&rt->dst); |
1582 | 1588 | ||
1583 | /* Duplicate redirect: silently ignore. */ | 1589 | /* Duplicate redirect: silently ignore. */ |
1584 | if (neigh == rt->dst.neighbour) | 1590 | if (neigh == dst_get_neighbour(&rt->dst)) |
1585 | goto out; | 1591 | goto out; |
1586 | 1592 | ||
1587 | nrt = ip6_rt_copy(rt); | 1593 | nrt = ip6_rt_copy(rt, dest); |
1588 | if (nrt == NULL) | 1594 | if (nrt == NULL) |
1589 | goto out; | 1595 | goto out; |
1590 | 1596 | ||
@@ -1592,12 +1598,11 @@ void rt6_redirect(const struct in6_addr *dest, const struct in6_addr *src, | |||
1592 | if (on_link) | 1598 | if (on_link) |
1593 | nrt->rt6i_flags &= ~RTF_GATEWAY; | 1599 | nrt->rt6i_flags &= ~RTF_GATEWAY; |
1594 | 1600 | ||
1595 | ipv6_addr_copy(&nrt->rt6i_dst.addr, dest); | ||
1596 | nrt->rt6i_dst.plen = 128; | 1601 | nrt->rt6i_dst.plen = 128; |
1597 | nrt->dst.flags |= DST_HOST; | 1602 | nrt->dst.flags |= DST_HOST; |
1598 | 1603 | ||
1599 | ipv6_addr_copy(&nrt->rt6i_gateway, (struct in6_addr*)neigh->primary_key); | 1604 | ipv6_addr_copy(&nrt->rt6i_gateway, (struct in6_addr*)neigh->primary_key); |
1600 | nrt->rt6i_nexthop = neigh_clone(neigh); | 1605 | dst_set_neighbour(&nrt->dst, neigh_clone(neigh)); |
1601 | 1606 | ||
1602 | if (ip6_ins_rt(nrt)) | 1607 | if (ip6_ins_rt(nrt)) |
1603 | goto out; | 1608 | goto out; |
@@ -1677,7 +1682,7 @@ again: | |||
1677 | 1. It is connected route. Action: COW | 1682 | 1. It is connected route. Action: COW |
1678 | 2. It is gatewayed route or NONEXTHOP route. Action: clone it. | 1683 | 2. It is gatewayed route or NONEXTHOP route. Action: clone it. |
1679 | */ | 1684 | */ |
1680 | if (!rt->rt6i_nexthop && !(rt->rt6i_flags & RTF_NONEXTHOP)) | 1685 | if (!dst_get_neighbour(&rt->dst) && !(rt->rt6i_flags & RTF_NONEXTHOP)) |
1681 | nrt = rt6_alloc_cow(rt, daddr, saddr); | 1686 | nrt = rt6_alloc_cow(rt, daddr, saddr); |
1682 | else | 1687 | else |
1683 | nrt = rt6_alloc_clone(rt, daddr); | 1688 | nrt = rt6_alloc_clone(rt, daddr); |
@@ -1730,16 +1735,19 @@ void rt6_pmtu_discovery(const struct in6_addr *daddr, const struct in6_addr *sad | |||
1730 | * Misc support functions | 1735 | * Misc support functions |
1731 | */ | 1736 | */ |
1732 | 1737 | ||
1733 | static struct rt6_info * ip6_rt_copy(struct rt6_info *ort) | 1738 | static struct rt6_info *ip6_rt_copy(const struct rt6_info *ort, |
1739 | const struct in6_addr *dest) | ||
1734 | { | 1740 | { |
1735 | struct net *net = dev_net(ort->rt6i_dev); | 1741 | struct net *net = dev_net(ort->rt6i_dev); |
1736 | struct rt6_info *rt = ip6_dst_alloc(&net->ipv6.ip6_dst_ops, | 1742 | struct rt6_info *rt = ip6_dst_alloc(&net->ipv6.ip6_dst_ops, |
1737 | ort->dst.dev); | 1743 | ort->dst.dev, 0); |
1738 | 1744 | ||
1739 | if (rt) { | 1745 | if (rt) { |
1740 | rt->dst.input = ort->dst.input; | 1746 | rt->dst.input = ort->dst.input; |
1741 | rt->dst.output = ort->dst.output; | 1747 | rt->dst.output = ort->dst.output; |
1742 | 1748 | ||
1749 | ipv6_addr_copy(&rt->rt6i_dst.addr, dest); | ||
1750 | rt->rt6i_dst.plen = ort->rt6i_dst.plen; | ||
1743 | dst_copy_metrics(&rt->dst, &ort->dst); | 1751 | dst_copy_metrics(&rt->dst, &ort->dst); |
1744 | rt->dst.error = ort->dst.error; | 1752 | rt->dst.error = ort->dst.error; |
1745 | rt->rt6i_idev = ort->rt6i_idev; | 1753 | rt->rt6i_idev = ort->rt6i_idev; |
@@ -1752,7 +1760,6 @@ static struct rt6_info * ip6_rt_copy(struct rt6_info *ort) | |||
1752 | rt->rt6i_flags = ort->rt6i_flags & ~RTF_EXPIRES; | 1760 | rt->rt6i_flags = ort->rt6i_flags & ~RTF_EXPIRES; |
1753 | rt->rt6i_metric = 0; | 1761 | rt->rt6i_metric = 0; |
1754 | 1762 | ||
1755 | memcpy(&rt->rt6i_dst, &ort->rt6i_dst, sizeof(struct rt6key)); | ||
1756 | #ifdef CONFIG_IPV6_SUBTREES | 1763 | #ifdef CONFIG_IPV6_SUBTREES |
1757 | memcpy(&rt->rt6i_src, &ort->rt6i_src, sizeof(struct rt6key)); | 1764 | memcpy(&rt->rt6i_src, &ort->rt6i_src, sizeof(struct rt6key)); |
1758 | #endif | 1765 | #endif |
@@ -2013,7 +2020,7 @@ struct rt6_info *addrconf_dst_alloc(struct inet6_dev *idev, | |||
2013 | { | 2020 | { |
2014 | struct net *net = dev_net(idev->dev); | 2021 | struct net *net = dev_net(idev->dev); |
2015 | struct rt6_info *rt = ip6_dst_alloc(&net->ipv6.ip6_dst_ops, | 2022 | struct rt6_info *rt = ip6_dst_alloc(&net->ipv6.ip6_dst_ops, |
2016 | net->loopback_dev); | 2023 | net->loopback_dev, 0); |
2017 | struct neighbour *neigh; | 2024 | struct neighbour *neigh; |
2018 | 2025 | ||
2019 | if (rt == NULL) { | 2026 | if (rt == NULL) { |
@@ -2025,7 +2032,7 @@ struct rt6_info *addrconf_dst_alloc(struct inet6_dev *idev, | |||
2025 | 2032 | ||
2026 | in6_dev_hold(idev); | 2033 | in6_dev_hold(idev); |
2027 | 2034 | ||
2028 | rt->dst.flags = DST_HOST; | 2035 | rt->dst.flags |= DST_HOST; |
2029 | rt->dst.input = ip6_input; | 2036 | rt->dst.input = ip6_input; |
2030 | rt->dst.output = ip6_output; | 2037 | rt->dst.output = ip6_output; |
2031 | rt->rt6i_idev = idev; | 2038 | rt->rt6i_idev = idev; |
@@ -2042,7 +2049,7 @@ struct rt6_info *addrconf_dst_alloc(struct inet6_dev *idev, | |||
2042 | 2049 | ||
2043 | return ERR_CAST(neigh); | 2050 | return ERR_CAST(neigh); |
2044 | } | 2051 | } |
2045 | rt->rt6i_nexthop = neigh; | 2052 | dst_set_neighbour(&rt->dst, neigh); |
2046 | 2053 | ||
2047 | ipv6_addr_copy(&rt->rt6i_dst.addr, addr); | 2054 | ipv6_addr_copy(&rt->rt6i_dst.addr, addr); |
2048 | rt->rt6i_dst.plen = 128; | 2055 | rt->rt6i_dst.plen = 128; |
@@ -2407,8 +2414,8 @@ static int rt6_fill_node(struct net *net, | |||
2407 | if (rtnetlink_put_metrics(skb, dst_metrics_ptr(&rt->dst)) < 0) | 2414 | if (rtnetlink_put_metrics(skb, dst_metrics_ptr(&rt->dst)) < 0) |
2408 | goto nla_put_failure; | 2415 | goto nla_put_failure; |
2409 | 2416 | ||
2410 | if (rt->dst.neighbour) | 2417 | if (dst_get_neighbour(&rt->dst)) |
2411 | NLA_PUT(skb, RTA_GATEWAY, 16, &rt->dst.neighbour->primary_key); | 2418 | NLA_PUT(skb, RTA_GATEWAY, 16, &dst_get_neighbour(&rt->dst)->primary_key); |
2412 | 2419 | ||
2413 | if (rt->dst.dev) | 2420 | if (rt->dst.dev) |
2414 | NLA_PUT_U32(skb, RTA_OIF, rt->rt6i_dev->ifindex); | 2421 | NLA_PUT_U32(skb, RTA_OIF, rt->rt6i_dev->ifindex); |
@@ -2592,6 +2599,7 @@ struct rt6_proc_arg | |||
2592 | static int rt6_info_route(struct rt6_info *rt, void *p_arg) | 2599 | static int rt6_info_route(struct rt6_info *rt, void *p_arg) |
2593 | { | 2600 | { |
2594 | struct seq_file *m = p_arg; | 2601 | struct seq_file *m = p_arg; |
2602 | struct neighbour *n; | ||
2595 | 2603 | ||
2596 | seq_printf(m, "%pi6 %02x ", &rt->rt6i_dst.addr, rt->rt6i_dst.plen); | 2604 | seq_printf(m, "%pi6 %02x ", &rt->rt6i_dst.addr, rt->rt6i_dst.plen); |
2597 | 2605 | ||
@@ -2600,9 +2608,9 @@ static int rt6_info_route(struct rt6_info *rt, void *p_arg) | |||
2600 | #else | 2608 | #else |
2601 | seq_puts(m, "00000000000000000000000000000000 00 "); | 2609 | seq_puts(m, "00000000000000000000000000000000 00 "); |
2602 | #endif | 2610 | #endif |
2603 | 2611 | n = dst_get_neighbour(&rt->dst); | |
2604 | if (rt->rt6i_nexthop) { | 2612 | if (n) { |
2605 | seq_printf(m, "%pi6", rt->rt6i_nexthop->primary_key); | 2613 | seq_printf(m, "%pi6", n->primary_key); |
2606 | } else { | 2614 | } else { |
2607 | seq_puts(m, "00000000000000000000000000000000"); | 2615 | seq_puts(m, "00000000000000000000000000000000"); |
2608 | } | 2616 | } |
@@ -2925,9 +2933,9 @@ int __init ip6_route_init(void) | |||
2925 | goto xfrm6_init; | 2933 | goto xfrm6_init; |
2926 | 2934 | ||
2927 | ret = -ENOBUFS; | 2935 | ret = -ENOBUFS; |
2928 | if (__rtnl_register(PF_INET6, RTM_NEWROUTE, inet6_rtm_newroute, NULL) || | 2936 | if (__rtnl_register(PF_INET6, RTM_NEWROUTE, inet6_rtm_newroute, NULL, NULL) || |
2929 | __rtnl_register(PF_INET6, RTM_DELROUTE, inet6_rtm_delroute, NULL) || | 2937 | __rtnl_register(PF_INET6, RTM_DELROUTE, inet6_rtm_delroute, NULL, NULL) || |
2930 | __rtnl_register(PF_INET6, RTM_GETROUTE, inet6_rtm_getroute, NULL)) | 2938 | __rtnl_register(PF_INET6, RTM_GETROUTE, inet6_rtm_getroute, NULL, NULL)) |
2931 | goto fib6_rules_init; | 2939 | goto fib6_rules_init; |
2932 | 2940 | ||
2933 | ret = register_netdevice_notifier(&ip6_route_dev_notifier); | 2941 | ret = register_netdevice_notifier(&ip6_route_dev_notifier); |
diff --git a/net/ipv6/sit.c b/net/ipv6/sit.c index 1cca5761aea9..07bf1085458f 100644 --- a/net/ipv6/sit.c +++ b/net/ipv6/sit.c | |||
@@ -677,7 +677,7 @@ static netdev_tx_t ipip6_tunnel_xmit(struct sk_buff *skb, | |||
677 | struct neighbour *neigh = NULL; | 677 | struct neighbour *neigh = NULL; |
678 | 678 | ||
679 | if (skb_dst(skb)) | 679 | if (skb_dst(skb)) |
680 | neigh = skb_dst(skb)->neighbour; | 680 | neigh = dst_get_neighbour(skb_dst(skb)); |
681 | 681 | ||
682 | if (neigh == NULL) { | 682 | if (neigh == NULL) { |
683 | if (net_ratelimit()) | 683 | if (net_ratelimit()) |
@@ -702,7 +702,7 @@ static netdev_tx_t ipip6_tunnel_xmit(struct sk_buff *skb, | |||
702 | struct neighbour *neigh = NULL; | 702 | struct neighbour *neigh = NULL; |
703 | 703 | ||
704 | if (skb_dst(skb)) | 704 | if (skb_dst(skb)) |
705 | neigh = skb_dst(skb)->neighbour; | 705 | neigh = dst_get_neighbour(skb_dst(skb)); |
706 | 706 | ||
707 | if (neigh == NULL) { | 707 | if (neigh == NULL) { |
708 | if (net_ratelimit()) | 708 | if (net_ratelimit()) |
diff --git a/net/ipv6/syncookies.c b/net/ipv6/syncookies.c index 8b9644a8b697..89d5bf806222 100644 --- a/net/ipv6/syncookies.c +++ b/net/ipv6/syncookies.c | |||
@@ -223,6 +223,7 @@ struct sock *cookie_v6_check(struct sock *sk, struct sk_buff *skb) | |||
223 | ireq->wscale_ok = tcp_opt.wscale_ok; | 223 | ireq->wscale_ok = tcp_opt.wscale_ok; |
224 | ireq->tstamp_ok = tcp_opt.saw_tstamp; | 224 | ireq->tstamp_ok = tcp_opt.saw_tstamp; |
225 | req->ts_recent = tcp_opt.saw_tstamp ? tcp_opt.rcv_tsval : 0; | 225 | req->ts_recent = tcp_opt.saw_tstamp ? tcp_opt.rcv_tsval : 0; |
226 | treq->snt_synack = tcp_opt.saw_tstamp ? tcp_opt.rcv_tsecr : 0; | ||
226 | treq->rcv_isn = ntohl(th->seq) - 1; | 227 | treq->rcv_isn = ntohl(th->seq) - 1; |
227 | treq->snt_isn = cookie; | 228 | treq->snt_isn = cookie; |
228 | 229 | ||
diff --git a/net/ipv6/tcp_ipv6.c b/net/ipv6/tcp_ipv6.c index 87551ca568cd..78aa53492b3e 100644 --- a/net/ipv6/tcp_ipv6.c +++ b/net/ipv6/tcp_ipv6.c | |||
@@ -1341,6 +1341,7 @@ static int tcp_v6_conn_request(struct sock *sk, struct sk_buff *skb) | |||
1341 | } | 1341 | } |
1342 | have_isn: | 1342 | have_isn: |
1343 | tcp_rsk(req)->snt_isn = isn; | 1343 | tcp_rsk(req)->snt_isn = isn; |
1344 | tcp_rsk(req)->snt_synack = tcp_time_stamp; | ||
1344 | 1345 | ||
1345 | security_inet_conn_request(sk, skb, req); | 1346 | security_inet_conn_request(sk, skb, req); |
1346 | 1347 | ||
@@ -1509,6 +1510,10 @@ static struct sock * tcp_v6_syn_recv_sock(struct sock *sk, struct sk_buff *skb, | |||
1509 | tcp_sync_mss(newsk, dst_mtu(dst)); | 1510 | tcp_sync_mss(newsk, dst_mtu(dst)); |
1510 | newtp->advmss = dst_metric_advmss(dst); | 1511 | newtp->advmss = dst_metric_advmss(dst); |
1511 | tcp_initialize_rcv_mss(newsk); | 1512 | tcp_initialize_rcv_mss(newsk); |
1513 | if (tcp_rsk(req)->snt_synack) | ||
1514 | tcp_valid_rtt_meas(newsk, | ||
1515 | tcp_time_stamp - tcp_rsk(req)->snt_synack); | ||
1516 | newtp->total_retrans = req->retrans; | ||
1512 | 1517 | ||
1513 | newinet->inet_daddr = newinet->inet_saddr = LOOPBACK4_IPV6; | 1518 | newinet->inet_daddr = newinet->inet_saddr = LOOPBACK4_IPV6; |
1514 | newinet->inet_rcv_saddr = LOOPBACK4_IPV6; | 1519 | newinet->inet_rcv_saddr = LOOPBACK4_IPV6; |
diff --git a/net/ipv6/udp.c b/net/ipv6/udp.c index 41f8c9c08dba..29213b51c499 100644 --- a/net/ipv6/udp.c +++ b/net/ipv6/udp.c | |||
@@ -453,8 +453,11 @@ csum_copy_err: | |||
453 | } | 453 | } |
454 | unlock_sock_fast(sk, slow); | 454 | unlock_sock_fast(sk, slow); |
455 | 455 | ||
456 | if (flags & MSG_DONTWAIT) | 456 | if (noblock) |
457 | return -EAGAIN; | 457 | return -EAGAIN; |
458 | |||
459 | /* starting over for a new packet */ | ||
460 | msg->msg_flags &= ~MSG_TRUNC; | ||
458 | goto try_again; | 461 | goto try_again; |
459 | } | 462 | } |
460 | 463 | ||
@@ -1356,7 +1359,7 @@ static struct sk_buff *udp6_ufo_fragment(struct sk_buff *skb, u32 features) | |||
1356 | fptr = (struct frag_hdr *)(skb_network_header(skb) + unfrag_ip6hlen); | 1359 | fptr = (struct frag_hdr *)(skb_network_header(skb) + unfrag_ip6hlen); |
1357 | fptr->nexthdr = nexthdr; | 1360 | fptr->nexthdr = nexthdr; |
1358 | fptr->reserved = 0; | 1361 | fptr->reserved = 0; |
1359 | ipv6_select_ident(fptr); | 1362 | ipv6_select_ident(fptr, (struct rt6_info *)skb_dst(skb)); |
1360 | 1363 | ||
1361 | /* Fragment the skb. ipv6 header and the remaining fields of the | 1364 | /* Fragment the skb. ipv6 header and the remaining fields of the |
1362 | * fragment header are updated in ipv6_gso_segment() | 1365 | * fragment header are updated in ipv6_gso_segment() |