aboutsummaryrefslogtreecommitdiffstats
path: root/net/ipv6
diff options
context:
space:
mode:
Diffstat (limited to 'net/ipv6')
-rw-r--r--net/ipv6/Kconfig44
-rw-r--r--net/ipv6/Makefile4
-rw-r--r--net/ipv6/addrconf.c663
-rw-r--r--net/ipv6/af_inet6.c21
-rw-r--r--net/ipv6/ah6.c89
-rw-r--r--net/ipv6/anycast.c8
-rw-r--r--net/ipv6/datagram.c20
-rw-r--r--net/ipv6/esp6.c16
-rw-r--r--net/ipv6/exthdrs.c233
-rw-r--r--net/ipv6/fib6_rules.c305
-rw-r--r--net/ipv6/icmp.c31
-rw-r--r--net/ipv6/inet6_connection_sock.c3
-rw-r--r--net/ipv6/ip6_fib.c463
-rw-r--r--net/ipv6/ip6_input.c2
-rw-r--r--net/ipv6/ip6_output.c106
-rw-r--r--net/ipv6/ipcomp6.c7
-rw-r--r--net/ipv6/ipv6_sockglue.c10
-rw-r--r--net/ipv6/ipv6_syms.c3
-rw-r--r--net/ipv6/mcast.c2
-rw-r--r--net/ipv6/mip6.c519
-rw-r--r--net/ipv6/ndisc.c53
-rw-r--r--net/ipv6/netfilter.c2
-rw-r--r--net/ipv6/netfilter/Makefile2
-rw-r--r--net/ipv6/netfilter/ip6_queue.c16
-rw-r--r--net/ipv6/netfilter/ip6_tables.c24
-rw-r--r--net/ipv6/netfilter/ip6t_HL.c9
-rw-r--r--net/ipv6/netfilter/ip6t_LOG.c4
-rw-r--r--net/ipv6/netfilter/ip6t_REJECT.c9
-rw-r--r--net/ipv6/netfilter/ip6t_ah.c1
-rw-r--r--net/ipv6/netfilter/ip6t_dst.c220
-rw-r--r--net/ipv6/netfilter/ip6t_frag.c1
-rw-r--r--net/ipv6/netfilter/ip6t_hbh.c49
-rw-r--r--net/ipv6/netfilter/ip6t_ipv6header.c1
-rw-r--r--net/ipv6/netfilter/ip6t_owner.c1
-rw-r--r--net/ipv6/netfilter/ip6t_rt.c1
-rw-r--r--net/ipv6/netfilter/ip6table_filter.c4
-rw-r--r--net/ipv6/netfilter/ip6table_mangle.c12
-rw-r--r--net/ipv6/netfilter/ip6table_raw.c2
-rw-r--r--net/ipv6/netfilter/nf_conntrack_l3proto_ipv6.c2
-rw-r--r--net/ipv6/netfilter/nf_conntrack_proto_icmpv6.c2
-rw-r--r--net/ipv6/netfilter/nf_conntrack_reasm.c12
-rw-r--r--net/ipv6/raw.c49
-rw-r--r--net/ipv6/reassembly.c14
-rw-r--r--net/ipv6/route.c1059
-rw-r--r--net/ipv6/tcp_ipv6.c23
-rw-r--r--net/ipv6/udp.c104
-rw-r--r--net/ipv6/xfrm6_input.c110
-rw-r--r--net/ipv6/xfrm6_mode_ro.c93
-rw-r--r--net/ipv6/xfrm6_mode_transport.c5
-rw-r--r--net/ipv6/xfrm6_mode_tunnel.c3
-rw-r--r--net/ipv6/xfrm6_output.c18
-rw-r--r--net/ipv6/xfrm6_policy.c87
-rw-r--r--net/ipv6/xfrm6_state.c189
-rw-r--r--net/ipv6/xfrm6_tunnel.c2
54 files changed, 3325 insertions, 1407 deletions
diff --git a/net/ipv6/Kconfig b/net/ipv6/Kconfig
index 0ba06c0c5d39..a2d211da2aba 100644
--- a/net/ipv6/Kconfig
+++ b/net/ipv6/Kconfig
@@ -98,6 +98,15 @@ config INET6_IPCOMP
98 98
99 If unsure, say Y. 99 If unsure, say Y.
100 100
101config IPV6_MIP6
102 bool "IPv6: Mobility (EXPERIMENTAL)"
103 depends on IPV6 && EXPERIMENTAL
104 select XFRM
105 ---help---
106 Support for IPv6 Mobility described in RFC 3775.
107
108 If unsure, say N.
109
101config INET6_XFRM_TUNNEL 110config INET6_XFRM_TUNNEL
102 tristate 111 tristate
103 select INET6_TUNNEL 112 select INET6_TUNNEL
@@ -127,6 +136,13 @@ config INET6_XFRM_MODE_TUNNEL
127 136
128 If unsure, say Y. 137 If unsure, say Y.
129 138
139config INET6_XFRM_MODE_ROUTEOPTIMIZATION
140 tristate "IPv6: MIPv6 route optimization mode (EXPERIMENTAL)"
141 depends on IPV6 && EXPERIMENTAL
142 select XFRM
143 ---help---
144 Support for MIPv6 route optimization mode.
145
130config IPV6_TUNNEL 146config IPV6_TUNNEL
131 tristate "IPv6: IPv6-in-IPv6 tunnel" 147 tristate "IPv6: IPv6-in-IPv6 tunnel"
132 select INET6_TUNNEL 148 select INET6_TUNNEL
@@ -136,3 +152,31 @@ config IPV6_TUNNEL
136 152
137 If unsure, say N. 153 If unsure, say N.
138 154
155config IPV6_SUBTREES
156 bool "IPv6: source address based routing"
157 depends on IPV6 && EXPERIMENTAL
158 ---help---
159 Enable routing by source address or prefix.
160
161 The destination address is still the primary routing key, so mixing
162 normal and source prefix specific routes in the same routing table
163 may sometimes lead to unintended routing behavior. This can be
164 avoided by defining different routing tables for the normal and
165 source prefix specific routes.
166
167 If unsure, say N.
168
169config IPV6_MULTIPLE_TABLES
170 bool "IPv6: Multiple Routing Tables"
171 depends on IPV6 && EXPERIMENTAL
172 select FIB_RULES
173 ---help---
174 Support multiple routing tables.
175
176config IPV6_ROUTE_FWMARK
177 bool "IPv6: use netfilter MARK value as routing key"
178 depends on IPV6_MULTIPLE_TABLES && NETFILTER
179 ---help---
180 If you say Y here, you will be able to specify different routes for
181 packets with different mark values (see iptables(8), MARK target).
182
diff --git a/net/ipv6/Makefile b/net/ipv6/Makefile
index 386e0a626948..0213c6612b58 100644
--- a/net/ipv6/Makefile
+++ b/net/ipv6/Makefile
@@ -13,6 +13,9 @@ ipv6-objs := af_inet6.o anycast.o ip6_output.o ip6_input.o addrconf.o sit.o \
13ipv6-$(CONFIG_XFRM) += xfrm6_policy.o xfrm6_state.o xfrm6_input.o \ 13ipv6-$(CONFIG_XFRM) += xfrm6_policy.o xfrm6_state.o xfrm6_input.o \
14 xfrm6_output.o 14 xfrm6_output.o
15ipv6-$(CONFIG_NETFILTER) += netfilter.o 15ipv6-$(CONFIG_NETFILTER) += netfilter.o
16ipv6-$(CONFIG_IPV6_MULTIPLE_TABLES) += fib6_rules.o
17ipv6-$(CONFIG_IPV6_MIP6) += mip6.o
18
16ipv6-objs += $(ipv6-y) 19ipv6-objs += $(ipv6-y)
17 20
18obj-$(CONFIG_INET6_AH) += ah6.o 21obj-$(CONFIG_INET6_AH) += ah6.o
@@ -22,6 +25,7 @@ obj-$(CONFIG_INET6_XFRM_TUNNEL) += xfrm6_tunnel.o
22obj-$(CONFIG_INET6_TUNNEL) += tunnel6.o 25obj-$(CONFIG_INET6_TUNNEL) += tunnel6.o
23obj-$(CONFIG_INET6_XFRM_MODE_TRANSPORT) += xfrm6_mode_transport.o 26obj-$(CONFIG_INET6_XFRM_MODE_TRANSPORT) += xfrm6_mode_transport.o
24obj-$(CONFIG_INET6_XFRM_MODE_TUNNEL) += xfrm6_mode_tunnel.o 27obj-$(CONFIG_INET6_XFRM_MODE_TUNNEL) += xfrm6_mode_tunnel.o
28obj-$(CONFIG_INET6_XFRM_MODE_ROUTEOPTIMIZATION) += xfrm6_mode_ro.o
25obj-$(CONFIG_NETFILTER) += netfilter/ 29obj-$(CONFIG_NETFILTER) += netfilter/
26 30
27obj-$(CONFIG_IPV6_TUNNEL) += ip6_tunnel.o 31obj-$(CONFIG_IPV6_TUNNEL) += ip6_tunnel.o
diff --git a/net/ipv6/addrconf.c b/net/ipv6/addrconf.c
index c7852b38e03e..c18676352397 100644
--- a/net/ipv6/addrconf.c
+++ b/net/ipv6/addrconf.c
@@ -48,6 +48,7 @@
48#include <linux/net.h> 48#include <linux/net.h>
49#include <linux/in6.h> 49#include <linux/in6.h>
50#include <linux/netdevice.h> 50#include <linux/netdevice.h>
51#include <linux/if_addr.h>
51#include <linux/if_arp.h> 52#include <linux/if_arp.h>
52#include <linux/if_arcnet.h> 53#include <linux/if_arcnet.h>
53#include <linux/if_infiniband.h> 54#include <linux/if_infiniband.h>
@@ -72,6 +73,7 @@
72#include <net/addrconf.h> 73#include <net/addrconf.h>
73#include <net/tcp.h> 74#include <net/tcp.h>
74#include <net/ip.h> 75#include <net/ip.h>
76#include <net/netlink.h>
75#include <linux/if_tunnel.h> 77#include <linux/if_tunnel.h>
76#include <linux/rtnetlink.h> 78#include <linux/rtnetlink.h>
77 79
@@ -117,9 +119,6 @@ static int ipv6_count_addresses(struct inet6_dev *idev);
117static struct inet6_ifaddr *inet6_addr_lst[IN6_ADDR_HSIZE]; 119static struct inet6_ifaddr *inet6_addr_lst[IN6_ADDR_HSIZE];
118static DEFINE_RWLOCK(addrconf_hash_lock); 120static DEFINE_RWLOCK(addrconf_hash_lock);
119 121
120/* Protects inet6 devices */
121DEFINE_RWLOCK(addrconf_lock);
122
123static void addrconf_verify(unsigned long); 122static void addrconf_verify(unsigned long);
124 123
125static DEFINE_TIMER(addr_chk_timer, addrconf_verify, 0, 0); 124static DEFINE_TIMER(addr_chk_timer, addrconf_verify, 0, 0);
@@ -144,7 +143,7 @@ static int ipv6_chk_same_addr(const struct in6_addr *addr, struct net_device *de
144 143
145static ATOMIC_NOTIFIER_HEAD(inet6addr_chain); 144static ATOMIC_NOTIFIER_HEAD(inet6addr_chain);
146 145
147struct ipv6_devconf ipv6_devconf = { 146struct ipv6_devconf ipv6_devconf __read_mostly = {
148 .forwarding = 0, 147 .forwarding = 0,
149 .hop_limit = IPV6_DEFAULT_HOPLIMIT, 148 .hop_limit = IPV6_DEFAULT_HOPLIMIT,
150 .mtu6 = IPV6_MIN_MTU, 149 .mtu6 = IPV6_MIN_MTU,
@@ -173,9 +172,10 @@ struct ipv6_devconf ipv6_devconf = {
173 .accept_ra_rt_info_max_plen = 0, 172 .accept_ra_rt_info_max_plen = 0,
174#endif 173#endif
175#endif 174#endif
175 .proxy_ndp = 0,
176}; 176};
177 177
178static struct ipv6_devconf ipv6_devconf_dflt = { 178static struct ipv6_devconf ipv6_devconf_dflt __read_mostly = {
179 .forwarding = 0, 179 .forwarding = 0,
180 .hop_limit = IPV6_DEFAULT_HOPLIMIT, 180 .hop_limit = IPV6_DEFAULT_HOPLIMIT,
181 .mtu6 = IPV6_MIN_MTU, 181 .mtu6 = IPV6_MIN_MTU,
@@ -203,6 +203,7 @@ static struct ipv6_devconf ipv6_devconf_dflt = {
203 .accept_ra_rt_info_max_plen = 0, 203 .accept_ra_rt_info_max_plen = 0,
204#endif 204#endif
205#endif 205#endif
206 .proxy_ndp = 0,
206}; 207};
207 208
208/* IPv6 Wildcard Address and Loopback Address defined by RFC2553 */ 209/* IPv6 Wildcard Address and Loopback Address defined by RFC2553 */
@@ -314,6 +315,12 @@ static void addrconf_mod_timer(struct inet6_ifaddr *ifp,
314 315
315/* Nobody refers to this device, we may destroy it. */ 316/* Nobody refers to this device, we may destroy it. */
316 317
318static void in6_dev_finish_destroy_rcu(struct rcu_head *head)
319{
320 struct inet6_dev *idev = container_of(head, struct inet6_dev, rcu);
321 kfree(idev);
322}
323
317void in6_dev_finish_destroy(struct inet6_dev *idev) 324void in6_dev_finish_destroy(struct inet6_dev *idev)
318{ 325{
319 struct net_device *dev = idev->dev; 326 struct net_device *dev = idev->dev;
@@ -328,7 +335,7 @@ void in6_dev_finish_destroy(struct inet6_dev *idev)
328 return; 335 return;
329 } 336 }
330 snmp6_free_dev(idev); 337 snmp6_free_dev(idev);
331 kfree(idev); 338 call_rcu(&idev->rcu, in6_dev_finish_destroy_rcu);
332} 339}
333 340
334static struct inet6_dev * ipv6_add_dev(struct net_device *dev) 341static struct inet6_dev * ipv6_add_dev(struct net_device *dev)
@@ -404,9 +411,8 @@ static struct inet6_dev * ipv6_add_dev(struct net_device *dev)
404 if (netif_carrier_ok(dev)) 411 if (netif_carrier_ok(dev))
405 ndev->if_flags |= IF_READY; 412 ndev->if_flags |= IF_READY;
406 413
407 write_lock_bh(&addrconf_lock); 414 /* protected by rtnl_lock */
408 dev->ip6_ptr = ndev; 415 rcu_assign_pointer(dev->ip6_ptr, ndev);
409 write_unlock_bh(&addrconf_lock);
410 416
411 ipv6_mc_init_dev(ndev); 417 ipv6_mc_init_dev(ndev);
412 ndev->tstamp = jiffies; 418 ndev->tstamp = jiffies;
@@ -470,7 +476,7 @@ static void addrconf_forward_change(void)
470 476
471 read_lock(&dev_base_lock); 477 read_lock(&dev_base_lock);
472 for (dev=dev_base; dev; dev=dev->next) { 478 for (dev=dev_base; dev; dev=dev->next) {
473 read_lock(&addrconf_lock); 479 rcu_read_lock();
474 idev = __in6_dev_get(dev); 480 idev = __in6_dev_get(dev);
475 if (idev) { 481 if (idev) {
476 int changed = (!idev->cnf.forwarding) ^ (!ipv6_devconf.forwarding); 482 int changed = (!idev->cnf.forwarding) ^ (!ipv6_devconf.forwarding);
@@ -478,7 +484,7 @@ static void addrconf_forward_change(void)
478 if (changed) 484 if (changed)
479 dev_forward_change(idev); 485 dev_forward_change(idev);
480 } 486 }
481 read_unlock(&addrconf_lock); 487 rcu_read_unlock();
482 } 488 }
483 read_unlock(&dev_base_lock); 489 read_unlock(&dev_base_lock);
484} 490}
@@ -539,7 +545,7 @@ ipv6_add_addr(struct inet6_dev *idev, const struct in6_addr *addr, int pfxlen,
539 int hash; 545 int hash;
540 int err = 0; 546 int err = 0;
541 547
542 read_lock_bh(&addrconf_lock); 548 rcu_read_lock_bh();
543 if (idev->dead) { 549 if (idev->dead) {
544 err = -ENODEV; /*XXX*/ 550 err = -ENODEV; /*XXX*/
545 goto out2; 551 goto out2;
@@ -608,7 +614,7 @@ ipv6_add_addr(struct inet6_dev *idev, const struct in6_addr *addr, int pfxlen,
608 in6_ifa_hold(ifa); 614 in6_ifa_hold(ifa);
609 write_unlock(&idev->lock); 615 write_unlock(&idev->lock);
610out2: 616out2:
611 read_unlock_bh(&addrconf_lock); 617 rcu_read_unlock_bh();
612 618
613 if (likely(err == 0)) 619 if (likely(err == 0))
614 atomic_notifier_call_chain(&inet6addr_chain, NETDEV_UP, ifa); 620 atomic_notifier_call_chain(&inet6addr_chain, NETDEV_UP, ifa);
@@ -734,7 +740,7 @@ static void ipv6_del_addr(struct inet6_ifaddr *ifp)
734 740
735 if (rt && ((rt->rt6i_flags & (RTF_GATEWAY | RTF_DEFAULT)) == 0)) { 741 if (rt && ((rt->rt6i_flags & (RTF_GATEWAY | RTF_DEFAULT)) == 0)) {
736 if (onlink == 0) { 742 if (onlink == 0) {
737 ip6_del_rt(rt, NULL, NULL, NULL); 743 ip6_del_rt(rt);
738 rt = NULL; 744 rt = NULL;
739 } else if (!(rt->rt6i_flags & RTF_EXPIRES)) { 745 } else if (!(rt->rt6i_flags & RTF_EXPIRES)) {
740 rt->rt6i_expires = expires; 746 rt->rt6i_expires = expires;
@@ -911,7 +917,7 @@ int ipv6_dev_get_saddr(struct net_device *daddr_dev,
911 memset(&hiscore, 0, sizeof(hiscore)); 917 memset(&hiscore, 0, sizeof(hiscore));
912 918
913 read_lock(&dev_base_lock); 919 read_lock(&dev_base_lock);
914 read_lock(&addrconf_lock); 920 rcu_read_lock();
915 921
916 for (dev = dev_base; dev; dev=dev->next) { 922 for (dev = dev_base; dev; dev=dev->next) {
917 struct inet6_dev *idev; 923 struct inet6_dev *idev;
@@ -1032,9 +1038,27 @@ int ipv6_dev_get_saddr(struct net_device *daddr_dev,
1032 continue; 1038 continue;
1033 } 1039 }
1034 1040
1035 /* Rule 4: Prefer home address -- not implemented yet */ 1041 /* Rule 4: Prefer home address */
1042#ifdef CONFIG_IPV6_MIP6
1043 if (hiscore.rule < 4) {
1044 if (ifa_result->flags & IFA_F_HOMEADDRESS)
1045 hiscore.attrs |= IPV6_SADDR_SCORE_HOA;
1046 hiscore.rule++;
1047 }
1048 if (ifa->flags & IFA_F_HOMEADDRESS) {
1049 score.attrs |= IPV6_SADDR_SCORE_HOA;
1050 if (!(ifa_result->flags & IFA_F_HOMEADDRESS)) {
1051 score.rule = 4;
1052 goto record_it;
1053 }
1054 } else {
1055 if (hiscore.attrs & IPV6_SADDR_SCORE_HOA)
1056 continue;
1057 }
1058#else
1036 if (hiscore.rule < 4) 1059 if (hiscore.rule < 4)
1037 hiscore.rule++; 1060 hiscore.rule++;
1061#endif
1038 1062
1039 /* Rule 5: Prefer outgoing interface */ 1063 /* Rule 5: Prefer outgoing interface */
1040 if (hiscore.rule < 5) { 1064 if (hiscore.rule < 5) {
@@ -1123,7 +1147,7 @@ record_it:
1123 } 1147 }
1124 read_unlock_bh(&idev->lock); 1148 read_unlock_bh(&idev->lock);
1125 } 1149 }
1126 read_unlock(&addrconf_lock); 1150 rcu_read_unlock();
1127 read_unlock(&dev_base_lock); 1151 read_unlock(&dev_base_lock);
1128 1152
1129 if (!ifa_result) 1153 if (!ifa_result)
@@ -1147,7 +1171,7 @@ int ipv6_get_lladdr(struct net_device *dev, struct in6_addr *addr)
1147 struct inet6_dev *idev; 1171 struct inet6_dev *idev;
1148 int err = -EADDRNOTAVAIL; 1172 int err = -EADDRNOTAVAIL;
1149 1173
1150 read_lock(&addrconf_lock); 1174 rcu_read_lock();
1151 if ((idev = __in6_dev_get(dev)) != NULL) { 1175 if ((idev = __in6_dev_get(dev)) != NULL) {
1152 struct inet6_ifaddr *ifp; 1176 struct inet6_ifaddr *ifp;
1153 1177
@@ -1161,7 +1185,7 @@ int ipv6_get_lladdr(struct net_device *dev, struct in6_addr *addr)
1161 } 1185 }
1162 read_unlock_bh(&idev->lock); 1186 read_unlock_bh(&idev->lock);
1163 } 1187 }
1164 read_unlock(&addrconf_lock); 1188 rcu_read_unlock();
1165 return err; 1189 return err;
1166} 1190}
1167 1191
@@ -1462,7 +1486,7 @@ static void ipv6_regen_rndid(unsigned long data)
1462 struct inet6_dev *idev = (struct inet6_dev *) data; 1486 struct inet6_dev *idev = (struct inet6_dev *) data;
1463 unsigned long expires; 1487 unsigned long expires;
1464 1488
1465 read_lock_bh(&addrconf_lock); 1489 rcu_read_lock_bh();
1466 write_lock_bh(&idev->lock); 1490 write_lock_bh(&idev->lock);
1467 1491
1468 if (idev->dead) 1492 if (idev->dead)
@@ -1486,7 +1510,7 @@ static void ipv6_regen_rndid(unsigned long data)
1486 1510
1487out: 1511out:
1488 write_unlock_bh(&idev->lock); 1512 write_unlock_bh(&idev->lock);
1489 read_unlock_bh(&addrconf_lock); 1513 rcu_read_unlock_bh();
1490 in6_dev_put(idev); 1514 in6_dev_put(idev);
1491} 1515}
1492 1516
@@ -1507,59 +1531,56 @@ static void
1507addrconf_prefix_route(struct in6_addr *pfx, int plen, struct net_device *dev, 1531addrconf_prefix_route(struct in6_addr *pfx, int plen, struct net_device *dev,
1508 unsigned long expires, u32 flags) 1532 unsigned long expires, u32 flags)
1509{ 1533{
1510 struct in6_rtmsg rtmsg; 1534 struct fib6_config cfg = {
1535 .fc_table = RT6_TABLE_PREFIX,
1536 .fc_metric = IP6_RT_PRIO_ADDRCONF,
1537 .fc_ifindex = dev->ifindex,
1538 .fc_expires = expires,
1539 .fc_dst_len = plen,
1540 .fc_flags = RTF_UP | flags,
1541 };
1511 1542
1512 memset(&rtmsg, 0, sizeof(rtmsg)); 1543 ipv6_addr_copy(&cfg.fc_dst, pfx);
1513 ipv6_addr_copy(&rtmsg.rtmsg_dst, pfx);
1514 rtmsg.rtmsg_dst_len = plen;
1515 rtmsg.rtmsg_metric = IP6_RT_PRIO_ADDRCONF;
1516 rtmsg.rtmsg_ifindex = dev->ifindex;
1517 rtmsg.rtmsg_info = expires;
1518 rtmsg.rtmsg_flags = RTF_UP|flags;
1519 rtmsg.rtmsg_type = RTMSG_NEWROUTE;
1520 1544
1521 /* Prevent useless cloning on PtP SIT. 1545 /* Prevent useless cloning on PtP SIT.
1522 This thing is done here expecting that the whole 1546 This thing is done here expecting that the whole
1523 class of non-broadcast devices need not cloning. 1547 class of non-broadcast devices need not cloning.
1524 */ 1548 */
1525 if (dev->type == ARPHRD_SIT && (dev->flags&IFF_POINTOPOINT)) 1549 if (dev->type == ARPHRD_SIT && (dev->flags & IFF_POINTOPOINT))
1526 rtmsg.rtmsg_flags |= RTF_NONEXTHOP; 1550 cfg.fc_flags |= RTF_NONEXTHOP;
1527 1551
1528 ip6_route_add(&rtmsg, NULL, NULL, NULL); 1552 ip6_route_add(&cfg);
1529} 1553}
1530 1554
1531/* Create "default" multicast route to the interface */ 1555/* Create "default" multicast route to the interface */
1532 1556
1533static void addrconf_add_mroute(struct net_device *dev) 1557static void addrconf_add_mroute(struct net_device *dev)
1534{ 1558{
1535 struct in6_rtmsg rtmsg; 1559 struct fib6_config cfg = {
1560 .fc_table = RT6_TABLE_LOCAL,
1561 .fc_metric = IP6_RT_PRIO_ADDRCONF,
1562 .fc_ifindex = dev->ifindex,
1563 .fc_dst_len = 8,
1564 .fc_flags = RTF_UP,
1565 };
1566
1567 ipv6_addr_set(&cfg.fc_dst, htonl(0xFF000000), 0, 0, 0);
1536 1568
1537 memset(&rtmsg, 0, sizeof(rtmsg)); 1569 ip6_route_add(&cfg);
1538 ipv6_addr_set(&rtmsg.rtmsg_dst,
1539 htonl(0xFF000000), 0, 0, 0);
1540 rtmsg.rtmsg_dst_len = 8;
1541 rtmsg.rtmsg_metric = IP6_RT_PRIO_ADDRCONF;
1542 rtmsg.rtmsg_ifindex = dev->ifindex;
1543 rtmsg.rtmsg_flags = RTF_UP;
1544 rtmsg.rtmsg_type = RTMSG_NEWROUTE;
1545 ip6_route_add(&rtmsg, NULL, NULL, NULL);
1546} 1570}
1547 1571
1548static void sit_route_add(struct net_device *dev) 1572static void sit_route_add(struct net_device *dev)
1549{ 1573{
1550 struct in6_rtmsg rtmsg; 1574 struct fib6_config cfg = {
1551 1575 .fc_table = RT6_TABLE_MAIN,
1552 memset(&rtmsg, 0, sizeof(rtmsg)); 1576 .fc_metric = IP6_RT_PRIO_ADDRCONF,
1553 1577 .fc_ifindex = dev->ifindex,
1554 rtmsg.rtmsg_type = RTMSG_NEWROUTE; 1578 .fc_dst_len = 96,
1555 rtmsg.rtmsg_metric = IP6_RT_PRIO_ADDRCONF; 1579 .fc_flags = RTF_UP | RTF_NONEXTHOP,
1580 };
1556 1581
1557 /* prefix length - 96 bits "::d.d.d.d" */ 1582 /* prefix length - 96 bits "::d.d.d.d" */
1558 rtmsg.rtmsg_dst_len = 96; 1583 ip6_route_add(&cfg);
1559 rtmsg.rtmsg_flags = RTF_UP|RTF_NONEXTHOP;
1560 rtmsg.rtmsg_ifindex = dev->ifindex;
1561
1562 ip6_route_add(&rtmsg, NULL, NULL, NULL);
1563} 1584}
1564 1585
1565static void addrconf_add_lroute(struct net_device *dev) 1586static void addrconf_add_lroute(struct net_device *dev)
@@ -1660,7 +1681,7 @@ void addrconf_prefix_rcv(struct net_device *dev, u8 *opt, int len)
1660 if (rt && ((rt->rt6i_flags & (RTF_GATEWAY | RTF_DEFAULT)) == 0)) { 1681 if (rt && ((rt->rt6i_flags & (RTF_GATEWAY | RTF_DEFAULT)) == 0)) {
1661 if (rt->rt6i_flags&RTF_EXPIRES) { 1682 if (rt->rt6i_flags&RTF_EXPIRES) {
1662 if (valid_lft == 0) { 1683 if (valid_lft == 0) {
1663 ip6_del_rt(rt, NULL, NULL, NULL); 1684 ip6_del_rt(rt);
1664 rt = NULL; 1685 rt = NULL;
1665 } else { 1686 } else {
1666 rt->rt6i_expires = jiffies + rt_expires; 1687 rt->rt6i_expires = jiffies + rt_expires;
@@ -1870,12 +1891,11 @@ err_exit:
1870 * Manual configuration of address on an interface 1891 * Manual configuration of address on an interface
1871 */ 1892 */
1872static int inet6_addr_add(int ifindex, struct in6_addr *pfx, int plen, 1893static int inet6_addr_add(int ifindex, struct in6_addr *pfx, int plen,
1873 __u32 prefered_lft, __u32 valid_lft) 1894 __u8 ifa_flags, __u32 prefered_lft, __u32 valid_lft)
1874{ 1895{
1875 struct inet6_ifaddr *ifp; 1896 struct inet6_ifaddr *ifp;
1876 struct inet6_dev *idev; 1897 struct inet6_dev *idev;
1877 struct net_device *dev; 1898 struct net_device *dev;
1878 __u8 ifa_flags = 0;
1879 int scope; 1899 int scope;
1880 1900
1881 ASSERT_RTNL(); 1901 ASSERT_RTNL();
@@ -1887,9 +1907,6 @@ static int inet6_addr_add(int ifindex, struct in6_addr *pfx, int plen,
1887 if ((dev = __dev_get_by_index(ifindex)) == NULL) 1907 if ((dev = __dev_get_by_index(ifindex)) == NULL)
1888 return -ENODEV; 1908 return -ENODEV;
1889 1909
1890 if (!(dev->flags&IFF_UP))
1891 return -ENETDOWN;
1892
1893 if ((idev = addrconf_add_dev(dev)) == NULL) 1910 if ((idev = addrconf_add_dev(dev)) == NULL)
1894 return -ENOBUFS; 1911 return -ENOBUFS;
1895 1912
@@ -1971,7 +1988,7 @@ int addrconf_add_ifaddr(void __user *arg)
1971 1988
1972 rtnl_lock(); 1989 rtnl_lock();
1973 err = inet6_addr_add(ireq.ifr6_ifindex, &ireq.ifr6_addr, ireq.ifr6_prefixlen, 1990 err = inet6_addr_add(ireq.ifr6_ifindex, &ireq.ifr6_addr, ireq.ifr6_prefixlen,
1974 INFINITY_LIFE_TIME, INFINITY_LIFE_TIME); 1991 IFA_F_PERMANENT, INFINITY_LIFE_TIME, INFINITY_LIFE_TIME);
1975 rtnl_unlock(); 1992 rtnl_unlock();
1976 return err; 1993 return err;
1977} 1994}
@@ -2344,10 +2361,10 @@ static int addrconf_ifdown(struct net_device *dev, int how)
2344 Do not dev_put! 2361 Do not dev_put!
2345 */ 2362 */
2346 if (how == 1) { 2363 if (how == 1) {
2347 write_lock_bh(&addrconf_lock);
2348 dev->ip6_ptr = NULL;
2349 idev->dead = 1; 2364 idev->dead = 1;
2350 write_unlock_bh(&addrconf_lock); 2365
2366 /* protected by rtnl_lock */
2367 rcu_assign_pointer(dev->ip6_ptr, NULL);
2351 2368
2352 /* Step 1.5: remove snmp6 entry */ 2369 /* Step 1.5: remove snmp6 entry */
2353 snmp6_unregister_dev(idev); 2370 snmp6_unregister_dev(idev);
@@ -2514,7 +2531,8 @@ static void addrconf_dad_start(struct inet6_ifaddr *ifp, u32 flags)
2514 spin_lock_bh(&ifp->lock); 2531 spin_lock_bh(&ifp->lock);
2515 2532
2516 if (dev->flags&(IFF_NOARP|IFF_LOOPBACK) || 2533 if (dev->flags&(IFF_NOARP|IFF_LOOPBACK) ||
2517 !(ifp->flags&IFA_F_TENTATIVE)) { 2534 !(ifp->flags&IFA_F_TENTATIVE) ||
2535 ifp->flags & IFA_F_NODAD) {
2518 ifp->flags &= ~IFA_F_TENTATIVE; 2536 ifp->flags &= ~IFA_F_TENTATIVE;
2519 spin_unlock_bh(&ifp->lock); 2537 spin_unlock_bh(&ifp->lock);
2520 read_unlock_bh(&idev->lock); 2538 read_unlock_bh(&idev->lock);
@@ -2759,6 +2777,26 @@ void if6_proc_exit(void)
2759} 2777}
2760#endif /* CONFIG_PROC_FS */ 2778#endif /* CONFIG_PROC_FS */
2761 2779
2780#ifdef CONFIG_IPV6_MIP6
2781/* Check if address is a home address configured on any interface. */
2782int ipv6_chk_home_addr(struct in6_addr *addr)
2783{
2784 int ret = 0;
2785 struct inet6_ifaddr * ifp;
2786 u8 hash = ipv6_addr_hash(addr);
2787 read_lock_bh(&addrconf_hash_lock);
2788 for (ifp = inet6_addr_lst[hash]; ifp; ifp = ifp->lst_next) {
2789 if (ipv6_addr_cmp(&ifp->addr, addr) == 0 &&
2790 (ifp->flags & IFA_F_HOMEADDRESS)) {
2791 ret = 1;
2792 break;
2793 }
2794 }
2795 read_unlock_bh(&addrconf_hash_lock);
2796 return ret;
2797}
2798#endif
2799
2762/* 2800/*
2763 * Periodic address status verification 2801 * Periodic address status verification
2764 */ 2802 */
@@ -2869,66 +2907,68 @@ restart:
2869 spin_unlock_bh(&addrconf_verify_lock); 2907 spin_unlock_bh(&addrconf_verify_lock);
2870} 2908}
2871 2909
2910static struct in6_addr *extract_addr(struct nlattr *addr, struct nlattr *local)
2911{
2912 struct in6_addr *pfx = NULL;
2913
2914 if (addr)
2915 pfx = nla_data(addr);
2916
2917 if (local) {
2918 if (pfx && nla_memcmp(local, pfx, sizeof(*pfx)))
2919 pfx = NULL;
2920 else
2921 pfx = nla_data(local);
2922 }
2923
2924 return pfx;
2925}
2926
2927static struct nla_policy ifa_ipv6_policy[IFA_MAX+1] __read_mostly = {
2928 [IFA_ADDRESS] = { .len = sizeof(struct in6_addr) },
2929 [IFA_LOCAL] = { .len = sizeof(struct in6_addr) },
2930 [IFA_CACHEINFO] = { .len = sizeof(struct ifa_cacheinfo) },
2931};
2932
2872static int 2933static int
2873inet6_rtm_deladdr(struct sk_buff *skb, struct nlmsghdr *nlh, void *arg) 2934inet6_rtm_deladdr(struct sk_buff *skb, struct nlmsghdr *nlh, void *arg)
2874{ 2935{
2875 struct rtattr **rta = arg; 2936 struct ifaddrmsg *ifm;
2876 struct ifaddrmsg *ifm = NLMSG_DATA(nlh); 2937 struct nlattr *tb[IFA_MAX+1];
2877 struct in6_addr *pfx; 2938 struct in6_addr *pfx;
2939 int err;
2878 2940
2879 pfx = NULL; 2941 err = nlmsg_parse(nlh, sizeof(*ifm), tb, IFA_MAX, ifa_ipv6_policy);
2880 if (rta[IFA_ADDRESS-1]) { 2942 if (err < 0)
2881 if (RTA_PAYLOAD(rta[IFA_ADDRESS-1]) < sizeof(*pfx)) 2943 return err;
2882 return -EINVAL; 2944
2883 pfx = RTA_DATA(rta[IFA_ADDRESS-1]); 2945 ifm = nlmsg_data(nlh);
2884 } 2946 pfx = extract_addr(tb[IFA_ADDRESS], tb[IFA_LOCAL]);
2885 if (rta[IFA_LOCAL-1]) {
2886 if (RTA_PAYLOAD(rta[IFA_LOCAL-1]) < sizeof(*pfx) ||
2887 (pfx && memcmp(pfx, RTA_DATA(rta[IFA_LOCAL-1]), sizeof(*pfx))))
2888 return -EINVAL;
2889 pfx = RTA_DATA(rta[IFA_LOCAL-1]);
2890 }
2891 if (pfx == NULL) 2947 if (pfx == NULL)
2892 return -EINVAL; 2948 return -EINVAL;
2893 2949
2894 return inet6_addr_del(ifm->ifa_index, pfx, ifm->ifa_prefixlen); 2950 return inet6_addr_del(ifm->ifa_index, pfx, ifm->ifa_prefixlen);
2895} 2951}
2896 2952
2897static int 2953static int inet6_addr_modify(struct inet6_ifaddr *ifp, u8 ifa_flags,
2898inet6_addr_modify(int ifindex, struct in6_addr *pfx, 2954 u32 prefered_lft, u32 valid_lft)
2899 __u32 prefered_lft, __u32 valid_lft)
2900{ 2955{
2901 struct inet6_ifaddr *ifp = NULL;
2902 struct net_device *dev;
2903 int ifa_flags = 0;
2904
2905 if ((dev = __dev_get_by_index(ifindex)) == NULL)
2906 return -ENODEV;
2907
2908 if (!(dev->flags&IFF_UP))
2909 return -ENETDOWN;
2910
2911 if (!valid_lft || (prefered_lft > valid_lft)) 2956 if (!valid_lft || (prefered_lft > valid_lft))
2912 return -EINVAL; 2957 return -EINVAL;
2913 2958
2914 ifp = ipv6_get_ifaddr(pfx, dev, 1);
2915 if (ifp == NULL)
2916 return -ENOENT;
2917
2918 if (valid_lft == INFINITY_LIFE_TIME) 2959 if (valid_lft == INFINITY_LIFE_TIME)
2919 ifa_flags = IFA_F_PERMANENT; 2960 ifa_flags |= IFA_F_PERMANENT;
2920 else if (valid_lft >= 0x7FFFFFFF/HZ) 2961 else if (valid_lft >= 0x7FFFFFFF/HZ)
2921 valid_lft = 0x7FFFFFFF/HZ; 2962 valid_lft = 0x7FFFFFFF/HZ;
2922 2963
2923 if (prefered_lft == 0) 2964 if (prefered_lft == 0)
2924 ifa_flags = IFA_F_DEPRECATED; 2965 ifa_flags |= IFA_F_DEPRECATED;
2925 else if ((prefered_lft >= 0x7FFFFFFF/HZ) && 2966 else if ((prefered_lft >= 0x7FFFFFFF/HZ) &&
2926 (prefered_lft != INFINITY_LIFE_TIME)) 2967 (prefered_lft != INFINITY_LIFE_TIME))
2927 prefered_lft = 0x7FFFFFFF/HZ; 2968 prefered_lft = 0x7FFFFFFF/HZ;
2928 2969
2929 spin_lock_bh(&ifp->lock); 2970 spin_lock_bh(&ifp->lock);
2930 ifp->flags = (ifp->flags & ~(IFA_F_DEPRECATED|IFA_F_PERMANENT)) | ifa_flags; 2971 ifp->flags = (ifp->flags & ~(IFA_F_DEPRECATED | IFA_F_PERMANENT | IFA_F_NODAD | IFA_F_HOMEADDRESS)) | ifa_flags;
2931
2932 ifp->tstamp = jiffies; 2972 ifp->tstamp = jiffies;
2933 ifp->valid_lft = valid_lft; 2973 ifp->valid_lft = valid_lft;
2934 ifp->prefered_lft = prefered_lft; 2974 ifp->prefered_lft = prefered_lft;
@@ -2936,7 +2976,6 @@ inet6_addr_modify(int ifindex, struct in6_addr *pfx,
2936 spin_unlock_bh(&ifp->lock); 2976 spin_unlock_bh(&ifp->lock);
2937 if (!(ifp->flags&IFA_F_TENTATIVE)) 2977 if (!(ifp->flags&IFA_F_TENTATIVE))
2938 ipv6_ifa_notify(0, ifp); 2978 ipv6_ifa_notify(0, ifp);
2939 in6_ifa_put(ifp);
2940 2979
2941 addrconf_verify(0); 2980 addrconf_verify(0);
2942 2981
@@ -2946,172 +2985,189 @@ inet6_addr_modify(int ifindex, struct in6_addr *pfx,
2946static int 2985static int
2947inet6_rtm_newaddr(struct sk_buff *skb, struct nlmsghdr *nlh, void *arg) 2986inet6_rtm_newaddr(struct sk_buff *skb, struct nlmsghdr *nlh, void *arg)
2948{ 2987{
2949 struct rtattr **rta = arg; 2988 struct ifaddrmsg *ifm;
2950 struct ifaddrmsg *ifm = NLMSG_DATA(nlh); 2989 struct nlattr *tb[IFA_MAX+1];
2951 struct in6_addr *pfx; 2990 struct in6_addr *pfx;
2952 __u32 valid_lft = INFINITY_LIFE_TIME, prefered_lft = INFINITY_LIFE_TIME; 2991 struct inet6_ifaddr *ifa;
2992 struct net_device *dev;
2993 u32 valid_lft = INFINITY_LIFE_TIME, preferred_lft = INFINITY_LIFE_TIME;
2994 u8 ifa_flags;
2995 int err;
2953 2996
2954 pfx = NULL; 2997 err = nlmsg_parse(nlh, sizeof(*ifm), tb, IFA_MAX, ifa_ipv6_policy);
2955 if (rta[IFA_ADDRESS-1]) { 2998 if (err < 0)
2956 if (RTA_PAYLOAD(rta[IFA_ADDRESS-1]) < sizeof(*pfx)) 2999 return err;
2957 return -EINVAL; 3000
2958 pfx = RTA_DATA(rta[IFA_ADDRESS-1]); 3001 ifm = nlmsg_data(nlh);
2959 } 3002 pfx = extract_addr(tb[IFA_ADDRESS], tb[IFA_LOCAL]);
2960 if (rta[IFA_LOCAL-1]) {
2961 if (RTA_PAYLOAD(rta[IFA_LOCAL-1]) < sizeof(*pfx) ||
2962 (pfx && memcmp(pfx, RTA_DATA(rta[IFA_LOCAL-1]), sizeof(*pfx))))
2963 return -EINVAL;
2964 pfx = RTA_DATA(rta[IFA_LOCAL-1]);
2965 }
2966 if (pfx == NULL) 3003 if (pfx == NULL)
2967 return -EINVAL; 3004 return -EINVAL;
2968 3005
2969 if (rta[IFA_CACHEINFO-1]) { 3006 if (tb[IFA_CACHEINFO]) {
2970 struct ifa_cacheinfo *ci; 3007 struct ifa_cacheinfo *ci;
2971 if (RTA_PAYLOAD(rta[IFA_CACHEINFO-1]) < sizeof(*ci)) 3008
2972 return -EINVAL; 3009 ci = nla_data(tb[IFA_CACHEINFO]);
2973 ci = RTA_DATA(rta[IFA_CACHEINFO-1]);
2974 valid_lft = ci->ifa_valid; 3010 valid_lft = ci->ifa_valid;
2975 prefered_lft = ci->ifa_prefered; 3011 preferred_lft = ci->ifa_prefered;
3012 } else {
3013 preferred_lft = INFINITY_LIFE_TIME;
3014 valid_lft = INFINITY_LIFE_TIME;
2976 } 3015 }
2977 3016
2978 if (nlh->nlmsg_flags & NLM_F_REPLACE) { 3017 dev = __dev_get_by_index(ifm->ifa_index);
2979 int ret; 3018 if (dev == NULL)
2980 ret = inet6_addr_modify(ifm->ifa_index, pfx, 3019 return -ENODEV;
2981 prefered_lft, valid_lft); 3020
2982 if (ret == 0 || !(nlh->nlmsg_flags & NLM_F_CREATE)) 3021 /* We ignore other flags so far. */
2983 return ret; 3022 ifa_flags = ifm->ifa_flags & (IFA_F_NODAD | IFA_F_HOMEADDRESS);
3023
3024 ifa = ipv6_get_ifaddr(pfx, dev, 1);
3025 if (ifa == NULL) {
3026 /*
3027 * It would be best to check for !NLM_F_CREATE here but
3028 * userspace alreay relies on not having to provide this.
3029 */
3030 return inet6_addr_add(ifm->ifa_index, pfx, ifm->ifa_prefixlen,
3031 ifa_flags, preferred_lft, valid_lft);
2984 } 3032 }
2985 3033
2986 return inet6_addr_add(ifm->ifa_index, pfx, ifm->ifa_prefixlen, 3034 if (nlh->nlmsg_flags & NLM_F_EXCL ||
2987 prefered_lft, valid_lft); 3035 !(nlh->nlmsg_flags & NLM_F_REPLACE))
3036 err = -EEXIST;
3037 else
3038 err = inet6_addr_modify(ifa, ifa_flags, preferred_lft, valid_lft);
3039
3040 in6_ifa_put(ifa);
3041
3042 return err;
3043}
3044
3045static void put_ifaddrmsg(struct nlmsghdr *nlh, u8 prefixlen, u8 flags,
3046 u8 scope, int ifindex)
3047{
3048 struct ifaddrmsg *ifm;
2988 3049
3050 ifm = nlmsg_data(nlh);
3051 ifm->ifa_family = AF_INET6;
3052 ifm->ifa_prefixlen = prefixlen;
3053 ifm->ifa_flags = flags;
3054 ifm->ifa_scope = scope;
3055 ifm->ifa_index = ifindex;
2989} 3056}
2990 3057
2991/* Maximum length of ifa_cacheinfo attributes */ 3058static int put_cacheinfo(struct sk_buff *skb, unsigned long cstamp,
2992#define INET6_IFADDR_RTA_SPACE \ 3059 unsigned long tstamp, u32 preferred, u32 valid)
2993 RTA_SPACE(16) /* IFA_ADDRESS */ + \ 3060{
2994 RTA_SPACE(sizeof(struct ifa_cacheinfo)) /* CACHEINFO */ 3061 struct ifa_cacheinfo ci;
3062
3063 ci.cstamp = (u32)(TIME_DELTA(cstamp, INITIAL_JIFFIES) / HZ * 100
3064 + TIME_DELTA(cstamp, INITIAL_JIFFIES) % HZ * 100 / HZ);
3065 ci.tstamp = (u32)(TIME_DELTA(tstamp, INITIAL_JIFFIES) / HZ * 100
3066 + TIME_DELTA(tstamp, INITIAL_JIFFIES) % HZ * 100 / HZ);
3067 ci.ifa_prefered = preferred;
3068 ci.ifa_valid = valid;
3069
3070 return nla_put(skb, IFA_CACHEINFO, sizeof(ci), &ci);
3071}
3072
3073static inline int rt_scope(int ifa_scope)
3074{
3075 if (ifa_scope & IFA_HOST)
3076 return RT_SCOPE_HOST;
3077 else if (ifa_scope & IFA_LINK)
3078 return RT_SCOPE_LINK;
3079 else if (ifa_scope & IFA_SITE)
3080 return RT_SCOPE_SITE;
3081 else
3082 return RT_SCOPE_UNIVERSE;
3083}
3084
3085static inline int inet6_ifaddr_msgsize(void)
3086{
3087 return nlmsg_total_size(sizeof(struct ifaddrmsg) +
3088 nla_total_size(16) +
3089 nla_total_size(sizeof(struct ifa_cacheinfo)) +
3090 128);
3091}
2995 3092
2996static int inet6_fill_ifaddr(struct sk_buff *skb, struct inet6_ifaddr *ifa, 3093static int inet6_fill_ifaddr(struct sk_buff *skb, struct inet6_ifaddr *ifa,
2997 u32 pid, u32 seq, int event, unsigned int flags) 3094 u32 pid, u32 seq, int event, unsigned int flags)
2998{ 3095{
2999 struct ifaddrmsg *ifm;
3000 struct nlmsghdr *nlh; 3096 struct nlmsghdr *nlh;
3001 struct ifa_cacheinfo ci; 3097 u32 preferred, valid;
3002 unsigned char *b = skb->tail; 3098
3099 nlh = nlmsg_put(skb, pid, seq, event, sizeof(struct ifaddrmsg), flags);
3100 if (nlh == NULL)
3101 return -ENOBUFS;
3102
3103 put_ifaddrmsg(nlh, ifa->prefix_len, ifa->flags, rt_scope(ifa->scope),
3104 ifa->idev->dev->ifindex);
3003 3105
3004 nlh = NLMSG_NEW(skb, pid, seq, event, sizeof(*ifm), flags);
3005 ifm = NLMSG_DATA(nlh);
3006 ifm->ifa_family = AF_INET6;
3007 ifm->ifa_prefixlen = ifa->prefix_len;
3008 ifm->ifa_flags = ifa->flags;
3009 ifm->ifa_scope = RT_SCOPE_UNIVERSE;
3010 if (ifa->scope&IFA_HOST)
3011 ifm->ifa_scope = RT_SCOPE_HOST;
3012 else if (ifa->scope&IFA_LINK)
3013 ifm->ifa_scope = RT_SCOPE_LINK;
3014 else if (ifa->scope&IFA_SITE)
3015 ifm->ifa_scope = RT_SCOPE_SITE;
3016 ifm->ifa_index = ifa->idev->dev->ifindex;
3017 RTA_PUT(skb, IFA_ADDRESS, 16, &ifa->addr);
3018 if (!(ifa->flags&IFA_F_PERMANENT)) { 3106 if (!(ifa->flags&IFA_F_PERMANENT)) {
3019 ci.ifa_prefered = ifa->prefered_lft; 3107 preferred = ifa->prefered_lft;
3020 ci.ifa_valid = ifa->valid_lft; 3108 valid = ifa->valid_lft;
3021 if (ci.ifa_prefered != INFINITY_LIFE_TIME) { 3109 if (preferred != INFINITY_LIFE_TIME) {
3022 long tval = (jiffies - ifa->tstamp)/HZ; 3110 long tval = (jiffies - ifa->tstamp)/HZ;
3023 ci.ifa_prefered -= tval; 3111 preferred -= tval;
3024 if (ci.ifa_valid != INFINITY_LIFE_TIME) 3112 if (valid != INFINITY_LIFE_TIME)
3025 ci.ifa_valid -= tval; 3113 valid -= tval;
3026 } 3114 }
3027 } else { 3115 } else {
3028 ci.ifa_prefered = INFINITY_LIFE_TIME; 3116 preferred = INFINITY_LIFE_TIME;
3029 ci.ifa_valid = INFINITY_LIFE_TIME; 3117 valid = INFINITY_LIFE_TIME;
3030 } 3118 }
3031 ci.cstamp = (__u32)(TIME_DELTA(ifa->cstamp, INITIAL_JIFFIES) / HZ * 100
3032 + TIME_DELTA(ifa->cstamp, INITIAL_JIFFIES) % HZ * 100 / HZ);
3033 ci.tstamp = (__u32)(TIME_DELTA(ifa->tstamp, INITIAL_JIFFIES) / HZ * 100
3034 + TIME_DELTA(ifa->tstamp, INITIAL_JIFFIES) % HZ * 100 / HZ);
3035 RTA_PUT(skb, IFA_CACHEINFO, sizeof(ci), &ci);
3036 nlh->nlmsg_len = skb->tail - b;
3037 return skb->len;
3038 3119
3039nlmsg_failure: 3120 if (nla_put(skb, IFA_ADDRESS, 16, &ifa->addr) < 0 ||
3040rtattr_failure: 3121 put_cacheinfo(skb, ifa->cstamp, ifa->tstamp, preferred, valid) < 0)
3041 skb_trim(skb, b - skb->data); 3122 return nlmsg_cancel(skb, nlh);
3042 return -1; 3123
3124 return nlmsg_end(skb, nlh);
3043} 3125}
3044 3126
3045static int inet6_fill_ifmcaddr(struct sk_buff *skb, struct ifmcaddr6 *ifmca, 3127static int inet6_fill_ifmcaddr(struct sk_buff *skb, struct ifmcaddr6 *ifmca,
3046 u32 pid, u32 seq, int event, u16 flags) 3128 u32 pid, u32 seq, int event, u16 flags)
3047{ 3129{
3048 struct ifaddrmsg *ifm;
3049 struct nlmsghdr *nlh; 3130 struct nlmsghdr *nlh;
3050 struct ifa_cacheinfo ci; 3131 u8 scope = RT_SCOPE_UNIVERSE;
3051 unsigned char *b = skb->tail; 3132 int ifindex = ifmca->idev->dev->ifindex;
3052
3053 nlh = NLMSG_NEW(skb, pid, seq, event, sizeof(*ifm), flags);
3054 ifm = NLMSG_DATA(nlh);
3055 ifm->ifa_family = AF_INET6;
3056 ifm->ifa_prefixlen = 128;
3057 ifm->ifa_flags = IFA_F_PERMANENT;
3058 ifm->ifa_scope = RT_SCOPE_UNIVERSE;
3059 if (ipv6_addr_scope(&ifmca->mca_addr)&IFA_SITE)
3060 ifm->ifa_scope = RT_SCOPE_SITE;
3061 ifm->ifa_index = ifmca->idev->dev->ifindex;
3062 RTA_PUT(skb, IFA_MULTICAST, 16, &ifmca->mca_addr);
3063 ci.cstamp = (__u32)(TIME_DELTA(ifmca->mca_cstamp, INITIAL_JIFFIES) / HZ
3064 * 100 + TIME_DELTA(ifmca->mca_cstamp, INITIAL_JIFFIES) % HZ
3065 * 100 / HZ);
3066 ci.tstamp = (__u32)(TIME_DELTA(ifmca->mca_tstamp, INITIAL_JIFFIES) / HZ
3067 * 100 + TIME_DELTA(ifmca->mca_tstamp, INITIAL_JIFFIES) % HZ
3068 * 100 / HZ);
3069 ci.ifa_prefered = INFINITY_LIFE_TIME;
3070 ci.ifa_valid = INFINITY_LIFE_TIME;
3071 RTA_PUT(skb, IFA_CACHEINFO, sizeof(ci), &ci);
3072 nlh->nlmsg_len = skb->tail - b;
3073 return skb->len;
3074 3133
3075nlmsg_failure: 3134 if (ipv6_addr_scope(&ifmca->mca_addr) & IFA_SITE)
3076rtattr_failure: 3135 scope = RT_SCOPE_SITE;
3077 skb_trim(skb, b - skb->data); 3136
3078 return -1; 3137 nlh = nlmsg_put(skb, pid, seq, event, sizeof(struct ifaddrmsg), flags);
3138 if (nlh == NULL)
3139 return -ENOBUFS;
3140
3141 put_ifaddrmsg(nlh, 128, IFA_F_PERMANENT, scope, ifindex);
3142 if (nla_put(skb, IFA_MULTICAST, 16, &ifmca->mca_addr) < 0 ||
3143 put_cacheinfo(skb, ifmca->mca_cstamp, ifmca->mca_tstamp,
3144 INFINITY_LIFE_TIME, INFINITY_LIFE_TIME) < 0)
3145 return nlmsg_cancel(skb, nlh);
3146
3147 return nlmsg_end(skb, nlh);
3079} 3148}
3080 3149
3081static int inet6_fill_ifacaddr(struct sk_buff *skb, struct ifacaddr6 *ifaca, 3150static int inet6_fill_ifacaddr(struct sk_buff *skb, struct ifacaddr6 *ifaca,
3082 u32 pid, u32 seq, int event, unsigned int flags) 3151 u32 pid, u32 seq, int event, unsigned int flags)
3083{ 3152{
3084 struct ifaddrmsg *ifm;
3085 struct nlmsghdr *nlh; 3153 struct nlmsghdr *nlh;
3086 struct ifa_cacheinfo ci; 3154 u8 scope = RT_SCOPE_UNIVERSE;
3087 unsigned char *b = skb->tail; 3155 int ifindex = ifaca->aca_idev->dev->ifindex;
3088
3089 nlh = NLMSG_NEW(skb, pid, seq, event, sizeof(*ifm), flags);
3090 ifm = NLMSG_DATA(nlh);
3091 ifm->ifa_family = AF_INET6;
3092 ifm->ifa_prefixlen = 128;
3093 ifm->ifa_flags = IFA_F_PERMANENT;
3094 ifm->ifa_scope = RT_SCOPE_UNIVERSE;
3095 if (ipv6_addr_scope(&ifaca->aca_addr)&IFA_SITE)
3096 ifm->ifa_scope = RT_SCOPE_SITE;
3097 ifm->ifa_index = ifaca->aca_idev->dev->ifindex;
3098 RTA_PUT(skb, IFA_ANYCAST, 16, &ifaca->aca_addr);
3099 ci.cstamp = (__u32)(TIME_DELTA(ifaca->aca_cstamp, INITIAL_JIFFIES) / HZ
3100 * 100 + TIME_DELTA(ifaca->aca_cstamp, INITIAL_JIFFIES) % HZ
3101 * 100 / HZ);
3102 ci.tstamp = (__u32)(TIME_DELTA(ifaca->aca_tstamp, INITIAL_JIFFIES) / HZ
3103 * 100 + TIME_DELTA(ifaca->aca_tstamp, INITIAL_JIFFIES) % HZ
3104 * 100 / HZ);
3105 ci.ifa_prefered = INFINITY_LIFE_TIME;
3106 ci.ifa_valid = INFINITY_LIFE_TIME;
3107 RTA_PUT(skb, IFA_CACHEINFO, sizeof(ci), &ci);
3108 nlh->nlmsg_len = skb->tail - b;
3109 return skb->len;
3110 3156
3111nlmsg_failure: 3157 if (ipv6_addr_scope(&ifaca->aca_addr) & IFA_SITE)
3112rtattr_failure: 3158 scope = RT_SCOPE_SITE;
3113 skb_trim(skb, b - skb->data); 3159
3114 return -1; 3160 nlh = nlmsg_put(skb, pid, seq, event, sizeof(struct ifaddrmsg), flags);
3161 if (nlh == NULL)
3162 return -ENOBUFS;
3163
3164 put_ifaddrmsg(nlh, 128, IFA_F_PERMANENT, scope, ifindex);
3165 if (nla_put(skb, IFA_ANYCAST, 16, &ifaca->aca_addr) < 0 ||
3166 put_cacheinfo(skb, ifaca->aca_cstamp, ifaca->aca_tstamp,
3167 INFINITY_LIFE_TIME, INFINITY_LIFE_TIME) < 0)
3168 return nlmsg_cancel(skb, nlh);
3169
3170 return nlmsg_end(skb, nlh);
3115} 3171}
3116 3172
3117enum addr_type_t 3173enum addr_type_t
@@ -3222,79 +3278,74 @@ static int inet6_dump_ifacaddr(struct sk_buff *skb, struct netlink_callback *cb)
3222 return inet6_dump_addr(skb, cb, type); 3278 return inet6_dump_addr(skb, cb, type);
3223} 3279}
3224 3280
3225static int inet6_rtm_getaddr(struct sk_buff *in_skb, 3281static int inet6_rtm_getaddr(struct sk_buff *in_skb, struct nlmsghdr* nlh,
3226 struct nlmsghdr* nlh, void *arg) 3282 void *arg)
3227{ 3283{
3228 struct rtattr **rta = arg; 3284 struct ifaddrmsg *ifm;
3229 struct ifaddrmsg *ifm = NLMSG_DATA(nlh); 3285 struct nlattr *tb[IFA_MAX+1];
3230 struct in6_addr *addr = NULL; 3286 struct in6_addr *addr = NULL;
3231 struct net_device *dev = NULL; 3287 struct net_device *dev = NULL;
3232 struct inet6_ifaddr *ifa; 3288 struct inet6_ifaddr *ifa;
3233 struct sk_buff *skb; 3289 struct sk_buff *skb;
3234 int size = NLMSG_SPACE(sizeof(struct ifaddrmsg) + INET6_IFADDR_RTA_SPACE);
3235 int err; 3290 int err;
3236 3291
3237 if (rta[IFA_ADDRESS-1]) { 3292 err = nlmsg_parse(nlh, sizeof(*ifm), tb, IFA_MAX, ifa_ipv6_policy);
3238 if (RTA_PAYLOAD(rta[IFA_ADDRESS-1]) < sizeof(*addr)) 3293 if (err < 0)
3239 return -EINVAL; 3294 goto errout;
3240 addr = RTA_DATA(rta[IFA_ADDRESS-1]); 3295
3241 } 3296 addr = extract_addr(tb[IFA_ADDRESS], tb[IFA_LOCAL]);
3242 if (rta[IFA_LOCAL-1]) { 3297 if (addr == NULL) {
3243 if (RTA_PAYLOAD(rta[IFA_LOCAL-1]) < sizeof(*addr) || 3298 err = -EINVAL;
3244 (addr && memcmp(addr, RTA_DATA(rta[IFA_LOCAL-1]), sizeof(*addr)))) 3299 goto errout;
3245 return -EINVAL;
3246 addr = RTA_DATA(rta[IFA_LOCAL-1]);
3247 } 3300 }
3248 if (addr == NULL)
3249 return -EINVAL;
3250 3301
3302 ifm = nlmsg_data(nlh);
3251 if (ifm->ifa_index) 3303 if (ifm->ifa_index)
3252 dev = __dev_get_by_index(ifm->ifa_index); 3304 dev = __dev_get_by_index(ifm->ifa_index);
3253 3305
3254 if ((ifa = ipv6_get_ifaddr(addr, dev, 1)) == NULL) 3306 if ((ifa = ipv6_get_ifaddr(addr, dev, 1)) == NULL) {
3255 return -EADDRNOTAVAIL; 3307 err = -EADDRNOTAVAIL;
3308 goto errout;
3309 }
3256 3310
3257 if ((skb = alloc_skb(size, GFP_KERNEL)) == NULL) { 3311 if ((skb = nlmsg_new(inet6_ifaddr_msgsize(), GFP_KERNEL)) == NULL) {
3258 err = -ENOBUFS; 3312 err = -ENOBUFS;
3259 goto out; 3313 goto errout_ifa;
3260 } 3314 }
3261 3315
3262 NETLINK_CB(skb).dst_pid = NETLINK_CB(in_skb).pid;
3263 err = inet6_fill_ifaddr(skb, ifa, NETLINK_CB(in_skb).pid, 3316 err = inet6_fill_ifaddr(skb, ifa, NETLINK_CB(in_skb).pid,
3264 nlh->nlmsg_seq, RTM_NEWADDR, 0); 3317 nlh->nlmsg_seq, RTM_NEWADDR, 0);
3265 if (err < 0) { 3318 if (err < 0) {
3266 err = -EMSGSIZE; 3319 kfree_skb(skb);
3267 goto out_free; 3320 goto errout_ifa;
3268 } 3321 }
3269 3322
3270 err = netlink_unicast(rtnl, skb, NETLINK_CB(in_skb).pid, MSG_DONTWAIT); 3323 err = rtnl_unicast(skb, NETLINK_CB(in_skb).pid);
3271 if (err > 0) 3324errout_ifa:
3272 err = 0;
3273out:
3274 in6_ifa_put(ifa); 3325 in6_ifa_put(ifa);
3326errout:
3275 return err; 3327 return err;
3276out_free:
3277 kfree_skb(skb);
3278 goto out;
3279} 3328}
3280 3329
3281static void inet6_ifa_notify(int event, struct inet6_ifaddr *ifa) 3330static void inet6_ifa_notify(int event, struct inet6_ifaddr *ifa)
3282{ 3331{
3283 struct sk_buff *skb; 3332 struct sk_buff *skb;
3284 int size = NLMSG_SPACE(sizeof(struct ifaddrmsg) + INET6_IFADDR_RTA_SPACE); 3333 int err = -ENOBUFS;
3285 3334
3286 skb = alloc_skb(size, GFP_ATOMIC); 3335 skb = nlmsg_new(inet6_ifaddr_msgsize(), GFP_ATOMIC);
3287 if (!skb) { 3336 if (skb == NULL)
3288 netlink_set_err(rtnl, 0, RTNLGRP_IPV6_IFADDR, ENOBUFS); 3337 goto errout;
3289 return; 3338
3290 } 3339 err = inet6_fill_ifaddr(skb, ifa, 0, 0, event, 0);
3291 if (inet6_fill_ifaddr(skb, ifa, current->pid, 0, event, 0) < 0) { 3340 if (err < 0) {
3292 kfree_skb(skb); 3341 kfree_skb(skb);
3293 netlink_set_err(rtnl, 0, RTNLGRP_IPV6_IFADDR, EINVAL); 3342 goto errout;
3294 return;
3295 } 3343 }
3296 NETLINK_CB(skb).dst_group = RTNLGRP_IPV6_IFADDR; 3344
3297 netlink_broadcast(rtnl, skb, 0, RTNLGRP_IPV6_IFADDR, GFP_ATOMIC); 3345 err = rtnl_notify(skb, 0, RTNLGRP_IPV6_IFADDR, NULL, GFP_ATOMIC);
3346errout:
3347 if (err < 0)
3348 rtnl_set_sk_err(RTNLGRP_IPV6_IFADDR, err);
3298} 3349}
3299 3350
3300static void inline ipv6_store_devconf(struct ipv6_devconf *cnf, 3351static void inline ipv6_store_devconf(struct ipv6_devconf *cnf,
@@ -3329,6 +3380,7 @@ static void inline ipv6_store_devconf(struct ipv6_devconf *cnf,
3329 array[DEVCONF_ACCEPT_RA_RT_INFO_MAX_PLEN] = cnf->accept_ra_rt_info_max_plen; 3380 array[DEVCONF_ACCEPT_RA_RT_INFO_MAX_PLEN] = cnf->accept_ra_rt_info_max_plen;
3330#endif 3381#endif
3331#endif 3382#endif
3383 array[DEVCONF_PROXY_NDP] = cnf->proxy_ndp;
3332} 3384}
3333 3385
3334/* Maximum length of ifinfomsg attributes */ 3386/* Maximum length of ifinfomsg attributes */
@@ -3435,20 +3487,23 @@ static int inet6_dump_ifinfo(struct sk_buff *skb, struct netlink_callback *cb)
3435void inet6_ifinfo_notify(int event, struct inet6_dev *idev) 3487void inet6_ifinfo_notify(int event, struct inet6_dev *idev)
3436{ 3488{
3437 struct sk_buff *skb; 3489 struct sk_buff *skb;
3438 int size = NLMSG_SPACE(sizeof(struct ifinfomsg) + INET6_IFINFO_RTA_SPACE); 3490 int payload = sizeof(struct ifinfomsg) + INET6_IFINFO_RTA_SPACE;
3491 int err = -ENOBUFS;
3439 3492
3440 skb = alloc_skb(size, GFP_ATOMIC); 3493 skb = nlmsg_new(nlmsg_total_size(payload), GFP_ATOMIC);
3441 if (!skb) { 3494 if (skb == NULL)
3442 netlink_set_err(rtnl, 0, RTNLGRP_IPV6_IFINFO, ENOBUFS); 3495 goto errout;
3443 return; 3496
3444 } 3497 err = inet6_fill_ifinfo(skb, idev, 0, 0, event, 0);
3445 if (inet6_fill_ifinfo(skb, idev, current->pid, 0, event, 0) < 0) { 3498 if (err < 0) {
3446 kfree_skb(skb); 3499 kfree_skb(skb);
3447 netlink_set_err(rtnl, 0, RTNLGRP_IPV6_IFINFO, EINVAL); 3500 goto errout;
3448 return;
3449 } 3501 }
3450 NETLINK_CB(skb).dst_group = RTNLGRP_IPV6_IFINFO; 3502
3451 netlink_broadcast(rtnl, skb, 0, RTNLGRP_IPV6_IFINFO, GFP_ATOMIC); 3503 err = rtnl_notify(skb, 0, RTNLGRP_IPV6_IFADDR, NULL, GFP_ATOMIC);
3504errout:
3505 if (err < 0)
3506 rtnl_set_sk_err(RTNLGRP_IPV6_IFADDR, err);
3452} 3507}
3453 3508
3454/* Maximum length of prefix_cacheinfo attributes */ 3509/* Maximum length of prefix_cacheinfo attributes */
@@ -3500,20 +3555,23 @@ static void inet6_prefix_notify(int event, struct inet6_dev *idev,
3500 struct prefix_info *pinfo) 3555 struct prefix_info *pinfo)
3501{ 3556{
3502 struct sk_buff *skb; 3557 struct sk_buff *skb;
3503 int size = NLMSG_SPACE(sizeof(struct prefixmsg) + INET6_PREFIX_RTA_SPACE); 3558 int payload = sizeof(struct prefixmsg) + INET6_PREFIX_RTA_SPACE;
3559 int err = -ENOBUFS;
3504 3560
3505 skb = alloc_skb(size, GFP_ATOMIC); 3561 skb = nlmsg_new(nlmsg_total_size(payload), GFP_ATOMIC);
3506 if (!skb) { 3562 if (skb == NULL)
3507 netlink_set_err(rtnl, 0, RTNLGRP_IPV6_PREFIX, ENOBUFS); 3563 goto errout;
3508 return; 3564
3509 } 3565 err = inet6_fill_prefix(skb, idev, pinfo, 0, 0, event, 0);
3510 if (inet6_fill_prefix(skb, idev, pinfo, current->pid, 0, event, 0) < 0) { 3566 if (err < 0) {
3511 kfree_skb(skb); 3567 kfree_skb(skb);
3512 netlink_set_err(rtnl, 0, RTNLGRP_IPV6_PREFIX, EINVAL); 3568 goto errout;
3513 return;
3514 } 3569 }
3515 NETLINK_CB(skb).dst_group = RTNLGRP_IPV6_PREFIX; 3570
3516 netlink_broadcast(rtnl, skb, 0, RTNLGRP_IPV6_PREFIX, GFP_ATOMIC); 3571 err = rtnl_notify(skb, 0, RTNLGRP_IPV6_PREFIX, NULL, GFP_ATOMIC);
3572errout:
3573 if (err < 0)
3574 rtnl_set_sk_err(RTNLGRP_IPV6_PREFIX, err);
3517} 3575}
3518 3576
3519static struct rtnetlink_link inet6_rtnetlink_table[RTM_NR_MSGTYPES] = { 3577static struct rtnetlink_link inet6_rtnetlink_table[RTM_NR_MSGTYPES] = {
@@ -3528,6 +3586,9 @@ static struct rtnetlink_link inet6_rtnetlink_table[RTM_NR_MSGTYPES] = {
3528 [RTM_DELROUTE - RTM_BASE] = { .doit = inet6_rtm_delroute, }, 3586 [RTM_DELROUTE - RTM_BASE] = { .doit = inet6_rtm_delroute, },
3529 [RTM_GETROUTE - RTM_BASE] = { .doit = inet6_rtm_getroute, 3587 [RTM_GETROUTE - RTM_BASE] = { .doit = inet6_rtm_getroute,
3530 .dumpit = inet6_dump_fib, }, 3588 .dumpit = inet6_dump_fib, },
3589#ifdef CONFIG_IPV6_MULTIPLE_TABLES
3590 [RTM_GETRULE - RTM_BASE] = { .dumpit = fib6_rules_dump, },
3591#endif
3531}; 3592};
3532 3593
3533static void __ipv6_ifa_notify(int event, struct inet6_ifaddr *ifp) 3594static void __ipv6_ifa_notify(int event, struct inet6_ifaddr *ifp)
@@ -3536,7 +3597,7 @@ static void __ipv6_ifa_notify(int event, struct inet6_ifaddr *ifp)
3536 3597
3537 switch (event) { 3598 switch (event) {
3538 case RTM_NEWADDR: 3599 case RTM_NEWADDR:
3539 ip6_ins_rt(ifp->rt, NULL, NULL, NULL); 3600 ip6_ins_rt(ifp->rt);
3540 if (ifp->idev->cnf.forwarding) 3601 if (ifp->idev->cnf.forwarding)
3541 addrconf_join_anycast(ifp); 3602 addrconf_join_anycast(ifp);
3542 break; 3603 break;
@@ -3545,7 +3606,7 @@ static void __ipv6_ifa_notify(int event, struct inet6_ifaddr *ifp)
3545 addrconf_leave_anycast(ifp); 3606 addrconf_leave_anycast(ifp);
3546 addrconf_leave_solict(ifp->idev, &ifp->addr); 3607 addrconf_leave_solict(ifp->idev, &ifp->addr);
3547 dst_hold(&ifp->rt->u.dst); 3608 dst_hold(&ifp->rt->u.dst);
3548 if (ip6_del_rt(ifp->rt, NULL, NULL, NULL)) 3609 if (ip6_del_rt(ifp->rt))
3549 dst_free(&ifp->rt->u.dst); 3610 dst_free(&ifp->rt->u.dst);
3550 break; 3611 break;
3551 } 3612 }
@@ -3553,10 +3614,10 @@ static void __ipv6_ifa_notify(int event, struct inet6_ifaddr *ifp)
3553 3614
3554static void ipv6_ifa_notify(int event, struct inet6_ifaddr *ifp) 3615static void ipv6_ifa_notify(int event, struct inet6_ifaddr *ifp)
3555{ 3616{
3556 read_lock_bh(&addrconf_lock); 3617 rcu_read_lock_bh();
3557 if (likely(ifp->idev->dead == 0)) 3618 if (likely(ifp->idev->dead == 0))
3558 __ipv6_ifa_notify(event, ifp); 3619 __ipv6_ifa_notify(event, ifp);
3559 read_unlock_bh(&addrconf_lock); 3620 rcu_read_unlock_bh();
3560} 3621}
3561 3622
3562#ifdef CONFIG_SYSCTL 3623#ifdef CONFIG_SYSCTL
@@ -3653,7 +3714,7 @@ static struct addrconf_sysctl_table
3653 ctl_table addrconf_conf_dir[2]; 3714 ctl_table addrconf_conf_dir[2];
3654 ctl_table addrconf_proto_dir[2]; 3715 ctl_table addrconf_proto_dir[2];
3655 ctl_table addrconf_root_dir[2]; 3716 ctl_table addrconf_root_dir[2];
3656} addrconf_sysctl = { 3717} addrconf_sysctl __read_mostly = {
3657 .sysctl_header = NULL, 3718 .sysctl_header = NULL,
3658 .addrconf_vars = { 3719 .addrconf_vars = {
3659 { 3720 {
@@ -3843,6 +3904,14 @@ static struct addrconf_sysctl_table
3843#endif 3904#endif
3844#endif 3905#endif
3845 { 3906 {
3907 .ctl_name = NET_IPV6_PROXY_NDP,
3908 .procname = "proxy_ndp",
3909 .data = &ipv6_devconf.proxy_ndp,
3910 .maxlen = sizeof(int),
3911 .mode = 0644,
3912 .proc_handler = &proc_dointvec,
3913 },
3914 {
3846 .ctl_name = 0, /* sentinel */ 3915 .ctl_name = 0, /* sentinel */
3847 } 3916 }
3848 }, 3917 },
diff --git a/net/ipv6/af_inet6.c b/net/ipv6/af_inet6.c
index ac85e9c532c2..bf6e8aff19d4 100644
--- a/net/ipv6/af_inet6.c
+++ b/net/ipv6/af_inet6.c
@@ -59,6 +59,9 @@
59#ifdef CONFIG_IPV6_TUNNEL 59#ifdef CONFIG_IPV6_TUNNEL
60#include <net/ip6_tunnel.h> 60#include <net/ip6_tunnel.h>
61#endif 61#endif
62#ifdef CONFIG_IPV6_MIP6
63#include <net/mip6.h>
64#endif
62 65
63#include <asm/uaccess.h> 66#include <asm/uaccess.h>
64#include <asm/system.h> 67#include <asm/system.h>
@@ -67,7 +70,7 @@ MODULE_AUTHOR("Cast of dozens");
67MODULE_DESCRIPTION("IPv6 protocol stack for Linux"); 70MODULE_DESCRIPTION("IPv6 protocol stack for Linux");
68MODULE_LICENSE("GPL"); 71MODULE_LICENSE("GPL");
69 72
70int sysctl_ipv6_bindv6only; 73int sysctl_ipv6_bindv6only __read_mostly;
71 74
72/* The inetsw table contains everything that inet_create needs to 75/* The inetsw table contains everything that inet_create needs to
73 * build a new socket. 76 * build a new socket.
@@ -637,6 +640,7 @@ int inet6_sk_rebuild_header(struct sock *sk)
637 fl.oif = sk->sk_bound_dev_if; 640 fl.oif = sk->sk_bound_dev_if;
638 fl.fl_ip_dport = inet->dport; 641 fl.fl_ip_dport = inet->dport;
639 fl.fl_ip_sport = inet->sport; 642 fl.fl_ip_sport = inet->sport;
643 security_sk_classify_flow(sk, &fl);
640 644
641 if (np->opt && np->opt->srcrt) { 645 if (np->opt && np->opt->srcrt) {
642 struct rt0_hdr *rt0 = (struct rt0_hdr *) np->opt->srcrt; 646 struct rt0_hdr *rt0 = (struct rt0_hdr *) np->opt->srcrt;
@@ -658,7 +662,7 @@ int inet6_sk_rebuild_header(struct sock *sk)
658 return err; 662 return err;
659 } 663 }
660 664
661 __ip6_dst_store(sk, dst, NULL); 665 __ip6_dst_store(sk, dst, NULL, NULL);
662 } 666 }
663 667
664 return 0; 668 return 0;
@@ -757,6 +761,8 @@ static int __init inet6_init(void)
757 struct list_head *r; 761 struct list_head *r;
758 int err; 762 int err;
759 763
764 BUILD_BUG_ON(sizeof(struct inet6_skb_parm) > sizeof(dummy_skb->cb));
765
760#ifdef MODULE 766#ifdef MODULE
761#if 0 /* FIXME --RR */ 767#if 0 /* FIXME --RR */
762 if (!mod_member_present(&__this_module, can_unload)) 768 if (!mod_member_present(&__this_module, can_unload))
@@ -766,11 +772,6 @@ static int __init inet6_init(void)
766#endif 772#endif
767#endif 773#endif
768 774
769 if (sizeof(struct inet6_skb_parm) > sizeof(dummy_skb->cb)) {
770 printk(KERN_CRIT "inet6_proto_init: size fault\n");
771 return -EINVAL;
772 }
773
774 err = proto_register(&tcpv6_prot, 1); 775 err = proto_register(&tcpv6_prot, 1);
775 if (err) 776 if (err)
776 goto out; 777 goto out;
@@ -856,6 +857,9 @@ static int __init inet6_init(void)
856 ipv6_frag_init(); 857 ipv6_frag_init();
857 ipv6_nodata_init(); 858 ipv6_nodata_init();
858 ipv6_destopt_init(); 859 ipv6_destopt_init();
860#ifdef CONFIG_IPV6_MIP6
861 mip6_init();
862#endif
859 863
860 /* Init v6 transport protocols. */ 864 /* Init v6 transport protocols. */
861 udpv6_init(); 865 udpv6_init();
@@ -919,6 +923,9 @@ static void __exit inet6_exit(void)
919 tcp6_proc_exit(); 923 tcp6_proc_exit();
920 raw6_proc_exit(); 924 raw6_proc_exit();
921#endif 925#endif
926#ifdef CONFIG_IPV6_MIP6
927 mip6_fini();
928#endif
922 /* Cleanup code parts. */ 929 /* Cleanup code parts. */
923 sit_cleanup(); 930 sit_cleanup();
924 ip6_flowlabel_cleanup(); 931 ip6_flowlabel_cleanup();
diff --git a/net/ipv6/ah6.c b/net/ipv6/ah6.c
index 00ffa7bc6c9f..b0d83e8e4252 100644
--- a/net/ipv6/ah6.c
+++ b/net/ipv6/ah6.c
@@ -74,6 +74,66 @@ bad:
74 return 0; 74 return 0;
75} 75}
76 76
77#ifdef CONFIG_IPV6_MIP6
78/**
79 * ipv6_rearrange_destopt - rearrange IPv6 destination options header
80 * @iph: IPv6 header
81 * @destopt: destionation options header
82 */
83static void ipv6_rearrange_destopt(struct ipv6hdr *iph, struct ipv6_opt_hdr *destopt)
84{
85 u8 *opt = (u8 *)destopt;
86 int len = ipv6_optlen(destopt);
87 int off = 0;
88 int optlen = 0;
89
90 off += 2;
91 len -= 2;
92
93 while (len > 0) {
94
95 switch (opt[off]) {
96
97 case IPV6_TLV_PAD0:
98 optlen = 1;
99 break;
100 default:
101 if (len < 2)
102 goto bad;
103 optlen = opt[off+1]+2;
104 if (len < optlen)
105 goto bad;
106
107 /* Rearrange the source address in @iph and the
108 * addresses in home address option for final source.
109 * See 11.3.2 of RFC 3775 for details.
110 */
111 if (opt[off] == IPV6_TLV_HAO) {
112 struct in6_addr final_addr;
113 struct ipv6_destopt_hao *hao;
114
115 hao = (struct ipv6_destopt_hao *)&opt[off];
116 if (hao->length != sizeof(hao->addr)) {
117 if (net_ratelimit())
118 printk(KERN_WARNING "destopt hao: invalid header length: %u\n", hao->length);
119 goto bad;
120 }
121 ipv6_addr_copy(&final_addr, &hao->addr);
122 ipv6_addr_copy(&hao->addr, &iph->saddr);
123 ipv6_addr_copy(&iph->saddr, &final_addr);
124 }
125 break;
126 }
127
128 off += optlen;
129 len -= optlen;
130 }
131 /* Note: ok if len == 0 */
132bad:
133 return;
134}
135#endif
136
77/** 137/**
78 * ipv6_rearrange_rthdr - rearrange IPv6 routing header 138 * ipv6_rearrange_rthdr - rearrange IPv6 routing header
79 * @iph: IPv6 header 139 * @iph: IPv6 header
@@ -113,7 +173,7 @@ static void ipv6_rearrange_rthdr(struct ipv6hdr *iph, struct ipv6_rt_hdr *rthdr)
113 ipv6_addr_copy(&iph->daddr, &final_addr); 173 ipv6_addr_copy(&iph->daddr, &final_addr);
114} 174}
115 175
116static int ipv6_clear_mutable_options(struct ipv6hdr *iph, int len) 176static int ipv6_clear_mutable_options(struct ipv6hdr *iph, int len, int dir)
117{ 177{
118 union { 178 union {
119 struct ipv6hdr *iph; 179 struct ipv6hdr *iph;
@@ -128,8 +188,12 @@ static int ipv6_clear_mutable_options(struct ipv6hdr *iph, int len)
128 188
129 while (exthdr.raw < end) { 189 while (exthdr.raw < end) {
130 switch (nexthdr) { 190 switch (nexthdr) {
131 case NEXTHDR_HOP:
132 case NEXTHDR_DEST: 191 case NEXTHDR_DEST:
192#ifdef CONFIG_IPV6_MIP6
193 if (dir == XFRM_POLICY_OUT)
194 ipv6_rearrange_destopt(iph, exthdr.opth);
195#endif
196 case NEXTHDR_HOP:
133 if (!zero_out_mutable_opts(exthdr.opth)) { 197 if (!zero_out_mutable_opts(exthdr.opth)) {
134 LIMIT_NETDEBUG( 198 LIMIT_NETDEBUG(
135 KERN_WARNING "overrun %sopts\n", 199 KERN_WARNING "overrun %sopts\n",
@@ -164,6 +228,9 @@ static int ah6_output(struct xfrm_state *x, struct sk_buff *skb)
164 u8 nexthdr; 228 u8 nexthdr;
165 char tmp_base[8]; 229 char tmp_base[8];
166 struct { 230 struct {
231#ifdef CONFIG_IPV6_MIP6
232 struct in6_addr saddr;
233#endif
167 struct in6_addr daddr; 234 struct in6_addr daddr;
168 char hdrs[0]; 235 char hdrs[0];
169 } *tmp_ext; 236 } *tmp_ext;
@@ -188,10 +255,15 @@ static int ah6_output(struct xfrm_state *x, struct sk_buff *skb)
188 err = -ENOMEM; 255 err = -ENOMEM;
189 goto error; 256 goto error;
190 } 257 }
258#ifdef CONFIG_IPV6_MIP6
259 memcpy(tmp_ext, &top_iph->saddr, extlen);
260#else
191 memcpy(tmp_ext, &top_iph->daddr, extlen); 261 memcpy(tmp_ext, &top_iph->daddr, extlen);
262#endif
192 err = ipv6_clear_mutable_options(top_iph, 263 err = ipv6_clear_mutable_options(top_iph,
193 extlen - sizeof(*tmp_ext) + 264 extlen - sizeof(*tmp_ext) +
194 sizeof(*top_iph)); 265 sizeof(*top_iph),
266 XFRM_POLICY_OUT);
195 if (err) 267 if (err)
196 goto error_free_iph; 268 goto error_free_iph;
197 } 269 }
@@ -222,7 +294,11 @@ static int ah6_output(struct xfrm_state *x, struct sk_buff *skb)
222 294
223 memcpy(top_iph, tmp_base, sizeof(tmp_base)); 295 memcpy(top_iph, tmp_base, sizeof(tmp_base));
224 if (tmp_ext) { 296 if (tmp_ext) {
297#ifdef CONFIG_IPV6_MIP6
298 memcpy(&top_iph->saddr, tmp_ext, extlen);
299#else
225 memcpy(&top_iph->daddr, tmp_ext, extlen); 300 memcpy(&top_iph->daddr, tmp_ext, extlen);
301#endif
226error_free_iph: 302error_free_iph:
227 kfree(tmp_ext); 303 kfree(tmp_ext);
228 } 304 }
@@ -282,7 +358,7 @@ static int ah6_input(struct xfrm_state *x, struct sk_buff *skb)
282 if (!tmp_hdr) 358 if (!tmp_hdr)
283 goto out; 359 goto out;
284 memcpy(tmp_hdr, skb->nh.raw, hdr_len); 360 memcpy(tmp_hdr, skb->nh.raw, hdr_len);
285 if (ipv6_clear_mutable_options(skb->nh.ipv6h, hdr_len)) 361 if (ipv6_clear_mutable_options(skb->nh.ipv6h, hdr_len, XFRM_POLICY_IN))
286 goto free_out; 362 goto free_out;
287 skb->nh.ipv6h->priority = 0; 363 skb->nh.ipv6h->priority = 0;
288 skb->nh.ipv6h->flow_lbl[0] = 0; 364 skb->nh.ipv6h->flow_lbl[0] = 0;
@@ -398,7 +474,7 @@ static int ah6_init_state(struct xfrm_state *x)
398 goto error; 474 goto error;
399 475
400 x->props.header_len = XFRM_ALIGN8(sizeof(struct ipv6_auth_hdr) + ahp->icv_trunc_len); 476 x->props.header_len = XFRM_ALIGN8(sizeof(struct ipv6_auth_hdr) + ahp->icv_trunc_len);
401 if (x->props.mode) 477 if (x->props.mode == XFRM_MODE_TUNNEL)
402 x->props.header_len += sizeof(struct ipv6hdr); 478 x->props.header_len += sizeof(struct ipv6hdr);
403 x->data = ahp; 479 x->data = ahp;
404 480
@@ -435,7 +511,8 @@ static struct xfrm_type ah6_type =
435 .init_state = ah6_init_state, 511 .init_state = ah6_init_state,
436 .destructor = ah6_destroy, 512 .destructor = ah6_destroy,
437 .input = ah6_input, 513 .input = ah6_input,
438 .output = ah6_output 514 .output = ah6_output,
515 .hdr_offset = xfrm6_find_1stfragopt,
439}; 516};
440 517
441static struct inet6_protocol ah6_protocol = { 518static struct inet6_protocol ah6_protocol = {
diff --git a/net/ipv6/anycast.c b/net/ipv6/anycast.c
index f6881d7a0385..a9604764e015 100644
--- a/net/ipv6/anycast.c
+++ b/net/ipv6/anycast.c
@@ -56,7 +56,7 @@ ip6_onlink(struct in6_addr *addr, struct net_device *dev)
56 int onlink; 56 int onlink;
57 57
58 onlink = 0; 58 onlink = 0;
59 read_lock(&addrconf_lock); 59 rcu_read_lock();
60 idev = __in6_dev_get(dev); 60 idev = __in6_dev_get(dev);
61 if (idev) { 61 if (idev) {
62 read_lock_bh(&idev->lock); 62 read_lock_bh(&idev->lock);
@@ -68,7 +68,7 @@ ip6_onlink(struct in6_addr *addr, struct net_device *dev)
68 } 68 }
69 read_unlock_bh(&idev->lock); 69 read_unlock_bh(&idev->lock);
70 } 70 }
71 read_unlock(&addrconf_lock); 71 rcu_read_unlock();
72 return onlink; 72 return onlink;
73} 73}
74 74
@@ -335,7 +335,7 @@ int ipv6_dev_ac_inc(struct net_device *dev, struct in6_addr *addr)
335 write_unlock_bh(&idev->lock); 335 write_unlock_bh(&idev->lock);
336 336
337 dst_hold(&rt->u.dst); 337 dst_hold(&rt->u.dst);
338 if (ip6_ins_rt(rt, NULL, NULL, NULL)) 338 if (ip6_ins_rt(rt))
339 dst_release(&rt->u.dst); 339 dst_release(&rt->u.dst);
340 340
341 addrconf_join_solict(dev, &aca->aca_addr); 341 addrconf_join_solict(dev, &aca->aca_addr);
@@ -378,7 +378,7 @@ int __ipv6_dev_ac_dec(struct inet6_dev *idev, struct in6_addr *addr)
378 addrconf_leave_solict(idev, &aca->aca_addr); 378 addrconf_leave_solict(idev, &aca->aca_addr);
379 379
380 dst_hold(&aca->aca_rt->u.dst); 380 dst_hold(&aca->aca_rt->u.dst);
381 if (ip6_del_rt(aca->aca_rt, NULL, NULL, NULL)) 381 if (ip6_del_rt(aca->aca_rt))
382 dst_free(&aca->aca_rt->u.dst); 382 dst_free(&aca->aca_rt->u.dst);
383 else 383 else
384 dst_release(&aca->aca_rt->u.dst); 384 dst_release(&aca->aca_rt->u.dst);
diff --git a/net/ipv6/datagram.c b/net/ipv6/datagram.c
index 3b55b4c8e2d1..7206747022fc 100644
--- a/net/ipv6/datagram.c
+++ b/net/ipv6/datagram.c
@@ -156,6 +156,8 @@ ipv4_connected:
156 if (!fl.oif && (addr_type&IPV6_ADDR_MULTICAST)) 156 if (!fl.oif && (addr_type&IPV6_ADDR_MULTICAST))
157 fl.oif = np->mcast_oif; 157 fl.oif = np->mcast_oif;
158 158
159 security_sk_classify_flow(sk, &fl);
160
159 if (flowlabel) { 161 if (flowlabel) {
160 if (flowlabel->opt && flowlabel->opt->srcrt) { 162 if (flowlabel->opt && flowlabel->opt->srcrt) {
161 struct rt0_hdr *rt0 = (struct rt0_hdr *) flowlabel->opt->srcrt; 163 struct rt0_hdr *rt0 = (struct rt0_hdr *) flowlabel->opt->srcrt;
@@ -191,7 +193,12 @@ ipv4_connected:
191 193
192 ip6_dst_store(sk, dst, 194 ip6_dst_store(sk, dst,
193 ipv6_addr_equal(&fl.fl6_dst, &np->daddr) ? 195 ipv6_addr_equal(&fl.fl6_dst, &np->daddr) ?
194 &np->daddr : NULL); 196 &np->daddr : NULL,
197#ifdef CONFIG_IPV6_SUBTREES
198 ipv6_addr_equal(&fl.fl6_src, &np->saddr) ?
199 &np->saddr :
200#endif
201 NULL);
195 202
196 sk->sk_state = TCP_ESTABLISHED; 203 sk->sk_state = TCP_ESTABLISHED;
197out: 204out:
@@ -641,10 +648,13 @@ int datagram_send_ctl(struct msghdr *msg, struct flowi *fl,
641 648
642 rthdr = (struct ipv6_rt_hdr *)CMSG_DATA(cmsg); 649 rthdr = (struct ipv6_rt_hdr *)CMSG_DATA(cmsg);
643 650
644 /* 651 switch (rthdr->type) {
645 * TYPE 0 652 case IPV6_SRCRT_TYPE_0:
646 */ 653#ifdef CONFIG_IPV6_MIP6
647 if (rthdr->type) { 654 case IPV6_SRCRT_TYPE_2:
655#endif
656 break;
657 default:
648 err = -EINVAL; 658 err = -EINVAL;
649 goto exit_f; 659 goto exit_f;
650 } 660 }
diff --git a/net/ipv6/esp6.c b/net/ipv6/esp6.c
index 2ebfd281e721..e78680a9985b 100644
--- a/net/ipv6/esp6.c
+++ b/net/ipv6/esp6.c
@@ -99,8 +99,13 @@ static int esp6_output(struct xfrm_state *x, struct sk_buff *skb)
99 esph->seq_no = htonl(++x->replay.oseq); 99 esph->seq_no = htonl(++x->replay.oseq);
100 xfrm_aevent_doreplay(x); 100 xfrm_aevent_doreplay(x);
101 101
102 if (esp->conf.ivlen) 102 if (esp->conf.ivlen) {
103 if (unlikely(!esp->conf.ivinitted)) {
104 get_random_bytes(esp->conf.ivec, esp->conf.ivlen);
105 esp->conf.ivinitted = 1;
106 }
103 crypto_blkcipher_set_iv(tfm, esp->conf.ivec, esp->conf.ivlen); 107 crypto_blkcipher_set_iv(tfm, esp->conf.ivec, esp->conf.ivlen);
108 }
104 109
105 do { 110 do {
106 struct scatterlist *sg = &esp->sgbuf[0]; 111 struct scatterlist *sg = &esp->sgbuf[0];
@@ -237,7 +242,7 @@ static u32 esp6_get_max_size(struct xfrm_state *x, int mtu)
237 struct esp_data *esp = x->data; 242 struct esp_data *esp = x->data;
238 u32 blksize = ALIGN(crypto_blkcipher_blocksize(esp->conf.tfm), 4); 243 u32 blksize = ALIGN(crypto_blkcipher_blocksize(esp->conf.tfm), 4);
239 244
240 if (x->props.mode) { 245 if (x->props.mode == XFRM_MODE_TUNNEL) {
241 mtu = ALIGN(mtu + 2, blksize); 246 mtu = ALIGN(mtu + 2, blksize);
242 } else { 247 } else {
243 /* The worst case. */ 248 /* The worst case. */
@@ -353,12 +358,12 @@ static int esp6_init_state(struct xfrm_state *x)
353 esp->conf.ivec = kmalloc(esp->conf.ivlen, GFP_KERNEL); 358 esp->conf.ivec = kmalloc(esp->conf.ivlen, GFP_KERNEL);
354 if (unlikely(esp->conf.ivec == NULL)) 359 if (unlikely(esp->conf.ivec == NULL))
355 goto error; 360 goto error;
356 get_random_bytes(esp->conf.ivec, esp->conf.ivlen); 361 esp->conf.ivinitted = 0;
357 } 362 }
358 if (crypto_blkcipher_setkey(tfm, esp->conf.key, esp->conf.key_len)) 363 if (crypto_blkcipher_setkey(tfm, esp->conf.key, esp->conf.key_len))
359 goto error; 364 goto error;
360 x->props.header_len = sizeof(struct ipv6_esp_hdr) + esp->conf.ivlen; 365 x->props.header_len = sizeof(struct ipv6_esp_hdr) + esp->conf.ivlen;
361 if (x->props.mode) 366 if (x->props.mode == XFRM_MODE_TUNNEL)
362 x->props.header_len += sizeof(struct ipv6hdr); 367 x->props.header_len += sizeof(struct ipv6hdr);
363 x->data = esp; 368 x->data = esp;
364 return 0; 369 return 0;
@@ -379,7 +384,8 @@ static struct xfrm_type esp6_type =
379 .destructor = esp6_destroy, 384 .destructor = esp6_destroy,
380 .get_max_size = esp6_get_max_size, 385 .get_max_size = esp6_get_max_size,
381 .input = esp6_input, 386 .input = esp6_input,
382 .output = esp6_output 387 .output = esp6_output,
388 .hdr_offset = xfrm6_find_1stfragopt,
383}; 389};
384 390
385static struct inet6_protocol esp6_protocol = { 391static struct inet6_protocol esp6_protocol = {
diff --git a/net/ipv6/exthdrs.c b/net/ipv6/exthdrs.c
index 86dac106873b..88c96b10684c 100644
--- a/net/ipv6/exthdrs.c
+++ b/net/ipv6/exthdrs.c
@@ -43,9 +43,54 @@
43#include <net/ndisc.h> 43#include <net/ndisc.h>
44#include <net/ip6_route.h> 44#include <net/ip6_route.h>
45#include <net/addrconf.h> 45#include <net/addrconf.h>
46#ifdef CONFIG_IPV6_MIP6
47#include <net/xfrm.h>
48#endif
46 49
47#include <asm/uaccess.h> 50#include <asm/uaccess.h>
48 51
52int ipv6_find_tlv(struct sk_buff *skb, int offset, int type)
53{
54 int packet_len = skb->tail - skb->nh.raw;
55 struct ipv6_opt_hdr *hdr;
56 int len;
57
58 if (offset + 2 > packet_len)
59 goto bad;
60 hdr = (struct ipv6_opt_hdr*)(skb->nh.raw + offset);
61 len = ((hdr->hdrlen + 1) << 3);
62
63 if (offset + len > packet_len)
64 goto bad;
65
66 offset += 2;
67 len -= 2;
68
69 while (len > 0) {
70 int opttype = skb->nh.raw[offset];
71 int optlen;
72
73 if (opttype == type)
74 return offset;
75
76 switch (opttype) {
77 case IPV6_TLV_PAD0:
78 optlen = 1;
79 break;
80 default:
81 optlen = skb->nh.raw[offset + 1] + 2;
82 if (optlen > len)
83 goto bad;
84 break;
85 }
86 offset += optlen;
87 len -= optlen;
88 }
89 /* not_found */
90 bad:
91 return -1;
92}
93
49/* 94/*
50 * Parsing tlv encoded headers. 95 * Parsing tlv encoded headers.
51 * 96 *
@@ -56,7 +101,7 @@
56 101
57struct tlvtype_proc { 102struct tlvtype_proc {
58 int type; 103 int type;
59 int (*func)(struct sk_buff *skb, int offset); 104 int (*func)(struct sk_buff **skbp, int offset);
60}; 105};
61 106
62/********************* 107/*********************
@@ -65,8 +110,10 @@ struct tlvtype_proc {
65 110
66/* An unknown option is detected, decide what to do */ 111/* An unknown option is detected, decide what to do */
67 112
68static int ip6_tlvopt_unknown(struct sk_buff *skb, int optoff) 113static int ip6_tlvopt_unknown(struct sk_buff **skbp, int optoff)
69{ 114{
115 struct sk_buff *skb = *skbp;
116
70 switch ((skb->nh.raw[optoff] & 0xC0) >> 6) { 117 switch ((skb->nh.raw[optoff] & 0xC0) >> 6) {
71 case 0: /* ignore */ 118 case 0: /* ignore */
72 return 1; 119 return 1;
@@ -91,8 +138,9 @@ static int ip6_tlvopt_unknown(struct sk_buff *skb, int optoff)
91 138
92/* Parse tlv encoded option header (hop-by-hop or destination) */ 139/* Parse tlv encoded option header (hop-by-hop or destination) */
93 140
94static int ip6_parse_tlv(struct tlvtype_proc *procs, struct sk_buff *skb) 141static int ip6_parse_tlv(struct tlvtype_proc *procs, struct sk_buff **skbp)
95{ 142{
143 struct sk_buff *skb = *skbp;
96 struct tlvtype_proc *curr; 144 struct tlvtype_proc *curr;
97 int off = skb->h.raw - skb->nh.raw; 145 int off = skb->h.raw - skb->nh.raw;
98 int len = ((skb->h.raw[1]+1)<<3); 146 int len = ((skb->h.raw[1]+1)<<3);
@@ -122,13 +170,13 @@ static int ip6_parse_tlv(struct tlvtype_proc *procs, struct sk_buff *skb)
122 /* type specific length/alignment 170 /* type specific length/alignment
123 checks will be performed in the 171 checks will be performed in the
124 func(). */ 172 func(). */
125 if (curr->func(skb, off) == 0) 173 if (curr->func(skbp, off) == 0)
126 return 0; 174 return 0;
127 break; 175 break;
128 } 176 }
129 } 177 }
130 if (curr->type < 0) { 178 if (curr->type < 0) {
131 if (ip6_tlvopt_unknown(skb, off) == 0) 179 if (ip6_tlvopt_unknown(skbp, off) == 0)
132 return 0; 180 return 0;
133 } 181 }
134 break; 182 break;
@@ -147,8 +195,85 @@ bad:
147 Destination options header. 195 Destination options header.
148 *****************************/ 196 *****************************/
149 197
198#ifdef CONFIG_IPV6_MIP6
199static int ipv6_dest_hao(struct sk_buff **skbp, int optoff)
200{
201 struct sk_buff *skb = *skbp;
202 struct ipv6_destopt_hao *hao;
203 struct inet6_skb_parm *opt = IP6CB(skb);
204 struct ipv6hdr *ipv6h = (struct ipv6hdr *)skb->nh.raw;
205 struct in6_addr tmp_addr;
206 int ret;
207
208 if (opt->dsthao) {
209 LIMIT_NETDEBUG(KERN_DEBUG "hao duplicated\n");
210 goto discard;
211 }
212 opt->dsthao = opt->dst1;
213 opt->dst1 = 0;
214
215 hao = (struct ipv6_destopt_hao *)(skb->nh.raw + optoff);
216
217 if (hao->length != 16) {
218 LIMIT_NETDEBUG(
219 KERN_DEBUG "hao invalid option length = %d\n", hao->length);
220 goto discard;
221 }
222
223 if (!(ipv6_addr_type(&hao->addr) & IPV6_ADDR_UNICAST)) {
224 LIMIT_NETDEBUG(
225 KERN_DEBUG "hao is not an unicast addr: " NIP6_FMT "\n", NIP6(hao->addr));
226 goto discard;
227 }
228
229 ret = xfrm6_input_addr(skb, (xfrm_address_t *)&ipv6h->daddr,
230 (xfrm_address_t *)&hao->addr, IPPROTO_DSTOPTS);
231 if (unlikely(ret < 0))
232 goto discard;
233
234 if (skb_cloned(skb)) {
235 struct sk_buff *skb2 = skb_copy(skb, GFP_ATOMIC);
236 struct inet6_skb_parm *opt2;
237
238 if (skb2 == NULL)
239 goto discard;
240
241 opt2 = IP6CB(skb2);
242 memcpy(opt2, opt, sizeof(*opt2));
243
244 kfree_skb(skb);
245
246 /* update all variable using below by copied skbuff */
247 *skbp = skb = skb2;
248 hao = (struct ipv6_destopt_hao *)(skb2->nh.raw + optoff);
249 ipv6h = (struct ipv6hdr *)skb2->nh.raw;
250 }
251
252 if (skb->ip_summed == CHECKSUM_COMPLETE)
253 skb->ip_summed = CHECKSUM_NONE;
254
255 ipv6_addr_copy(&tmp_addr, &ipv6h->saddr);
256 ipv6_addr_copy(&ipv6h->saddr, &hao->addr);
257 ipv6_addr_copy(&hao->addr, &tmp_addr);
258
259 if (skb->tstamp.off_sec == 0)
260 __net_timestamp(skb);
261
262 return 1;
263
264 discard:
265 kfree_skb(skb);
266 return 0;
267}
268#endif
269
150static struct tlvtype_proc tlvprocdestopt_lst[] = { 270static struct tlvtype_proc tlvprocdestopt_lst[] = {
151 /* No destination options are defined now */ 271#ifdef CONFIG_IPV6_MIP6
272 {
273 .type = IPV6_TLV_HAO,
274 .func = ipv6_dest_hao,
275 },
276#endif
152 {-1, NULL} 277 {-1, NULL}
153}; 278};
154 279
@@ -156,6 +281,9 @@ static int ipv6_destopt_rcv(struct sk_buff **skbp)
156{ 281{
157 struct sk_buff *skb = *skbp; 282 struct sk_buff *skb = *skbp;
158 struct inet6_skb_parm *opt = IP6CB(skb); 283 struct inet6_skb_parm *opt = IP6CB(skb);
284#ifdef CONFIG_IPV6_MIP6
285 __u16 dstbuf;
286#endif
159 287
160 if (!pskb_may_pull(skb, (skb->h.raw-skb->data)+8) || 288 if (!pskb_may_pull(skb, (skb->h.raw-skb->data)+8) ||
161 !pskb_may_pull(skb, (skb->h.raw-skb->data)+((skb->h.raw[1]+1)<<3))) { 289 !pskb_may_pull(skb, (skb->h.raw-skb->data)+((skb->h.raw[1]+1)<<3))) {
@@ -166,10 +294,19 @@ static int ipv6_destopt_rcv(struct sk_buff **skbp)
166 294
167 opt->lastopt = skb->h.raw - skb->nh.raw; 295 opt->lastopt = skb->h.raw - skb->nh.raw;
168 opt->dst1 = skb->h.raw - skb->nh.raw; 296 opt->dst1 = skb->h.raw - skb->nh.raw;
297#ifdef CONFIG_IPV6_MIP6
298 dstbuf = opt->dst1;
299#endif
169 300
170 if (ip6_parse_tlv(tlvprocdestopt_lst, skb)) { 301 if (ip6_parse_tlv(tlvprocdestopt_lst, skbp)) {
302 skb = *skbp;
171 skb->h.raw += ((skb->h.raw[1]+1)<<3); 303 skb->h.raw += ((skb->h.raw[1]+1)<<3);
304 opt = IP6CB(skb);
305#ifdef CONFIG_IPV6_MIP6
306 opt->nhoff = dstbuf;
307#else
172 opt->nhoff = opt->dst1; 308 opt->nhoff = opt->dst1;
309#endif
173 return 1; 310 return 1;
174 } 311 }
175 312
@@ -219,7 +356,7 @@ static int ipv6_rthdr_rcv(struct sk_buff **skbp)
219{ 356{
220 struct sk_buff *skb = *skbp; 357 struct sk_buff *skb = *skbp;
221 struct inet6_skb_parm *opt = IP6CB(skb); 358 struct inet6_skb_parm *opt = IP6CB(skb);
222 struct in6_addr *addr; 359 struct in6_addr *addr = NULL;
223 struct in6_addr daddr; 360 struct in6_addr daddr;
224 int n, i; 361 int n, i;
225 362
@@ -244,6 +381,23 @@ static int ipv6_rthdr_rcv(struct sk_buff **skbp)
244 381
245looped_back: 382looped_back:
246 if (hdr->segments_left == 0) { 383 if (hdr->segments_left == 0) {
384 switch (hdr->type) {
385#ifdef CONFIG_IPV6_MIP6
386 case IPV6_SRCRT_TYPE_2:
387 /* Silently discard type 2 header unless it was
388 * processed by own
389 */
390 if (!addr) {
391 IP6_INC_STATS_BH(IPSTATS_MIB_INADDRERRORS);
392 kfree_skb(skb);
393 return -1;
394 }
395 break;
396#endif
397 default:
398 break;
399 }
400
247 opt->lastopt = skb->h.raw - skb->nh.raw; 401 opt->lastopt = skb->h.raw - skb->nh.raw;
248 opt->srcrt = skb->h.raw - skb->nh.raw; 402 opt->srcrt = skb->h.raw - skb->nh.raw;
249 skb->h.raw += (hdr->hdrlen + 1) << 3; 403 skb->h.raw += (hdr->hdrlen + 1) << 3;
@@ -253,17 +407,29 @@ looped_back:
253 return 1; 407 return 1;
254 } 408 }
255 409
256 if (hdr->type != IPV6_SRCRT_TYPE_0) { 410 switch (hdr->type) {
411 case IPV6_SRCRT_TYPE_0:
412 if (hdr->hdrlen & 0x01) {
413 IP6_INC_STATS_BH(IPSTATS_MIB_INHDRERRORS);
414 icmpv6_param_prob(skb, ICMPV6_HDR_FIELD, (&hdr->hdrlen) - skb->nh.raw);
415 return -1;
416 }
417 break;
418#ifdef CONFIG_IPV6_MIP6
419 case IPV6_SRCRT_TYPE_2:
420 /* Silently discard invalid RTH type 2 */
421 if (hdr->hdrlen != 2 || hdr->segments_left != 1) {
422 IP6_INC_STATS_BH(IPSTATS_MIB_INHDRERRORS);
423 kfree_skb(skb);
424 return -1;
425 }
426 break;
427#endif
428 default:
257 IP6_INC_STATS_BH(IPSTATS_MIB_INHDRERRORS); 429 IP6_INC_STATS_BH(IPSTATS_MIB_INHDRERRORS);
258 icmpv6_param_prob(skb, ICMPV6_HDR_FIELD, (&hdr->type) - skb->nh.raw); 430 icmpv6_param_prob(skb, ICMPV6_HDR_FIELD, (&hdr->type) - skb->nh.raw);
259 return -1; 431 return -1;
260 } 432 }
261
262 if (hdr->hdrlen & 0x01) {
263 IP6_INC_STATS_BH(IPSTATS_MIB_INHDRERRORS);
264 icmpv6_param_prob(skb, ICMPV6_HDR_FIELD, (&hdr->hdrlen) - skb->nh.raw);
265 return -1;
266 }
267 433
268 /* 434 /*
269 * This is the routing header forwarding algorithm from 435 * This is the routing header forwarding algorithm from
@@ -294,7 +460,7 @@ looped_back:
294 hdr = (struct ipv6_rt_hdr *) skb2->h.raw; 460 hdr = (struct ipv6_rt_hdr *) skb2->h.raw;
295 } 461 }
296 462
297 if (skb->ip_summed == CHECKSUM_HW) 463 if (skb->ip_summed == CHECKSUM_COMPLETE)
298 skb->ip_summed = CHECKSUM_NONE; 464 skb->ip_summed = CHECKSUM_NONE;
299 465
300 i = n - --hdr->segments_left; 466 i = n - --hdr->segments_left;
@@ -303,6 +469,27 @@ looped_back:
303 addr = rthdr->addr; 469 addr = rthdr->addr;
304 addr += i - 1; 470 addr += i - 1;
305 471
472 switch (hdr->type) {
473#ifdef CONFIG_IPV6_MIP6
474 case IPV6_SRCRT_TYPE_2:
475 if (xfrm6_input_addr(skb, (xfrm_address_t *)addr,
476 (xfrm_address_t *)&skb->nh.ipv6h->saddr,
477 IPPROTO_ROUTING) < 0) {
478 IP6_INC_STATS_BH(IPSTATS_MIB_INADDRERRORS);
479 kfree_skb(skb);
480 return -1;
481 }
482 if (!ipv6_chk_home_addr(addr)) {
483 IP6_INC_STATS_BH(IPSTATS_MIB_INADDRERRORS);
484 kfree_skb(skb);
485 return -1;
486 }
487 break;
488#endif
489 default:
490 break;
491 }
492
306 if (ipv6_addr_is_multicast(addr)) { 493 if (ipv6_addr_is_multicast(addr)) {
307 IP6_INC_STATS_BH(IPSTATS_MIB_INADDRERRORS); 494 IP6_INC_STATS_BH(IPSTATS_MIB_INADDRERRORS);
308 kfree_skb(skb); 495 kfree_skb(skb);
@@ -421,8 +608,10 @@ EXPORT_SYMBOL_GPL(ipv6_invert_rthdr);
421 608
422/* Router Alert as of RFC 2711 */ 609/* Router Alert as of RFC 2711 */
423 610
424static int ipv6_hop_ra(struct sk_buff *skb, int optoff) 611static int ipv6_hop_ra(struct sk_buff **skbp, int optoff)
425{ 612{
613 struct sk_buff *skb = *skbp;
614
426 if (skb->nh.raw[optoff+1] == 2) { 615 if (skb->nh.raw[optoff+1] == 2) {
427 IP6CB(skb)->ra = optoff; 616 IP6CB(skb)->ra = optoff;
428 return 1; 617 return 1;
@@ -435,8 +624,9 @@ static int ipv6_hop_ra(struct sk_buff *skb, int optoff)
435 624
436/* Jumbo payload */ 625/* Jumbo payload */
437 626
438static int ipv6_hop_jumbo(struct sk_buff *skb, int optoff) 627static int ipv6_hop_jumbo(struct sk_buff **skbp, int optoff)
439{ 628{
629 struct sk_buff *skb = *skbp;
440 u32 pkt_len; 630 u32 pkt_len;
441 631
442 if (skb->nh.raw[optoff+1] != 4 || (optoff&3) != 2) { 632 if (skb->nh.raw[optoff+1] != 4 || (optoff&3) != 2) {
@@ -485,8 +675,9 @@ static struct tlvtype_proc tlvprochopopt_lst[] = {
485 { -1, } 675 { -1, }
486}; 676};
487 677
488int ipv6_parse_hopopts(struct sk_buff *skb) 678int ipv6_parse_hopopts(struct sk_buff **skbp)
489{ 679{
680 struct sk_buff *skb = *skbp;
490 struct inet6_skb_parm *opt = IP6CB(skb); 681 struct inet6_skb_parm *opt = IP6CB(skb);
491 682
492 /* 683 /*
@@ -502,8 +693,10 @@ int ipv6_parse_hopopts(struct sk_buff *skb)
502 } 693 }
503 694
504 opt->hop = sizeof(struct ipv6hdr); 695 opt->hop = sizeof(struct ipv6hdr);
505 if (ip6_parse_tlv(tlvprochopopt_lst, skb)) { 696 if (ip6_parse_tlv(tlvprochopopt_lst, skbp)) {
697 skb = *skbp;
506 skb->h.raw += (skb->h.raw[1]+1)<<3; 698 skb->h.raw += (skb->h.raw[1]+1)<<3;
699 opt = IP6CB(skb);
507 opt->nhoff = sizeof(struct ipv6hdr); 700 opt->nhoff = sizeof(struct ipv6hdr);
508 return 1; 701 return 1;
509 } 702 }
diff --git a/net/ipv6/fib6_rules.c b/net/ipv6/fib6_rules.c
new file mode 100644
index 000000000000..34f5bfaddfc2
--- /dev/null
+++ b/net/ipv6/fib6_rules.c
@@ -0,0 +1,305 @@
1/*
2 * net/ipv6/fib6_rules.c IPv6 Routing Policy Rules
3 *
4 * Copyright (C)2003-2006 Helsinki University of Technology
5 * Copyright (C)2003-2006 USAGI/WIDE Project
6 *
7 * This program is free software; you can redistribute it and/or
8 * modify it under the terms of the GNU General Public License as
9 * published by the Free Software Foundation, version 2.
10 *
11 * Authors
12 * Thomas Graf <tgraf@suug.ch>
13 * Ville Nuorvala <vnuorval@tcs.hut.fi>
14 */
15
16#include <linux/config.h>
17#include <linux/netdevice.h>
18
19#include <net/fib_rules.h>
20#include <net/ipv6.h>
21#include <net/ip6_route.h>
22#include <net/netlink.h>
23
24struct fib6_rule
25{
26 struct fib_rule common;
27 struct rt6key src;
28 struct rt6key dst;
29#ifdef CONFIG_IPV6_ROUTE_FWMARK
30 u32 fwmark;
31 u32 fwmask;
32#endif
33 u8 tclass;
34};
35
36static struct fib_rules_ops fib6_rules_ops;
37
38static struct fib6_rule main_rule = {
39 .common = {
40 .refcnt = ATOMIC_INIT(2),
41 .pref = 0x7FFE,
42 .action = FR_ACT_TO_TBL,
43 .table = RT6_TABLE_MAIN,
44 },
45};
46
47static struct fib6_rule local_rule = {
48 .common = {
49 .refcnt = ATOMIC_INIT(2),
50 .pref = 0,
51 .action = FR_ACT_TO_TBL,
52 .table = RT6_TABLE_LOCAL,
53 .flags = FIB_RULE_PERMANENT,
54 },
55};
56
57static LIST_HEAD(fib6_rules);
58
59struct dst_entry *fib6_rule_lookup(struct flowi *fl, int flags,
60 pol_lookup_t lookup)
61{
62 struct fib_lookup_arg arg = {
63 .lookup_ptr = lookup,
64 };
65
66 fib_rules_lookup(&fib6_rules_ops, fl, flags, &arg);
67 if (arg.rule)
68 fib_rule_put(arg.rule);
69
70 if (arg.result)
71 return (struct dst_entry *) arg.result;
72
73 dst_hold(&ip6_null_entry.u.dst);
74 return &ip6_null_entry.u.dst;
75}
76
77static int fib6_rule_action(struct fib_rule *rule, struct flowi *flp,
78 int flags, struct fib_lookup_arg *arg)
79{
80 struct rt6_info *rt = NULL;
81 struct fib6_table *table;
82 pol_lookup_t lookup = arg->lookup_ptr;
83
84 switch (rule->action) {
85 case FR_ACT_TO_TBL:
86 break;
87 case FR_ACT_UNREACHABLE:
88 rt = &ip6_null_entry;
89 goto discard_pkt;
90 default:
91 case FR_ACT_BLACKHOLE:
92 rt = &ip6_blk_hole_entry;
93 goto discard_pkt;
94 case FR_ACT_PROHIBIT:
95 rt = &ip6_prohibit_entry;
96 goto discard_pkt;
97 }
98
99 table = fib6_get_table(rule->table);
100 if (table)
101 rt = lookup(table, flp, flags);
102
103 if (rt != &ip6_null_entry)
104 goto out;
105 dst_release(&rt->u.dst);
106 rt = NULL;
107 goto out;
108
109discard_pkt:
110 dst_hold(&rt->u.dst);
111out:
112 arg->result = rt;
113 return rt == NULL ? -EAGAIN : 0;
114}
115
116
117static int fib6_rule_match(struct fib_rule *rule, struct flowi *fl, int flags)
118{
119 struct fib6_rule *r = (struct fib6_rule *) rule;
120
121 if (!ipv6_prefix_equal(&fl->fl6_dst, &r->dst.addr, r->dst.plen))
122 return 0;
123
124 if ((flags & RT6_LOOKUP_F_HAS_SADDR) &&
125 !ipv6_prefix_equal(&fl->fl6_src, &r->src.addr, r->src.plen))
126 return 0;
127
128 if (r->tclass && r->tclass != ((ntohl(fl->fl6_flowlabel) >> 20) & 0xff))
129 return 0;
130
131#ifdef CONFIG_IPV6_ROUTE_FWMARK
132 if ((r->fwmark ^ fl->fl6_fwmark) & r->fwmask)
133 return 0;
134#endif
135
136 return 1;
137}
138
139static struct nla_policy fib6_rule_policy[FRA_MAX+1] __read_mostly = {
140 [FRA_IFNAME] = { .type = NLA_STRING, .len = IFNAMSIZ - 1 },
141 [FRA_PRIORITY] = { .type = NLA_U32 },
142 [FRA_SRC] = { .len = sizeof(struct in6_addr) },
143 [FRA_DST] = { .len = sizeof(struct in6_addr) },
144 [FRA_FWMARK] = { .type = NLA_U32 },
145 [FRA_FWMASK] = { .type = NLA_U32 },
146 [FRA_TABLE] = { .type = NLA_U32 },
147};
148
149static int fib6_rule_configure(struct fib_rule *rule, struct sk_buff *skb,
150 struct nlmsghdr *nlh, struct fib_rule_hdr *frh,
151 struct nlattr **tb)
152{
153 int err = -EINVAL;
154 struct fib6_rule *rule6 = (struct fib6_rule *) rule;
155
156 if (frh->src_len > 128 || frh->dst_len > 128 ||
157 (frh->tos & ~IPV6_FLOWINFO_MASK))
158 goto errout;
159
160 if (rule->action == FR_ACT_TO_TBL) {
161 if (rule->table == RT6_TABLE_UNSPEC)
162 goto errout;
163
164 if (fib6_new_table(rule->table) == NULL) {
165 err = -ENOBUFS;
166 goto errout;
167 }
168 }
169
170 if (tb[FRA_SRC])
171 nla_memcpy(&rule6->src.addr, tb[FRA_SRC],
172 sizeof(struct in6_addr));
173
174 if (tb[FRA_DST])
175 nla_memcpy(&rule6->dst.addr, tb[FRA_DST],
176 sizeof(struct in6_addr));
177
178#ifdef CONFIG_IPV6_ROUTE_FWMARK
179 if (tb[FRA_FWMARK]) {
180 rule6->fwmark = nla_get_u32(tb[FRA_FWMARK]);
181 if (rule6->fwmark) {
182 /*
183 * if the mark value is non-zero,
184 * all bits are compared by default
185 * unless a mask is explicitly specified.
186 */
187 rule6->fwmask = 0xFFFFFFFF;
188 }
189 }
190
191 if (tb[FRA_FWMASK])
192 rule6->fwmask = nla_get_u32(tb[FRA_FWMASK]);
193#endif
194
195 rule6->src.plen = frh->src_len;
196 rule6->dst.plen = frh->dst_len;
197 rule6->tclass = frh->tos;
198
199 err = 0;
200errout:
201 return err;
202}
203
204static int fib6_rule_compare(struct fib_rule *rule, struct fib_rule_hdr *frh,
205 struct nlattr **tb)
206{
207 struct fib6_rule *rule6 = (struct fib6_rule *) rule;
208
209 if (frh->src_len && (rule6->src.plen != frh->src_len))
210 return 0;
211
212 if (frh->dst_len && (rule6->dst.plen != frh->dst_len))
213 return 0;
214
215 if (frh->tos && (rule6->tclass != frh->tos))
216 return 0;
217
218 if (tb[FRA_SRC] &&
219 nla_memcmp(tb[FRA_SRC], &rule6->src.addr, sizeof(struct in6_addr)))
220 return 0;
221
222 if (tb[FRA_DST] &&
223 nla_memcmp(tb[FRA_DST], &rule6->dst.addr, sizeof(struct in6_addr)))
224 return 0;
225
226#ifdef CONFIG_IPV6_ROUTE_FWMARK
227 if (tb[FRA_FWMARK] && (rule6->fwmark != nla_get_u32(tb[FRA_FWMARK])))
228 return 0;
229
230 if (tb[FRA_FWMASK] && (rule6->fwmask != nla_get_u32(tb[FRA_FWMASK])))
231 return 0;
232#endif
233
234 return 1;
235}
236
237static int fib6_rule_fill(struct fib_rule *rule, struct sk_buff *skb,
238 struct nlmsghdr *nlh, struct fib_rule_hdr *frh)
239{
240 struct fib6_rule *rule6 = (struct fib6_rule *) rule;
241
242 frh->family = AF_INET6;
243 frh->dst_len = rule6->dst.plen;
244 frh->src_len = rule6->src.plen;
245 frh->tos = rule6->tclass;
246
247 if (rule6->dst.plen)
248 NLA_PUT(skb, FRA_DST, sizeof(struct in6_addr),
249 &rule6->dst.addr);
250
251 if (rule6->src.plen)
252 NLA_PUT(skb, FRA_SRC, sizeof(struct in6_addr),
253 &rule6->src.addr);
254
255#ifdef CONFIG_IPV6_ROUTE_FWMARK
256 if (rule6->fwmark)
257 NLA_PUT_U32(skb, FRA_FWMARK, rule6->fwmark);
258
259 if (rule6->fwmask || rule6->fwmark)
260 NLA_PUT_U32(skb, FRA_FWMASK, rule6->fwmask);
261#endif
262
263 return 0;
264
265nla_put_failure:
266 return -ENOBUFS;
267}
268
269int fib6_rules_dump(struct sk_buff *skb, struct netlink_callback *cb)
270{
271 return fib_rules_dump(skb, cb, AF_INET6);
272}
273
274static u32 fib6_rule_default_pref(void)
275{
276 return 0x3FFF;
277}
278
279static struct fib_rules_ops fib6_rules_ops = {
280 .family = AF_INET6,
281 .rule_size = sizeof(struct fib6_rule),
282 .action = fib6_rule_action,
283 .match = fib6_rule_match,
284 .configure = fib6_rule_configure,
285 .compare = fib6_rule_compare,
286 .fill = fib6_rule_fill,
287 .default_pref = fib6_rule_default_pref,
288 .nlgroup = RTNLGRP_IPV6_RULE,
289 .policy = fib6_rule_policy,
290 .rules_list = &fib6_rules,
291 .owner = THIS_MODULE,
292};
293
294void __init fib6_rules_init(void)
295{
296 list_add_tail(&local_rule.common.list, &fib6_rules);
297 list_add_tail(&main_rule.common.list, &fib6_rules);
298
299 fib_rules_register(&fib6_rules_ops);
300}
301
302void fib6_rules_cleanup(void)
303{
304 fib_rules_unregister(&fib6_rules_ops);
305}
diff --git a/net/ipv6/icmp.c b/net/ipv6/icmp.c
index 356a8a7ef22a..4ec876066b3f 100644
--- a/net/ipv6/icmp.c
+++ b/net/ipv6/icmp.c
@@ -151,7 +151,7 @@ static int is_ineligible(struct sk_buff *skb)
151 return 0; 151 return 0;
152} 152}
153 153
154static int sysctl_icmpv6_time = 1*HZ; 154static int sysctl_icmpv6_time __read_mostly = 1*HZ;
155 155
156/* 156/*
157 * Check the ICMP output rate limit 157 * Check the ICMP output rate limit
@@ -273,6 +273,29 @@ static int icmpv6_getfrag(void *from, char *to, int offset, int len, int odd, st
273 return 0; 273 return 0;
274} 274}
275 275
276#ifdef CONFIG_IPV6_MIP6
277static void mip6_addr_swap(struct sk_buff *skb)
278{
279 struct ipv6hdr *iph = skb->nh.ipv6h;
280 struct inet6_skb_parm *opt = IP6CB(skb);
281 struct ipv6_destopt_hao *hao;
282 struct in6_addr tmp;
283 int off;
284
285 if (opt->dsthao) {
286 off = ipv6_find_tlv(skb, opt->dsthao, IPV6_TLV_HAO);
287 if (likely(off >= 0)) {
288 hao = (struct ipv6_destopt_hao *)(skb->nh.raw + off);
289 ipv6_addr_copy(&tmp, &iph->saddr);
290 ipv6_addr_copy(&iph->saddr, &hao->addr);
291 ipv6_addr_copy(&hao->addr, &tmp);
292 }
293 }
294}
295#else
296static inline void mip6_addr_swap(struct sk_buff *skb) {}
297#endif
298
276/* 299/*
277 * Send an ICMP message in response to a packet in error 300 * Send an ICMP message in response to a packet in error
278 */ 301 */
@@ -350,6 +373,8 @@ void icmpv6_send(struct sk_buff *skb, int type, int code, __u32 info,
350 return; 373 return;
351 } 374 }
352 375
376 mip6_addr_swap(skb);
377
353 memset(&fl, 0, sizeof(fl)); 378 memset(&fl, 0, sizeof(fl));
354 fl.proto = IPPROTO_ICMPV6; 379 fl.proto = IPPROTO_ICMPV6;
355 ipv6_addr_copy(&fl.fl6_dst, &hdr->saddr); 380 ipv6_addr_copy(&fl.fl6_dst, &hdr->saddr);
@@ -358,6 +383,7 @@ void icmpv6_send(struct sk_buff *skb, int type, int code, __u32 info,
358 fl.oif = iif; 383 fl.oif = iif;
359 fl.fl_icmp_type = type; 384 fl.fl_icmp_type = type;
360 fl.fl_icmp_code = code; 385 fl.fl_icmp_code = code;
386 security_skb_classify_flow(skb, &fl);
361 387
362 if (icmpv6_xmit_lock()) 388 if (icmpv6_xmit_lock())
363 return; 389 return;
@@ -472,6 +498,7 @@ static void icmpv6_echo_reply(struct sk_buff *skb)
472 ipv6_addr_copy(&fl.fl6_src, saddr); 498 ipv6_addr_copy(&fl.fl6_src, saddr);
473 fl.oif = skb->dev->ifindex; 499 fl.oif = skb->dev->ifindex;
474 fl.fl_icmp_type = ICMPV6_ECHO_REPLY; 500 fl.fl_icmp_type = ICMPV6_ECHO_REPLY;
501 security_skb_classify_flow(skb, &fl);
475 502
476 if (icmpv6_xmit_lock()) 503 if (icmpv6_xmit_lock())
477 return; 504 return;
@@ -604,7 +631,7 @@ static int icmpv6_rcv(struct sk_buff **pskb)
604 631
605 /* Perform checksum. */ 632 /* Perform checksum. */
606 switch (skb->ip_summed) { 633 switch (skb->ip_summed) {
607 case CHECKSUM_HW: 634 case CHECKSUM_COMPLETE:
608 if (!csum_ipv6_magic(saddr, daddr, skb->len, IPPROTO_ICMPV6, 635 if (!csum_ipv6_magic(saddr, daddr, skb->len, IPPROTO_ICMPV6,
609 skb->csum)) 636 skb->csum))
610 break; 637 break;
diff --git a/net/ipv6/inet6_connection_sock.c b/net/ipv6/inet6_connection_sock.c
index bf491077b822..827f41d1478b 100644
--- a/net/ipv6/inet6_connection_sock.c
+++ b/net/ipv6/inet6_connection_sock.c
@@ -157,6 +157,7 @@ int inet6_csk_xmit(struct sk_buff *skb, int ipfragok)
157 fl.oif = sk->sk_bound_dev_if; 157 fl.oif = sk->sk_bound_dev_if;
158 fl.fl_ip_sport = inet->sport; 158 fl.fl_ip_sport = inet->sport;
159 fl.fl_ip_dport = inet->dport; 159 fl.fl_ip_dport = inet->dport;
160 security_sk_classify_flow(sk, &fl);
160 161
161 if (np->opt && np->opt->srcrt) { 162 if (np->opt && np->opt->srcrt) {
162 struct rt0_hdr *rt0 = (struct rt0_hdr *)np->opt->srcrt; 163 struct rt0_hdr *rt0 = (struct rt0_hdr *)np->opt->srcrt;
@@ -185,7 +186,7 @@ int inet6_csk_xmit(struct sk_buff *skb, int ipfragok)
185 return err; 186 return err;
186 } 187 }
187 188
188 __ip6_dst_store(sk, dst, NULL); 189 __ip6_dst_store(sk, dst, NULL, NULL);
189 } 190 }
190 191
191 skb->dst = dst_clone(dst); 192 skb->dst = dst_clone(dst);
diff --git a/net/ipv6/ip6_fib.c b/net/ipv6/ip6_fib.c
index 764221220afd..8fcae7a6510b 100644
--- a/net/ipv6/ip6_fib.c
+++ b/net/ipv6/ip6_fib.c
@@ -18,6 +18,7 @@
18 * Yuji SEKIYA @USAGI: Support default route on router node; 18 * Yuji SEKIYA @USAGI: Support default route on router node;
19 * remove ip6_null_entry from the top of 19 * remove ip6_null_entry from the top of
20 * routing table. 20 * routing table.
21 * Ville Nuorvala: Fixed routing subtrees.
21 */ 22 */
22#include <linux/errno.h> 23#include <linux/errno.h>
23#include <linux/types.h> 24#include <linux/types.h>
@@ -26,6 +27,7 @@
26#include <linux/netdevice.h> 27#include <linux/netdevice.h>
27#include <linux/in6.h> 28#include <linux/in6.h>
28#include <linux/init.h> 29#include <linux/init.h>
30#include <linux/list.h>
29 31
30#ifdef CONFIG_PROC_FS 32#ifdef CONFIG_PROC_FS
31#include <linux/proc_fs.h> 33#include <linux/proc_fs.h>
@@ -68,19 +70,19 @@ struct fib6_cleaner_t
68 void *arg; 70 void *arg;
69}; 71};
70 72
71DEFINE_RWLOCK(fib6_walker_lock); 73static DEFINE_RWLOCK(fib6_walker_lock);
72
73 74
74#ifdef CONFIG_IPV6_SUBTREES 75#ifdef CONFIG_IPV6_SUBTREES
75#define FWS_INIT FWS_S 76#define FWS_INIT FWS_S
76#define SUBTREE(fn) ((fn)->subtree)
77#else 77#else
78#define FWS_INIT FWS_L 78#define FWS_INIT FWS_L
79#define SUBTREE(fn) NULL
80#endif 79#endif
81 80
82static void fib6_prune_clones(struct fib6_node *fn, struct rt6_info *rt); 81static void fib6_prune_clones(struct fib6_node *fn, struct rt6_info *rt);
82static struct rt6_info * fib6_find_prefix(struct fib6_node *fn);
83static struct fib6_node * fib6_repair_tree(struct fib6_node *fn); 83static struct fib6_node * fib6_repair_tree(struct fib6_node *fn);
84static int fib6_walk(struct fib6_walker_t *w);
85static int fib6_walk_continue(struct fib6_walker_t *w);
84 86
85/* 87/*
86 * A routing update causes an increase of the serial number on the 88 * A routing update causes an increase of the serial number on the
@@ -93,13 +95,31 @@ static __u32 rt_sernum;
93 95
94static DEFINE_TIMER(ip6_fib_timer, fib6_run_gc, 0, 0); 96static DEFINE_TIMER(ip6_fib_timer, fib6_run_gc, 0, 0);
95 97
96struct fib6_walker_t fib6_walker_list = { 98static struct fib6_walker_t fib6_walker_list = {
97 .prev = &fib6_walker_list, 99 .prev = &fib6_walker_list,
98 .next = &fib6_walker_list, 100 .next = &fib6_walker_list,
99}; 101};
100 102
101#define FOR_WALKERS(w) for ((w)=fib6_walker_list.next; (w) != &fib6_walker_list; (w)=(w)->next) 103#define FOR_WALKERS(w) for ((w)=fib6_walker_list.next; (w) != &fib6_walker_list; (w)=(w)->next)
102 104
105static inline void fib6_walker_link(struct fib6_walker_t *w)
106{
107 write_lock_bh(&fib6_walker_lock);
108 w->next = fib6_walker_list.next;
109 w->prev = &fib6_walker_list;
110 w->next->prev = w;
111 w->prev->next = w;
112 write_unlock_bh(&fib6_walker_lock);
113}
114
115static inline void fib6_walker_unlink(struct fib6_walker_t *w)
116{
117 write_lock_bh(&fib6_walker_lock);
118 w->next->prev = w->prev;
119 w->prev->next = w->next;
120 w->prev = w->next = w;
121 write_unlock_bh(&fib6_walker_lock);
122}
103static __inline__ u32 fib6_new_sernum(void) 123static __inline__ u32 fib6_new_sernum(void)
104{ 124{
105 u32 n = ++rt_sernum; 125 u32 n = ++rt_sernum;
@@ -147,6 +167,253 @@ static __inline__ void rt6_release(struct rt6_info *rt)
147 dst_free(&rt->u.dst); 167 dst_free(&rt->u.dst);
148} 168}
149 169
170static struct fib6_table fib6_main_tbl = {
171 .tb6_id = RT6_TABLE_MAIN,
172 .tb6_lock = RW_LOCK_UNLOCKED,
173 .tb6_root = {
174 .leaf = &ip6_null_entry,
175 .fn_flags = RTN_ROOT | RTN_TL_ROOT | RTN_RTINFO,
176 },
177};
178
179#ifdef CONFIG_IPV6_MULTIPLE_TABLES
180#define FIB_TABLE_HASHSZ 256
181#else
182#define FIB_TABLE_HASHSZ 1
183#endif
184static struct hlist_head fib_table_hash[FIB_TABLE_HASHSZ];
185
186static void fib6_link_table(struct fib6_table *tb)
187{
188 unsigned int h;
189
190 h = tb->tb6_id & (FIB_TABLE_HASHSZ - 1);
191
192 /*
193 * No protection necessary, this is the only list mutatation
194 * operation, tables never disappear once they exist.
195 */
196 hlist_add_head_rcu(&tb->tb6_hlist, &fib_table_hash[h]);
197}
198
199#ifdef CONFIG_IPV6_MULTIPLE_TABLES
200static struct fib6_table fib6_local_tbl = {
201 .tb6_id = RT6_TABLE_LOCAL,
202 .tb6_lock = RW_LOCK_UNLOCKED,
203 .tb6_root = {
204 .leaf = &ip6_null_entry,
205 .fn_flags = RTN_ROOT | RTN_TL_ROOT | RTN_RTINFO,
206 },
207};
208
209static struct fib6_table *fib6_alloc_table(u32 id)
210{
211 struct fib6_table *table;
212
213 table = kzalloc(sizeof(*table), GFP_ATOMIC);
214 if (table != NULL) {
215 table->tb6_id = id;
216 table->tb6_lock = RW_LOCK_UNLOCKED;
217 table->tb6_root.leaf = &ip6_null_entry;
218 table->tb6_root.fn_flags = RTN_ROOT | RTN_TL_ROOT | RTN_RTINFO;
219 }
220
221 return table;
222}
223
224struct fib6_table *fib6_new_table(u32 id)
225{
226 struct fib6_table *tb;
227
228 if (id == 0)
229 id = RT6_TABLE_MAIN;
230 tb = fib6_get_table(id);
231 if (tb)
232 return tb;
233
234 tb = fib6_alloc_table(id);
235 if (tb != NULL)
236 fib6_link_table(tb);
237
238 return tb;
239}
240
241struct fib6_table *fib6_get_table(u32 id)
242{
243 struct fib6_table *tb;
244 struct hlist_node *node;
245 unsigned int h;
246
247 if (id == 0)
248 id = RT6_TABLE_MAIN;
249 h = id & (FIB_TABLE_HASHSZ - 1);
250 rcu_read_lock();
251 hlist_for_each_entry_rcu(tb, node, &fib_table_hash[h], tb6_hlist) {
252 if (tb->tb6_id == id) {
253 rcu_read_unlock();
254 return tb;
255 }
256 }
257 rcu_read_unlock();
258
259 return NULL;
260}
261
262static void __init fib6_tables_init(void)
263{
264 fib6_link_table(&fib6_main_tbl);
265 fib6_link_table(&fib6_local_tbl);
266}
267
268#else
269
270struct fib6_table *fib6_new_table(u32 id)
271{
272 return fib6_get_table(id);
273}
274
275struct fib6_table *fib6_get_table(u32 id)
276{
277 return &fib6_main_tbl;
278}
279
280struct dst_entry *fib6_rule_lookup(struct flowi *fl, int flags,
281 pol_lookup_t lookup)
282{
283 return (struct dst_entry *) lookup(&fib6_main_tbl, fl, flags);
284}
285
286static void __init fib6_tables_init(void)
287{
288 fib6_link_table(&fib6_main_tbl);
289}
290
291#endif
292
293static int fib6_dump_node(struct fib6_walker_t *w)
294{
295 int res;
296 struct rt6_info *rt;
297
298 for (rt = w->leaf; rt; rt = rt->u.next) {
299 res = rt6_dump_route(rt, w->args);
300 if (res < 0) {
301 /* Frame is full, suspend walking */
302 w->leaf = rt;
303 return 1;
304 }
305 BUG_TRAP(res!=0);
306 }
307 w->leaf = NULL;
308 return 0;
309}
310
311static void fib6_dump_end(struct netlink_callback *cb)
312{
313 struct fib6_walker_t *w = (void*)cb->args[2];
314
315 if (w) {
316 cb->args[2] = 0;
317 kfree(w);
318 }
319 cb->done = (void*)cb->args[3];
320 cb->args[1] = 3;
321}
322
323static int fib6_dump_done(struct netlink_callback *cb)
324{
325 fib6_dump_end(cb);
326 return cb->done ? cb->done(cb) : 0;
327}
328
329static int fib6_dump_table(struct fib6_table *table, struct sk_buff *skb,
330 struct netlink_callback *cb)
331{
332 struct fib6_walker_t *w;
333 int res;
334
335 w = (void *)cb->args[2];
336 w->root = &table->tb6_root;
337
338 if (cb->args[4] == 0) {
339 read_lock_bh(&table->tb6_lock);
340 res = fib6_walk(w);
341 read_unlock_bh(&table->tb6_lock);
342 if (res > 0)
343 cb->args[4] = 1;
344 } else {
345 read_lock_bh(&table->tb6_lock);
346 res = fib6_walk_continue(w);
347 read_unlock_bh(&table->tb6_lock);
348 if (res != 0) {
349 if (res < 0)
350 fib6_walker_unlink(w);
351 goto end;
352 }
353 fib6_walker_unlink(w);
354 cb->args[4] = 0;
355 }
356end:
357 return res;
358}
359
360int inet6_dump_fib(struct sk_buff *skb, struct netlink_callback *cb)
361{
362 unsigned int h, s_h;
363 unsigned int e = 0, s_e;
364 struct rt6_rtnl_dump_arg arg;
365 struct fib6_walker_t *w;
366 struct fib6_table *tb;
367 struct hlist_node *node;
368 int res = 0;
369
370 s_h = cb->args[0];
371 s_e = cb->args[1];
372
373 w = (void *)cb->args[2];
374 if (w == NULL) {
375 /* New dump:
376 *
377 * 1. hook callback destructor.
378 */
379 cb->args[3] = (long)cb->done;
380 cb->done = fib6_dump_done;
381
382 /*
383 * 2. allocate and initialize walker.
384 */
385 w = kzalloc(sizeof(*w), GFP_ATOMIC);
386 if (w == NULL)
387 return -ENOMEM;
388 w->func = fib6_dump_node;
389 cb->args[2] = (long)w;
390 }
391
392 arg.skb = skb;
393 arg.cb = cb;
394 w->args = &arg;
395
396 for (h = s_h; h < FIB_TABLE_HASHSZ; h++, s_e = 0) {
397 e = 0;
398 hlist_for_each_entry(tb, node, &fib_table_hash[h], tb6_hlist) {
399 if (e < s_e)
400 goto next;
401 res = fib6_dump_table(tb, skb, cb);
402 if (res != 0)
403 goto out;
404next:
405 e++;
406 }
407 }
408out:
409 cb->args[1] = e;
410 cb->args[0] = h;
411
412 res = res < 0 ? res : skb->len;
413 if (res <= 0)
414 fib6_dump_end(cb);
415 return res;
416}
150 417
151/* 418/*
152 * Routing Table 419 * Routing Table
@@ -343,7 +610,7 @@ insert_above:
343 */ 610 */
344 611
345static int fib6_add_rt2node(struct fib6_node *fn, struct rt6_info *rt, 612static int fib6_add_rt2node(struct fib6_node *fn, struct rt6_info *rt,
346 struct nlmsghdr *nlh, struct netlink_skb_parms *req) 613 struct nl_info *info)
347{ 614{
348 struct rt6_info *iter = NULL; 615 struct rt6_info *iter = NULL;
349 struct rt6_info **ins; 616 struct rt6_info **ins;
@@ -398,7 +665,7 @@ out:
398 *ins = rt; 665 *ins = rt;
399 rt->rt6i_node = fn; 666 rt->rt6i_node = fn;
400 atomic_inc(&rt->rt6i_ref); 667 atomic_inc(&rt->rt6i_ref);
401 inet6_rt_notify(RTM_NEWROUTE, rt, nlh, req); 668 inet6_rt_notify(RTM_NEWROUTE, rt, info);
402 rt6_stats.fib_rt_entries++; 669 rt6_stats.fib_rt_entries++;
403 670
404 if ((fn->fn_flags & RTN_RTINFO) == 0) { 671 if ((fn->fn_flags & RTN_RTINFO) == 0) {
@@ -428,10 +695,9 @@ void fib6_force_start_gc(void)
428 * with source addr info in sub-trees 695 * with source addr info in sub-trees
429 */ 696 */
430 697
431int fib6_add(struct fib6_node *root, struct rt6_info *rt, 698int fib6_add(struct fib6_node *root, struct rt6_info *rt, struct nl_info *info)
432 struct nlmsghdr *nlh, void *_rtattr, struct netlink_skb_parms *req)
433{ 699{
434 struct fib6_node *fn; 700 struct fib6_node *fn, *pn = NULL;
435 int err = -ENOMEM; 701 int err = -ENOMEM;
436 702
437 fn = fib6_add_1(root, &rt->rt6i_dst.addr, sizeof(struct in6_addr), 703 fn = fib6_add_1(root, &rt->rt6i_dst.addr, sizeof(struct in6_addr),
@@ -440,6 +706,8 @@ int fib6_add(struct fib6_node *root, struct rt6_info *rt,
440 if (fn == NULL) 706 if (fn == NULL)
441 goto out; 707 goto out;
442 708
709 pn = fn;
710
443#ifdef CONFIG_IPV6_SUBTREES 711#ifdef CONFIG_IPV6_SUBTREES
444 if (rt->rt6i_src.plen) { 712 if (rt->rt6i_src.plen) {
445 struct fib6_node *sn; 713 struct fib6_node *sn;
@@ -485,10 +753,6 @@ int fib6_add(struct fib6_node *root, struct rt6_info *rt,
485 /* Now link new subtree to main tree */ 753 /* Now link new subtree to main tree */
486 sfn->parent = fn; 754 sfn->parent = fn;
487 fn->subtree = sfn; 755 fn->subtree = sfn;
488 if (fn->leaf == NULL) {
489 fn->leaf = rt;
490 atomic_inc(&rt->rt6i_ref);
491 }
492 } else { 756 } else {
493 sn = fib6_add_1(fn->subtree, &rt->rt6i_src.addr, 757 sn = fib6_add_1(fn->subtree, &rt->rt6i_src.addr,
494 sizeof(struct in6_addr), rt->rt6i_src.plen, 758 sizeof(struct in6_addr), rt->rt6i_src.plen,
@@ -498,21 +762,42 @@ int fib6_add(struct fib6_node *root, struct rt6_info *rt,
498 goto st_failure; 762 goto st_failure;
499 } 763 }
500 764
765 if (fn->leaf == NULL) {
766 fn->leaf = rt;
767 atomic_inc(&rt->rt6i_ref);
768 }
501 fn = sn; 769 fn = sn;
502 } 770 }
503#endif 771#endif
504 772
505 err = fib6_add_rt2node(fn, rt, nlh, req); 773 err = fib6_add_rt2node(fn, rt, info);
506 774
507 if (err == 0) { 775 if (err == 0) {
508 fib6_start_gc(rt); 776 fib6_start_gc(rt);
509 if (!(rt->rt6i_flags&RTF_CACHE)) 777 if (!(rt->rt6i_flags&RTF_CACHE))
510 fib6_prune_clones(fn, rt); 778 fib6_prune_clones(pn, rt);
511 } 779 }
512 780
513out: 781out:
514 if (err) 782 if (err) {
783#ifdef CONFIG_IPV6_SUBTREES
784 /*
785 * If fib6_add_1 has cleared the old leaf pointer in the
786 * super-tree leaf node we have to find a new one for it.
787 */
788 if (pn != fn && !pn->leaf && !(pn->fn_flags & RTN_RTINFO)) {
789 pn->leaf = fib6_find_prefix(pn);
790#if RT6_DEBUG >= 2
791 if (!pn->leaf) {
792 BUG_TRAP(pn->leaf != NULL);
793 pn->leaf = &ip6_null_entry;
794 }
795#endif
796 atomic_inc(&pn->leaf->rt6i_ref);
797 }
798#endif
515 dst_free(&rt->u.dst); 799 dst_free(&rt->u.dst);
800 }
516 return err; 801 return err;
517 802
518#ifdef CONFIG_IPV6_SUBTREES 803#ifdef CONFIG_IPV6_SUBTREES
@@ -543,6 +828,9 @@ static struct fib6_node * fib6_lookup_1(struct fib6_node *root,
543 struct fib6_node *fn; 828 struct fib6_node *fn;
544 int dir; 829 int dir;
545 830
831 if (unlikely(args->offset == 0))
832 return NULL;
833
546 /* 834 /*
547 * Descend on a tree 835 * Descend on a tree
548 */ 836 */
@@ -564,33 +852,26 @@ static struct fib6_node * fib6_lookup_1(struct fib6_node *root,
564 break; 852 break;
565 } 853 }
566 854
567 while ((fn->fn_flags & RTN_ROOT) == 0) { 855 while(fn) {
568#ifdef CONFIG_IPV6_SUBTREES 856 if (FIB6_SUBTREE(fn) || fn->fn_flags & RTN_RTINFO) {
569 if (fn->subtree) {
570 struct fib6_node *st;
571 struct lookup_args *narg;
572
573 narg = args + 1;
574
575 if (narg->addr) {
576 st = fib6_lookup_1(fn->subtree, narg);
577
578 if (st && !(st->fn_flags & RTN_ROOT))
579 return st;
580 }
581 }
582#endif
583
584 if (fn->fn_flags & RTN_RTINFO) {
585 struct rt6key *key; 857 struct rt6key *key;
586 858
587 key = (struct rt6key *) ((u8 *) fn->leaf + 859 key = (struct rt6key *) ((u8 *) fn->leaf +
588 args->offset); 860 args->offset);
589 861
590 if (ipv6_prefix_equal(&key->addr, args->addr, key->plen)) 862 if (ipv6_prefix_equal(&key->addr, args->addr, key->plen)) {
591 return fn; 863#ifdef CONFIG_IPV6_SUBTREES
864 if (fn->subtree)
865 fn = fib6_lookup_1(fn->subtree, args + 1);
866#endif
867 if (!fn || fn->fn_flags & RTN_RTINFO)
868 return fn;
869 }
592 } 870 }
593 871
872 if (fn->fn_flags & RTN_ROOT)
873 break;
874
594 fn = fn->parent; 875 fn = fn->parent;
595 } 876 }
596 877
@@ -600,18 +881,24 @@ static struct fib6_node * fib6_lookup_1(struct fib6_node *root,
600struct fib6_node * fib6_lookup(struct fib6_node *root, struct in6_addr *daddr, 881struct fib6_node * fib6_lookup(struct fib6_node *root, struct in6_addr *daddr,
601 struct in6_addr *saddr) 882 struct in6_addr *saddr)
602{ 883{
603 struct lookup_args args[2];
604 struct fib6_node *fn; 884 struct fib6_node *fn;
605 885 struct lookup_args args[] = {
606 args[0].offset = offsetof(struct rt6_info, rt6i_dst); 886 {
607 args[0].addr = daddr; 887 .offset = offsetof(struct rt6_info, rt6i_dst),
608 888 .addr = daddr,
889 },
609#ifdef CONFIG_IPV6_SUBTREES 890#ifdef CONFIG_IPV6_SUBTREES
610 args[1].offset = offsetof(struct rt6_info, rt6i_src); 891 {
611 args[1].addr = saddr; 892 .offset = offsetof(struct rt6_info, rt6i_src),
893 .addr = saddr,
894 },
612#endif 895#endif
896 {
897 .offset = 0, /* sentinel */
898 }
899 };
613 900
614 fn = fib6_lookup_1(root, args); 901 fn = fib6_lookup_1(root, daddr ? args : args + 1);
615 902
616 if (fn == NULL || fn->fn_flags & RTN_TL_ROOT) 903 if (fn == NULL || fn->fn_flags & RTN_TL_ROOT)
617 fn = root; 904 fn = root;
@@ -667,10 +954,8 @@ struct fib6_node * fib6_locate(struct fib6_node *root,
667#ifdef CONFIG_IPV6_SUBTREES 954#ifdef CONFIG_IPV6_SUBTREES
668 if (src_len) { 955 if (src_len) {
669 BUG_TRAP(saddr!=NULL); 956 BUG_TRAP(saddr!=NULL);
670 if (fn == NULL) 957 if (fn && fn->subtree)
671 fn = fn->subtree; 958 fn = fib6_locate_1(fn->subtree, saddr, src_len,
672 if (fn)
673 fn = fib6_locate_1(fn, saddr, src_len,
674 offsetof(struct rt6_info, rt6i_src)); 959 offsetof(struct rt6_info, rt6i_src));
675 } 960 }
676#endif 961#endif
@@ -699,7 +984,7 @@ static struct rt6_info * fib6_find_prefix(struct fib6_node *fn)
699 if(fn->right) 984 if(fn->right)
700 return fn->right->leaf; 985 return fn->right->leaf;
701 986
702 fn = SUBTREE(fn); 987 fn = FIB6_SUBTREE(fn);
703 } 988 }
704 return NULL; 989 return NULL;
705} 990}
@@ -730,7 +1015,7 @@ static struct fib6_node * fib6_repair_tree(struct fib6_node *fn)
730 if (fn->right) child = fn->right, children |= 1; 1015 if (fn->right) child = fn->right, children |= 1;
731 if (fn->left) child = fn->left, children |= 2; 1016 if (fn->left) child = fn->left, children |= 2;
732 1017
733 if (children == 3 || SUBTREE(fn) 1018 if (children == 3 || FIB6_SUBTREE(fn)
734#ifdef CONFIG_IPV6_SUBTREES 1019#ifdef CONFIG_IPV6_SUBTREES
735 /* Subtree root (i.e. fn) may have one child */ 1020 /* Subtree root (i.e. fn) may have one child */
736 || (children && fn->fn_flags&RTN_ROOT) 1021 || (children && fn->fn_flags&RTN_ROOT)
@@ -749,9 +1034,9 @@ static struct fib6_node * fib6_repair_tree(struct fib6_node *fn)
749 1034
750 pn = fn->parent; 1035 pn = fn->parent;
751#ifdef CONFIG_IPV6_SUBTREES 1036#ifdef CONFIG_IPV6_SUBTREES
752 if (SUBTREE(pn) == fn) { 1037 if (FIB6_SUBTREE(pn) == fn) {
753 BUG_TRAP(fn->fn_flags&RTN_ROOT); 1038 BUG_TRAP(fn->fn_flags&RTN_ROOT);
754 SUBTREE(pn) = NULL; 1039 FIB6_SUBTREE(pn) = NULL;
755 nstate = FWS_L; 1040 nstate = FWS_L;
756 } else { 1041 } else {
757 BUG_TRAP(!(fn->fn_flags&RTN_ROOT)); 1042 BUG_TRAP(!(fn->fn_flags&RTN_ROOT));
@@ -799,7 +1084,7 @@ static struct fib6_node * fib6_repair_tree(struct fib6_node *fn)
799 read_unlock(&fib6_walker_lock); 1084 read_unlock(&fib6_walker_lock);
800 1085
801 node_free(fn); 1086 node_free(fn);
802 if (pn->fn_flags&RTN_RTINFO || SUBTREE(pn)) 1087 if (pn->fn_flags&RTN_RTINFO || FIB6_SUBTREE(pn))
803 return pn; 1088 return pn;
804 1089
805 rt6_release(pn->leaf); 1090 rt6_release(pn->leaf);
@@ -809,7 +1094,7 @@ static struct fib6_node * fib6_repair_tree(struct fib6_node *fn)
809} 1094}
810 1095
811static void fib6_del_route(struct fib6_node *fn, struct rt6_info **rtp, 1096static void fib6_del_route(struct fib6_node *fn, struct rt6_info **rtp,
812 struct nlmsghdr *nlh, void *_rtattr, struct netlink_skb_parms *req) 1097 struct nl_info *info)
813{ 1098{
814 struct fib6_walker_t *w; 1099 struct fib6_walker_t *w;
815 struct rt6_info *rt = *rtp; 1100 struct rt6_info *rt = *rtp;
@@ -865,11 +1150,11 @@ static void fib6_del_route(struct fib6_node *fn, struct rt6_info **rtp,
865 if (atomic_read(&rt->rt6i_ref) != 1) BUG(); 1150 if (atomic_read(&rt->rt6i_ref) != 1) BUG();
866 } 1151 }
867 1152
868 inet6_rt_notify(RTM_DELROUTE, rt, nlh, req); 1153 inet6_rt_notify(RTM_DELROUTE, rt, info);
869 rt6_release(rt); 1154 rt6_release(rt);
870} 1155}
871 1156
872int fib6_del(struct rt6_info *rt, struct nlmsghdr *nlh, void *_rtattr, struct netlink_skb_parms *req) 1157int fib6_del(struct rt6_info *rt, struct nl_info *info)
873{ 1158{
874 struct fib6_node *fn = rt->rt6i_node; 1159 struct fib6_node *fn = rt->rt6i_node;
875 struct rt6_info **rtp; 1160 struct rt6_info **rtp;
@@ -885,8 +1170,18 @@ int fib6_del(struct rt6_info *rt, struct nlmsghdr *nlh, void *_rtattr, struct ne
885 1170
886 BUG_TRAP(fn->fn_flags&RTN_RTINFO); 1171 BUG_TRAP(fn->fn_flags&RTN_RTINFO);
887 1172
888 if (!(rt->rt6i_flags&RTF_CACHE)) 1173 if (!(rt->rt6i_flags&RTF_CACHE)) {
889 fib6_prune_clones(fn, rt); 1174 struct fib6_node *pn = fn;
1175#ifdef CONFIG_IPV6_SUBTREES
1176 /* clones of this route might be in another subtree */
1177 if (rt->rt6i_src.plen) {
1178 while (!(pn->fn_flags&RTN_ROOT))
1179 pn = pn->parent;
1180 pn = pn->parent;
1181 }
1182#endif
1183 fib6_prune_clones(pn, rt);
1184 }
890 1185
891 /* 1186 /*
892 * Walk the leaf entries looking for ourself 1187 * Walk the leaf entries looking for ourself
@@ -894,7 +1189,7 @@ int fib6_del(struct rt6_info *rt, struct nlmsghdr *nlh, void *_rtattr, struct ne
894 1189
895 for (rtp = &fn->leaf; *rtp; rtp = &(*rtp)->u.next) { 1190 for (rtp = &fn->leaf; *rtp; rtp = &(*rtp)->u.next) {
896 if (*rtp == rt) { 1191 if (*rtp == rt) {
897 fib6_del_route(fn, rtp, nlh, _rtattr, req); 1192 fib6_del_route(fn, rtp, info);
898 return 0; 1193 return 0;
899 } 1194 }
900 } 1195 }
@@ -925,7 +1220,7 @@ int fib6_del(struct rt6_info *rt, struct nlmsghdr *nlh, void *_rtattr, struct ne
925 * <0 -> walk is terminated by an error. 1220 * <0 -> walk is terminated by an error.
926 */ 1221 */
927 1222
928int fib6_walk_continue(struct fib6_walker_t *w) 1223static int fib6_walk_continue(struct fib6_walker_t *w)
929{ 1224{
930 struct fib6_node *fn, *pn; 1225 struct fib6_node *fn, *pn;
931 1226
@@ -942,8 +1237,8 @@ int fib6_walk_continue(struct fib6_walker_t *w)
942 switch (w->state) { 1237 switch (w->state) {
943#ifdef CONFIG_IPV6_SUBTREES 1238#ifdef CONFIG_IPV6_SUBTREES
944 case FWS_S: 1239 case FWS_S:
945 if (SUBTREE(fn)) { 1240 if (FIB6_SUBTREE(fn)) {
946 w->node = SUBTREE(fn); 1241 w->node = FIB6_SUBTREE(fn);
947 continue; 1242 continue;
948 } 1243 }
949 w->state = FWS_L; 1244 w->state = FWS_L;
@@ -977,7 +1272,7 @@ int fib6_walk_continue(struct fib6_walker_t *w)
977 pn = fn->parent; 1272 pn = fn->parent;
978 w->node = pn; 1273 w->node = pn;
979#ifdef CONFIG_IPV6_SUBTREES 1274#ifdef CONFIG_IPV6_SUBTREES
980 if (SUBTREE(pn) == fn) { 1275 if (FIB6_SUBTREE(pn) == fn) {
981 BUG_TRAP(fn->fn_flags&RTN_ROOT); 1276 BUG_TRAP(fn->fn_flags&RTN_ROOT);
982 w->state = FWS_L; 1277 w->state = FWS_L;
983 continue; 1278 continue;
@@ -999,7 +1294,7 @@ int fib6_walk_continue(struct fib6_walker_t *w)
999 } 1294 }
1000} 1295}
1001 1296
1002int fib6_walk(struct fib6_walker_t *w) 1297static int fib6_walk(struct fib6_walker_t *w)
1003{ 1298{
1004 int res; 1299 int res;
1005 1300
@@ -1023,7 +1318,7 @@ static int fib6_clean_node(struct fib6_walker_t *w)
1023 res = c->func(rt, c->arg); 1318 res = c->func(rt, c->arg);
1024 if (res < 0) { 1319 if (res < 0) {
1025 w->leaf = rt; 1320 w->leaf = rt;
1026 res = fib6_del(rt, NULL, NULL, NULL); 1321 res = fib6_del(rt, NULL);
1027 if (res) { 1322 if (res) {
1028#if RT6_DEBUG >= 2 1323#if RT6_DEBUG >= 2
1029 printk(KERN_DEBUG "fib6_clean_node: del failed: rt=%p@%p err=%d\n", rt, rt->rt6i_node, res); 1324 printk(KERN_DEBUG "fib6_clean_node: del failed: rt=%p@%p err=%d\n", rt, rt->rt6i_node, res);
@@ -1049,9 +1344,9 @@ static int fib6_clean_node(struct fib6_walker_t *w)
1049 * ignoring pure split nodes) will be scanned. 1344 * ignoring pure split nodes) will be scanned.
1050 */ 1345 */
1051 1346
1052void fib6_clean_tree(struct fib6_node *root, 1347static void fib6_clean_tree(struct fib6_node *root,
1053 int (*func)(struct rt6_info *, void *arg), 1348 int (*func)(struct rt6_info *, void *arg),
1054 int prune, void *arg) 1349 int prune, void *arg)
1055{ 1350{
1056 struct fib6_cleaner_t c; 1351 struct fib6_cleaner_t c;
1057 1352
@@ -1064,6 +1359,25 @@ void fib6_clean_tree(struct fib6_node *root,
1064 fib6_walk(&c.w); 1359 fib6_walk(&c.w);
1065} 1360}
1066 1361
1362void fib6_clean_all(int (*func)(struct rt6_info *, void *arg),
1363 int prune, void *arg)
1364{
1365 struct fib6_table *table;
1366 struct hlist_node *node;
1367 unsigned int h;
1368
1369 rcu_read_lock();
1370 for (h = 0; h < FIB_TABLE_HASHSZ; h++) {
1371 hlist_for_each_entry_rcu(table, node, &fib_table_hash[h],
1372 tb6_hlist) {
1373 write_lock_bh(&table->tb6_lock);
1374 fib6_clean_tree(&table->tb6_root, func, prune, arg);
1375 write_unlock_bh(&table->tb6_lock);
1376 }
1377 }
1378 rcu_read_unlock();
1379}
1380
1067static int fib6_prune_clone(struct rt6_info *rt, void *arg) 1381static int fib6_prune_clone(struct rt6_info *rt, void *arg)
1068{ 1382{
1069 if (rt->rt6i_flags & RTF_CACHE) { 1383 if (rt->rt6i_flags & RTF_CACHE) {
@@ -1142,11 +1456,8 @@ void fib6_run_gc(unsigned long dummy)
1142 } 1456 }
1143 gc_args.more = 0; 1457 gc_args.more = 0;
1144 1458
1145
1146 write_lock_bh(&rt6_lock);
1147 ndisc_dst_gc(&gc_args.more); 1459 ndisc_dst_gc(&gc_args.more);
1148 fib6_clean_tree(&ip6_routing_table, fib6_age, 0, NULL); 1460 fib6_clean_all(fib6_age, 0, NULL);
1149 write_unlock_bh(&rt6_lock);
1150 1461
1151 if (gc_args.more) 1462 if (gc_args.more)
1152 mod_timer(&ip6_fib_timer, jiffies + ip6_rt_gc_interval); 1463 mod_timer(&ip6_fib_timer, jiffies + ip6_rt_gc_interval);
@@ -1161,10 +1472,10 @@ void __init fib6_init(void)
1161{ 1472{
1162 fib6_node_kmem = kmem_cache_create("fib6_nodes", 1473 fib6_node_kmem = kmem_cache_create("fib6_nodes",
1163 sizeof(struct fib6_node), 1474 sizeof(struct fib6_node),
1164 0, SLAB_HWCACHE_ALIGN, 1475 0, SLAB_HWCACHE_ALIGN|SLAB_PANIC,
1165 NULL, NULL); 1476 NULL, NULL);
1166 if (!fib6_node_kmem) 1477
1167 panic("cannot create fib6_nodes cache"); 1478 fib6_tables_init();
1168} 1479}
1169 1480
1170void fib6_gc_cleanup(void) 1481void fib6_gc_cleanup(void)
diff --git a/net/ipv6/ip6_input.c b/net/ipv6/ip6_input.c
index 25c2a9e03895..6b8e6d76a58b 100644
--- a/net/ipv6/ip6_input.c
+++ b/net/ipv6/ip6_input.c
@@ -111,7 +111,7 @@ int ipv6_rcv(struct sk_buff *skb, struct net_device *dev, struct packet_type *pt
111 } 111 }
112 112
113 if (hdr->nexthdr == NEXTHDR_HOP) { 113 if (hdr->nexthdr == NEXTHDR_HOP) {
114 if (ipv6_parse_hopopts(skb) < 0) { 114 if (ipv6_parse_hopopts(&skb) < 0) {
115 IP6_INC_STATS_BH(IPSTATS_MIB_INHDRERRORS); 115 IP6_INC_STATS_BH(IPSTATS_MIB_INHDRERRORS);
116 return 0; 116 return 0;
117 } 117 }
diff --git a/net/ipv6/ip6_output.c b/net/ipv6/ip6_output.c
index 4fb47a252913..66716911962e 100644
--- a/net/ipv6/ip6_output.c
+++ b/net/ipv6/ip6_output.c
@@ -308,6 +308,56 @@ static int ip6_call_ra_chain(struct sk_buff *skb, int sel)
308 return 0; 308 return 0;
309} 309}
310 310
311static int ip6_forward_proxy_check(struct sk_buff *skb)
312{
313 struct ipv6hdr *hdr = skb->nh.ipv6h;
314 u8 nexthdr = hdr->nexthdr;
315 int offset;
316
317 if (ipv6_ext_hdr(nexthdr)) {
318 offset = ipv6_skip_exthdr(skb, sizeof(*hdr), &nexthdr);
319 if (offset < 0)
320 return 0;
321 } else
322 offset = sizeof(struct ipv6hdr);
323
324 if (nexthdr == IPPROTO_ICMPV6) {
325 struct icmp6hdr *icmp6;
326
327 if (!pskb_may_pull(skb, skb->nh.raw + offset + 1 - skb->data))
328 return 0;
329
330 icmp6 = (struct icmp6hdr *)(skb->nh.raw + offset);
331
332 switch (icmp6->icmp6_type) {
333 case NDISC_ROUTER_SOLICITATION:
334 case NDISC_ROUTER_ADVERTISEMENT:
335 case NDISC_NEIGHBOUR_SOLICITATION:
336 case NDISC_NEIGHBOUR_ADVERTISEMENT:
337 case NDISC_REDIRECT:
338 /* For reaction involving unicast neighbor discovery
339 * message destined to the proxied address, pass it to
340 * input function.
341 */
342 return 1;
343 default:
344 break;
345 }
346 }
347
348 /*
349 * The proxying router can't forward traffic sent to a link-local
350 * address, so signal the sender and discard the packet. This
351 * behavior is clarified by the MIPv6 specification.
352 */
353 if (ipv6_addr_type(&hdr->daddr) & IPV6_ADDR_LINKLOCAL) {
354 dst_link_failure(skb);
355 return -1;
356 }
357
358 return 0;
359}
360
311static inline int ip6_forward_finish(struct sk_buff *skb) 361static inline int ip6_forward_finish(struct sk_buff *skb)
312{ 362{
313 return dst_output(skb); 363 return dst_output(skb);
@@ -362,6 +412,18 @@ int ip6_forward(struct sk_buff *skb)
362 return -ETIMEDOUT; 412 return -ETIMEDOUT;
363 } 413 }
364 414
415 /* XXX: idev->cnf.proxy_ndp? */
416 if (ipv6_devconf.proxy_ndp &&
417 pneigh_lookup(&nd_tbl, &hdr->daddr, skb->dev, 0)) {
418 int proxied = ip6_forward_proxy_check(skb);
419 if (proxied > 0)
420 return ip6_input(skb);
421 else if (proxied < 0) {
422 IP6_INC_STATS(IPSTATS_MIB_INDISCARDS);
423 goto drop;
424 }
425 }
426
365 if (!xfrm6_route_forward(skb)) { 427 if (!xfrm6_route_forward(skb)) {
366 IP6_INC_STATS(IPSTATS_MIB_INDISCARDS); 428 IP6_INC_STATS(IPSTATS_MIB_INDISCARDS);
367 goto drop; 429 goto drop;
@@ -475,17 +537,25 @@ int ip6_find_1stfragopt(struct sk_buff *skb, u8 **nexthdr)
475 switch (**nexthdr) { 537 switch (**nexthdr) {
476 538
477 case NEXTHDR_HOP: 539 case NEXTHDR_HOP:
540 break;
478 case NEXTHDR_ROUTING: 541 case NEXTHDR_ROUTING:
542 found_rhdr = 1;
543 break;
479 case NEXTHDR_DEST: 544 case NEXTHDR_DEST:
480 if (**nexthdr == NEXTHDR_ROUTING) found_rhdr = 1; 545#ifdef CONFIG_IPV6_MIP6
481 if (**nexthdr == NEXTHDR_DEST && found_rhdr) return offset; 546 if (ipv6_find_tlv(skb, offset, IPV6_TLV_HAO) >= 0)
482 offset += ipv6_optlen(exthdr); 547 break;
483 *nexthdr = &exthdr->nexthdr; 548#endif
484 exthdr = (struct ipv6_opt_hdr*)(skb->nh.raw + offset); 549 if (found_rhdr)
550 return offset;
485 break; 551 break;
486 default : 552 default :
487 return offset; 553 return offset;
488 } 554 }
555
556 offset += ipv6_optlen(exthdr);
557 *nexthdr = &exthdr->nexthdr;
558 exthdr = (struct ipv6_opt_hdr*)(skb->nh.raw + offset);
489 } 559 }
490 560
491 return offset; 561 return offset;
@@ -726,6 +796,14 @@ fail:
726 return err; 796 return err;
727} 797}
728 798
799static inline int ip6_rt_check(struct rt6key *rt_key,
800 struct in6_addr *fl_addr,
801 struct in6_addr *addr_cache)
802{
803 return ((rt_key->plen != 128 || !ipv6_addr_equal(fl_addr, &rt_key->addr)) &&
804 (addr_cache == NULL || !ipv6_addr_equal(fl_addr, addr_cache)));
805}
806
729static struct dst_entry *ip6_sk_dst_check(struct sock *sk, 807static struct dst_entry *ip6_sk_dst_check(struct sock *sk,
730 struct dst_entry *dst, 808 struct dst_entry *dst,
731 struct flowi *fl) 809 struct flowi *fl)
@@ -741,8 +819,8 @@ static struct dst_entry *ip6_sk_dst_check(struct sock *sk,
741 * that we do not support routing by source, TOS, 819 * that we do not support routing by source, TOS,
742 * and MSG_DONTROUTE --ANK (980726) 820 * and MSG_DONTROUTE --ANK (980726)
743 * 821 *
744 * 1. If route was host route, check that 822 * 1. ip6_rt_check(): If route was host route,
745 * cached destination is current. 823 * check that cached destination is current.
746 * If it is network route, we still may 824 * If it is network route, we still may
747 * check its validity using saved pointer 825 * check its validity using saved pointer
748 * to the last used address: daddr_cache. 826 * to the last used address: daddr_cache.
@@ -753,11 +831,11 @@ static struct dst_entry *ip6_sk_dst_check(struct sock *sk,
753 * sockets. 831 * sockets.
754 * 2. oif also should be the same. 832 * 2. oif also should be the same.
755 */ 833 */
756 if (((rt->rt6i_dst.plen != 128 || 834 if (ip6_rt_check(&rt->rt6i_dst, &fl->fl6_dst, np->daddr_cache) ||
757 !ipv6_addr_equal(&fl->fl6_dst, &rt->rt6i_dst.addr)) 835#ifdef CONFIG_IPV6_SUBTREES
758 && (np->daddr_cache == NULL || 836 ip6_rt_check(&rt->rt6i_src, &fl->fl6_src, np->saddr_cache) ||
759 !ipv6_addr_equal(&fl->fl6_dst, np->daddr_cache))) 837#endif
760 || (fl->oif && fl->oif != dst->dev->ifindex)) { 838 (fl->oif && fl->oif != dst->dev->ifindex)) {
761 dst_release(dst); 839 dst_release(dst);
762 dst = NULL; 840 dst = NULL;
763 } 841 }
@@ -866,7 +944,7 @@ static inline int ip6_ufo_append_data(struct sock *sk,
866 /* initialize protocol header pointer */ 944 /* initialize protocol header pointer */
867 skb->h.raw = skb->data + fragheaderlen; 945 skb->h.raw = skb->data + fragheaderlen;
868 946
869 skb->ip_summed = CHECKSUM_HW; 947 skb->ip_summed = CHECKSUM_PARTIAL;
870 skb->csum = 0; 948 skb->csum = 0;
871 sk->sk_sndmsg_off = 0; 949 sk->sk_sndmsg_off = 0;
872 } 950 }
@@ -963,7 +1041,7 @@ int ip6_append_data(struct sock *sk, int getfrag(void *from, char *to,
963 1041
964 hh_len = LL_RESERVED_SPACE(rt->u.dst.dev); 1042 hh_len = LL_RESERVED_SPACE(rt->u.dst.dev);
965 1043
966 fragheaderlen = sizeof(struct ipv6hdr) + (opt ? opt->opt_nflen : 0); 1044 fragheaderlen = sizeof(struct ipv6hdr) + rt->u.dst.nfheader_len + (opt ? opt->opt_nflen : 0);
967 maxfraglen = ((mtu - fragheaderlen) & ~7) + fragheaderlen - sizeof(struct frag_hdr); 1045 maxfraglen = ((mtu - fragheaderlen) & ~7) + fragheaderlen - sizeof(struct frag_hdr);
968 1046
969 if (mtu <= sizeof(struct ipv6hdr) + IPV6_MAXPLEN) { 1047 if (mtu <= sizeof(struct ipv6hdr) + IPV6_MAXPLEN) {
diff --git a/net/ipv6/ipcomp6.c b/net/ipv6/ipcomp6.c
index a81e9e9d93bd..ad9c6e824e62 100644
--- a/net/ipv6/ipcomp6.c
+++ b/net/ipv6/ipcomp6.c
@@ -212,7 +212,7 @@ static struct xfrm_state *ipcomp6_tunnel_create(struct xfrm_state *x)
212 memcpy(t->id.daddr.a6, x->id.daddr.a6, sizeof(struct in6_addr)); 212 memcpy(t->id.daddr.a6, x->id.daddr.a6, sizeof(struct in6_addr));
213 memcpy(&t->sel, &x->sel, sizeof(t->sel)); 213 memcpy(&t->sel, &x->sel, sizeof(t->sel));
214 t->props.family = AF_INET6; 214 t->props.family = AF_INET6;
215 t->props.mode = 1; 215 t->props.mode = XFRM_MODE_TUNNEL;
216 memcpy(t->props.saddr.a6, x->props.saddr.a6, sizeof(struct in6_addr)); 216 memcpy(t->props.saddr.a6, x->props.saddr.a6, sizeof(struct in6_addr));
217 217
218 if (xfrm_init_state(t)) 218 if (xfrm_init_state(t))
@@ -417,7 +417,7 @@ static int ipcomp6_init_state(struct xfrm_state *x)
417 goto out; 417 goto out;
418 418
419 x->props.header_len = 0; 419 x->props.header_len = 0;
420 if (x->props.mode) 420 if (x->props.mode == XFRM_MODE_TUNNEL)
421 x->props.header_len += sizeof(struct ipv6hdr); 421 x->props.header_len += sizeof(struct ipv6hdr);
422 422
423 mutex_lock(&ipcomp6_resource_mutex); 423 mutex_lock(&ipcomp6_resource_mutex);
@@ -429,7 +429,7 @@ static int ipcomp6_init_state(struct xfrm_state *x)
429 goto error; 429 goto error;
430 mutex_unlock(&ipcomp6_resource_mutex); 430 mutex_unlock(&ipcomp6_resource_mutex);
431 431
432 if (x->props.mode) { 432 if (x->props.mode == XFRM_MODE_TUNNEL) {
433 err = ipcomp6_tunnel_attach(x); 433 err = ipcomp6_tunnel_attach(x);
434 if (err) 434 if (err)
435 goto error_tunnel; 435 goto error_tunnel;
@@ -461,6 +461,7 @@ static struct xfrm_type ipcomp6_type =
461 .destructor = ipcomp6_destroy, 461 .destructor = ipcomp6_destroy,
462 .input = ipcomp6_input, 462 .input = ipcomp6_input,
463 .output = ipcomp6_output, 463 .output = ipcomp6_output,
464 .hdr_offset = xfrm6_find_1stfragopt,
464}; 465};
465 466
466static struct inet6_protocol ipcomp6_protocol = 467static struct inet6_protocol ipcomp6_protocol =
diff --git a/net/ipv6/ipv6_sockglue.c b/net/ipv6/ipv6_sockglue.c
index a5eaaf693abf..4f3bb7fcc8b5 100644
--- a/net/ipv6/ipv6_sockglue.c
+++ b/net/ipv6/ipv6_sockglue.c
@@ -407,8 +407,16 @@ static int do_ipv6_setsockopt(struct sock *sk, int level, int optname,
407 /* routing header option needs extra check */ 407 /* routing header option needs extra check */
408 if (optname == IPV6_RTHDR && opt->srcrt) { 408 if (optname == IPV6_RTHDR && opt->srcrt) {
409 struct ipv6_rt_hdr *rthdr = opt->srcrt; 409 struct ipv6_rt_hdr *rthdr = opt->srcrt;
410 if (rthdr->type) 410 switch (rthdr->type) {
411 case IPV6_SRCRT_TYPE_0:
412#ifdef CONFIG_IPV6_MIP6
413 case IPV6_SRCRT_TYPE_2:
414#endif
415 break;
416 default:
411 goto sticky_done; 417 goto sticky_done;
418 }
419
412 if ((rthdr->hdrlen & 1) || 420 if ((rthdr->hdrlen & 1) ||
413 (rthdr->hdrlen >> 1) != rthdr->segments_left) 421 (rthdr->hdrlen >> 1) != rthdr->segments_left)
414 goto sticky_done; 422 goto sticky_done;
diff --git a/net/ipv6/ipv6_syms.c b/net/ipv6/ipv6_syms.c
index dd4d1ce77769..0e8e0676a033 100644
--- a/net/ipv6/ipv6_syms.c
+++ b/net/ipv6/ipv6_syms.c
@@ -14,7 +14,6 @@ EXPORT_SYMBOL(ndisc_mc_map);
14EXPORT_SYMBOL(register_inet6addr_notifier); 14EXPORT_SYMBOL(register_inet6addr_notifier);
15EXPORT_SYMBOL(unregister_inet6addr_notifier); 15EXPORT_SYMBOL(unregister_inet6addr_notifier);
16EXPORT_SYMBOL(ip6_route_output); 16EXPORT_SYMBOL(ip6_route_output);
17EXPORT_SYMBOL(addrconf_lock);
18EXPORT_SYMBOL(ipv6_setsockopt); 17EXPORT_SYMBOL(ipv6_setsockopt);
19EXPORT_SYMBOL(ipv6_getsockopt); 18EXPORT_SYMBOL(ipv6_getsockopt);
20EXPORT_SYMBOL(inet6_register_protosw); 19EXPORT_SYMBOL(inet6_register_protosw);
@@ -31,6 +30,8 @@ EXPORT_SYMBOL(ipv6_chk_addr);
31EXPORT_SYMBOL(in6_dev_finish_destroy); 30EXPORT_SYMBOL(in6_dev_finish_destroy);
32#ifdef CONFIG_XFRM 31#ifdef CONFIG_XFRM
33EXPORT_SYMBOL(xfrm6_rcv); 32EXPORT_SYMBOL(xfrm6_rcv);
33EXPORT_SYMBOL(xfrm6_input_addr);
34EXPORT_SYMBOL(xfrm6_find_1stfragopt);
34#endif 35#endif
35EXPORT_SYMBOL(rt6_lookup); 36EXPORT_SYMBOL(rt6_lookup);
36EXPORT_SYMBOL(ipv6_push_nfrag_opts); 37EXPORT_SYMBOL(ipv6_push_nfrag_opts);
diff --git a/net/ipv6/mcast.c b/net/ipv6/mcast.c
index 639eb20c9f1f..3b114e3fa2f8 100644
--- a/net/ipv6/mcast.c
+++ b/net/ipv6/mcast.c
@@ -171,7 +171,7 @@ static int ip6_mc_leave_src(struct sock *sk, struct ipv6_mc_socklist *iml,
171 171
172#define IPV6_MLD_MAX_MSF 64 172#define IPV6_MLD_MAX_MSF 64
173 173
174int sysctl_mld_max_msf = IPV6_MLD_MAX_MSF; 174int sysctl_mld_max_msf __read_mostly = IPV6_MLD_MAX_MSF;
175 175
176/* 176/*
177 * socket join on multicast group 177 * socket join on multicast group
diff --git a/net/ipv6/mip6.c b/net/ipv6/mip6.c
new file mode 100644
index 000000000000..99d116caecda
--- /dev/null
+++ b/net/ipv6/mip6.c
@@ -0,0 +1,519 @@
1/*
2 * Copyright (C)2003-2006 Helsinki University of Technology
3 * Copyright (C)2003-2006 USAGI/WIDE Project
4 *
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation; either version 2 of the License, or
8 * (at your option) any later version.
9 *
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
14 *
15 * You should have received a copy of the GNU General Public License
16 * along with this program; if not, write to the Free Software
17 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
18 */
19/*
20 * Authors:
21 * Noriaki TAKAMIYA @USAGI
22 * Masahide NAKAMURA @USAGI
23 */
24
25#include <linux/config.h>
26#include <linux/module.h>
27#include <linux/skbuff.h>
28#include <linux/time.h>
29#include <linux/ipv6.h>
30#include <linux/icmpv6.h>
31#include <net/sock.h>
32#include <net/ipv6.h>
33#include <net/ip6_checksum.h>
34#include <net/xfrm.h>
35#include <net/mip6.h>
36
37static xfrm_address_t *mip6_xfrm_addr(struct xfrm_state *x, xfrm_address_t *addr)
38{
39 return x->coaddr;
40}
41
42static inline unsigned int calc_padlen(unsigned int len, unsigned int n)
43{
44 return (n - len + 16) & 0x7;
45}
46
47static inline void *mip6_padn(__u8 *data, __u8 padlen)
48{
49 if (!data)
50 return NULL;
51 if (padlen == 1) {
52 data[0] = MIP6_OPT_PAD_1;
53 } else if (padlen > 1) {
54 data[0] = MIP6_OPT_PAD_N;
55 data[1] = padlen - 2;
56 if (padlen > 2)
57 memset(data+2, 0, data[1]);
58 }
59 return data + padlen;
60}
61
62static inline void mip6_param_prob(struct sk_buff *skb, int code, int pos)
63{
64 icmpv6_send(skb, ICMPV6_PARAMPROB, code, pos, skb->dev);
65}
66
67static int mip6_mh_len(int type)
68{
69 int len = 0;
70
71 switch (type) {
72 case IP6_MH_TYPE_BRR:
73 len = 0;
74 break;
75 case IP6_MH_TYPE_HOTI:
76 case IP6_MH_TYPE_COTI:
77 case IP6_MH_TYPE_BU:
78 case IP6_MH_TYPE_BACK:
79 len = 1;
80 break;
81 case IP6_MH_TYPE_HOT:
82 case IP6_MH_TYPE_COT:
83 case IP6_MH_TYPE_BERROR:
84 len = 2;
85 break;
86 }
87 return len;
88}
89
90int mip6_mh_filter(struct sock *sk, struct sk_buff *skb)
91{
92 struct ip6_mh *mh;
93 int mhlen;
94
95 if (!pskb_may_pull(skb, (skb->h.raw - skb->data) + 8) ||
96 !pskb_may_pull(skb, (skb->h.raw - skb->data) + ((skb->h.raw[1] + 1) << 3)))
97 return -1;
98
99 mh = (struct ip6_mh *)skb->h.raw;
100
101 if (mh->ip6mh_hdrlen < mip6_mh_len(mh->ip6mh_type)) {
102 LIMIT_NETDEBUG(KERN_DEBUG "mip6: MH message too short: %d vs >=%d\n",
103 mh->ip6mh_hdrlen, mip6_mh_len(mh->ip6mh_type));
104 mip6_param_prob(skb, 0, (&mh->ip6mh_hdrlen) - skb->nh.raw);
105 return -1;
106 }
107 mhlen = (mh->ip6mh_hdrlen + 1) << 3;
108
109 if (skb->ip_summed == CHECKSUM_COMPLETE) {
110 skb->ip_summed = CHECKSUM_UNNECESSARY;
111 if (csum_ipv6_magic(&skb->nh.ipv6h->saddr,
112 &skb->nh.ipv6h->daddr,
113 mhlen, IPPROTO_MH,
114 skb->csum)) {
115 LIMIT_NETDEBUG(KERN_DEBUG "mip6: MH hw checksum failed\n");
116 skb->ip_summed = CHECKSUM_NONE;
117 }
118 }
119 if (skb->ip_summed == CHECKSUM_NONE) {
120 if (csum_ipv6_magic(&skb->nh.ipv6h->saddr,
121 &skb->nh.ipv6h->daddr,
122 mhlen, IPPROTO_MH,
123 skb_checksum(skb, 0, mhlen, 0))) {
124 LIMIT_NETDEBUG(KERN_DEBUG "mip6: MH checksum failed "
125 "[" NIP6_FMT " > " NIP6_FMT "]\n",
126 NIP6(skb->nh.ipv6h->saddr),
127 NIP6(skb->nh.ipv6h->daddr));
128 return -1;
129 }
130 skb->ip_summed = CHECKSUM_UNNECESSARY;
131 }
132
133 if (mh->ip6mh_proto != IPPROTO_NONE) {
134 LIMIT_NETDEBUG(KERN_DEBUG "mip6: MH invalid payload proto = %d\n",
135 mh->ip6mh_proto);
136 mip6_param_prob(skb, 0, (&mh->ip6mh_proto) - skb->nh.raw);
137 return -1;
138 }
139
140 return 0;
141}
142
143struct mip6_report_rate_limiter {
144 spinlock_t lock;
145 struct timeval stamp;
146 int iif;
147 struct in6_addr src;
148 struct in6_addr dst;
149};
150
151static struct mip6_report_rate_limiter mip6_report_rl = {
152 .lock = SPIN_LOCK_UNLOCKED
153};
154
155static int mip6_destopt_input(struct xfrm_state *x, struct sk_buff *skb)
156{
157 struct ipv6hdr *iph = skb->nh.ipv6h;
158 struct ipv6_destopt_hdr *destopt = (struct ipv6_destopt_hdr *)skb->data;
159
160 if (!ipv6_addr_equal(&iph->saddr, (struct in6_addr *)x->coaddr) &&
161 !ipv6_addr_any((struct in6_addr *)x->coaddr))
162 return -ENOENT;
163
164 return destopt->nexthdr;
165}
166
167/* Destination Option Header is inserted.
168 * IP Header's src address is replaced with Home Address Option in
169 * Destination Option Header.
170 */
171static int mip6_destopt_output(struct xfrm_state *x, struct sk_buff *skb)
172{
173 struct ipv6hdr *iph;
174 struct ipv6_destopt_hdr *dstopt;
175 struct ipv6_destopt_hao *hao;
176 u8 nexthdr;
177 int len;
178
179 iph = (struct ipv6hdr *)skb->data;
180 iph->payload_len = htons(skb->len - sizeof(*iph));
181
182 nexthdr = *skb->nh.raw;
183 *skb->nh.raw = IPPROTO_DSTOPTS;
184
185 dstopt = (struct ipv6_destopt_hdr *)skb->h.raw;
186 dstopt->nexthdr = nexthdr;
187
188 hao = mip6_padn((char *)(dstopt + 1),
189 calc_padlen(sizeof(*dstopt), 6));
190
191 hao->type = IPV6_TLV_HAO;
192 hao->length = sizeof(*hao) - 2;
193 BUG_TRAP(hao->length == 16);
194
195 len = ((char *)hao - (char *)dstopt) + sizeof(*hao);
196
197 memcpy(&hao->addr, &iph->saddr, sizeof(hao->addr));
198 memcpy(&iph->saddr, x->coaddr, sizeof(iph->saddr));
199
200 BUG_TRAP(len == x->props.header_len);
201 dstopt->hdrlen = (x->props.header_len >> 3) - 1;
202
203 return 0;
204}
205
206static inline int mip6_report_rl_allow(struct timeval *stamp,
207 struct in6_addr *dst,
208 struct in6_addr *src, int iif)
209{
210 int allow = 0;
211
212 spin_lock_bh(&mip6_report_rl.lock);
213 if (mip6_report_rl.stamp.tv_sec != stamp->tv_sec ||
214 mip6_report_rl.stamp.tv_usec != stamp->tv_usec ||
215 mip6_report_rl.iif != iif ||
216 !ipv6_addr_equal(&mip6_report_rl.src, src) ||
217 !ipv6_addr_equal(&mip6_report_rl.dst, dst)) {
218 mip6_report_rl.stamp.tv_sec = stamp->tv_sec;
219 mip6_report_rl.stamp.tv_usec = stamp->tv_usec;
220 mip6_report_rl.iif = iif;
221 ipv6_addr_copy(&mip6_report_rl.src, src);
222 ipv6_addr_copy(&mip6_report_rl.dst, dst);
223 allow = 1;
224 }
225 spin_unlock_bh(&mip6_report_rl.lock);
226 return allow;
227}
228
229static int mip6_destopt_reject(struct xfrm_state *x, struct sk_buff *skb, struct flowi *fl)
230{
231 struct inet6_skb_parm *opt = (struct inet6_skb_parm *)skb->cb;
232 struct ipv6_destopt_hao *hao = NULL;
233 struct xfrm_selector sel;
234 int offset;
235 struct timeval stamp;
236 int err = 0;
237
238 if (unlikely(fl->proto == IPPROTO_MH &&
239 fl->fl_mh_type <= IP6_MH_TYPE_MAX))
240 goto out;
241
242 if (likely(opt->dsthao)) {
243 offset = ipv6_find_tlv(skb, opt->dsthao, IPV6_TLV_HAO);
244 if (likely(offset >= 0))
245 hao = (struct ipv6_destopt_hao *)(skb->nh.raw + offset);
246 }
247
248 skb_get_timestamp(skb, &stamp);
249
250 if (!mip6_report_rl_allow(&stamp, &skb->nh.ipv6h->daddr,
251 hao ? &hao->addr : &skb->nh.ipv6h->saddr,
252 opt->iif))
253 goto out;
254
255 memset(&sel, 0, sizeof(sel));
256 memcpy(&sel.daddr, (xfrm_address_t *)&skb->nh.ipv6h->daddr,
257 sizeof(sel.daddr));
258 sel.prefixlen_d = 128;
259 memcpy(&sel.saddr, (xfrm_address_t *)&skb->nh.ipv6h->saddr,
260 sizeof(sel.saddr));
261 sel.prefixlen_s = 128;
262 sel.family = AF_INET6;
263 sel.proto = fl->proto;
264 sel.dport = xfrm_flowi_dport(fl);
265 if (sel.dport)
266 sel.dport_mask = ~((__u16)0);
267 sel.sport = xfrm_flowi_sport(fl);
268 if (sel.sport)
269 sel.sport_mask = ~((__u16)0);
270 sel.ifindex = fl->oif;
271
272 err = km_report(IPPROTO_DSTOPTS, &sel,
273 (hao ? (xfrm_address_t *)&hao->addr : NULL));
274
275 out:
276 return err;
277}
278
279static int mip6_destopt_offset(struct xfrm_state *x, struct sk_buff *skb,
280 u8 **nexthdr)
281{
282 u16 offset = sizeof(struct ipv6hdr);
283 struct ipv6_opt_hdr *exthdr = (struct ipv6_opt_hdr*)(skb->nh.ipv6h + 1);
284 unsigned int packet_len = skb->tail - skb->nh.raw;
285 int found_rhdr = 0;
286
287 *nexthdr = &skb->nh.ipv6h->nexthdr;
288
289 while (offset + 1 <= packet_len) {
290
291 switch (**nexthdr) {
292 case NEXTHDR_HOP:
293 break;
294 case NEXTHDR_ROUTING:
295 found_rhdr = 1;
296 break;
297 case NEXTHDR_DEST:
298 /*
299 * HAO MUST NOT appear more than once.
300 * XXX: It is better to try to find by the end of
301 * XXX: packet if HAO exists.
302 */
303 if (ipv6_find_tlv(skb, offset, IPV6_TLV_HAO) >= 0) {
304 LIMIT_NETDEBUG(KERN_WARNING "mip6: hao exists already, override\n");
305 return offset;
306 }
307
308 if (found_rhdr)
309 return offset;
310
311 break;
312 default:
313 return offset;
314 }
315
316 offset += ipv6_optlen(exthdr);
317 *nexthdr = &exthdr->nexthdr;
318 exthdr = (struct ipv6_opt_hdr*)(skb->nh.raw + offset);
319 }
320
321 return offset;
322}
323
324static int mip6_destopt_init_state(struct xfrm_state *x)
325{
326 if (x->id.spi) {
327 printk(KERN_INFO "%s: spi is not 0: %u\n", __FUNCTION__,
328 x->id.spi);
329 return -EINVAL;
330 }
331 if (x->props.mode != XFRM_MODE_ROUTEOPTIMIZATION) {
332 printk(KERN_INFO "%s: state's mode is not %u: %u\n",
333 __FUNCTION__, XFRM_MODE_ROUTEOPTIMIZATION, x->props.mode);
334 return -EINVAL;
335 }
336
337 x->props.header_len = sizeof(struct ipv6_destopt_hdr) +
338 calc_padlen(sizeof(struct ipv6_destopt_hdr), 6) +
339 sizeof(struct ipv6_destopt_hao);
340 BUG_TRAP(x->props.header_len == 24);
341
342 return 0;
343}
344
345/*
346 * Do nothing about destroying since it has no specific operation for
347 * destination options header unlike IPsec protocols.
348 */
349static void mip6_destopt_destroy(struct xfrm_state *x)
350{
351}
352
353static struct xfrm_type mip6_destopt_type =
354{
355 .description = "MIP6DESTOPT",
356 .owner = THIS_MODULE,
357 .proto = IPPROTO_DSTOPTS,
358 .flags = XFRM_TYPE_NON_FRAGMENT,
359 .init_state = mip6_destopt_init_state,
360 .destructor = mip6_destopt_destroy,
361 .input = mip6_destopt_input,
362 .output = mip6_destopt_output,
363 .reject = mip6_destopt_reject,
364 .hdr_offset = mip6_destopt_offset,
365 .local_addr = mip6_xfrm_addr,
366};
367
368static int mip6_rthdr_input(struct xfrm_state *x, struct sk_buff *skb)
369{
370 struct rt2_hdr *rt2 = (struct rt2_hdr *)skb->data;
371
372 if (!ipv6_addr_equal(&rt2->addr, (struct in6_addr *)x->coaddr) &&
373 !ipv6_addr_any((struct in6_addr *)x->coaddr))
374 return -ENOENT;
375
376 return rt2->rt_hdr.nexthdr;
377}
378
379/* Routing Header type 2 is inserted.
380 * IP Header's dst address is replaced with Routing Header's Home Address.
381 */
382static int mip6_rthdr_output(struct xfrm_state *x, struct sk_buff *skb)
383{
384 struct ipv6hdr *iph;
385 struct rt2_hdr *rt2;
386 u8 nexthdr;
387
388 iph = (struct ipv6hdr *)skb->data;
389 iph->payload_len = htons(skb->len - sizeof(*iph));
390
391 nexthdr = *skb->nh.raw;
392 *skb->nh.raw = IPPROTO_ROUTING;
393
394 rt2 = (struct rt2_hdr *)skb->h.raw;
395 rt2->rt_hdr.nexthdr = nexthdr;
396 rt2->rt_hdr.hdrlen = (x->props.header_len >> 3) - 1;
397 rt2->rt_hdr.type = IPV6_SRCRT_TYPE_2;
398 rt2->rt_hdr.segments_left = 1;
399 memset(&rt2->reserved, 0, sizeof(rt2->reserved));
400
401 BUG_TRAP(rt2->rt_hdr.hdrlen == 2);
402
403 memcpy(&rt2->addr, &iph->daddr, sizeof(rt2->addr));
404 memcpy(&iph->daddr, x->coaddr, sizeof(iph->daddr));
405
406 return 0;
407}
408
409static int mip6_rthdr_offset(struct xfrm_state *x, struct sk_buff *skb,
410 u8 **nexthdr)
411{
412 u16 offset = sizeof(struct ipv6hdr);
413 struct ipv6_opt_hdr *exthdr = (struct ipv6_opt_hdr*)(skb->nh.ipv6h + 1);
414 unsigned int packet_len = skb->tail - skb->nh.raw;
415 int found_rhdr = 0;
416
417 *nexthdr = &skb->nh.ipv6h->nexthdr;
418
419 while (offset + 1 <= packet_len) {
420
421 switch (**nexthdr) {
422 case NEXTHDR_HOP:
423 break;
424 case NEXTHDR_ROUTING:
425 if (offset + 3 <= packet_len) {
426 struct ipv6_rt_hdr *rt;
427 rt = (struct ipv6_rt_hdr *)(skb->nh.raw + offset);
428 if (rt->type != 0)
429 return offset;
430 }
431 found_rhdr = 1;
432 break;
433 case NEXTHDR_DEST:
434 if (ipv6_find_tlv(skb, offset, IPV6_TLV_HAO) >= 0)
435 return offset;
436
437 if (found_rhdr)
438 return offset;
439
440 break;
441 default:
442 return offset;
443 }
444
445 offset += ipv6_optlen(exthdr);
446 *nexthdr = &exthdr->nexthdr;
447 exthdr = (struct ipv6_opt_hdr*)(skb->nh.raw + offset);
448 }
449
450 return offset;
451}
452
453static int mip6_rthdr_init_state(struct xfrm_state *x)
454{
455 if (x->id.spi) {
456 printk(KERN_INFO "%s: spi is not 0: %u\n", __FUNCTION__,
457 x->id.spi);
458 return -EINVAL;
459 }
460 if (x->props.mode != XFRM_MODE_ROUTEOPTIMIZATION) {
461 printk(KERN_INFO "%s: state's mode is not %u: %u\n",
462 __FUNCTION__, XFRM_MODE_ROUTEOPTIMIZATION, x->props.mode);
463 return -EINVAL;
464 }
465
466 x->props.header_len = sizeof(struct rt2_hdr);
467
468 return 0;
469}
470
471/*
472 * Do nothing about destroying since it has no specific operation for routing
473 * header type 2 unlike IPsec protocols.
474 */
475static void mip6_rthdr_destroy(struct xfrm_state *x)
476{
477}
478
479static struct xfrm_type mip6_rthdr_type =
480{
481 .description = "MIP6RT",
482 .owner = THIS_MODULE,
483 .proto = IPPROTO_ROUTING,
484 .flags = XFRM_TYPE_NON_FRAGMENT,
485 .init_state = mip6_rthdr_init_state,
486 .destructor = mip6_rthdr_destroy,
487 .input = mip6_rthdr_input,
488 .output = mip6_rthdr_output,
489 .hdr_offset = mip6_rthdr_offset,
490 .remote_addr = mip6_xfrm_addr,
491};
492
493int __init mip6_init(void)
494{
495 printk(KERN_INFO "Mobile IPv6\n");
496
497 if (xfrm_register_type(&mip6_destopt_type, AF_INET6) < 0) {
498 printk(KERN_INFO "%s: can't add xfrm type(destopt)\n", __FUNCTION__);
499 goto mip6_destopt_xfrm_fail;
500 }
501 if (xfrm_register_type(&mip6_rthdr_type, AF_INET6) < 0) {
502 printk(KERN_INFO "%s: can't add xfrm type(rthdr)\n", __FUNCTION__);
503 goto mip6_rthdr_xfrm_fail;
504 }
505 return 0;
506
507 mip6_rthdr_xfrm_fail:
508 xfrm_unregister_type(&mip6_destopt_type, AF_INET6);
509 mip6_destopt_xfrm_fail:
510 return -EAGAIN;
511}
512
513void __exit mip6_fini(void)
514{
515 if (xfrm_unregister_type(&mip6_rthdr_type, AF_INET6) < 0)
516 printk(KERN_INFO "%s: can't remove xfrm type(rthdr)\n", __FUNCTION__);
517 if (xfrm_unregister_type(&mip6_destopt_type, AF_INET6) < 0)
518 printk(KERN_INFO "%s: can't remove xfrm type(destopt)\n", __FUNCTION__);
519}
diff --git a/net/ipv6/ndisc.c b/net/ipv6/ndisc.c
index b50055b9278d..0304b5fe8d6a 100644
--- a/net/ipv6/ndisc.c
+++ b/net/ipv6/ndisc.c
@@ -62,6 +62,7 @@
62#include <linux/sysctl.h> 62#include <linux/sysctl.h>
63#endif 63#endif
64 64
65#include <linux/if_addr.h>
65#include <linux/if_arp.h> 66#include <linux/if_arp.h>
66#include <linux/ipv6.h> 67#include <linux/ipv6.h>
67#include <linux/icmpv6.h> 68#include <linux/icmpv6.h>
@@ -411,7 +412,8 @@ static void pndisc_destructor(struct pneigh_entry *n)
411 */ 412 */
412 413
413static inline void ndisc_flow_init(struct flowi *fl, u8 type, 414static inline void ndisc_flow_init(struct flowi *fl, u8 type,
414 struct in6_addr *saddr, struct in6_addr *daddr) 415 struct in6_addr *saddr, struct in6_addr *daddr,
416 int oif)
415{ 417{
416 memset(fl, 0, sizeof(*fl)); 418 memset(fl, 0, sizeof(*fl));
417 ipv6_addr_copy(&fl->fl6_src, saddr); 419 ipv6_addr_copy(&fl->fl6_src, saddr);
@@ -419,6 +421,8 @@ static inline void ndisc_flow_init(struct flowi *fl, u8 type,
419 fl->proto = IPPROTO_ICMPV6; 421 fl->proto = IPPROTO_ICMPV6;
420 fl->fl_icmp_type = type; 422 fl->fl_icmp_type = type;
421 fl->fl_icmp_code = 0; 423 fl->fl_icmp_code = 0;
424 fl->oif = oif;
425 security_sk_classify_flow(ndisc_socket->sk, fl);
422} 426}
423 427
424static void ndisc_send_na(struct net_device *dev, struct neighbour *neigh, 428static void ndisc_send_na(struct net_device *dev, struct neighbour *neigh,
@@ -450,7 +454,8 @@ static void ndisc_send_na(struct net_device *dev, struct neighbour *neigh,
450 src_addr = &tmpaddr; 454 src_addr = &tmpaddr;
451 } 455 }
452 456
453 ndisc_flow_init(&fl, NDISC_NEIGHBOUR_ADVERTISEMENT, src_addr, daddr); 457 ndisc_flow_init(&fl, NDISC_NEIGHBOUR_ADVERTISEMENT, src_addr, daddr,
458 dev->ifindex);
454 459
455 dst = ndisc_dst_alloc(dev, neigh, daddr, ip6_output); 460 dst = ndisc_dst_alloc(dev, neigh, daddr, ip6_output);
456 if (!dst) 461 if (!dst)
@@ -491,7 +496,7 @@ static void ndisc_send_na(struct net_device *dev, struct neighbour *neigh,
491 msg->icmph.icmp6_unused = 0; 496 msg->icmph.icmp6_unused = 0;
492 msg->icmph.icmp6_router = router; 497 msg->icmph.icmp6_router = router;
493 msg->icmph.icmp6_solicited = solicited; 498 msg->icmph.icmp6_solicited = solicited;
494 msg->icmph.icmp6_override = !!override; 499 msg->icmph.icmp6_override = override;
495 500
496 /* Set the target address. */ 501 /* Set the target address. */
497 ipv6_addr_copy(&msg->target, solicited_addr); 502 ipv6_addr_copy(&msg->target, solicited_addr);
@@ -540,7 +545,8 @@ void ndisc_send_ns(struct net_device *dev, struct neighbour *neigh,
540 saddr = &addr_buf; 545 saddr = &addr_buf;
541 } 546 }
542 547
543 ndisc_flow_init(&fl, NDISC_NEIGHBOUR_SOLICITATION, saddr, daddr); 548 ndisc_flow_init(&fl, NDISC_NEIGHBOUR_SOLICITATION, saddr, daddr,
549 dev->ifindex);
544 550
545 dst = ndisc_dst_alloc(dev, neigh, daddr, ip6_output); 551 dst = ndisc_dst_alloc(dev, neigh, daddr, ip6_output);
546 if (!dst) 552 if (!dst)
@@ -615,7 +621,8 @@ void ndisc_send_rs(struct net_device *dev, struct in6_addr *saddr,
615 int len; 621 int len;
616 int err; 622 int err;
617 623
618 ndisc_flow_init(&fl, NDISC_ROUTER_SOLICITATION, saddr, daddr); 624 ndisc_flow_init(&fl, NDISC_ROUTER_SOLICITATION, saddr, daddr,
625 dev->ifindex);
619 626
620 dst = ndisc_dst_alloc(dev, NULL, daddr, ip6_output); 627 dst = ndisc_dst_alloc(dev, NULL, daddr, ip6_output);
621 if (!dst) 628 if (!dst)
@@ -729,8 +736,10 @@ static void ndisc_recv_ns(struct sk_buff *skb)
729 struct inet6_ifaddr *ifp; 736 struct inet6_ifaddr *ifp;
730 struct inet6_dev *idev = NULL; 737 struct inet6_dev *idev = NULL;
731 struct neighbour *neigh; 738 struct neighbour *neigh;
739 struct pneigh_entry *pneigh = NULL;
732 int dad = ipv6_addr_any(saddr); 740 int dad = ipv6_addr_any(saddr);
733 int inc; 741 int inc;
742 int is_router;
734 743
735 if (ipv6_addr_is_multicast(&msg->target)) { 744 if (ipv6_addr_is_multicast(&msg->target)) {
736 ND_PRINTK2(KERN_WARNING 745 ND_PRINTK2(KERN_WARNING
@@ -815,7 +824,9 @@ static void ndisc_recv_ns(struct sk_buff *skb)
815 824
816 if (ipv6_chk_acast_addr(dev, &msg->target) || 825 if (ipv6_chk_acast_addr(dev, &msg->target) ||
817 (idev->cnf.forwarding && 826 (idev->cnf.forwarding &&
818 pneigh_lookup(&nd_tbl, &msg->target, dev, 0))) { 827 (ipv6_devconf.proxy_ndp || idev->cnf.proxy_ndp) &&
828 (pneigh = pneigh_lookup(&nd_tbl,
829 &msg->target, dev, 0)) != NULL)) {
819 if (!(NEIGH_CB(skb)->flags & LOCALLY_ENQUEUED) && 830 if (!(NEIGH_CB(skb)->flags & LOCALLY_ENQUEUED) &&
820 skb->pkt_type != PACKET_HOST && 831 skb->pkt_type != PACKET_HOST &&
821 inc != 0 && 832 inc != 0 &&
@@ -836,12 +847,14 @@ static void ndisc_recv_ns(struct sk_buff *skb)
836 goto out; 847 goto out;
837 } 848 }
838 849
850 is_router = !!(pneigh ? pneigh->flags & NTF_ROUTER : idev->cnf.forwarding);
851
839 if (dad) { 852 if (dad) {
840 struct in6_addr maddr; 853 struct in6_addr maddr;
841 854
842 ipv6_addr_all_nodes(&maddr); 855 ipv6_addr_all_nodes(&maddr);
843 ndisc_send_na(dev, NULL, &maddr, &msg->target, 856 ndisc_send_na(dev, NULL, &maddr, &msg->target,
844 idev->cnf.forwarding, 0, (ifp != NULL), 1); 857 is_router, 0, (ifp != NULL), 1);
845 goto out; 858 goto out;
846 } 859 }
847 860
@@ -862,7 +875,7 @@ static void ndisc_recv_ns(struct sk_buff *skb)
862 NEIGH_UPDATE_F_OVERRIDE); 875 NEIGH_UPDATE_F_OVERRIDE);
863 if (neigh || !dev->hard_header) { 876 if (neigh || !dev->hard_header) {
864 ndisc_send_na(dev, neigh, saddr, &msg->target, 877 ndisc_send_na(dev, neigh, saddr, &msg->target,
865 idev->cnf.forwarding, 878 is_router,
866 1, (ifp != NULL && inc), inc); 879 1, (ifp != NULL && inc), inc);
867 if (neigh) 880 if (neigh)
868 neigh_release(neigh); 881 neigh_release(neigh);
@@ -945,6 +958,20 @@ static void ndisc_recv_na(struct sk_buff *skb)
945 if (neigh->nud_state & NUD_FAILED) 958 if (neigh->nud_state & NUD_FAILED)
946 goto out; 959 goto out;
947 960
961 /*
962 * Don't update the neighbor cache entry on a proxy NA from
963 * ourselves because either the proxied node is off link or it
964 * has already sent a NA to us.
965 */
966 if (lladdr && !memcmp(lladdr, dev->dev_addr, dev->addr_len) &&
967 ipv6_devconf.forwarding && ipv6_devconf.proxy_ndp &&
968 pneigh_lookup(&nd_tbl, &msg->target, dev, 0)) {
969 /* XXX: idev->cnf.prixy_ndp */
970 WARN_ON(skb->dst != NULL &&
971 ((struct rt6_info *)skb->dst)->rt6i_idev);
972 goto out;
973 }
974
948 neigh_update(neigh, lladdr, 975 neigh_update(neigh, lladdr,
949 msg->icmph.icmp6_solicited ? NUD_REACHABLE : NUD_STALE, 976 msg->icmph.icmp6_solicited ? NUD_REACHABLE : NUD_STALE,
950 NEIGH_UPDATE_F_WEAK_OVERRIDE| 977 NEIGH_UPDATE_F_WEAK_OVERRIDE|
@@ -959,7 +986,7 @@ static void ndisc_recv_na(struct sk_buff *skb)
959 struct rt6_info *rt; 986 struct rt6_info *rt;
960 rt = rt6_get_dflt_router(saddr, dev); 987 rt = rt6_get_dflt_router(saddr, dev);
961 if (rt) 988 if (rt)
962 ip6_del_rt(rt, NULL, NULL, NULL); 989 ip6_del_rt(rt);
963 } 990 }
964 991
965out: 992out:
@@ -1112,7 +1139,7 @@ static void ndisc_router_discovery(struct sk_buff *skb)
1112 1139
1113 if (rt && lifetime == 0) { 1140 if (rt && lifetime == 0) {
1114 neigh_clone(neigh); 1141 neigh_clone(neigh);
1115 ip6_del_rt(rt, NULL, NULL, NULL); 1142 ip6_del_rt(rt);
1116 rt = NULL; 1143 rt = NULL;
1117 } 1144 }
1118 1145
@@ -1344,7 +1371,8 @@ static void ndisc_redirect_rcv(struct sk_buff *skb)
1344 1371
1345 neigh = __neigh_lookup(&nd_tbl, target, skb->dev, 1); 1372 neigh = __neigh_lookup(&nd_tbl, target, skb->dev, 1);
1346 if (neigh) { 1373 if (neigh) {
1347 rt6_redirect(dest, &skb->nh.ipv6h->saddr, neigh, lladdr, 1374 rt6_redirect(dest, &skb->nh.ipv6h->daddr,
1375 &skb->nh.ipv6h->saddr, neigh, lladdr,
1348 on_link); 1376 on_link);
1349 neigh_release(neigh); 1377 neigh_release(neigh);
1350 } 1378 }
@@ -1380,7 +1408,8 @@ void ndisc_send_redirect(struct sk_buff *skb, struct neighbour *neigh,
1380 return; 1408 return;
1381 } 1409 }
1382 1410
1383 ndisc_flow_init(&fl, NDISC_REDIRECT, &saddr_buf, &skb->nh.ipv6h->saddr); 1411 ndisc_flow_init(&fl, NDISC_REDIRECT, &saddr_buf, &skb->nh.ipv6h->saddr,
1412 dev->ifindex);
1384 1413
1385 dst = ip6_route_output(NULL, &fl); 1414 dst = ip6_route_output(NULL, &fl);
1386 if (dst == NULL) 1415 if (dst == NULL)
diff --git a/net/ipv6/netfilter.c b/net/ipv6/netfilter.c
index 395a417ba955..580b1aba6722 100644
--- a/net/ipv6/netfilter.c
+++ b/net/ipv6/netfilter.c
@@ -87,7 +87,7 @@ unsigned int nf_ip6_checksum(struct sk_buff *skb, unsigned int hook,
87 unsigned int csum = 0; 87 unsigned int csum = 0;
88 88
89 switch (skb->ip_summed) { 89 switch (skb->ip_summed) {
90 case CHECKSUM_HW: 90 case CHECKSUM_COMPLETE:
91 if (hook != NF_IP6_PRE_ROUTING && hook != NF_IP6_LOCAL_IN) 91 if (hook != NF_IP6_PRE_ROUTING && hook != NF_IP6_LOCAL_IN)
92 break; 92 break;
93 if (!csum_ipv6_magic(&ip6h->saddr, &ip6h->daddr, 93 if (!csum_ipv6_magic(&ip6h->saddr, &ip6h->daddr,
diff --git a/net/ipv6/netfilter/Makefile b/net/ipv6/netfilter/Makefile
index eeeb57d4c9c5..ac1dfebde175 100644
--- a/net/ipv6/netfilter/Makefile
+++ b/net/ipv6/netfilter/Makefile
@@ -5,7 +5,7 @@
5# Link order matters here. 5# Link order matters here.
6obj-$(CONFIG_IP6_NF_IPTABLES) += ip6_tables.o 6obj-$(CONFIG_IP6_NF_IPTABLES) += ip6_tables.o
7obj-$(CONFIG_IP6_NF_MATCH_RT) += ip6t_rt.o 7obj-$(CONFIG_IP6_NF_MATCH_RT) += ip6t_rt.o
8obj-$(CONFIG_IP6_NF_MATCH_OPTS) += ip6t_hbh.o ip6t_dst.o 8obj-$(CONFIG_IP6_NF_MATCH_OPTS) += ip6t_hbh.o
9obj-$(CONFIG_IP6_NF_MATCH_IPV6HEADER) += ip6t_ipv6header.o 9obj-$(CONFIG_IP6_NF_MATCH_IPV6HEADER) += ip6t_ipv6header.o
10obj-$(CONFIG_IP6_NF_MATCH_FRAG) += ip6t_frag.o 10obj-$(CONFIG_IP6_NF_MATCH_FRAG) += ip6t_frag.o
11obj-$(CONFIG_IP6_NF_MATCH_AH) += ip6t_ah.o 11obj-$(CONFIG_IP6_NF_MATCH_AH) += ip6t_ah.o
diff --git a/net/ipv6/netfilter/ip6_queue.c b/net/ipv6/netfilter/ip6_queue.c
index 968a14be0d05..9510c24ca8d2 100644
--- a/net/ipv6/netfilter/ip6_queue.c
+++ b/net/ipv6/netfilter/ip6_queue.c
@@ -56,15 +56,15 @@ struct ipq_queue_entry {
56 56
57typedef int (*ipq_cmpfn)(struct ipq_queue_entry *, unsigned long); 57typedef int (*ipq_cmpfn)(struct ipq_queue_entry *, unsigned long);
58 58
59static unsigned char copy_mode = IPQ_COPY_NONE; 59static unsigned char copy_mode __read_mostly = IPQ_COPY_NONE;
60static unsigned int queue_maxlen = IPQ_QMAX_DEFAULT; 60static unsigned int queue_maxlen __read_mostly = IPQ_QMAX_DEFAULT;
61static DEFINE_RWLOCK(queue_lock); 61static DEFINE_RWLOCK(queue_lock);
62static int peer_pid; 62static int peer_pid __read_mostly;
63static unsigned int copy_range; 63static unsigned int copy_range __read_mostly;
64static unsigned int queue_total; 64static unsigned int queue_total;
65static unsigned int queue_dropped = 0; 65static unsigned int queue_dropped = 0;
66static unsigned int queue_user_dropped = 0; 66static unsigned int queue_user_dropped = 0;
67static struct sock *ipqnl; 67static struct sock *ipqnl __read_mostly;
68static LIST_HEAD(queue_list); 68static LIST_HEAD(queue_list);
69static DEFINE_MUTEX(ipqnl_mutex); 69static DEFINE_MUTEX(ipqnl_mutex);
70 70
@@ -206,9 +206,9 @@ ipq_build_packet_message(struct ipq_queue_entry *entry, int *errp)
206 break; 206 break;
207 207
208 case IPQ_COPY_PACKET: 208 case IPQ_COPY_PACKET:
209 if (entry->skb->ip_summed == CHECKSUM_HW && 209 if ((entry->skb->ip_summed == CHECKSUM_PARTIAL ||
210 (*errp = skb_checksum_help(entry->skb, 210 entry->skb->ip_summed == CHECKSUM_COMPLETE) &&
211 entry->info->outdev == NULL))) { 211 (*errp = skb_checksum_help(entry->skb))) {
212 read_unlock_bh(&queue_lock); 212 read_unlock_bh(&queue_lock);
213 return NULL; 213 return NULL;
214 } 214 }
diff --git a/net/ipv6/netfilter/ip6_tables.c b/net/ipv6/netfilter/ip6_tables.c
index c9d6b23cd3f7..4ab368fa0b8f 100644
--- a/net/ipv6/netfilter/ip6_tables.c
+++ b/net/ipv6/netfilter/ip6_tables.c
@@ -70,9 +70,6 @@ do { \
70#define IP_NF_ASSERT(x) 70#define IP_NF_ASSERT(x)
71#endif 71#endif
72 72
73
74#include <linux/netfilter_ipv4/listhelp.h>
75
76#if 0 73#if 0
77/* All the better to debug you with... */ 74/* All the better to debug you with... */
78#define static 75#define static
@@ -220,8 +217,7 @@ ip6t_error(struct sk_buff **pskb,
220 const struct net_device *out, 217 const struct net_device *out,
221 unsigned int hooknum, 218 unsigned int hooknum,
222 const struct xt_target *target, 219 const struct xt_target *target,
223 const void *targinfo, 220 const void *targinfo)
224 void *userinfo)
225{ 221{
226 if (net_ratelimit()) 222 if (net_ratelimit())
227 printk("ip6_tables: error: `%s'\n", (char *)targinfo); 223 printk("ip6_tables: error: `%s'\n", (char *)targinfo);
@@ -258,8 +254,7 @@ ip6t_do_table(struct sk_buff **pskb,
258 unsigned int hook, 254 unsigned int hook,
259 const struct net_device *in, 255 const struct net_device *in,
260 const struct net_device *out, 256 const struct net_device *out,
261 struct xt_table *table, 257 struct xt_table *table)
262 void *userdata)
263{ 258{
264 static const char nulldevname[IFNAMSIZ] __attribute__((aligned(sizeof(long)))); 259 static const char nulldevname[IFNAMSIZ] __attribute__((aligned(sizeof(long))));
265 int offset = 0; 260 int offset = 0;
@@ -349,8 +344,7 @@ ip6t_do_table(struct sk_buff **pskb,
349 in, out, 344 in, out,
350 hook, 345 hook,
351 t->u.kernel.target, 346 t->u.kernel.target,
352 t->data, 347 t->data);
353 userdata);
354 348
355#ifdef CONFIG_NETFILTER_DEBUG 349#ifdef CONFIG_NETFILTER_DEBUG
356 if (((struct ip6t_entry *)table_base)->comefrom 350 if (((struct ip6t_entry *)table_base)->comefrom
@@ -507,8 +501,7 @@ cleanup_match(struct ip6t_entry_match *m, unsigned int *i)
507 return 1; 501 return 1;
508 502
509 if (m->u.kernel.match->destroy) 503 if (m->u.kernel.match->destroy)
510 m->u.kernel.match->destroy(m->u.kernel.match, m->data, 504 m->u.kernel.match->destroy(m->u.kernel.match, m->data);
511 m->u.match_size - sizeof(*m));
512 module_put(m->u.kernel.match->me); 505 module_put(m->u.kernel.match->me);
513 return 0; 506 return 0;
514} 507}
@@ -561,7 +554,6 @@ check_match(struct ip6t_entry_match *m,
561 554
562 if (m->u.kernel.match->checkentry 555 if (m->u.kernel.match->checkentry
563 && !m->u.kernel.match->checkentry(name, ipv6, match, m->data, 556 && !m->u.kernel.match->checkentry(name, ipv6, match, m->data,
564 m->u.match_size - sizeof(*m),
565 hookmask)) { 557 hookmask)) {
566 duprintf("ip_tables: check failed for `%s'.\n", 558 duprintf("ip_tables: check failed for `%s'.\n",
567 m->u.kernel.match->name); 559 m->u.kernel.match->name);
@@ -618,12 +610,10 @@ check_entry(struct ip6t_entry *e, const char *name, unsigned int size,
618 if (t->u.kernel.target == &ip6t_standard_target) { 610 if (t->u.kernel.target == &ip6t_standard_target) {
619 if (!standard_check(t, size)) { 611 if (!standard_check(t, size)) {
620 ret = -EINVAL; 612 ret = -EINVAL;
621 goto cleanup_matches; 613 goto err;
622 } 614 }
623 } else if (t->u.kernel.target->checkentry 615 } else if (t->u.kernel.target->checkentry
624 && !t->u.kernel.target->checkentry(name, e, target, t->data, 616 && !t->u.kernel.target->checkentry(name, e, target, t->data,
625 t->u.target_size
626 - sizeof(*t),
627 e->comefrom)) { 617 e->comefrom)) {
628 duprintf("ip_tables: check failed for `%s'.\n", 618 duprintf("ip_tables: check failed for `%s'.\n",
629 t->u.kernel.target->name); 619 t->u.kernel.target->name);
@@ -695,8 +685,7 @@ cleanup_entry(struct ip6t_entry *e, unsigned int *i)
695 IP6T_MATCH_ITERATE(e, cleanup_match, NULL); 685 IP6T_MATCH_ITERATE(e, cleanup_match, NULL);
696 t = ip6t_get_target(e); 686 t = ip6t_get_target(e);
697 if (t->u.kernel.target->destroy) 687 if (t->u.kernel.target->destroy)
698 t->u.kernel.target->destroy(t->u.kernel.target, t->data, 688 t->u.kernel.target->destroy(t->u.kernel.target, t->data);
699 t->u.target_size - sizeof(*t));
700 module_put(t->u.kernel.target->me); 689 module_put(t->u.kernel.target->me);
701 return 0; 690 return 0;
702} 691}
@@ -1352,7 +1341,6 @@ icmp6_checkentry(const char *tablename,
1352 const void *entry, 1341 const void *entry,
1353 const struct xt_match *match, 1342 const struct xt_match *match,
1354 void *matchinfo, 1343 void *matchinfo,
1355 unsigned int matchsize,
1356 unsigned int hook_mask) 1344 unsigned int hook_mask)
1357{ 1345{
1358 const struct ip6t_icmp *icmpinfo = matchinfo; 1346 const struct ip6t_icmp *icmpinfo = matchinfo;
diff --git a/net/ipv6/netfilter/ip6t_HL.c b/net/ipv6/netfilter/ip6t_HL.c
index b8eff8ee69b1..435750f664dd 100644
--- a/net/ipv6/netfilter/ip6t_HL.c
+++ b/net/ipv6/netfilter/ip6t_HL.c
@@ -22,11 +22,10 @@ static unsigned int ip6t_hl_target(struct sk_buff **pskb,
22 const struct net_device *out, 22 const struct net_device *out,
23 unsigned int hooknum, 23 unsigned int hooknum,
24 const struct xt_target *target, 24 const struct xt_target *target,
25 const void *targinfo, void *userinfo) 25 const void *targinfo)
26{ 26{
27 struct ipv6hdr *ip6h; 27 struct ipv6hdr *ip6h;
28 const struct ip6t_HL_info *info = targinfo; 28 const struct ip6t_HL_info *info = targinfo;
29 u_int16_t diffs[2];
30 int new_hl; 29 int new_hl;
31 30
32 if (!skb_make_writable(pskb, (*pskb)->len)) 31 if (!skb_make_writable(pskb, (*pskb)->len))
@@ -53,11 +52,8 @@ static unsigned int ip6t_hl_target(struct sk_buff **pskb,
53 break; 52 break;
54 } 53 }
55 54
56 if (new_hl != ip6h->hop_limit) { 55 if (new_hl != ip6h->hop_limit)
57 diffs[0] = htons(((unsigned)ip6h->hop_limit) << 8) ^ 0xFFFF;
58 ip6h->hop_limit = new_hl; 56 ip6h->hop_limit = new_hl;
59 diffs[1] = htons(((unsigned)ip6h->hop_limit) << 8);
60 }
61 57
62 return IP6T_CONTINUE; 58 return IP6T_CONTINUE;
63} 59}
@@ -66,7 +62,6 @@ static int ip6t_hl_checkentry(const char *tablename,
66 const void *entry, 62 const void *entry,
67 const struct xt_target *target, 63 const struct xt_target *target,
68 void *targinfo, 64 void *targinfo,
69 unsigned int targinfosize,
70 unsigned int hook_mask) 65 unsigned int hook_mask)
71{ 66{
72 struct ip6t_HL_info *info = targinfo; 67 struct ip6t_HL_info *info = targinfo;
diff --git a/net/ipv6/netfilter/ip6t_LOG.c b/net/ipv6/netfilter/ip6t_LOG.c
index 73c6300109d6..0cf537d30185 100644
--- a/net/ipv6/netfilter/ip6t_LOG.c
+++ b/net/ipv6/netfilter/ip6t_LOG.c
@@ -427,8 +427,7 @@ ip6t_log_target(struct sk_buff **pskb,
427 const struct net_device *out, 427 const struct net_device *out,
428 unsigned int hooknum, 428 unsigned int hooknum,
429 const struct xt_target *target, 429 const struct xt_target *target,
430 const void *targinfo, 430 const void *targinfo)
431 void *userinfo)
432{ 431{
433 const struct ip6t_log_info *loginfo = targinfo; 432 const struct ip6t_log_info *loginfo = targinfo;
434 struct nf_loginfo li; 433 struct nf_loginfo li;
@@ -452,7 +451,6 @@ static int ip6t_log_checkentry(const char *tablename,
452 const void *entry, 451 const void *entry,
453 const struct xt_target *target, 452 const struct xt_target *target,
454 void *targinfo, 453 void *targinfo,
455 unsigned int targinfosize,
456 unsigned int hook_mask) 454 unsigned int hook_mask)
457{ 455{
458 const struct ip6t_log_info *loginfo = targinfo; 456 const struct ip6t_log_info *loginfo = targinfo;
diff --git a/net/ipv6/netfilter/ip6t_REJECT.c b/net/ipv6/netfilter/ip6t_REJECT.c
index 8629ba195d2d..311eae82feb3 100644
--- a/net/ipv6/netfilter/ip6t_REJECT.c
+++ b/net/ipv6/netfilter/ip6t_REJECT.c
@@ -96,6 +96,7 @@ static void send_reset(struct sk_buff *oldskb)
96 ipv6_addr_copy(&fl.fl6_dst, &oip6h->saddr); 96 ipv6_addr_copy(&fl.fl6_dst, &oip6h->saddr);
97 fl.fl_ip_sport = otcph.dest; 97 fl.fl_ip_sport = otcph.dest;
98 fl.fl_ip_dport = otcph.source; 98 fl.fl_ip_dport = otcph.source;
99 security_skb_classify_flow(oldskb, &fl);
99 dst = ip6_route_output(NULL, &fl); 100 dst = ip6_route_output(NULL, &fl);
100 if (dst == NULL) 101 if (dst == NULL)
101 return; 102 return;
@@ -179,8 +180,7 @@ static unsigned int reject6_target(struct sk_buff **pskb,
179 const struct net_device *out, 180 const struct net_device *out,
180 unsigned int hooknum, 181 unsigned int hooknum,
181 const struct xt_target *target, 182 const struct xt_target *target,
182 const void *targinfo, 183 const void *targinfo)
183 void *userinfo)
184{ 184{
185 const struct ip6t_reject_info *reject = targinfo; 185 const struct ip6t_reject_info *reject = targinfo;
186 186
@@ -223,7 +223,6 @@ static int check(const char *tablename,
223 const void *entry, 223 const void *entry,
224 const struct xt_target *target, 224 const struct xt_target *target,
225 void *targinfo, 225 void *targinfo,
226 unsigned int targinfosize,
227 unsigned int hook_mask) 226 unsigned int hook_mask)
228{ 227{
229 const struct ip6t_reject_info *rejinfo = targinfo; 228 const struct ip6t_reject_info *rejinfo = targinfo;
@@ -256,9 +255,7 @@ static struct ip6t_target ip6t_reject_reg = {
256 255
257static int __init ip6t_reject_init(void) 256static int __init ip6t_reject_init(void)
258{ 257{
259 if (ip6t_register_target(&ip6t_reject_reg)) 258 return ip6t_register_target(&ip6t_reject_reg);
260 return -EINVAL;
261 return 0;
262} 259}
263 260
264static void __exit ip6t_reject_fini(void) 261static void __exit ip6t_reject_fini(void)
diff --git a/net/ipv6/netfilter/ip6t_ah.c b/net/ipv6/netfilter/ip6t_ah.c
index 2f7bb20c758b..ec1b1608156c 100644
--- a/net/ipv6/netfilter/ip6t_ah.c
+++ b/net/ipv6/netfilter/ip6t_ah.c
@@ -102,7 +102,6 @@ checkentry(const char *tablename,
102 const void *entry, 102 const void *entry,
103 const struct xt_match *match, 103 const struct xt_match *match,
104 void *matchinfo, 104 void *matchinfo,
105 unsigned int matchinfosize,
106 unsigned int hook_mask) 105 unsigned int hook_mask)
107{ 106{
108 const struct ip6t_ah *ahinfo = matchinfo; 107 const struct ip6t_ah *ahinfo = matchinfo;
diff --git a/net/ipv6/netfilter/ip6t_dst.c b/net/ipv6/netfilter/ip6t_dst.c
deleted file mode 100644
index 9422413d0571..000000000000
--- a/net/ipv6/netfilter/ip6t_dst.c
+++ /dev/null
@@ -1,220 +0,0 @@
1/* Kernel module to match Hop-by-Hop and Destination parameters. */
2
3/* (C) 2001-2002 Andras Kis-Szabo <kisza@sch.bme.hu>
4 *
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License version 2 as
7 * published by the Free Software Foundation.
8 */
9
10#include <linux/module.h>
11#include <linux/skbuff.h>
12#include <linux/ipv6.h>
13#include <linux/types.h>
14#include <net/checksum.h>
15#include <net/ipv6.h>
16
17#include <asm/byteorder.h>
18
19#include <linux/netfilter_ipv6/ip6_tables.h>
20#include <linux/netfilter_ipv6/ip6t_opts.h>
21
22#define HOPBYHOP 0
23
24MODULE_LICENSE("GPL");
25#if HOPBYHOP
26MODULE_DESCRIPTION("IPv6 HbH match");
27#else
28MODULE_DESCRIPTION("IPv6 DST match");
29#endif
30MODULE_AUTHOR("Andras Kis-Szabo <kisza@sch.bme.hu>");
31
32#if 0
33#define DEBUGP printk
34#else
35#define DEBUGP(format, args...)
36#endif
37
38/*
39 * (Type & 0xC0) >> 6
40 * 0 -> ignorable
41 * 1 -> must drop the packet
42 * 2 -> send ICMP PARM PROB regardless and drop packet
43 * 3 -> Send ICMP if not a multicast address and drop packet
44 * (Type & 0x20) >> 5
45 * 0 -> invariant
46 * 1 -> can change the routing
47 * (Type & 0x1F) Type
48 * 0 -> Pad1 (only 1 byte!)
49 * 1 -> PadN LENGTH info (total length = length + 2)
50 * C0 | 2 -> JUMBO 4 x x x x ( xxxx > 64k )
51 * 5 -> RTALERT 2 x x
52 */
53
54static int
55match(const struct sk_buff *skb,
56 const struct net_device *in,
57 const struct net_device *out,
58 const struct xt_match *match,
59 const void *matchinfo,
60 int offset,
61 unsigned int protoff,
62 int *hotdrop)
63{
64 struct ipv6_opt_hdr _optsh, *oh;
65 const struct ip6t_opts *optinfo = matchinfo;
66 unsigned int temp;
67 unsigned int ptr;
68 unsigned int hdrlen = 0;
69 unsigned int ret = 0;
70 u8 _opttype, *tp = NULL;
71 u8 _optlen, *lp = NULL;
72 unsigned int optlen;
73
74#if HOPBYHOP
75 if (ipv6_find_hdr(skb, &ptr, NEXTHDR_HOP, NULL) < 0)
76#else
77 if (ipv6_find_hdr(skb, &ptr, NEXTHDR_DEST, NULL) < 0)
78#endif
79 return 0;
80
81 oh = skb_header_pointer(skb, ptr, sizeof(_optsh), &_optsh);
82 if (oh == NULL) {
83 *hotdrop = 1;
84 return 0;
85 }
86
87 hdrlen = ipv6_optlen(oh);
88 if (skb->len - ptr < hdrlen) {
89 /* Packet smaller than it's length field */
90 return 0;
91 }
92
93 DEBUGP("IPv6 OPTS LEN %u %u ", hdrlen, oh->hdrlen);
94
95 DEBUGP("len %02X %04X %02X ",
96 optinfo->hdrlen, hdrlen,
97 (!(optinfo->flags & IP6T_OPTS_LEN) ||
98 ((optinfo->hdrlen == hdrlen) ^
99 !!(optinfo->invflags & IP6T_OPTS_INV_LEN))));
100
101 ret = (oh != NULL) &&
102 (!(optinfo->flags & IP6T_OPTS_LEN) ||
103 ((optinfo->hdrlen == hdrlen) ^
104 !!(optinfo->invflags & IP6T_OPTS_INV_LEN)));
105
106 ptr += 2;
107 hdrlen -= 2;
108 if (!(optinfo->flags & IP6T_OPTS_OPTS)) {
109 return ret;
110 } else if (optinfo->flags & IP6T_OPTS_NSTRICT) {
111 DEBUGP("Not strict - not implemented");
112 } else {
113 DEBUGP("Strict ");
114 DEBUGP("#%d ", optinfo->optsnr);
115 for (temp = 0; temp < optinfo->optsnr; temp++) {
116 /* type field exists ? */
117 if (hdrlen < 1)
118 break;
119 tp = skb_header_pointer(skb, ptr, sizeof(_opttype),
120 &_opttype);
121 if (tp == NULL)
122 break;
123
124 /* Type check */
125 if (*tp != (optinfo->opts[temp] & 0xFF00) >> 8) {
126 DEBUGP("Tbad %02X %02X\n",
127 *tp,
128 (optinfo->opts[temp] & 0xFF00) >> 8);
129 return 0;
130 } else {
131 DEBUGP("Tok ");
132 }
133 /* Length check */
134 if (*tp) {
135 u16 spec_len;
136
137 /* length field exists ? */
138 if (hdrlen < 2)
139 break;
140 lp = skb_header_pointer(skb, ptr + 1,
141 sizeof(_optlen),
142 &_optlen);
143 if (lp == NULL)
144 break;
145 spec_len = optinfo->opts[temp] & 0x00FF;
146
147 if (spec_len != 0x00FF && spec_len != *lp) {
148 DEBUGP("Lbad %02X %04X\n", *lp,
149 spec_len);
150 return 0;
151 }
152 DEBUGP("Lok ");
153 optlen = *lp + 2;
154 } else {
155 DEBUGP("Pad1\n");
156 optlen = 1;
157 }
158
159 /* Step to the next */
160 DEBUGP("len%04X \n", optlen);
161
162 if ((ptr > skb->len - optlen || hdrlen < optlen) &&
163 (temp < optinfo->optsnr - 1)) {
164 DEBUGP("new pointer is too large! \n");
165 break;
166 }
167 ptr += optlen;
168 hdrlen -= optlen;
169 }
170 if (temp == optinfo->optsnr)
171 return ret;
172 else
173 return 0;
174 }
175
176 return 0;
177}
178
179/* Called when user tries to insert an entry of this type. */
180static int
181checkentry(const char *tablename,
182 const void *info,
183 const struct xt_match *match,
184 void *matchinfo,
185 unsigned int matchinfosize,
186 unsigned int hook_mask)
187{
188 const struct ip6t_opts *optsinfo = matchinfo;
189
190 if (optsinfo->invflags & ~IP6T_OPTS_INV_MASK) {
191 DEBUGP("ip6t_opts: unknown flags %X\n", optsinfo->invflags);
192 return 0;
193 }
194 return 1;
195}
196
197static struct ip6t_match opts_match = {
198#if HOPBYHOP
199 .name = "hbh",
200#else
201 .name = "dst",
202#endif
203 .match = match,
204 .matchsize = sizeof(struct ip6t_opts),
205 .checkentry = checkentry,
206 .me = THIS_MODULE,
207};
208
209static int __init ip6t_dst_init(void)
210{
211 return ip6t_register_match(&opts_match);
212}
213
214static void __exit ip6t_dst_fini(void)
215{
216 ip6t_unregister_match(&opts_match);
217}
218
219module_init(ip6t_dst_init);
220module_exit(ip6t_dst_fini);
diff --git a/net/ipv6/netfilter/ip6t_frag.c b/net/ipv6/netfilter/ip6t_frag.c
index 06768c84bd31..78d9c8b9e28a 100644
--- a/net/ipv6/netfilter/ip6t_frag.c
+++ b/net/ipv6/netfilter/ip6t_frag.c
@@ -119,7 +119,6 @@ checkentry(const char *tablename,
119 const void *ip, 119 const void *ip,
120 const struct xt_match *match, 120 const struct xt_match *match,
121 void *matchinfo, 121 void *matchinfo,
122 unsigned int matchinfosize,
123 unsigned int hook_mask) 122 unsigned int hook_mask)
124{ 123{
125 const struct ip6t_frag *fraginfo = matchinfo; 124 const struct ip6t_frag *fraginfo = matchinfo;
diff --git a/net/ipv6/netfilter/ip6t_hbh.c b/net/ipv6/netfilter/ip6t_hbh.c
index 374f1be85c0d..d32a205e3af2 100644
--- a/net/ipv6/netfilter/ip6t_hbh.c
+++ b/net/ipv6/netfilter/ip6t_hbh.c
@@ -19,15 +19,10 @@
19#include <linux/netfilter_ipv6/ip6_tables.h> 19#include <linux/netfilter_ipv6/ip6_tables.h>
20#include <linux/netfilter_ipv6/ip6t_opts.h> 20#include <linux/netfilter_ipv6/ip6t_opts.h>
21 21
22#define HOPBYHOP 1
23
24MODULE_LICENSE("GPL"); 22MODULE_LICENSE("GPL");
25#if HOPBYHOP 23MODULE_DESCRIPTION("IPv6 opts match");
26MODULE_DESCRIPTION("IPv6 HbH match");
27#else
28MODULE_DESCRIPTION("IPv6 DST match");
29#endif
30MODULE_AUTHOR("Andras Kis-Szabo <kisza@sch.bme.hu>"); 24MODULE_AUTHOR("Andras Kis-Szabo <kisza@sch.bme.hu>");
25MODULE_ALIAS("ip6t_dst");
31 26
32#if 0 27#if 0
33#define DEBUGP printk 28#define DEBUGP printk
@@ -71,11 +66,7 @@ match(const struct sk_buff *skb,
71 u8 _optlen, *lp = NULL; 66 u8 _optlen, *lp = NULL;
72 unsigned int optlen; 67 unsigned int optlen;
73 68
74#if HOPBYHOP 69 if (ipv6_find_hdr(skb, &ptr, match->data, NULL) < 0)
75 if (ipv6_find_hdr(skb, &ptr, NEXTHDR_HOP, NULL) < 0)
76#else
77 if (ipv6_find_hdr(skb, &ptr, NEXTHDR_DEST, NULL) < 0)
78#endif
79 return 0; 70 return 0;
80 71
81 oh = skb_header_pointer(skb, ptr, sizeof(_optsh), &_optsh); 72 oh = skb_header_pointer(skb, ptr, sizeof(_optsh), &_optsh);
@@ -182,7 +173,6 @@ checkentry(const char *tablename,
182 const void *entry, 173 const void *entry,
183 const struct xt_match *match, 174 const struct xt_match *match,
184 void *matchinfo, 175 void *matchinfo,
185 unsigned int matchinfosize,
186 unsigned int hook_mask) 176 unsigned int hook_mask)
187{ 177{
188 const struct ip6t_opts *optsinfo = matchinfo; 178 const struct ip6t_opts *optsinfo = matchinfo;
@@ -194,26 +184,35 @@ checkentry(const char *tablename,
194 return 1; 184 return 1;
195} 185}
196 186
197static struct ip6t_match opts_match = { 187static struct xt_match opts_match[] = {
198#if HOPBYHOP 188 {
199 .name = "hbh", 189 .name = "hbh",
200#else 190 .family = AF_INET6,
201 .name = "dst", 191 .match = match,
202#endif 192 .matchsize = sizeof(struct ip6t_opts),
203 .match = match, 193 .checkentry = checkentry,
204 .matchsize = sizeof(struct ip6t_opts), 194 .me = THIS_MODULE,
205 .checkentry = checkentry, 195 .data = NEXTHDR_HOP,
206 .me = THIS_MODULE, 196 },
197 {
198 .name = "dst",
199 .family = AF_INET6,
200 .match = match,
201 .matchsize = sizeof(struct ip6t_opts),
202 .checkentry = checkentry,
203 .me = THIS_MODULE,
204 .data = NEXTHDR_DEST,
205 },
207}; 206};
208 207
209static int __init ip6t_hbh_init(void) 208static int __init ip6t_hbh_init(void)
210{ 209{
211 return ip6t_register_match(&opts_match); 210 return xt_register_matches(opts_match, ARRAY_SIZE(opts_match));
212} 211}
213 212
214static void __exit ip6t_hbh_fini(void) 213static void __exit ip6t_hbh_fini(void)
215{ 214{
216 ip6t_unregister_match(&opts_match); 215 xt_unregister_matches(opts_match, ARRAY_SIZE(opts_match));
217} 216}
218 217
219module_init(ip6t_hbh_init); 218module_init(ip6t_hbh_init);
diff --git a/net/ipv6/netfilter/ip6t_ipv6header.c b/net/ipv6/netfilter/ip6t_ipv6header.c
index 9375eeb1369f..3093c398002f 100644
--- a/net/ipv6/netfilter/ip6t_ipv6header.c
+++ b/net/ipv6/netfilter/ip6t_ipv6header.c
@@ -128,7 +128,6 @@ ipv6header_checkentry(const char *tablename,
128 const void *ip, 128 const void *ip,
129 const struct xt_match *match, 129 const struct xt_match *match,
130 void *matchinfo, 130 void *matchinfo,
131 unsigned int matchsize,
132 unsigned int hook_mask) 131 unsigned int hook_mask)
133{ 132{
134 const struct ip6t_ipv6header_info *info = matchinfo; 133 const struct ip6t_ipv6header_info *info = matchinfo;
diff --git a/net/ipv6/netfilter/ip6t_owner.c b/net/ipv6/netfilter/ip6t_owner.c
index 5d047990cd44..4eb9bbc4ebc3 100644
--- a/net/ipv6/netfilter/ip6t_owner.c
+++ b/net/ipv6/netfilter/ip6t_owner.c
@@ -57,7 +57,6 @@ checkentry(const char *tablename,
57 const void *ip, 57 const void *ip,
58 const struct xt_match *match, 58 const struct xt_match *match,
59 void *matchinfo, 59 void *matchinfo,
60 unsigned int matchsize,
61 unsigned int hook_mask) 60 unsigned int hook_mask)
62{ 61{
63 const struct ip6t_owner_info *info = matchinfo; 62 const struct ip6t_owner_info *info = matchinfo;
diff --git a/net/ipv6/netfilter/ip6t_rt.c b/net/ipv6/netfilter/ip6t_rt.c
index fbb0184a41d8..bcb2e168a5bc 100644
--- a/net/ipv6/netfilter/ip6t_rt.c
+++ b/net/ipv6/netfilter/ip6t_rt.c
@@ -197,7 +197,6 @@ checkentry(const char *tablename,
197 const void *entry, 197 const void *entry,
198 const struct xt_match *match, 198 const struct xt_match *match,
199 void *matchinfo, 199 void *matchinfo,
200 unsigned int matchinfosize,
201 unsigned int hook_mask) 200 unsigned int hook_mask)
202{ 201{
203 const struct ip6t_rt *rtinfo = matchinfo; 202 const struct ip6t_rt *rtinfo = matchinfo;
diff --git a/net/ipv6/netfilter/ip6table_filter.c b/net/ipv6/netfilter/ip6table_filter.c
index 60976c0c58e8..2fc07c74decf 100644
--- a/net/ipv6/netfilter/ip6table_filter.c
+++ b/net/ipv6/netfilter/ip6table_filter.c
@@ -108,7 +108,7 @@ ip6t_hook(unsigned int hook,
108 const struct net_device *out, 108 const struct net_device *out,
109 int (*okfn)(struct sk_buff *)) 109 int (*okfn)(struct sk_buff *))
110{ 110{
111 return ip6t_do_table(pskb, hook, in, out, &packet_filter, NULL); 111 return ip6t_do_table(pskb, hook, in, out, &packet_filter);
112} 112}
113 113
114static unsigned int 114static unsigned int
@@ -128,7 +128,7 @@ ip6t_local_out_hook(unsigned int hook,
128 } 128 }
129#endif 129#endif
130 130
131 return ip6t_do_table(pskb, hook, in, out, &packet_filter, NULL); 131 return ip6t_do_table(pskb, hook, in, out, &packet_filter);
132} 132}
133 133
134static struct nf_hook_ops ip6t_ops[] = { 134static struct nf_hook_ops ip6t_ops[] = {
diff --git a/net/ipv6/netfilter/ip6table_mangle.c b/net/ipv6/netfilter/ip6table_mangle.c
index 03a13eab1dae..386ea260e767 100644
--- a/net/ipv6/netfilter/ip6table_mangle.c
+++ b/net/ipv6/netfilter/ip6table_mangle.c
@@ -138,7 +138,7 @@ ip6t_route_hook(unsigned int hook,
138 const struct net_device *out, 138 const struct net_device *out,
139 int (*okfn)(struct sk_buff *)) 139 int (*okfn)(struct sk_buff *))
140{ 140{
141 return ip6t_do_table(pskb, hook, in, out, &packet_mangler, NULL); 141 return ip6t_do_table(pskb, hook, in, out, &packet_mangler);
142} 142}
143 143
144static unsigned int 144static unsigned int
@@ -174,18 +174,14 @@ ip6t_local_hook(unsigned int hook,
174 /* flowlabel and prio (includes version, which shouldn't change either */ 174 /* flowlabel and prio (includes version, which shouldn't change either */
175 flowlabel = *((u_int32_t *) (*pskb)->nh.ipv6h); 175 flowlabel = *((u_int32_t *) (*pskb)->nh.ipv6h);
176 176
177 ret = ip6t_do_table(pskb, hook, in, out, &packet_mangler, NULL); 177 ret = ip6t_do_table(pskb, hook, in, out, &packet_mangler);
178 178
179 if (ret != NF_DROP && ret != NF_STOLEN 179 if (ret != NF_DROP && ret != NF_STOLEN
180 && (memcmp(&(*pskb)->nh.ipv6h->saddr, &saddr, sizeof(saddr)) 180 && (memcmp(&(*pskb)->nh.ipv6h->saddr, &saddr, sizeof(saddr))
181 || memcmp(&(*pskb)->nh.ipv6h->daddr, &daddr, sizeof(daddr)) 181 || memcmp(&(*pskb)->nh.ipv6h->daddr, &daddr, sizeof(daddr))
182 || (*pskb)->nfmark != nfmark 182 || (*pskb)->nfmark != nfmark
183 || (*pskb)->nh.ipv6h->hop_limit != hop_limit)) { 183 || (*pskb)->nh.ipv6h->hop_limit != hop_limit))
184 184 return ip6_route_me_harder(*pskb) == 0 ? ret : NF_DROP;
185 /* something which could affect routing has changed */
186
187 DEBUGP("ip6table_mangle: we'd need to re-route a packet\n");
188 }
189 185
190 return ret; 186 return ret;
191} 187}
diff --git a/net/ipv6/netfilter/ip6table_raw.c b/net/ipv6/netfilter/ip6table_raw.c
index 61a7c58e99f8..b4154da575c0 100644
--- a/net/ipv6/netfilter/ip6table_raw.c
+++ b/net/ipv6/netfilter/ip6table_raw.c
@@ -122,7 +122,7 @@ ip6t_hook(unsigned int hook,
122 const struct net_device *out, 122 const struct net_device *out,
123 int (*okfn)(struct sk_buff *)) 123 int (*okfn)(struct sk_buff *))
124{ 124{
125 return ip6t_do_table(pskb, hook, in, out, &packet_raw, NULL); 125 return ip6t_do_table(pskb, hook, in, out, &packet_raw);
126} 126}
127 127
128static struct nf_hook_ops ip6t_ops[] = { 128static struct nf_hook_ops ip6t_ops[] = {
diff --git a/net/ipv6/netfilter/nf_conntrack_l3proto_ipv6.c b/net/ipv6/netfilter/nf_conntrack_l3proto_ipv6.c
index c2ab38ff46af..e5e53fff9e38 100644
--- a/net/ipv6/netfilter/nf_conntrack_l3proto_ipv6.c
+++ b/net/ipv6/netfilter/nf_conntrack_l3proto_ipv6.c
@@ -335,7 +335,7 @@ static struct nf_hook_ops ipv6_conntrack_ops[] = {
335/* From nf_conntrack_proto_icmpv6.c */ 335/* From nf_conntrack_proto_icmpv6.c */
336extern unsigned int nf_ct_icmpv6_timeout; 336extern unsigned int nf_ct_icmpv6_timeout;
337 337
338/* From nf_conntrack_frag6.c */ 338/* From nf_conntrack_reasm.c */
339extern unsigned int nf_ct_frag6_timeout; 339extern unsigned int nf_ct_frag6_timeout;
340extern unsigned int nf_ct_frag6_low_thresh; 340extern unsigned int nf_ct_frag6_low_thresh;
341extern unsigned int nf_ct_frag6_high_thresh; 341extern unsigned int nf_ct_frag6_high_thresh;
diff --git a/net/ipv6/netfilter/nf_conntrack_proto_icmpv6.c b/net/ipv6/netfilter/nf_conntrack_proto_icmpv6.c
index ef18a7b7014b..34d447208ffd 100644
--- a/net/ipv6/netfilter/nf_conntrack_proto_icmpv6.c
+++ b/net/ipv6/netfilter/nf_conntrack_proto_icmpv6.c
@@ -33,7 +33,7 @@
33#include <net/netfilter/nf_conntrack_core.h> 33#include <net/netfilter/nf_conntrack_core.h>
34#include <net/netfilter/ipv6/nf_conntrack_icmpv6.h> 34#include <net/netfilter/ipv6/nf_conntrack_icmpv6.h>
35 35
36unsigned long nf_ct_icmpv6_timeout = 30*HZ; 36unsigned long nf_ct_icmpv6_timeout __read_mostly = 30*HZ;
37 37
38#if 0 38#if 0
39#define DEBUGP printk 39#define DEBUGP printk
diff --git a/net/ipv6/netfilter/nf_conntrack_reasm.c b/net/ipv6/netfilter/nf_conntrack_reasm.c
index 00d5583807f7..bf93c1ea6be9 100644
--- a/net/ipv6/netfilter/nf_conntrack_reasm.c
+++ b/net/ipv6/netfilter/nf_conntrack_reasm.c
@@ -54,9 +54,9 @@
54#define NF_CT_FRAG6_LOW_THRESH 196608 /* == 192*1024 */ 54#define NF_CT_FRAG6_LOW_THRESH 196608 /* == 192*1024 */
55#define NF_CT_FRAG6_TIMEOUT IPV6_FRAG_TIMEOUT 55#define NF_CT_FRAG6_TIMEOUT IPV6_FRAG_TIMEOUT
56 56
57unsigned int nf_ct_frag6_high_thresh = 256*1024; 57unsigned int nf_ct_frag6_high_thresh __read_mostly = 256*1024;
58unsigned int nf_ct_frag6_low_thresh = 192*1024; 58unsigned int nf_ct_frag6_low_thresh __read_mostly = 192*1024;
59unsigned long nf_ct_frag6_timeout = IPV6_FRAG_TIMEOUT; 59unsigned long nf_ct_frag6_timeout __read_mostly = IPV6_FRAG_TIMEOUT;
60 60
61struct nf_ct_frag6_skb_cb 61struct nf_ct_frag6_skb_cb
62{ 62{
@@ -408,7 +408,7 @@ static int nf_ct_frag6_queue(struct nf_ct_frag6_queue *fq, struct sk_buff *skb,
408 return -1; 408 return -1;
409 } 409 }
410 410
411 if (skb->ip_summed == CHECKSUM_HW) 411 if (skb->ip_summed == CHECKSUM_COMPLETE)
412 skb->csum = csum_sub(skb->csum, 412 skb->csum = csum_sub(skb->csum,
413 csum_partial(skb->nh.raw, 413 csum_partial(skb->nh.raw,
414 (u8*)(fhdr + 1) - skb->nh.raw, 414 (u8*)(fhdr + 1) - skb->nh.raw,
@@ -640,7 +640,7 @@ nf_ct_frag6_reasm(struct nf_ct_frag6_queue *fq, struct net_device *dev)
640 head->len += fp->len; 640 head->len += fp->len;
641 if (head->ip_summed != fp->ip_summed) 641 if (head->ip_summed != fp->ip_summed)
642 head->ip_summed = CHECKSUM_NONE; 642 head->ip_summed = CHECKSUM_NONE;
643 else if (head->ip_summed == CHECKSUM_HW) 643 else if (head->ip_summed == CHECKSUM_COMPLETE)
644 head->csum = csum_add(head->csum, fp->csum); 644 head->csum = csum_add(head->csum, fp->csum);
645 head->truesize += fp->truesize; 645 head->truesize += fp->truesize;
646 atomic_sub(fp->truesize, &nf_ct_frag6_mem); 646 atomic_sub(fp->truesize, &nf_ct_frag6_mem);
@@ -652,7 +652,7 @@ nf_ct_frag6_reasm(struct nf_ct_frag6_queue *fq, struct net_device *dev)
652 head->nh.ipv6h->payload_len = htons(payload_len); 652 head->nh.ipv6h->payload_len = htons(payload_len);
653 653
654 /* Yes, and fold redundant checksum back. 8) */ 654 /* Yes, and fold redundant checksum back. 8) */
655 if (head->ip_summed == CHECKSUM_HW) 655 if (head->ip_summed == CHECKSUM_COMPLETE)
656 head->csum = csum_partial(head->nh.raw, head->h.raw-head->nh.raw, head->csum); 656 head->csum = csum_partial(head->nh.raw, head->h.raw-head->nh.raw, head->csum);
657 657
658 fq->fragments = NULL; 658 fq->fragments = NULL;
diff --git a/net/ipv6/raw.c b/net/ipv6/raw.c
index 15b862d8acab..d09329ca3267 100644
--- a/net/ipv6/raw.c
+++ b/net/ipv6/raw.c
@@ -50,6 +50,9 @@
50#include <net/udp.h> 50#include <net/udp.h>
51#include <net/inet_common.h> 51#include <net/inet_common.h>
52#include <net/tcp_states.h> 52#include <net/tcp_states.h>
53#ifdef CONFIG_IPV6_MIP6
54#include <net/mip6.h>
55#endif
53 56
54#include <net/rawv6.h> 57#include <net/rawv6.h>
55#include <net/xfrm.h> 58#include <net/xfrm.h>
@@ -169,8 +172,32 @@ int ipv6_raw_deliver(struct sk_buff *skb, int nexthdr)
169 sk = __raw_v6_lookup(sk, nexthdr, daddr, saddr, IP6CB(skb)->iif); 172 sk = __raw_v6_lookup(sk, nexthdr, daddr, saddr, IP6CB(skb)->iif);
170 173
171 while (sk) { 174 while (sk) {
175 int filtered;
176
172 delivered = 1; 177 delivered = 1;
173 if (nexthdr != IPPROTO_ICMPV6 || !icmpv6_filter(sk, skb)) { 178 switch (nexthdr) {
179 case IPPROTO_ICMPV6:
180 filtered = icmpv6_filter(sk, skb);
181 break;
182#ifdef CONFIG_IPV6_MIP6
183 case IPPROTO_MH:
184 /* XXX: To validate MH only once for each packet,
185 * this is placed here. It should be after checking
186 * xfrm policy, however it doesn't. The checking xfrm
187 * policy is placed in rawv6_rcv() because it is
188 * required for each socket.
189 */
190 filtered = mip6_mh_filter(sk, skb);
191 break;
192#endif
193 default:
194 filtered = 0;
195 break;
196 }
197
198 if (filtered < 0)
199 break;
200 if (filtered == 0) {
174 struct sk_buff *clone = skb_clone(skb, GFP_ATOMIC); 201 struct sk_buff *clone = skb_clone(skb, GFP_ATOMIC);
175 202
176 /* Not releasing hash table! */ 203 /* Not releasing hash table! */
@@ -334,7 +361,7 @@ int rawv6_rcv(struct sock *sk, struct sk_buff *skb)
334 if (!rp->checksum) 361 if (!rp->checksum)
335 skb->ip_summed = CHECKSUM_UNNECESSARY; 362 skb->ip_summed = CHECKSUM_UNNECESSARY;
336 363
337 if (skb->ip_summed == CHECKSUM_HW) { 364 if (skb->ip_summed == CHECKSUM_COMPLETE) {
338 skb_postpull_rcsum(skb, skb->nh.raw, 365 skb_postpull_rcsum(skb, skb->nh.raw,
339 skb->h.raw - skb->nh.raw); 366 skb->h.raw - skb->nh.raw);
340 if (!csum_ipv6_magic(&skb->nh.ipv6h->saddr, 367 if (!csum_ipv6_magic(&skb->nh.ipv6h->saddr,
@@ -582,6 +609,9 @@ static void rawv6_probe_proto_opt(struct flowi *fl, struct msghdr *msg)
582 struct iovec *iov; 609 struct iovec *iov;
583 u8 __user *type = NULL; 610 u8 __user *type = NULL;
584 u8 __user *code = NULL; 611 u8 __user *code = NULL;
612#ifdef CONFIG_IPV6_MIP6
613 u8 len = 0;
614#endif
585 int probed = 0; 615 int probed = 0;
586 int i; 616 int i;
587 617
@@ -613,6 +643,20 @@ static void rawv6_probe_proto_opt(struct flowi *fl, struct msghdr *msg)
613 probed = 1; 643 probed = 1;
614 } 644 }
615 break; 645 break;
646#ifdef CONFIG_IPV6_MIP6
647 case IPPROTO_MH:
648 if (iov->iov_base && iov->iov_len < 1)
649 break;
650 /* check if type field is readable or not. */
651 if (iov->iov_len > 2 - len) {
652 u8 __user *p = iov->iov_base;
653 get_user(fl->fl_mh_type, &p[2 - len]);
654 probed = 1;
655 } else
656 len += iov->iov_len;
657
658 break;
659#endif
616 default: 660 default:
617 probed = 1; 661 probed = 1;
618 break; 662 break;
@@ -759,6 +803,7 @@ static int rawv6_sendmsg(struct kiocb *iocb, struct sock *sk,
759 803
760 if (!fl.oif && ipv6_addr_is_multicast(&fl.fl6_dst)) 804 if (!fl.oif && ipv6_addr_is_multicast(&fl.fl6_dst))
761 fl.oif = np->mcast_oif; 805 fl.oif = np->mcast_oif;
806 security_sk_classify_flow(sk, &fl);
762 807
763 err = ip6_dst_lookup(sk, &dst, &fl); 808 err = ip6_dst_lookup(sk, &dst, &fl);
764 if (err) 809 if (err)
diff --git a/net/ipv6/reassembly.c b/net/ipv6/reassembly.c
index 4e299c69e1c6..f39bbedd1327 100644
--- a/net/ipv6/reassembly.c
+++ b/net/ipv6/reassembly.c
@@ -53,10 +53,10 @@
53#include <net/ndisc.h> 53#include <net/ndisc.h>
54#include <net/addrconf.h> 54#include <net/addrconf.h>
55 55
56int sysctl_ip6frag_high_thresh = 256*1024; 56int sysctl_ip6frag_high_thresh __read_mostly = 256*1024;
57int sysctl_ip6frag_low_thresh = 192*1024; 57int sysctl_ip6frag_low_thresh __read_mostly = 192*1024;
58 58
59int sysctl_ip6frag_time = IPV6_FRAG_TIMEOUT; 59int sysctl_ip6frag_time __read_mostly = IPV6_FRAG_TIMEOUT;
60 60
61struct ip6frag_skb_cb 61struct ip6frag_skb_cb
62{ 62{
@@ -152,7 +152,7 @@ static unsigned int ip6qhashfn(u32 id, struct in6_addr *saddr,
152} 152}
153 153
154static struct timer_list ip6_frag_secret_timer; 154static struct timer_list ip6_frag_secret_timer;
155int sysctl_ip6frag_secret_interval = 10 * 60 * HZ; 155int sysctl_ip6frag_secret_interval __read_mostly = 10 * 60 * HZ;
156 156
157static void ip6_frag_secret_rebuild(unsigned long dummy) 157static void ip6_frag_secret_rebuild(unsigned long dummy)
158{ 158{
@@ -433,7 +433,7 @@ static void ip6_frag_queue(struct frag_queue *fq, struct sk_buff *skb,
433 return; 433 return;
434 } 434 }
435 435
436 if (skb->ip_summed == CHECKSUM_HW) 436 if (skb->ip_summed == CHECKSUM_COMPLETE)
437 skb->csum = csum_sub(skb->csum, 437 skb->csum = csum_sub(skb->csum,
438 csum_partial(skb->nh.raw, (u8*)(fhdr+1)-skb->nh.raw, 0)); 438 csum_partial(skb->nh.raw, (u8*)(fhdr+1)-skb->nh.raw, 0));
439 439
@@ -647,7 +647,7 @@ static int ip6_frag_reasm(struct frag_queue *fq, struct sk_buff **skb_in,
647 head->len += fp->len; 647 head->len += fp->len;
648 if (head->ip_summed != fp->ip_summed) 648 if (head->ip_summed != fp->ip_summed)
649 head->ip_summed = CHECKSUM_NONE; 649 head->ip_summed = CHECKSUM_NONE;
650 else if (head->ip_summed == CHECKSUM_HW) 650 else if (head->ip_summed == CHECKSUM_COMPLETE)
651 head->csum = csum_add(head->csum, fp->csum); 651 head->csum = csum_add(head->csum, fp->csum);
652 head->truesize += fp->truesize; 652 head->truesize += fp->truesize;
653 atomic_sub(fp->truesize, &ip6_frag_mem); 653 atomic_sub(fp->truesize, &ip6_frag_mem);
@@ -662,7 +662,7 @@ static int ip6_frag_reasm(struct frag_queue *fq, struct sk_buff **skb_in,
662 *skb_in = head; 662 *skb_in = head;
663 663
664 /* Yes, and fold redundant checksum back. 8) */ 664 /* Yes, and fold redundant checksum back. 8) */
665 if (head->ip_summed == CHECKSUM_HW) 665 if (head->ip_summed == CHECKSUM_COMPLETE)
666 head->csum = csum_partial(head->nh.raw, head->h.raw-head->nh.raw, head->csum); 666 head->csum = csum_partial(head->nh.raw, head->h.raw-head->nh.raw, head->csum);
667 667
668 IP6_INC_STATS_BH(IPSTATS_MIB_REASMOKS); 668 IP6_INC_STATS_BH(IPSTATS_MIB_REASMOKS);
diff --git a/net/ipv6/route.c b/net/ipv6/route.c
index d9baca062d24..d6b4b4f48d18 100644
--- a/net/ipv6/route.c
+++ b/net/ipv6/route.c
@@ -22,6 +22,8 @@
22 * routers in REACHABLE, STALE, DELAY or PROBE states). 22 * routers in REACHABLE, STALE, DELAY or PROBE states).
23 * - always select the same router if it is (probably) 23 * - always select the same router if it is (probably)
24 * reachable. otherwise, round-robin the list. 24 * reachable. otherwise, round-robin the list.
25 * Ville Nuorvala
26 * Fixed routing subtrees.
25 */ 27 */
26 28
27#include <linux/capability.h> 29#include <linux/capability.h>
@@ -35,7 +37,6 @@
35#include <linux/netdevice.h> 37#include <linux/netdevice.h>
36#include <linux/in6.h> 38#include <linux/in6.h>
37#include <linux/init.h> 39#include <linux/init.h>
38#include <linux/netlink.h>
39#include <linux/if_arp.h> 40#include <linux/if_arp.h>
40 41
41#ifdef CONFIG_PROC_FS 42#ifdef CONFIG_PROC_FS
@@ -54,6 +55,7 @@
54#include <net/dst.h> 55#include <net/dst.h>
55#include <net/xfrm.h> 56#include <net/xfrm.h>
56#include <net/netevent.h> 57#include <net/netevent.h>
58#include <net/netlink.h>
57 59
58#include <asm/uaccess.h> 60#include <asm/uaccess.h>
59 61
@@ -74,9 +76,6 @@
74 76
75#define CLONE_OFFLINK_ROUTE 0 77#define CLONE_OFFLINK_ROUTE 0
76 78
77#define RT6_SELECT_F_IFACE 0x1
78#define RT6_SELECT_F_REACHABLE 0x2
79
80static int ip6_rt_max_size = 4096; 79static int ip6_rt_max_size = 4096;
81static int ip6_rt_gc_min_interval = HZ / 2; 80static int ip6_rt_gc_min_interval = HZ / 2;
82static int ip6_rt_gc_timeout = 60*HZ; 81static int ip6_rt_gc_timeout = 60*HZ;
@@ -140,15 +139,49 @@ struct rt6_info ip6_null_entry = {
140 .rt6i_ref = ATOMIC_INIT(1), 139 .rt6i_ref = ATOMIC_INIT(1),
141}; 140};
142 141
143struct fib6_node ip6_routing_table = { 142#ifdef CONFIG_IPV6_MULTIPLE_TABLES
144 .leaf = &ip6_null_entry,
145 .fn_flags = RTN_ROOT | RTN_TL_ROOT | RTN_RTINFO,
146};
147 143
148/* Protects all the ip6 fib */ 144struct rt6_info ip6_prohibit_entry = {
145 .u = {
146 .dst = {
147 .__refcnt = ATOMIC_INIT(1),
148 .__use = 1,
149 .dev = &loopback_dev,
150 .obsolete = -1,
151 .error = -EACCES,
152 .metrics = { [RTAX_HOPLIMIT - 1] = 255, },
153 .input = ip6_pkt_discard,
154 .output = ip6_pkt_discard_out,
155 .ops = &ip6_dst_ops,
156 .path = (struct dst_entry*)&ip6_prohibit_entry,
157 }
158 },
159 .rt6i_flags = (RTF_REJECT | RTF_NONEXTHOP),
160 .rt6i_metric = ~(u32) 0,
161 .rt6i_ref = ATOMIC_INIT(1),
162};
149 163
150DEFINE_RWLOCK(rt6_lock); 164struct rt6_info ip6_blk_hole_entry = {
165 .u = {
166 .dst = {
167 .__refcnt = ATOMIC_INIT(1),
168 .__use = 1,
169 .dev = &loopback_dev,
170 .obsolete = -1,
171 .error = -EINVAL,
172 .metrics = { [RTAX_HOPLIMIT - 1] = 255, },
173 .input = ip6_pkt_discard,
174 .output = ip6_pkt_discard_out,
175 .ops = &ip6_dst_ops,
176 .path = (struct dst_entry*)&ip6_blk_hole_entry,
177 }
178 },
179 .rt6i_flags = (RTF_REJECT | RTF_NONEXTHOP),
180 .rt6i_metric = ~(u32) 0,
181 .rt6i_ref = ATOMIC_INIT(1),
182};
151 183
184#endif
152 185
153/* allocate dst with ip6_dst_ops */ 186/* allocate dst with ip6_dst_ops */
154static __inline__ struct rt6_info *ip6_dst_alloc(void) 187static __inline__ struct rt6_info *ip6_dst_alloc(void)
@@ -188,8 +221,14 @@ static __inline__ int rt6_check_expired(const struct rt6_info *rt)
188 time_after(jiffies, rt->rt6i_expires)); 221 time_after(jiffies, rt->rt6i_expires));
189} 222}
190 223
224static inline int rt6_need_strict(struct in6_addr *daddr)
225{
226 return (ipv6_addr_type(daddr) &
227 (IPV6_ADDR_MULTICAST | IPV6_ADDR_LINKLOCAL));
228}
229
191/* 230/*
192 * Route lookup. Any rt6_lock is implied. 231 * Route lookup. Any table->tb6_lock is implied.
193 */ 232 */
194 233
195static __inline__ struct rt6_info *rt6_device_match(struct rt6_info *rt, 234static __inline__ struct rt6_info *rt6_device_match(struct rt6_info *rt,
@@ -298,7 +337,7 @@ static int rt6_score_route(struct rt6_info *rt, int oif,
298 int m, n; 337 int m, n;
299 338
300 m = rt6_check_dev(rt, oif); 339 m = rt6_check_dev(rt, oif);
301 if (!m && (strict & RT6_SELECT_F_IFACE)) 340 if (!m && (strict & RT6_LOOKUP_F_IFACE))
302 return -1; 341 return -1;
303#ifdef CONFIG_IPV6_ROUTER_PREF 342#ifdef CONFIG_IPV6_ROUTER_PREF
304 m |= IPV6_DECODE_PREF(IPV6_EXTRACT_PREF(rt->rt6i_flags)) << 2; 343 m |= IPV6_DECODE_PREF(IPV6_EXTRACT_PREF(rt->rt6i_flags)) << 2;
@@ -306,7 +345,7 @@ static int rt6_score_route(struct rt6_info *rt, int oif,
306 n = rt6_check_neigh(rt); 345 n = rt6_check_neigh(rt);
307 if (n > 1) 346 if (n > 1)
308 m |= 16; 347 m |= 16;
309 else if (!n && strict & RT6_SELECT_F_REACHABLE) 348 else if (!n && strict & RT6_LOOKUP_F_REACHABLE)
310 return -1; 349 return -1;
311 return m; 350 return m;
312} 351}
@@ -346,7 +385,7 @@ static struct rt6_info *rt6_select(struct rt6_info **head, int oif,
346 } 385 }
347 386
348 if (!match && 387 if (!match &&
349 (strict & RT6_SELECT_F_REACHABLE) && 388 (strict & RT6_LOOKUP_F_REACHABLE) &&
350 last && last != rt0) { 389 last && last != rt0) {
351 /* no entries matched; do round-robin */ 390 /* no entries matched; do round-robin */
352 static DEFINE_SPINLOCK(lock); 391 static DEFINE_SPINLOCK(lock);
@@ -417,7 +456,7 @@ int rt6_route_rcv(struct net_device *dev, u8 *opt, int len,
417 rt = rt6_get_route_info(prefix, rinfo->prefix_len, gwaddr, dev->ifindex); 456 rt = rt6_get_route_info(prefix, rinfo->prefix_len, gwaddr, dev->ifindex);
418 457
419 if (rt && !lifetime) { 458 if (rt && !lifetime) {
420 ip6_del_rt(rt, NULL, NULL, NULL); 459 ip6_del_rt(rt);
421 rt = NULL; 460 rt = NULL;
422 } 461 }
423 462
@@ -441,44 +480,95 @@ int rt6_route_rcv(struct net_device *dev, u8 *opt, int len,
441} 480}
442#endif 481#endif
443 482
444struct rt6_info *rt6_lookup(struct in6_addr *daddr, struct in6_addr *saddr, 483#define BACKTRACK(saddr) \
445 int oif, int strict) 484do { \
485 if (rt == &ip6_null_entry) { \
486 struct fib6_node *pn; \
487 while (fn) { \
488 if (fn->fn_flags & RTN_TL_ROOT) \
489 goto out; \
490 pn = fn->parent; \
491 if (FIB6_SUBTREE(pn) && FIB6_SUBTREE(pn) != fn) \
492 fn = fib6_lookup(pn->subtree, NULL, saddr); \
493 else \
494 fn = pn; \
495 if (fn->fn_flags & RTN_RTINFO) \
496 goto restart; \
497 } \
498 } \
499} while(0)
500
501static struct rt6_info *ip6_pol_route_lookup(struct fib6_table *table,
502 struct flowi *fl, int flags)
446{ 503{
447 struct fib6_node *fn; 504 struct fib6_node *fn;
448 struct rt6_info *rt; 505 struct rt6_info *rt;
449 506
450 read_lock_bh(&rt6_lock); 507 read_lock_bh(&table->tb6_lock);
451 fn = fib6_lookup(&ip6_routing_table, daddr, saddr); 508 fn = fib6_lookup(&table->tb6_root, &fl->fl6_dst, &fl->fl6_src);
452 rt = rt6_device_match(fn->leaf, oif, strict); 509restart:
510 rt = fn->leaf;
511 rt = rt6_device_match(rt, fl->oif, flags);
512 BACKTRACK(&fl->fl6_src);
513out:
453 dst_hold(&rt->u.dst); 514 dst_hold(&rt->u.dst);
454 rt->u.dst.__use++; 515 read_unlock_bh(&table->tb6_lock);
455 read_unlock_bh(&rt6_lock);
456 516
457 rt->u.dst.lastuse = jiffies; 517 rt->u.dst.lastuse = jiffies;
458 if (rt->u.dst.error == 0) 518 rt->u.dst.__use++;
459 return rt; 519
460 dst_release(&rt->u.dst); 520 return rt;
521
522}
523
524struct rt6_info *rt6_lookup(struct in6_addr *daddr, struct in6_addr *saddr,
525 int oif, int strict)
526{
527 struct flowi fl = {
528 .oif = oif,
529 .nl_u = {
530 .ip6_u = {
531 .daddr = *daddr,
532 /* TODO: saddr */
533 },
534 },
535 };
536 struct dst_entry *dst;
537 int flags = strict ? RT6_LOOKUP_F_IFACE : 0;
538
539 dst = fib6_rule_lookup(&fl, flags, ip6_pol_route_lookup);
540 if (dst->error == 0)
541 return (struct rt6_info *) dst;
542
543 dst_release(dst);
544
461 return NULL; 545 return NULL;
462} 546}
463 547
464/* ip6_ins_rt is called with FREE rt6_lock. 548/* ip6_ins_rt is called with FREE table->tb6_lock.
465 It takes new route entry, the addition fails by any reason the 549 It takes new route entry, the addition fails by any reason the
466 route is freed. In any case, if caller does not hold it, it may 550 route is freed. In any case, if caller does not hold it, it may
467 be destroyed. 551 be destroyed.
468 */ 552 */
469 553
470int ip6_ins_rt(struct rt6_info *rt, struct nlmsghdr *nlh, 554static int __ip6_ins_rt(struct rt6_info *rt, struct nl_info *info)
471 void *_rtattr, struct netlink_skb_parms *req)
472{ 555{
473 int err; 556 int err;
557 struct fib6_table *table;
474 558
475 write_lock_bh(&rt6_lock); 559 table = rt->rt6i_table;
476 err = fib6_add(&ip6_routing_table, rt, nlh, _rtattr, req); 560 write_lock_bh(&table->tb6_lock);
477 write_unlock_bh(&rt6_lock); 561 err = fib6_add(&table->tb6_root, rt, info);
562 write_unlock_bh(&table->tb6_lock);
478 563
479 return err; 564 return err;
480} 565}
481 566
567int ip6_ins_rt(struct rt6_info *rt)
568{
569 return __ip6_ins_rt(rt, NULL);
570}
571
482static struct rt6_info *rt6_alloc_cow(struct rt6_info *ort, struct in6_addr *daddr, 572static struct rt6_info *rt6_alloc_cow(struct rt6_info *ort, struct in6_addr *daddr,
483 struct in6_addr *saddr) 573 struct in6_addr *saddr)
484{ 574{
@@ -532,51 +622,39 @@ static struct rt6_info *rt6_alloc_clone(struct rt6_info *ort, struct in6_addr *d
532 return rt; 622 return rt;
533} 623}
534 624
535#define BACKTRACK() \ 625static struct rt6_info *ip6_pol_route_input(struct fib6_table *table,
536if (rt == &ip6_null_entry) { \ 626 struct flowi *fl, int flags)
537 while ((fn = fn->parent) != NULL) { \
538 if (fn->fn_flags & RTN_ROOT) { \
539 goto out; \
540 } \
541 if (fn->fn_flags & RTN_RTINFO) \
542 goto restart; \
543 } \
544}
545
546
547void ip6_route_input(struct sk_buff *skb)
548{ 627{
549 struct fib6_node *fn; 628 struct fib6_node *fn;
550 struct rt6_info *rt, *nrt; 629 struct rt6_info *rt, *nrt;
551 int strict; 630 int strict = 0;
552 int attempts = 3; 631 int attempts = 3;
553 int err; 632 int err;
554 int reachable = RT6_SELECT_F_REACHABLE; 633 int reachable = RT6_LOOKUP_F_REACHABLE;
555 634
556 strict = ipv6_addr_type(&skb->nh.ipv6h->daddr) & (IPV6_ADDR_MULTICAST|IPV6_ADDR_LINKLOCAL) ? RT6_SELECT_F_IFACE : 0; 635 strict |= flags & RT6_LOOKUP_F_IFACE;
557 636
558relookup: 637relookup:
559 read_lock_bh(&rt6_lock); 638 read_lock_bh(&table->tb6_lock);
560 639
561restart_2: 640restart_2:
562 fn = fib6_lookup(&ip6_routing_table, &skb->nh.ipv6h->daddr, 641 fn = fib6_lookup(&table->tb6_root, &fl->fl6_dst, &fl->fl6_src);
563 &skb->nh.ipv6h->saddr);
564 642
565restart: 643restart:
566 rt = rt6_select(&fn->leaf, skb->dev->ifindex, strict | reachable); 644 rt = rt6_select(&fn->leaf, fl->iif, strict | reachable);
567 BACKTRACK(); 645 BACKTRACK(&fl->fl6_src);
568 if (rt == &ip6_null_entry || 646 if (rt == &ip6_null_entry ||
569 rt->rt6i_flags & RTF_CACHE) 647 rt->rt6i_flags & RTF_CACHE)
570 goto out; 648 goto out;
571 649
572 dst_hold(&rt->u.dst); 650 dst_hold(&rt->u.dst);
573 read_unlock_bh(&rt6_lock); 651 read_unlock_bh(&table->tb6_lock);
574 652
575 if (!rt->rt6i_nexthop && !(rt->rt6i_flags & RTF_NONEXTHOP)) 653 if (!rt->rt6i_nexthop && !(rt->rt6i_flags & RTF_NONEXTHOP))
576 nrt = rt6_alloc_cow(rt, &skb->nh.ipv6h->daddr, &skb->nh.ipv6h->saddr); 654 nrt = rt6_alloc_cow(rt, &fl->fl6_dst, &fl->fl6_src);
577 else { 655 else {
578#if CLONE_OFFLINK_ROUTE 656#if CLONE_OFFLINK_ROUTE
579 nrt = rt6_alloc_clone(rt, &skb->nh.ipv6h->daddr); 657 nrt = rt6_alloc_clone(rt, &fl->fl6_dst);
580#else 658#else
581 goto out2; 659 goto out2;
582#endif 660#endif
@@ -587,7 +665,7 @@ restart:
587 665
588 dst_hold(&rt->u.dst); 666 dst_hold(&rt->u.dst);
589 if (nrt) { 667 if (nrt) {
590 err = ip6_ins_rt(nrt, NULL, NULL, &NETLINK_CB(skb)); 668 err = ip6_ins_rt(nrt);
591 if (!err) 669 if (!err)
592 goto out2; 670 goto out2;
593 } 671 }
@@ -596,7 +674,7 @@ restart:
596 goto out2; 674 goto out2;
597 675
598 /* 676 /*
599 * Race condition! In the gap, when rt6_lock was 677 * Race condition! In the gap, when table->tb6_lock was
600 * released someone could insert this route. Relookup. 678 * released someone could insert this route. Relookup.
601 */ 679 */
602 dst_release(&rt->u.dst); 680 dst_release(&rt->u.dst);
@@ -608,40 +686,63 @@ out:
608 goto restart_2; 686 goto restart_2;
609 } 687 }
610 dst_hold(&rt->u.dst); 688 dst_hold(&rt->u.dst);
611 read_unlock_bh(&rt6_lock); 689 read_unlock_bh(&table->tb6_lock);
612out2: 690out2:
613 rt->u.dst.lastuse = jiffies; 691 rt->u.dst.lastuse = jiffies;
614 rt->u.dst.__use++; 692 rt->u.dst.__use++;
615 skb->dst = (struct dst_entry *) rt; 693
616 return; 694 return rt;
617} 695}
618 696
619struct dst_entry * ip6_route_output(struct sock *sk, struct flowi *fl) 697void ip6_route_input(struct sk_buff *skb)
698{
699 struct ipv6hdr *iph = skb->nh.ipv6h;
700 struct flowi fl = {
701 .iif = skb->dev->ifindex,
702 .nl_u = {
703 .ip6_u = {
704 .daddr = iph->daddr,
705 .saddr = iph->saddr,
706#ifdef CONFIG_IPV6_ROUTE_FWMARK
707 .fwmark = skb->nfmark,
708#endif
709 .flowlabel = (* (u32 *) iph)&IPV6_FLOWINFO_MASK,
710 },
711 },
712 .proto = iph->nexthdr,
713 };
714 int flags = rt6_need_strict(&iph->daddr) ? RT6_LOOKUP_F_IFACE : 0;
715
716 skb->dst = fib6_rule_lookup(&fl, flags, ip6_pol_route_input);
717}
718
719static struct rt6_info *ip6_pol_route_output(struct fib6_table *table,
720 struct flowi *fl, int flags)
620{ 721{
621 struct fib6_node *fn; 722 struct fib6_node *fn;
622 struct rt6_info *rt, *nrt; 723 struct rt6_info *rt, *nrt;
623 int strict; 724 int strict = 0;
624 int attempts = 3; 725 int attempts = 3;
625 int err; 726 int err;
626 int reachable = RT6_SELECT_F_REACHABLE; 727 int reachable = RT6_LOOKUP_F_REACHABLE;
627 728
628 strict = ipv6_addr_type(&fl->fl6_dst) & (IPV6_ADDR_MULTICAST|IPV6_ADDR_LINKLOCAL) ? RT6_SELECT_F_IFACE : 0; 729 strict |= flags & RT6_LOOKUP_F_IFACE;
629 730
630relookup: 731relookup:
631 read_lock_bh(&rt6_lock); 732 read_lock_bh(&table->tb6_lock);
632 733
633restart_2: 734restart_2:
634 fn = fib6_lookup(&ip6_routing_table, &fl->fl6_dst, &fl->fl6_src); 735 fn = fib6_lookup(&table->tb6_root, &fl->fl6_dst, &fl->fl6_src);
635 736
636restart: 737restart:
637 rt = rt6_select(&fn->leaf, fl->oif, strict | reachable); 738 rt = rt6_select(&fn->leaf, fl->oif, strict | reachable);
638 BACKTRACK(); 739 BACKTRACK(&fl->fl6_src);
639 if (rt == &ip6_null_entry || 740 if (rt == &ip6_null_entry ||
640 rt->rt6i_flags & RTF_CACHE) 741 rt->rt6i_flags & RTF_CACHE)
641 goto out; 742 goto out;
642 743
643 dst_hold(&rt->u.dst); 744 dst_hold(&rt->u.dst);
644 read_unlock_bh(&rt6_lock); 745 read_unlock_bh(&table->tb6_lock);
645 746
646 if (!rt->rt6i_nexthop && !(rt->rt6i_flags & RTF_NONEXTHOP)) 747 if (!rt->rt6i_nexthop && !(rt->rt6i_flags & RTF_NONEXTHOP))
647 nrt = rt6_alloc_cow(rt, &fl->fl6_dst, &fl->fl6_src); 748 nrt = rt6_alloc_cow(rt, &fl->fl6_dst, &fl->fl6_src);
@@ -658,7 +759,7 @@ restart:
658 759
659 dst_hold(&rt->u.dst); 760 dst_hold(&rt->u.dst);
660 if (nrt) { 761 if (nrt) {
661 err = ip6_ins_rt(nrt, NULL, NULL, NULL); 762 err = ip6_ins_rt(nrt);
662 if (!err) 763 if (!err)
663 goto out2; 764 goto out2;
664 } 765 }
@@ -667,7 +768,7 @@ restart:
667 goto out2; 768 goto out2;
668 769
669 /* 770 /*
670 * Race condition! In the gap, when rt6_lock was 771 * Race condition! In the gap, when table->tb6_lock was
671 * released someone could insert this route. Relookup. 772 * released someone could insert this route. Relookup.
672 */ 773 */
673 dst_release(&rt->u.dst); 774 dst_release(&rt->u.dst);
@@ -679,11 +780,21 @@ out:
679 goto restart_2; 780 goto restart_2;
680 } 781 }
681 dst_hold(&rt->u.dst); 782 dst_hold(&rt->u.dst);
682 read_unlock_bh(&rt6_lock); 783 read_unlock_bh(&table->tb6_lock);
683out2: 784out2:
684 rt->u.dst.lastuse = jiffies; 785 rt->u.dst.lastuse = jiffies;
685 rt->u.dst.__use++; 786 rt->u.dst.__use++;
686 return &rt->u.dst; 787 return rt;
788}
789
790struct dst_entry * ip6_route_output(struct sock *sk, struct flowi *fl)
791{
792 int flags = 0;
793
794 if (rt6_need_strict(&fl->fl6_dst))
795 flags |= RT6_LOOKUP_F_IFACE;
796
797 return fib6_rule_lookup(fl, flags, ip6_pol_route_output);
687} 798}
688 799
689 800
@@ -709,7 +820,7 @@ static struct dst_entry *ip6_negative_advice(struct dst_entry *dst)
709 820
710 if (rt) { 821 if (rt) {
711 if (rt->rt6i_flags & RTF_CACHE) 822 if (rt->rt6i_flags & RTF_CACHE)
712 ip6_del_rt(rt, NULL, NULL, NULL); 823 ip6_del_rt(rt);
713 else 824 else
714 dst_release(dst); 825 dst_release(dst);
715 } 826 }
@@ -747,8 +858,6 @@ static void ip6_rt_update_pmtu(struct dst_entry *dst, u32 mtu)
747 } 858 }
748} 859}
749 860
750/* Protected by rt6_lock. */
751static struct dst_entry *ndisc_dst_gc_list;
752static int ipv6_get_mtu(struct net_device *dev); 861static int ipv6_get_mtu(struct net_device *dev);
753 862
754static inline unsigned int ipv6_advmss(unsigned int mtu) 863static inline unsigned int ipv6_advmss(unsigned int mtu)
@@ -769,6 +878,9 @@ static inline unsigned int ipv6_advmss(unsigned int mtu)
769 return mtu; 878 return mtu;
770} 879}
771 880
881static struct dst_entry *ndisc_dst_gc_list;
882static DEFINE_SPINLOCK(ndisc_lock);
883
772struct dst_entry *ndisc_dst_alloc(struct net_device *dev, 884struct dst_entry *ndisc_dst_alloc(struct net_device *dev,
773 struct neighbour *neigh, 885 struct neighbour *neigh,
774 struct in6_addr *addr, 886 struct in6_addr *addr,
@@ -809,10 +921,10 @@ struct dst_entry *ndisc_dst_alloc(struct net_device *dev,
809 rt->rt6i_dst.plen = 128; 921 rt->rt6i_dst.plen = 128;
810#endif 922#endif
811 923
812 write_lock_bh(&rt6_lock); 924 spin_lock_bh(&ndisc_lock);
813 rt->u.dst.next = ndisc_dst_gc_list; 925 rt->u.dst.next = ndisc_dst_gc_list;
814 ndisc_dst_gc_list = &rt->u.dst; 926 ndisc_dst_gc_list = &rt->u.dst;
815 write_unlock_bh(&rt6_lock); 927 spin_unlock_bh(&ndisc_lock);
816 928
817 fib6_force_start_gc(); 929 fib6_force_start_gc();
818 930
@@ -826,8 +938,11 @@ int ndisc_dst_gc(int *more)
826 int freed; 938 int freed;
827 939
828 next = NULL; 940 next = NULL;
941 freed = 0;
942
943 spin_lock_bh(&ndisc_lock);
829 pprev = &ndisc_dst_gc_list; 944 pprev = &ndisc_dst_gc_list;
830 freed = 0; 945
831 while ((dst = *pprev) != NULL) { 946 while ((dst = *pprev) != NULL) {
832 if (!atomic_read(&dst->__refcnt)) { 947 if (!atomic_read(&dst->__refcnt)) {
833 *pprev = dst->next; 948 *pprev = dst->next;
@@ -839,6 +954,8 @@ int ndisc_dst_gc(int *more)
839 } 954 }
840 } 955 }
841 956
957 spin_unlock_bh(&ndisc_lock);
958
842 return freed; 959 return freed;
843} 960}
844 961
@@ -899,28 +1016,24 @@ int ipv6_get_hoplimit(struct net_device *dev)
899 * 1016 *
900 */ 1017 */
901 1018
902int ip6_route_add(struct in6_rtmsg *rtmsg, struct nlmsghdr *nlh, 1019int ip6_route_add(struct fib6_config *cfg)
903 void *_rtattr, struct netlink_skb_parms *req)
904{ 1020{
905 int err; 1021 int err;
906 struct rtmsg *r;
907 struct rtattr **rta;
908 struct rt6_info *rt = NULL; 1022 struct rt6_info *rt = NULL;
909 struct net_device *dev = NULL; 1023 struct net_device *dev = NULL;
910 struct inet6_dev *idev = NULL; 1024 struct inet6_dev *idev = NULL;
1025 struct fib6_table *table;
911 int addr_type; 1026 int addr_type;
912 1027
913 rta = (struct rtattr **) _rtattr; 1028 if (cfg->fc_dst_len > 128 || cfg->fc_src_len > 128)
914
915 if (rtmsg->rtmsg_dst_len > 128 || rtmsg->rtmsg_src_len > 128)
916 return -EINVAL; 1029 return -EINVAL;
917#ifndef CONFIG_IPV6_SUBTREES 1030#ifndef CONFIG_IPV6_SUBTREES
918 if (rtmsg->rtmsg_src_len) 1031 if (cfg->fc_src_len)
919 return -EINVAL; 1032 return -EINVAL;
920#endif 1033#endif
921 if (rtmsg->rtmsg_ifindex) { 1034 if (cfg->fc_ifindex) {
922 err = -ENODEV; 1035 err = -ENODEV;
923 dev = dev_get_by_index(rtmsg->rtmsg_ifindex); 1036 dev = dev_get_by_index(cfg->fc_ifindex);
924 if (!dev) 1037 if (!dev)
925 goto out; 1038 goto out;
926 idev = in6_dev_get(dev); 1039 idev = in6_dev_get(dev);
@@ -928,8 +1041,14 @@ int ip6_route_add(struct in6_rtmsg *rtmsg, struct nlmsghdr *nlh,
928 goto out; 1041 goto out;
929 } 1042 }
930 1043
931 if (rtmsg->rtmsg_metric == 0) 1044 if (cfg->fc_metric == 0)
932 rtmsg->rtmsg_metric = IP6_RT_PRIO_USER; 1045 cfg->fc_metric = IP6_RT_PRIO_USER;
1046
1047 table = fib6_new_table(cfg->fc_table);
1048 if (table == NULL) {
1049 err = -ENOBUFS;
1050 goto out;
1051 }
933 1052
934 rt = ip6_dst_alloc(); 1053 rt = ip6_dst_alloc();
935 1054
@@ -939,14 +1058,13 @@ int ip6_route_add(struct in6_rtmsg *rtmsg, struct nlmsghdr *nlh,
939 } 1058 }
940 1059
941 rt->u.dst.obsolete = -1; 1060 rt->u.dst.obsolete = -1;
942 rt->rt6i_expires = jiffies + clock_t_to_jiffies(rtmsg->rtmsg_info); 1061 rt->rt6i_expires = jiffies + clock_t_to_jiffies(cfg->fc_expires);
943 if (nlh && (r = NLMSG_DATA(nlh))) {
944 rt->rt6i_protocol = r->rtm_protocol;
945 } else {
946 rt->rt6i_protocol = RTPROT_BOOT;
947 }
948 1062
949 addr_type = ipv6_addr_type(&rtmsg->rtmsg_dst); 1063 if (cfg->fc_protocol == RTPROT_UNSPEC)
1064 cfg->fc_protocol = RTPROT_BOOT;
1065 rt->rt6i_protocol = cfg->fc_protocol;
1066
1067 addr_type = ipv6_addr_type(&cfg->fc_dst);
950 1068
951 if (addr_type & IPV6_ADDR_MULTICAST) 1069 if (addr_type & IPV6_ADDR_MULTICAST)
952 rt->u.dst.input = ip6_mc_input; 1070 rt->u.dst.input = ip6_mc_input;
@@ -955,24 +1073,22 @@ int ip6_route_add(struct in6_rtmsg *rtmsg, struct nlmsghdr *nlh,
955 1073
956 rt->u.dst.output = ip6_output; 1074 rt->u.dst.output = ip6_output;
957 1075
958 ipv6_addr_prefix(&rt->rt6i_dst.addr, 1076 ipv6_addr_prefix(&rt->rt6i_dst.addr, &cfg->fc_dst, cfg->fc_dst_len);
959 &rtmsg->rtmsg_dst, rtmsg->rtmsg_dst_len); 1077 rt->rt6i_dst.plen = cfg->fc_dst_len;
960 rt->rt6i_dst.plen = rtmsg->rtmsg_dst_len;
961 if (rt->rt6i_dst.plen == 128) 1078 if (rt->rt6i_dst.plen == 128)
962 rt->u.dst.flags = DST_HOST; 1079 rt->u.dst.flags = DST_HOST;
963 1080
964#ifdef CONFIG_IPV6_SUBTREES 1081#ifdef CONFIG_IPV6_SUBTREES
965 ipv6_addr_prefix(&rt->rt6i_src.addr, 1082 ipv6_addr_prefix(&rt->rt6i_src.addr, &cfg->fc_src, cfg->fc_src_len);
966 &rtmsg->rtmsg_src, rtmsg->rtmsg_src_len); 1083 rt->rt6i_src.plen = cfg->fc_src_len;
967 rt->rt6i_src.plen = rtmsg->rtmsg_src_len;
968#endif 1084#endif
969 1085
970 rt->rt6i_metric = rtmsg->rtmsg_metric; 1086 rt->rt6i_metric = cfg->fc_metric;
971 1087
972 /* We cannot add true routes via loopback here, 1088 /* We cannot add true routes via loopback here,
973 they would result in kernel looping; promote them to reject routes 1089 they would result in kernel looping; promote them to reject routes
974 */ 1090 */
975 if ((rtmsg->rtmsg_flags&RTF_REJECT) || 1091 if ((cfg->fc_flags & RTF_REJECT) ||
976 (dev && (dev->flags&IFF_LOOPBACK) && !(addr_type&IPV6_ADDR_LOOPBACK))) { 1092 (dev && (dev->flags&IFF_LOOPBACK) && !(addr_type&IPV6_ADDR_LOOPBACK))) {
977 /* hold loopback dev/idev if we haven't done so. */ 1093 /* hold loopback dev/idev if we haven't done so. */
978 if (dev != &loopback_dev) { 1094 if (dev != &loopback_dev) {
@@ -995,12 +1111,12 @@ int ip6_route_add(struct in6_rtmsg *rtmsg, struct nlmsghdr *nlh,
995 goto install_route; 1111 goto install_route;
996 } 1112 }
997 1113
998 if (rtmsg->rtmsg_flags & RTF_GATEWAY) { 1114 if (cfg->fc_flags & RTF_GATEWAY) {
999 struct in6_addr *gw_addr; 1115 struct in6_addr *gw_addr;
1000 int gwa_type; 1116 int gwa_type;
1001 1117
1002 gw_addr = &rtmsg->rtmsg_gateway; 1118 gw_addr = &cfg->fc_gateway;
1003 ipv6_addr_copy(&rt->rt6i_gateway, &rtmsg->rtmsg_gateway); 1119 ipv6_addr_copy(&rt->rt6i_gateway, gw_addr);
1004 gwa_type = ipv6_addr_type(gw_addr); 1120 gwa_type = ipv6_addr_type(gw_addr);
1005 1121
1006 if (gwa_type != (IPV6_ADDR_LINKLOCAL|IPV6_ADDR_UNICAST)) { 1122 if (gwa_type != (IPV6_ADDR_LINKLOCAL|IPV6_ADDR_UNICAST)) {
@@ -1017,7 +1133,7 @@ int ip6_route_add(struct in6_rtmsg *rtmsg, struct nlmsghdr *nlh,
1017 if (!(gwa_type&IPV6_ADDR_UNICAST)) 1133 if (!(gwa_type&IPV6_ADDR_UNICAST))
1018 goto out; 1134 goto out;
1019 1135
1020 grt = rt6_lookup(gw_addr, NULL, rtmsg->rtmsg_ifindex, 1); 1136 grt = rt6_lookup(gw_addr, NULL, cfg->fc_ifindex, 1);
1021 1137
1022 err = -EHOSTUNREACH; 1138 err = -EHOSTUNREACH;
1023 if (grt == NULL) 1139 if (grt == NULL)
@@ -1049,7 +1165,7 @@ int ip6_route_add(struct in6_rtmsg *rtmsg, struct nlmsghdr *nlh,
1049 if (dev == NULL) 1165 if (dev == NULL)
1050 goto out; 1166 goto out;
1051 1167
1052 if (rtmsg->rtmsg_flags & (RTF_GATEWAY|RTF_NONEXTHOP)) { 1168 if (cfg->fc_flags & (RTF_GATEWAY | RTF_NONEXTHOP)) {
1053 rt->rt6i_nexthop = __neigh_lookup_errno(&nd_tbl, &rt->rt6i_gateway, dev); 1169 rt->rt6i_nexthop = __neigh_lookup_errno(&nd_tbl, &rt->rt6i_gateway, dev);
1054 if (IS_ERR(rt->rt6i_nexthop)) { 1170 if (IS_ERR(rt->rt6i_nexthop)) {
1055 err = PTR_ERR(rt->rt6i_nexthop); 1171 err = PTR_ERR(rt->rt6i_nexthop);
@@ -1058,24 +1174,24 @@ int ip6_route_add(struct in6_rtmsg *rtmsg, struct nlmsghdr *nlh,
1058 } 1174 }
1059 } 1175 }
1060 1176
1061 rt->rt6i_flags = rtmsg->rtmsg_flags; 1177 rt->rt6i_flags = cfg->fc_flags;
1062 1178
1063install_route: 1179install_route:
1064 if (rta && rta[RTA_METRICS-1]) { 1180 if (cfg->fc_mx) {
1065 int attrlen = RTA_PAYLOAD(rta[RTA_METRICS-1]); 1181 struct nlattr *nla;
1066 struct rtattr *attr = RTA_DATA(rta[RTA_METRICS-1]); 1182 int remaining;
1067 1183
1068 while (RTA_OK(attr, attrlen)) { 1184 nla_for_each_attr(nla, cfg->fc_mx, cfg->fc_mx_len, remaining) {
1069 unsigned flavor = attr->rta_type; 1185 int type = nla->nla_type;
1070 if (flavor) { 1186
1071 if (flavor > RTAX_MAX) { 1187 if (type) {
1188 if (type > RTAX_MAX) {
1072 err = -EINVAL; 1189 err = -EINVAL;
1073 goto out; 1190 goto out;
1074 } 1191 }
1075 rt->u.dst.metrics[flavor-1] = 1192
1076 *(u32 *)RTA_DATA(attr); 1193 rt->u.dst.metrics[type - 1] = nla_get_u32(nla);
1077 } 1194 }
1078 attr = RTA_NEXT(attr, attrlen);
1079 } 1195 }
1080 } 1196 }
1081 1197
@@ -1087,7 +1203,8 @@ install_route:
1087 rt->u.dst.metrics[RTAX_ADVMSS-1] = ipv6_advmss(dst_mtu(&rt->u.dst)); 1203 rt->u.dst.metrics[RTAX_ADVMSS-1] = ipv6_advmss(dst_mtu(&rt->u.dst));
1088 rt->u.dst.dev = dev; 1204 rt->u.dst.dev = dev;
1089 rt->rt6i_idev = idev; 1205 rt->rt6i_idev = idev;
1090 return ip6_ins_rt(rt, nlh, _rtattr, req); 1206 rt->rt6i_table = table;
1207 return __ip6_ins_rt(rt, &cfg->fc_nlinfo);
1091 1208
1092out: 1209out:
1093 if (dev) 1210 if (dev)
@@ -1099,51 +1216,65 @@ out:
1099 return err; 1216 return err;
1100} 1217}
1101 1218
1102int ip6_del_rt(struct rt6_info *rt, struct nlmsghdr *nlh, void *_rtattr, struct netlink_skb_parms *req) 1219static int __ip6_del_rt(struct rt6_info *rt, struct nl_info *info)
1103{ 1220{
1104 int err; 1221 int err;
1222 struct fib6_table *table;
1105 1223
1106 write_lock_bh(&rt6_lock); 1224 if (rt == &ip6_null_entry)
1225 return -ENOENT;
1107 1226
1108 err = fib6_del(rt, nlh, _rtattr, req); 1227 table = rt->rt6i_table;
1228 write_lock_bh(&table->tb6_lock);
1229
1230 err = fib6_del(rt, info);
1109 dst_release(&rt->u.dst); 1231 dst_release(&rt->u.dst);
1110 1232
1111 write_unlock_bh(&rt6_lock); 1233 write_unlock_bh(&table->tb6_lock);
1112 1234
1113 return err; 1235 return err;
1114} 1236}
1115 1237
1116static int ip6_route_del(struct in6_rtmsg *rtmsg, struct nlmsghdr *nlh, void *_rtattr, struct netlink_skb_parms *req) 1238int ip6_del_rt(struct rt6_info *rt)
1117{ 1239{
1240 return __ip6_del_rt(rt, NULL);
1241}
1242
1243static int ip6_route_del(struct fib6_config *cfg)
1244{
1245 struct fib6_table *table;
1118 struct fib6_node *fn; 1246 struct fib6_node *fn;
1119 struct rt6_info *rt; 1247 struct rt6_info *rt;
1120 int err = -ESRCH; 1248 int err = -ESRCH;
1121 1249
1122 read_lock_bh(&rt6_lock); 1250 table = fib6_get_table(cfg->fc_table);
1251 if (table == NULL)
1252 return err;
1123 1253
1124 fn = fib6_locate(&ip6_routing_table, 1254 read_lock_bh(&table->tb6_lock);
1125 &rtmsg->rtmsg_dst, rtmsg->rtmsg_dst_len, 1255
1126 &rtmsg->rtmsg_src, rtmsg->rtmsg_src_len); 1256 fn = fib6_locate(&table->tb6_root,
1257 &cfg->fc_dst, cfg->fc_dst_len,
1258 &cfg->fc_src, cfg->fc_src_len);
1127 1259
1128 if (fn) { 1260 if (fn) {
1129 for (rt = fn->leaf; rt; rt = rt->u.next) { 1261 for (rt = fn->leaf; rt; rt = rt->u.next) {
1130 if (rtmsg->rtmsg_ifindex && 1262 if (cfg->fc_ifindex &&
1131 (rt->rt6i_dev == NULL || 1263 (rt->rt6i_dev == NULL ||
1132 rt->rt6i_dev->ifindex != rtmsg->rtmsg_ifindex)) 1264 rt->rt6i_dev->ifindex != cfg->fc_ifindex))
1133 continue; 1265 continue;
1134 if (rtmsg->rtmsg_flags&RTF_GATEWAY && 1266 if (cfg->fc_flags & RTF_GATEWAY &&
1135 !ipv6_addr_equal(&rtmsg->rtmsg_gateway, &rt->rt6i_gateway)) 1267 !ipv6_addr_equal(&cfg->fc_gateway, &rt->rt6i_gateway))
1136 continue; 1268 continue;
1137 if (rtmsg->rtmsg_metric && 1269 if (cfg->fc_metric && cfg->fc_metric != rt->rt6i_metric)
1138 rtmsg->rtmsg_metric != rt->rt6i_metric)
1139 continue; 1270 continue;
1140 dst_hold(&rt->u.dst); 1271 dst_hold(&rt->u.dst);
1141 read_unlock_bh(&rt6_lock); 1272 read_unlock_bh(&table->tb6_lock);
1142 1273
1143 return ip6_del_rt(rt, nlh, _rtattr, req); 1274 return __ip6_del_rt(rt, &cfg->fc_nlinfo);
1144 } 1275 }
1145 } 1276 }
1146 read_unlock_bh(&rt6_lock); 1277 read_unlock_bh(&table->tb6_lock);
1147 1278
1148 return err; 1279 return err;
1149} 1280}
@@ -1151,13 +1282,18 @@ static int ip6_route_del(struct in6_rtmsg *rtmsg, struct nlmsghdr *nlh, void *_r
1151/* 1282/*
1152 * Handle redirects 1283 * Handle redirects
1153 */ 1284 */
1154void rt6_redirect(struct in6_addr *dest, struct in6_addr *saddr, 1285struct ip6rd_flowi {
1155 struct neighbour *neigh, u8 *lladdr, int on_link) 1286 struct flowi fl;
1287 struct in6_addr gateway;
1288};
1289
1290static struct rt6_info *__ip6_route_redirect(struct fib6_table *table,
1291 struct flowi *fl,
1292 int flags)
1156{ 1293{
1157 struct rt6_info *rt, *nrt = NULL; 1294 struct ip6rd_flowi *rdfl = (struct ip6rd_flowi *)fl;
1158 int strict; 1295 struct rt6_info *rt;
1159 struct fib6_node *fn; 1296 struct fib6_node *fn;
1160 struct netevent_redirect netevent;
1161 1297
1162 /* 1298 /*
1163 * Get the "current" route for this destination and 1299 * Get the "current" route for this destination and
@@ -1169,10 +1305,9 @@ void rt6_redirect(struct in6_addr *dest, struct in6_addr *saddr,
1169 * is a bit fuzzy and one might need to check all possible 1305 * is a bit fuzzy and one might need to check all possible
1170 * routes. 1306 * routes.
1171 */ 1307 */
1172 strict = ipv6_addr_type(dest) & (IPV6_ADDR_MULTICAST | IPV6_ADDR_LINKLOCAL);
1173 1308
1174 read_lock_bh(&rt6_lock); 1309 read_lock_bh(&table->tb6_lock);
1175 fn = fib6_lookup(&ip6_routing_table, dest, NULL); 1310 fn = fib6_lookup(&table->tb6_root, &fl->fl6_dst, &fl->fl6_src);
1176restart: 1311restart:
1177 for (rt = fn->leaf; rt; rt = rt->u.next) { 1312 for (rt = fn->leaf; rt; rt = rt->u.next) {
1178 /* 1313 /*
@@ -1187,29 +1322,60 @@ restart:
1187 continue; 1322 continue;
1188 if (!(rt->rt6i_flags & RTF_GATEWAY)) 1323 if (!(rt->rt6i_flags & RTF_GATEWAY))
1189 continue; 1324 continue;
1190 if (neigh->dev != rt->rt6i_dev) 1325 if (fl->oif != rt->rt6i_dev->ifindex)
1191 continue; 1326 continue;
1192 if (!ipv6_addr_equal(saddr, &rt->rt6i_gateway)) 1327 if (!ipv6_addr_equal(&rdfl->gateway, &rt->rt6i_gateway))
1193 continue; 1328 continue;
1194 break; 1329 break;
1195 } 1330 }
1196 if (rt)
1197 dst_hold(&rt->u.dst);
1198 else if (strict) {
1199 while ((fn = fn->parent) != NULL) {
1200 if (fn->fn_flags & RTN_ROOT)
1201 break;
1202 if (fn->fn_flags & RTN_RTINFO)
1203 goto restart;
1204 }
1205 }
1206 read_unlock_bh(&rt6_lock);
1207 1331
1208 if (!rt) { 1332 if (!rt)
1333 rt = &ip6_null_entry;
1334 BACKTRACK(&fl->fl6_src);
1335out:
1336 dst_hold(&rt->u.dst);
1337
1338 read_unlock_bh(&table->tb6_lock);
1339
1340 return rt;
1341};
1342
1343static struct rt6_info *ip6_route_redirect(struct in6_addr *dest,
1344 struct in6_addr *src,
1345 struct in6_addr *gateway,
1346 struct net_device *dev)
1347{
1348 struct ip6rd_flowi rdfl = {
1349 .fl = {
1350 .oif = dev->ifindex,
1351 .nl_u = {
1352 .ip6_u = {
1353 .daddr = *dest,
1354 .saddr = *src,
1355 },
1356 },
1357 },
1358 .gateway = *gateway,
1359 };
1360 int flags = rt6_need_strict(dest) ? RT6_LOOKUP_F_IFACE : 0;
1361
1362 return (struct rt6_info *)fib6_rule_lookup((struct flowi *)&rdfl, flags, __ip6_route_redirect);
1363}
1364
1365void rt6_redirect(struct in6_addr *dest, struct in6_addr *src,
1366 struct in6_addr *saddr,
1367 struct neighbour *neigh, u8 *lladdr, int on_link)
1368{
1369 struct rt6_info *rt, *nrt = NULL;
1370 struct netevent_redirect netevent;
1371
1372 rt = ip6_route_redirect(dest, src, saddr, neigh->dev);
1373
1374 if (rt == &ip6_null_entry) {
1209 if (net_ratelimit()) 1375 if (net_ratelimit())
1210 printk(KERN_DEBUG "rt6_redirect: source isn't a valid nexthop " 1376 printk(KERN_DEBUG "rt6_redirect: source isn't a valid nexthop "
1211 "for redirect target\n"); 1377 "for redirect target\n");
1212 return; 1378 goto out;
1213 } 1379 }
1214 1380
1215 /* 1381 /*
@@ -1252,7 +1418,7 @@ restart:
1252 nrt->u.dst.metrics[RTAX_MTU-1] = ipv6_get_mtu(neigh->dev); 1418 nrt->u.dst.metrics[RTAX_MTU-1] = ipv6_get_mtu(neigh->dev);
1253 nrt->u.dst.metrics[RTAX_ADVMSS-1] = ipv6_advmss(dst_mtu(&nrt->u.dst)); 1419 nrt->u.dst.metrics[RTAX_ADVMSS-1] = ipv6_advmss(dst_mtu(&nrt->u.dst));
1254 1420
1255 if (ip6_ins_rt(nrt, NULL, NULL, NULL)) 1421 if (ip6_ins_rt(nrt))
1256 goto out; 1422 goto out;
1257 1423
1258 netevent.old = &rt->u.dst; 1424 netevent.old = &rt->u.dst;
@@ -1260,7 +1426,7 @@ restart:
1260 call_netevent_notifiers(NETEVENT_REDIRECT, &netevent); 1426 call_netevent_notifiers(NETEVENT_REDIRECT, &netevent);
1261 1427
1262 if (rt->rt6i_flags&RTF_CACHE) { 1428 if (rt->rt6i_flags&RTF_CACHE) {
1263 ip6_del_rt(rt, NULL, NULL, NULL); 1429 ip6_del_rt(rt);
1264 return; 1430 return;
1265 } 1431 }
1266 1432
@@ -1342,7 +1508,7 @@ void rt6_pmtu_discovery(struct in6_addr *daddr, struct in6_addr *saddr,
1342 dst_set_expires(&nrt->u.dst, ip6_rt_mtu_expires); 1508 dst_set_expires(&nrt->u.dst, ip6_rt_mtu_expires);
1343 nrt->rt6i_flags |= RTF_DYNAMIC|RTF_EXPIRES; 1509 nrt->rt6i_flags |= RTF_DYNAMIC|RTF_EXPIRES;
1344 1510
1345 ip6_ins_rt(nrt, NULL, NULL, NULL); 1511 ip6_ins_rt(nrt);
1346 } 1512 }
1347out: 1513out:
1348 dst_release(&rt->u.dst); 1514 dst_release(&rt->u.dst);
@@ -1378,6 +1544,7 @@ static struct rt6_info * ip6_rt_copy(struct rt6_info *ort)
1378#ifdef CONFIG_IPV6_SUBTREES 1544#ifdef CONFIG_IPV6_SUBTREES
1379 memcpy(&rt->rt6i_src, &ort->rt6i_src, sizeof(struct rt6key)); 1545 memcpy(&rt->rt6i_src, &ort->rt6i_src, sizeof(struct rt6key));
1380#endif 1546#endif
1547 rt->rt6i_table = ort->rt6i_table;
1381 } 1548 }
1382 return rt; 1549 return rt;
1383} 1550}
@@ -1388,9 +1555,14 @@ static struct rt6_info *rt6_get_route_info(struct in6_addr *prefix, int prefixle
1388{ 1555{
1389 struct fib6_node *fn; 1556 struct fib6_node *fn;
1390 struct rt6_info *rt = NULL; 1557 struct rt6_info *rt = NULL;
1558 struct fib6_table *table;
1559
1560 table = fib6_get_table(RT6_TABLE_INFO);
1561 if (table == NULL)
1562 return NULL;
1391 1563
1392 write_lock_bh(&rt6_lock); 1564 write_lock_bh(&table->tb6_lock);
1393 fn = fib6_locate(&ip6_routing_table, prefix ,prefixlen, NULL, 0); 1565 fn = fib6_locate(&table->tb6_root, prefix ,prefixlen, NULL, 0);
1394 if (!fn) 1566 if (!fn)
1395 goto out; 1567 goto out;
1396 1568
@@ -1405,7 +1577,7 @@ static struct rt6_info *rt6_get_route_info(struct in6_addr *prefix, int prefixle
1405 break; 1577 break;
1406 } 1578 }
1407out: 1579out:
1408 write_unlock_bh(&rt6_lock); 1580 write_unlock_bh(&table->tb6_lock);
1409 return rt; 1581 return rt;
1410} 1582}
1411 1583
@@ -1413,21 +1585,23 @@ static struct rt6_info *rt6_add_route_info(struct in6_addr *prefix, int prefixle
1413 struct in6_addr *gwaddr, int ifindex, 1585 struct in6_addr *gwaddr, int ifindex,
1414 unsigned pref) 1586 unsigned pref)
1415{ 1587{
1416 struct in6_rtmsg rtmsg; 1588 struct fib6_config cfg = {
1589 .fc_table = RT6_TABLE_INFO,
1590 .fc_metric = 1024,
1591 .fc_ifindex = ifindex,
1592 .fc_dst_len = prefixlen,
1593 .fc_flags = RTF_GATEWAY | RTF_ADDRCONF | RTF_ROUTEINFO |
1594 RTF_UP | RTF_PREF(pref),
1595 };
1596
1597 ipv6_addr_copy(&cfg.fc_dst, prefix);
1598 ipv6_addr_copy(&cfg.fc_gateway, gwaddr);
1417 1599
1418 memset(&rtmsg, 0, sizeof(rtmsg));
1419 rtmsg.rtmsg_type = RTMSG_NEWROUTE;
1420 ipv6_addr_copy(&rtmsg.rtmsg_dst, prefix);
1421 rtmsg.rtmsg_dst_len = prefixlen;
1422 ipv6_addr_copy(&rtmsg.rtmsg_gateway, gwaddr);
1423 rtmsg.rtmsg_metric = 1024;
1424 rtmsg.rtmsg_flags = RTF_GATEWAY | RTF_ADDRCONF | RTF_ROUTEINFO | RTF_UP | RTF_PREF(pref);
1425 /* We should treat it as a default route if prefix length is 0. */ 1600 /* We should treat it as a default route if prefix length is 0. */
1426 if (!prefixlen) 1601 if (!prefixlen)
1427 rtmsg.rtmsg_flags |= RTF_DEFAULT; 1602 cfg.fc_flags |= RTF_DEFAULT;
1428 rtmsg.rtmsg_ifindex = ifindex;
1429 1603
1430 ip6_route_add(&rtmsg, NULL, NULL, NULL); 1604 ip6_route_add(&cfg);
1431 1605
1432 return rt6_get_route_info(prefix, prefixlen, gwaddr, ifindex); 1606 return rt6_get_route_info(prefix, prefixlen, gwaddr, ifindex);
1433} 1607}
@@ -1436,12 +1610,14 @@ static struct rt6_info *rt6_add_route_info(struct in6_addr *prefix, int prefixle
1436struct rt6_info *rt6_get_dflt_router(struct in6_addr *addr, struct net_device *dev) 1610struct rt6_info *rt6_get_dflt_router(struct in6_addr *addr, struct net_device *dev)
1437{ 1611{
1438 struct rt6_info *rt; 1612 struct rt6_info *rt;
1439 struct fib6_node *fn; 1613 struct fib6_table *table;
1440 1614
1441 fn = &ip6_routing_table; 1615 table = fib6_get_table(RT6_TABLE_DFLT);
1616 if (table == NULL)
1617 return NULL;
1442 1618
1443 write_lock_bh(&rt6_lock); 1619 write_lock_bh(&table->tb6_lock);
1444 for (rt = fn->leaf; rt; rt=rt->u.next) { 1620 for (rt = table->tb6_root.leaf; rt; rt=rt->u.next) {
1445 if (dev == rt->rt6i_dev && 1621 if (dev == rt->rt6i_dev &&
1446 ((rt->rt6i_flags & (RTF_ADDRCONF | RTF_DEFAULT)) == (RTF_ADDRCONF | RTF_DEFAULT)) && 1622 ((rt->rt6i_flags & (RTF_ADDRCONF | RTF_DEFAULT)) == (RTF_ADDRCONF | RTF_DEFAULT)) &&
1447 ipv6_addr_equal(&rt->rt6i_gateway, addr)) 1623 ipv6_addr_equal(&rt->rt6i_gateway, addr))
@@ -1449,7 +1625,7 @@ struct rt6_info *rt6_get_dflt_router(struct in6_addr *addr, struct net_device *d
1449 } 1625 }
1450 if (rt) 1626 if (rt)
1451 dst_hold(&rt->u.dst); 1627 dst_hold(&rt->u.dst);
1452 write_unlock_bh(&rt6_lock); 1628 write_unlock_bh(&table->tb6_lock);
1453 return rt; 1629 return rt;
1454} 1630}
1455 1631
@@ -1457,43 +1633,65 @@ struct rt6_info *rt6_add_dflt_router(struct in6_addr *gwaddr,
1457 struct net_device *dev, 1633 struct net_device *dev,
1458 unsigned int pref) 1634 unsigned int pref)
1459{ 1635{
1460 struct in6_rtmsg rtmsg; 1636 struct fib6_config cfg = {
1637 .fc_table = RT6_TABLE_DFLT,
1638 .fc_metric = 1024,
1639 .fc_ifindex = dev->ifindex,
1640 .fc_flags = RTF_GATEWAY | RTF_ADDRCONF | RTF_DEFAULT |
1641 RTF_UP | RTF_EXPIRES | RTF_PREF(pref),
1642 };
1461 1643
1462 memset(&rtmsg, 0, sizeof(struct in6_rtmsg)); 1644 ipv6_addr_copy(&cfg.fc_gateway, gwaddr);
1463 rtmsg.rtmsg_type = RTMSG_NEWROUTE;
1464 ipv6_addr_copy(&rtmsg.rtmsg_gateway, gwaddr);
1465 rtmsg.rtmsg_metric = 1024;
1466 rtmsg.rtmsg_flags = RTF_GATEWAY | RTF_ADDRCONF | RTF_DEFAULT | RTF_UP | RTF_EXPIRES |
1467 RTF_PREF(pref);
1468 1645
1469 rtmsg.rtmsg_ifindex = dev->ifindex; 1646 ip6_route_add(&cfg);
1470 1647
1471 ip6_route_add(&rtmsg, NULL, NULL, NULL);
1472 return rt6_get_dflt_router(gwaddr, dev); 1648 return rt6_get_dflt_router(gwaddr, dev);
1473} 1649}
1474 1650
1475void rt6_purge_dflt_routers(void) 1651void rt6_purge_dflt_routers(void)
1476{ 1652{
1477 struct rt6_info *rt; 1653 struct rt6_info *rt;
1654 struct fib6_table *table;
1655
1656 /* NOTE: Keep consistent with rt6_get_dflt_router */
1657 table = fib6_get_table(RT6_TABLE_DFLT);
1658 if (table == NULL)
1659 return;
1478 1660
1479restart: 1661restart:
1480 read_lock_bh(&rt6_lock); 1662 read_lock_bh(&table->tb6_lock);
1481 for (rt = ip6_routing_table.leaf; rt; rt = rt->u.next) { 1663 for (rt = table->tb6_root.leaf; rt; rt = rt->u.next) {
1482 if (rt->rt6i_flags & (RTF_DEFAULT | RTF_ADDRCONF)) { 1664 if (rt->rt6i_flags & (RTF_DEFAULT | RTF_ADDRCONF)) {
1483 dst_hold(&rt->u.dst); 1665 dst_hold(&rt->u.dst);
1484 1666 read_unlock_bh(&table->tb6_lock);
1485 read_unlock_bh(&rt6_lock); 1667 ip6_del_rt(rt);
1486
1487 ip6_del_rt(rt, NULL, NULL, NULL);
1488
1489 goto restart; 1668 goto restart;
1490 } 1669 }
1491 } 1670 }
1492 read_unlock_bh(&rt6_lock); 1671 read_unlock_bh(&table->tb6_lock);
1672}
1673
1674static void rtmsg_to_fib6_config(struct in6_rtmsg *rtmsg,
1675 struct fib6_config *cfg)
1676{
1677 memset(cfg, 0, sizeof(*cfg));
1678
1679 cfg->fc_table = RT6_TABLE_MAIN;
1680 cfg->fc_ifindex = rtmsg->rtmsg_ifindex;
1681 cfg->fc_metric = rtmsg->rtmsg_metric;
1682 cfg->fc_expires = rtmsg->rtmsg_info;
1683 cfg->fc_dst_len = rtmsg->rtmsg_dst_len;
1684 cfg->fc_src_len = rtmsg->rtmsg_src_len;
1685 cfg->fc_flags = rtmsg->rtmsg_flags;
1686
1687 ipv6_addr_copy(&cfg->fc_dst, &rtmsg->rtmsg_dst);
1688 ipv6_addr_copy(&cfg->fc_src, &rtmsg->rtmsg_src);
1689 ipv6_addr_copy(&cfg->fc_gateway, &rtmsg->rtmsg_gateway);
1493} 1690}
1494 1691
1495int ipv6_route_ioctl(unsigned int cmd, void __user *arg) 1692int ipv6_route_ioctl(unsigned int cmd, void __user *arg)
1496{ 1693{
1694 struct fib6_config cfg;
1497 struct in6_rtmsg rtmsg; 1695 struct in6_rtmsg rtmsg;
1498 int err; 1696 int err;
1499 1697
@@ -1506,14 +1704,16 @@ int ipv6_route_ioctl(unsigned int cmd, void __user *arg)
1506 sizeof(struct in6_rtmsg)); 1704 sizeof(struct in6_rtmsg));
1507 if (err) 1705 if (err)
1508 return -EFAULT; 1706 return -EFAULT;
1509 1707
1708 rtmsg_to_fib6_config(&rtmsg, &cfg);
1709
1510 rtnl_lock(); 1710 rtnl_lock();
1511 switch (cmd) { 1711 switch (cmd) {
1512 case SIOCADDRT: 1712 case SIOCADDRT:
1513 err = ip6_route_add(&rtmsg, NULL, NULL, NULL); 1713 err = ip6_route_add(&cfg);
1514 break; 1714 break;
1515 case SIOCDELRT: 1715 case SIOCDELRT:
1516 err = ip6_route_del(&rtmsg, NULL, NULL, NULL); 1716 err = ip6_route_del(&cfg);
1517 break; 1717 break;
1518 default: 1718 default:
1519 err = -EINVAL; 1719 err = -EINVAL;
@@ -1587,6 +1787,7 @@ struct rt6_info *addrconf_dst_alloc(struct inet6_dev *idev,
1587 1787
1588 ipv6_addr_copy(&rt->rt6i_dst.addr, addr); 1788 ipv6_addr_copy(&rt->rt6i_dst.addr, addr);
1589 rt->rt6i_dst.plen = 128; 1789 rt->rt6i_dst.plen = 128;
1790 rt->rt6i_table = fib6_get_table(RT6_TABLE_LOCAL);
1590 1791
1591 atomic_set(&rt->u.dst.__refcnt, 1); 1792 atomic_set(&rt->u.dst.__refcnt, 1);
1592 1793
@@ -1605,9 +1806,7 @@ static int fib6_ifdown(struct rt6_info *rt, void *arg)
1605 1806
1606void rt6_ifdown(struct net_device *dev) 1807void rt6_ifdown(struct net_device *dev)
1607{ 1808{
1608 write_lock_bh(&rt6_lock); 1809 fib6_clean_all(fib6_ifdown, 0, dev);
1609 fib6_clean_tree(&ip6_routing_table, fib6_ifdown, 0, dev);
1610 write_unlock_bh(&rt6_lock);
1611} 1810}
1612 1811
1613struct rt6_mtu_change_arg 1812struct rt6_mtu_change_arg
@@ -1657,80 +1856,114 @@ static int rt6_mtu_change_route(struct rt6_info *rt, void *p_arg)
1657 1856
1658void rt6_mtu_change(struct net_device *dev, unsigned mtu) 1857void rt6_mtu_change(struct net_device *dev, unsigned mtu)
1659{ 1858{
1660 struct rt6_mtu_change_arg arg; 1859 struct rt6_mtu_change_arg arg = {
1860 .dev = dev,
1861 .mtu = mtu,
1862 };
1661 1863
1662 arg.dev = dev; 1864 fib6_clean_all(rt6_mtu_change_route, 0, &arg);
1663 arg.mtu = mtu;
1664 read_lock_bh(&rt6_lock);
1665 fib6_clean_tree(&ip6_routing_table, rt6_mtu_change_route, 0, &arg);
1666 read_unlock_bh(&rt6_lock);
1667} 1865}
1668 1866
1669static int inet6_rtm_to_rtmsg(struct rtmsg *r, struct rtattr **rta, 1867static struct nla_policy rtm_ipv6_policy[RTA_MAX+1] __read_mostly = {
1670 struct in6_rtmsg *rtmsg) 1868 [RTA_GATEWAY] = { .len = sizeof(struct in6_addr) },
1869 [RTA_OIF] = { .type = NLA_U32 },
1870 [RTA_IIF] = { .type = NLA_U32 },
1871 [RTA_PRIORITY] = { .type = NLA_U32 },
1872 [RTA_METRICS] = { .type = NLA_NESTED },
1873};
1874
1875static int rtm_to_fib6_config(struct sk_buff *skb, struct nlmsghdr *nlh,
1876 struct fib6_config *cfg)
1671{ 1877{
1672 memset(rtmsg, 0, sizeof(*rtmsg)); 1878 struct rtmsg *rtm;
1879 struct nlattr *tb[RTA_MAX+1];
1880 int err;
1673 1881
1674 rtmsg->rtmsg_dst_len = r->rtm_dst_len; 1882 err = nlmsg_parse(nlh, sizeof(*rtm), tb, RTA_MAX, rtm_ipv6_policy);
1675 rtmsg->rtmsg_src_len = r->rtm_src_len; 1883 if (err < 0)
1676 rtmsg->rtmsg_flags = RTF_UP; 1884 goto errout;
1677 if (r->rtm_type == RTN_UNREACHABLE)
1678 rtmsg->rtmsg_flags |= RTF_REJECT;
1679 1885
1680 if (rta[RTA_GATEWAY-1]) { 1886 err = -EINVAL;
1681 if (rta[RTA_GATEWAY-1]->rta_len != RTA_LENGTH(16)) 1887 rtm = nlmsg_data(nlh);
1682 return -EINVAL; 1888 memset(cfg, 0, sizeof(*cfg));
1683 memcpy(&rtmsg->rtmsg_gateway, RTA_DATA(rta[RTA_GATEWAY-1]), 16); 1889
1684 rtmsg->rtmsg_flags |= RTF_GATEWAY; 1890 cfg->fc_table = rtm->rtm_table;
1685 } 1891 cfg->fc_dst_len = rtm->rtm_dst_len;
1686 if (rta[RTA_DST-1]) { 1892 cfg->fc_src_len = rtm->rtm_src_len;
1687 if (RTA_PAYLOAD(rta[RTA_DST-1]) < ((r->rtm_dst_len+7)>>3)) 1893 cfg->fc_flags = RTF_UP;
1688 return -EINVAL; 1894 cfg->fc_protocol = rtm->rtm_protocol;
1689 memcpy(&rtmsg->rtmsg_dst, RTA_DATA(rta[RTA_DST-1]), ((r->rtm_dst_len+7)>>3)); 1895
1896 if (rtm->rtm_type == RTN_UNREACHABLE)
1897 cfg->fc_flags |= RTF_REJECT;
1898
1899 cfg->fc_nlinfo.pid = NETLINK_CB(skb).pid;
1900 cfg->fc_nlinfo.nlh = nlh;
1901
1902 if (tb[RTA_GATEWAY]) {
1903 nla_memcpy(&cfg->fc_gateway, tb[RTA_GATEWAY], 16);
1904 cfg->fc_flags |= RTF_GATEWAY;
1690 } 1905 }
1691 if (rta[RTA_SRC-1]) { 1906
1692 if (RTA_PAYLOAD(rta[RTA_SRC-1]) < ((r->rtm_src_len+7)>>3)) 1907 if (tb[RTA_DST]) {
1693 return -EINVAL; 1908 int plen = (rtm->rtm_dst_len + 7) >> 3;
1694 memcpy(&rtmsg->rtmsg_src, RTA_DATA(rta[RTA_SRC-1]), ((r->rtm_src_len+7)>>3)); 1909
1910 if (nla_len(tb[RTA_DST]) < plen)
1911 goto errout;
1912
1913 nla_memcpy(&cfg->fc_dst, tb[RTA_DST], plen);
1695 } 1914 }
1696 if (rta[RTA_OIF-1]) { 1915
1697 if (rta[RTA_OIF-1]->rta_len != RTA_LENGTH(sizeof(int))) 1916 if (tb[RTA_SRC]) {
1698 return -EINVAL; 1917 int plen = (rtm->rtm_src_len + 7) >> 3;
1699 memcpy(&rtmsg->rtmsg_ifindex, RTA_DATA(rta[RTA_OIF-1]), sizeof(int)); 1918
1919 if (nla_len(tb[RTA_SRC]) < plen)
1920 goto errout;
1921
1922 nla_memcpy(&cfg->fc_src, tb[RTA_SRC], plen);
1700 } 1923 }
1701 if (rta[RTA_PRIORITY-1]) { 1924
1702 if (rta[RTA_PRIORITY-1]->rta_len != RTA_LENGTH(4)) 1925 if (tb[RTA_OIF])
1703 return -EINVAL; 1926 cfg->fc_ifindex = nla_get_u32(tb[RTA_OIF]);
1704 memcpy(&rtmsg->rtmsg_metric, RTA_DATA(rta[RTA_PRIORITY-1]), 4); 1927
1928 if (tb[RTA_PRIORITY])
1929 cfg->fc_metric = nla_get_u32(tb[RTA_PRIORITY]);
1930
1931 if (tb[RTA_METRICS]) {
1932 cfg->fc_mx = nla_data(tb[RTA_METRICS]);
1933 cfg->fc_mx_len = nla_len(tb[RTA_METRICS]);
1705 } 1934 }
1706 return 0; 1935
1936 if (tb[RTA_TABLE])
1937 cfg->fc_table = nla_get_u32(tb[RTA_TABLE]);
1938
1939 err = 0;
1940errout:
1941 return err;
1707} 1942}
1708 1943
1709int inet6_rtm_delroute(struct sk_buff *skb, struct nlmsghdr* nlh, void *arg) 1944int inet6_rtm_delroute(struct sk_buff *skb, struct nlmsghdr* nlh, void *arg)
1710{ 1945{
1711 struct rtmsg *r = NLMSG_DATA(nlh); 1946 struct fib6_config cfg;
1712 struct in6_rtmsg rtmsg; 1947 int err;
1713 1948
1714 if (inet6_rtm_to_rtmsg(r, arg, &rtmsg)) 1949 err = rtm_to_fib6_config(skb, nlh, &cfg);
1715 return -EINVAL; 1950 if (err < 0)
1716 return ip6_route_del(&rtmsg, nlh, arg, &NETLINK_CB(skb)); 1951 return err;
1952
1953 return ip6_route_del(&cfg);
1717} 1954}
1718 1955
1719int inet6_rtm_newroute(struct sk_buff *skb, struct nlmsghdr* nlh, void *arg) 1956int inet6_rtm_newroute(struct sk_buff *skb, struct nlmsghdr* nlh, void *arg)
1720{ 1957{
1721 struct rtmsg *r = NLMSG_DATA(nlh); 1958 struct fib6_config cfg;
1722 struct in6_rtmsg rtmsg; 1959 int err;
1723 1960
1724 if (inet6_rtm_to_rtmsg(r, arg, &rtmsg)) 1961 err = rtm_to_fib6_config(skb, nlh, &cfg);
1725 return -EINVAL; 1962 if (err < 0)
1726 return ip6_route_add(&rtmsg, nlh, arg, &NETLINK_CB(skb)); 1963 return err;
1727}
1728 1964
1729struct rt6_rtnl_dump_arg 1965 return ip6_route_add(&cfg);
1730{ 1966}
1731 struct sk_buff *skb;
1732 struct netlink_callback *cb;
1733};
1734 1967
1735static int rt6_fill_node(struct sk_buff *skb, struct rt6_info *rt, 1968static int rt6_fill_node(struct sk_buff *skb, struct rt6_info *rt,
1736 struct in6_addr *dst, struct in6_addr *src, 1969 struct in6_addr *dst, struct in6_addr *src,
@@ -1738,9 +1971,9 @@ static int rt6_fill_node(struct sk_buff *skb, struct rt6_info *rt,
1738 int prefix, unsigned int flags) 1971 int prefix, unsigned int flags)
1739{ 1972{
1740 struct rtmsg *rtm; 1973 struct rtmsg *rtm;
1741 struct nlmsghdr *nlh; 1974 struct nlmsghdr *nlh;
1742 unsigned char *b = skb->tail;
1743 struct rta_cacheinfo ci; 1975 struct rta_cacheinfo ci;
1976 u32 table;
1744 1977
1745 if (prefix) { /* user wants prefix routes only */ 1978 if (prefix) { /* user wants prefix routes only */
1746 if (!(rt->rt6i_flags & RTF_PREFIX_RT)) { 1979 if (!(rt->rt6i_flags & RTF_PREFIX_RT)) {
@@ -1749,13 +1982,21 @@ static int rt6_fill_node(struct sk_buff *skb, struct rt6_info *rt,
1749 } 1982 }
1750 } 1983 }
1751 1984
1752 nlh = NLMSG_NEW(skb, pid, seq, type, sizeof(*rtm), flags); 1985 nlh = nlmsg_put(skb, pid, seq, type, sizeof(*rtm), flags);
1753 rtm = NLMSG_DATA(nlh); 1986 if (nlh == NULL)
1987 return -ENOBUFS;
1988
1989 rtm = nlmsg_data(nlh);
1754 rtm->rtm_family = AF_INET6; 1990 rtm->rtm_family = AF_INET6;
1755 rtm->rtm_dst_len = rt->rt6i_dst.plen; 1991 rtm->rtm_dst_len = rt->rt6i_dst.plen;
1756 rtm->rtm_src_len = rt->rt6i_src.plen; 1992 rtm->rtm_src_len = rt->rt6i_src.plen;
1757 rtm->rtm_tos = 0; 1993 rtm->rtm_tos = 0;
1758 rtm->rtm_table = RT_TABLE_MAIN; 1994 if (rt->rt6i_table)
1995 table = rt->rt6i_table->tb6_id;
1996 else
1997 table = RT6_TABLE_UNSPEC;
1998 rtm->rtm_table = table;
1999 NLA_PUT_U32(skb, RTA_TABLE, table);
1759 if (rt->rt6i_flags&RTF_REJECT) 2000 if (rt->rt6i_flags&RTF_REJECT)
1760 rtm->rtm_type = RTN_UNREACHABLE; 2001 rtm->rtm_type = RTN_UNREACHABLE;
1761 else if (rt->rt6i_dev && (rt->rt6i_dev->flags&IFF_LOOPBACK)) 2002 else if (rt->rt6i_dev && (rt->rt6i_dev->flags&IFF_LOOPBACK))
@@ -1776,31 +2017,35 @@ static int rt6_fill_node(struct sk_buff *skb, struct rt6_info *rt,
1776 rtm->rtm_flags |= RTM_F_CLONED; 2017 rtm->rtm_flags |= RTM_F_CLONED;
1777 2018
1778 if (dst) { 2019 if (dst) {
1779 RTA_PUT(skb, RTA_DST, 16, dst); 2020 NLA_PUT(skb, RTA_DST, 16, dst);
1780 rtm->rtm_dst_len = 128; 2021 rtm->rtm_dst_len = 128;
1781 } else if (rtm->rtm_dst_len) 2022 } else if (rtm->rtm_dst_len)
1782 RTA_PUT(skb, RTA_DST, 16, &rt->rt6i_dst.addr); 2023 NLA_PUT(skb, RTA_DST, 16, &rt->rt6i_dst.addr);
1783#ifdef CONFIG_IPV6_SUBTREES 2024#ifdef CONFIG_IPV6_SUBTREES
1784 if (src) { 2025 if (src) {
1785 RTA_PUT(skb, RTA_SRC, 16, src); 2026 NLA_PUT(skb, RTA_SRC, 16, src);
1786 rtm->rtm_src_len = 128; 2027 rtm->rtm_src_len = 128;
1787 } else if (rtm->rtm_src_len) 2028 } else if (rtm->rtm_src_len)
1788 RTA_PUT(skb, RTA_SRC, 16, &rt->rt6i_src.addr); 2029 NLA_PUT(skb, RTA_SRC, 16, &rt->rt6i_src.addr);
1789#endif 2030#endif
1790 if (iif) 2031 if (iif)
1791 RTA_PUT(skb, RTA_IIF, 4, &iif); 2032 NLA_PUT_U32(skb, RTA_IIF, iif);
1792 else if (dst) { 2033 else if (dst) {
1793 struct in6_addr saddr_buf; 2034 struct in6_addr saddr_buf;
1794 if (ipv6_get_saddr(&rt->u.dst, dst, &saddr_buf) == 0) 2035 if (ipv6_get_saddr(&rt->u.dst, dst, &saddr_buf) == 0)
1795 RTA_PUT(skb, RTA_PREFSRC, 16, &saddr_buf); 2036 NLA_PUT(skb, RTA_PREFSRC, 16, &saddr_buf);
1796 } 2037 }
2038
1797 if (rtnetlink_put_metrics(skb, rt->u.dst.metrics) < 0) 2039 if (rtnetlink_put_metrics(skb, rt->u.dst.metrics) < 0)
1798 goto rtattr_failure; 2040 goto nla_put_failure;
2041
1799 if (rt->u.dst.neighbour) 2042 if (rt->u.dst.neighbour)
1800 RTA_PUT(skb, RTA_GATEWAY, 16, &rt->u.dst.neighbour->primary_key); 2043 NLA_PUT(skb, RTA_GATEWAY, 16, &rt->u.dst.neighbour->primary_key);
2044
1801 if (rt->u.dst.dev) 2045 if (rt->u.dst.dev)
1802 RTA_PUT(skb, RTA_OIF, sizeof(int), &rt->rt6i_dev->ifindex); 2046 NLA_PUT_U32(skb, RTA_OIF, rt->rt6i_dev->ifindex);
1803 RTA_PUT(skb, RTA_PRIORITY, 4, &rt->rt6i_metric); 2047
2048 NLA_PUT_U32(skb, RTA_PRIORITY, rt->rt6i_metric);
1804 ci.rta_lastuse = jiffies_to_clock_t(jiffies - rt->u.dst.lastuse); 2049 ci.rta_lastuse = jiffies_to_clock_t(jiffies - rt->u.dst.lastuse);
1805 if (rt->rt6i_expires) 2050 if (rt->rt6i_expires)
1806 ci.rta_expires = jiffies_to_clock_t(rt->rt6i_expires - jiffies); 2051 ci.rta_expires = jiffies_to_clock_t(rt->rt6i_expires - jiffies);
@@ -1812,23 +2057,21 @@ static int rt6_fill_node(struct sk_buff *skb, struct rt6_info *rt,
1812 ci.rta_id = 0; 2057 ci.rta_id = 0;
1813 ci.rta_ts = 0; 2058 ci.rta_ts = 0;
1814 ci.rta_tsage = 0; 2059 ci.rta_tsage = 0;
1815 RTA_PUT(skb, RTA_CACHEINFO, sizeof(ci), &ci); 2060 NLA_PUT(skb, RTA_CACHEINFO, sizeof(ci), &ci);
1816 nlh->nlmsg_len = skb->tail - b;
1817 return skb->len;
1818 2061
1819nlmsg_failure: 2062 return nlmsg_end(skb, nlh);
1820rtattr_failure: 2063
1821 skb_trim(skb, b - skb->data); 2064nla_put_failure:
1822 return -1; 2065 return nlmsg_cancel(skb, nlh);
1823} 2066}
1824 2067
1825static int rt6_dump_route(struct rt6_info *rt, void *p_arg) 2068int rt6_dump_route(struct rt6_info *rt, void *p_arg)
1826{ 2069{
1827 struct rt6_rtnl_dump_arg *arg = (struct rt6_rtnl_dump_arg *) p_arg; 2070 struct rt6_rtnl_dump_arg *arg = (struct rt6_rtnl_dump_arg *) p_arg;
1828 int prefix; 2071 int prefix;
1829 2072
1830 if (arg->cb->nlh->nlmsg_len >= NLMSG_LENGTH(sizeof(struct rtmsg))) { 2073 if (nlmsg_len(arg->cb->nlh) >= sizeof(struct rtmsg)) {
1831 struct rtmsg *rtm = NLMSG_DATA(arg->cb->nlh); 2074 struct rtmsg *rtm = nlmsg_data(arg->cb->nlh);
1832 prefix = (rtm->rtm_flags & RTM_F_PREFIX) != 0; 2075 prefix = (rtm->rtm_flags & RTM_F_PREFIX) != 0;
1833 } else 2076 } else
1834 prefix = 0; 2077 prefix = 0;
@@ -1838,189 +2081,108 @@ static int rt6_dump_route(struct rt6_info *rt, void *p_arg)
1838 prefix, NLM_F_MULTI); 2081 prefix, NLM_F_MULTI);
1839} 2082}
1840 2083
1841static int fib6_dump_node(struct fib6_walker_t *w) 2084int inet6_rtm_getroute(struct sk_buff *in_skb, struct nlmsghdr* nlh, void *arg)
1842{ 2085{
1843 int res; 2086 struct nlattr *tb[RTA_MAX+1];
1844 struct rt6_info *rt; 2087 struct rt6_info *rt;
2088 struct sk_buff *skb;
2089 struct rtmsg *rtm;
2090 struct flowi fl;
2091 int err, iif = 0;
1845 2092
1846 for (rt = w->leaf; rt; rt = rt->u.next) { 2093 err = nlmsg_parse(nlh, sizeof(*rtm), tb, RTA_MAX, rtm_ipv6_policy);
1847 res = rt6_dump_route(rt, w->args); 2094 if (err < 0)
1848 if (res < 0) { 2095 goto errout;
1849 /* Frame is full, suspend walking */
1850 w->leaf = rt;
1851 return 1;
1852 }
1853 BUG_TRAP(res!=0);
1854 }
1855 w->leaf = NULL;
1856 return 0;
1857}
1858
1859static void fib6_dump_end(struct netlink_callback *cb)
1860{
1861 struct fib6_walker_t *w = (void*)cb->args[0];
1862
1863 if (w) {
1864 cb->args[0] = 0;
1865 fib6_walker_unlink(w);
1866 kfree(w);
1867 }
1868 cb->done = (void*)cb->args[1];
1869 cb->args[1] = 0;
1870}
1871
1872static int fib6_dump_done(struct netlink_callback *cb)
1873{
1874 fib6_dump_end(cb);
1875 return cb->done ? cb->done(cb) : 0;
1876}
1877
1878int inet6_dump_fib(struct sk_buff *skb, struct netlink_callback *cb)
1879{
1880 struct rt6_rtnl_dump_arg arg;
1881 struct fib6_walker_t *w;
1882 int res;
1883 2096
1884 arg.skb = skb; 2097 err = -EINVAL;
1885 arg.cb = cb; 2098 memset(&fl, 0, sizeof(fl));
1886 2099
1887 w = (void*)cb->args[0]; 2100 if (tb[RTA_SRC]) {
1888 if (w == NULL) { 2101 if (nla_len(tb[RTA_SRC]) < sizeof(struct in6_addr))
1889 /* New dump: 2102 goto errout;
1890 *
1891 * 1. hook callback destructor.
1892 */
1893 cb->args[1] = (long)cb->done;
1894 cb->done = fib6_dump_done;
1895 2103
1896 /* 2104 ipv6_addr_copy(&fl.fl6_src, nla_data(tb[RTA_SRC]));
1897 * 2. allocate and initialize walker.
1898 */
1899 w = kzalloc(sizeof(*w), GFP_ATOMIC);
1900 if (w == NULL)
1901 return -ENOMEM;
1902 RT6_TRACE("dump<%p", w);
1903 w->root = &ip6_routing_table;
1904 w->func = fib6_dump_node;
1905 w->args = &arg;
1906 cb->args[0] = (long)w;
1907 read_lock_bh(&rt6_lock);
1908 res = fib6_walk(w);
1909 read_unlock_bh(&rt6_lock);
1910 } else {
1911 w->args = &arg;
1912 read_lock_bh(&rt6_lock);
1913 res = fib6_walk_continue(w);
1914 read_unlock_bh(&rt6_lock);
1915 } 2105 }
1916#if RT6_DEBUG >= 3
1917 if (res <= 0 && skb->len == 0)
1918 RT6_TRACE("%p>dump end\n", w);
1919#endif
1920 res = res < 0 ? res : skb->len;
1921 /* res < 0 is an error. (really, impossible)
1922 res == 0 means that dump is complete, but skb still can contain data.
1923 res > 0 dump is not complete, but frame is full.
1924 */
1925 /* Destroy walker, if dump of this table is complete. */
1926 if (res <= 0)
1927 fib6_dump_end(cb);
1928 return res;
1929}
1930
1931int inet6_rtm_getroute(struct sk_buff *in_skb, struct nlmsghdr* nlh, void *arg)
1932{
1933 struct rtattr **rta = arg;
1934 int iif = 0;
1935 int err = -ENOBUFS;
1936 struct sk_buff *skb;
1937 struct flowi fl;
1938 struct rt6_info *rt;
1939 2106
1940 skb = alloc_skb(NLMSG_GOODSIZE, GFP_KERNEL); 2107 if (tb[RTA_DST]) {
1941 if (skb == NULL) 2108 if (nla_len(tb[RTA_DST]) < sizeof(struct in6_addr))
1942 goto out; 2109 goto errout;
1943 2110
1944 /* Reserve room for dummy headers, this skb can pass 2111 ipv6_addr_copy(&fl.fl6_dst, nla_data(tb[RTA_DST]));
1945 through good chunk of routing engine. 2112 }
1946 */
1947 skb->mac.raw = skb->data;
1948 skb_reserve(skb, MAX_HEADER + sizeof(struct ipv6hdr));
1949 2113
1950 memset(&fl, 0, sizeof(fl)); 2114 if (tb[RTA_IIF])
1951 if (rta[RTA_SRC-1]) 2115 iif = nla_get_u32(tb[RTA_IIF]);
1952 ipv6_addr_copy(&fl.fl6_src,
1953 (struct in6_addr*)RTA_DATA(rta[RTA_SRC-1]));
1954 if (rta[RTA_DST-1])
1955 ipv6_addr_copy(&fl.fl6_dst,
1956 (struct in6_addr*)RTA_DATA(rta[RTA_DST-1]));
1957 2116
1958 if (rta[RTA_IIF-1]) 2117 if (tb[RTA_OIF])
1959 memcpy(&iif, RTA_DATA(rta[RTA_IIF-1]), sizeof(int)); 2118 fl.oif = nla_get_u32(tb[RTA_OIF]);
1960 2119
1961 if (iif) { 2120 if (iif) {
1962 struct net_device *dev; 2121 struct net_device *dev;
1963 dev = __dev_get_by_index(iif); 2122 dev = __dev_get_by_index(iif);
1964 if (!dev) { 2123 if (!dev) {
1965 err = -ENODEV; 2124 err = -ENODEV;
1966 goto out_free; 2125 goto errout;
1967 } 2126 }
1968 } 2127 }
1969 2128
1970 fl.oif = 0; 2129 skb = alloc_skb(NLMSG_GOODSIZE, GFP_KERNEL);
1971 if (rta[RTA_OIF-1]) 2130 if (skb == NULL) {
1972 memcpy(&fl.oif, RTA_DATA(rta[RTA_OIF-1]), sizeof(int)); 2131 err = -ENOBUFS;
2132 goto errout;
2133 }
1973 2134
1974 rt = (struct rt6_info*)ip6_route_output(NULL, &fl); 2135 /* Reserve room for dummy headers, this skb can pass
2136 through good chunk of routing engine.
2137 */
2138 skb->mac.raw = skb->data;
2139 skb_reserve(skb, MAX_HEADER + sizeof(struct ipv6hdr));
1975 2140
2141 rt = (struct rt6_info*) ip6_route_output(NULL, &fl);
1976 skb->dst = &rt->u.dst; 2142 skb->dst = &rt->u.dst;
1977 2143
1978 NETLINK_CB(skb).dst_pid = NETLINK_CB(in_skb).pid; 2144 err = rt6_fill_node(skb, rt, &fl.fl6_dst, &fl.fl6_src, iif,
1979 err = rt6_fill_node(skb, rt,
1980 &fl.fl6_dst, &fl.fl6_src,
1981 iif,
1982 RTM_NEWROUTE, NETLINK_CB(in_skb).pid, 2145 RTM_NEWROUTE, NETLINK_CB(in_skb).pid,
1983 nlh->nlmsg_seq, 0, 0); 2146 nlh->nlmsg_seq, 0, 0);
1984 if (err < 0) { 2147 if (err < 0) {
1985 err = -EMSGSIZE; 2148 kfree_skb(skb);
1986 goto out_free; 2149 goto errout;
1987 } 2150 }
1988 2151
1989 err = netlink_unicast(rtnl, skb, NETLINK_CB(in_skb).pid, MSG_DONTWAIT); 2152 err = rtnl_unicast(skb, NETLINK_CB(in_skb).pid);
1990 if (err > 0) 2153errout:
1991 err = 0;
1992out:
1993 return err; 2154 return err;
1994out_free:
1995 kfree_skb(skb);
1996 goto out;
1997} 2155}
1998 2156
1999void inet6_rt_notify(int event, struct rt6_info *rt, struct nlmsghdr *nlh, 2157void inet6_rt_notify(int event, struct rt6_info *rt, struct nl_info *info)
2000 struct netlink_skb_parms *req)
2001{ 2158{
2002 struct sk_buff *skb; 2159 struct sk_buff *skb;
2003 int size = NLMSG_SPACE(sizeof(struct rtmsg)+256); 2160 u32 pid = 0, seq = 0;
2004 u32 pid = current->pid; 2161 struct nlmsghdr *nlh = NULL;
2005 u32 seq = 0; 2162 int payload = sizeof(struct rtmsg) + 256;
2006 2163 int err = -ENOBUFS;
2007 if (req) 2164
2008 pid = req->pid; 2165 if (info) {
2009 if (nlh) 2166 pid = info->pid;
2010 seq = nlh->nlmsg_seq; 2167 nlh = info->nlh;
2011 2168 if (nlh)
2012 skb = alloc_skb(size, gfp_any()); 2169 seq = nlh->nlmsg_seq;
2013 if (!skb) {
2014 netlink_set_err(rtnl, 0, RTNLGRP_IPV6_ROUTE, ENOBUFS);
2015 return;
2016 } 2170 }
2017 if (rt6_fill_node(skb, rt, NULL, NULL, 0, event, pid, seq, 0, 0) < 0) { 2171
2172 skb = nlmsg_new(nlmsg_total_size(payload), gfp_any());
2173 if (skb == NULL)
2174 goto errout;
2175
2176 err = rt6_fill_node(skb, rt, NULL, NULL, 0, event, pid, seq, 0, 0);
2177 if (err < 0) {
2018 kfree_skb(skb); 2178 kfree_skb(skb);
2019 netlink_set_err(rtnl, 0, RTNLGRP_IPV6_ROUTE, EINVAL); 2179 goto errout;
2020 return;
2021 } 2180 }
2022 NETLINK_CB(skb).dst_group = RTNLGRP_IPV6_ROUTE; 2181
2023 netlink_broadcast(rtnl, skb, 0, RTNLGRP_IPV6_ROUTE, gfp_any()); 2182 err = rtnl_notify(skb, pid, RTNLGRP_IPV6_ROUTE, nlh, gfp_any());
2183errout:
2184 if (err < 0)
2185 rtnl_set_sk_err(RTNLGRP_IPV6_ROUTE, err);
2024} 2186}
2025 2187
2026/* 2188/*
@@ -2096,16 +2258,13 @@ static int rt6_info_route(struct rt6_info *rt, void *p_arg)
2096 2258
2097static int rt6_proc_info(char *buffer, char **start, off_t offset, int length) 2259static int rt6_proc_info(char *buffer, char **start, off_t offset, int length)
2098{ 2260{
2099 struct rt6_proc_arg arg; 2261 struct rt6_proc_arg arg = {
2100 arg.buffer = buffer; 2262 .buffer = buffer,
2101 arg.offset = offset; 2263 .offset = offset,
2102 arg.length = length; 2264 .length = length,
2103 arg.skip = 0; 2265 };
2104 arg.len = 0;
2105 2266
2106 read_lock_bh(&rt6_lock); 2267 fib6_clean_all(rt6_info_route, 0, &arg);
2107 fib6_clean_tree(&ip6_routing_table, rt6_info_route, 0, &arg);
2108 read_unlock_bh(&rt6_lock);
2109 2268
2110 *start = buffer; 2269 *start = buffer;
2111 if (offset) 2270 if (offset)
@@ -2260,13 +2419,9 @@ void __init ip6_route_init(void)
2260{ 2419{
2261 struct proc_dir_entry *p; 2420 struct proc_dir_entry *p;
2262 2421
2263 ip6_dst_ops.kmem_cachep = kmem_cache_create("ip6_dst_cache", 2422 ip6_dst_ops.kmem_cachep =
2264 sizeof(struct rt6_info), 2423 kmem_cache_create("ip6_dst_cache", sizeof(struct rt6_info), 0,
2265 0, SLAB_HWCACHE_ALIGN, 2424 SLAB_HWCACHE_ALIGN|SLAB_PANIC, NULL, NULL);
2266 NULL, NULL);
2267 if (!ip6_dst_ops.kmem_cachep)
2268 panic("cannot create ip6_dst_cache");
2269
2270 fib6_init(); 2425 fib6_init();
2271#ifdef CONFIG_PROC_FS 2426#ifdef CONFIG_PROC_FS
2272 p = proc_net_create("ipv6_route", 0, rt6_proc_info); 2427 p = proc_net_create("ipv6_route", 0, rt6_proc_info);
@@ -2278,10 +2433,16 @@ void __init ip6_route_init(void)
2278#ifdef CONFIG_XFRM 2433#ifdef CONFIG_XFRM
2279 xfrm6_init(); 2434 xfrm6_init();
2280#endif 2435#endif
2436#ifdef CONFIG_IPV6_MULTIPLE_TABLES
2437 fib6_rules_init();
2438#endif
2281} 2439}
2282 2440
2283void ip6_route_cleanup(void) 2441void ip6_route_cleanup(void)
2284{ 2442{
2443#ifdef CONFIG_IPV6_MULTIPLE_TABLES
2444 fib6_rules_cleanup();
2445#endif
2285#ifdef CONFIG_PROC_FS 2446#ifdef CONFIG_PROC_FS
2286 proc_net_remove("ipv6_route"); 2447 proc_net_remove("ipv6_route");
2287 proc_net_remove("rt6_stats"); 2448 proc_net_remove("rt6_stats");
diff --git a/net/ipv6/tcp_ipv6.c b/net/ipv6/tcp_ipv6.c
index 802a1a6b1037..2546fc9f0a78 100644
--- a/net/ipv6/tcp_ipv6.c
+++ b/net/ipv6/tcp_ipv6.c
@@ -251,6 +251,8 @@ static int tcp_v6_connect(struct sock *sk, struct sockaddr *uaddr,
251 final_p = &final; 251 final_p = &final;
252 } 252 }
253 253
254 security_sk_classify_flow(sk, &fl);
255
254 err = ip6_dst_lookup(sk, &dst, &fl); 256 err = ip6_dst_lookup(sk, &dst, &fl);
255 if (err) 257 if (err)
256 goto failure; 258 goto failure;
@@ -270,7 +272,7 @@ static int tcp_v6_connect(struct sock *sk, struct sockaddr *uaddr,
270 inet->rcv_saddr = LOOPBACK4_IPV6; 272 inet->rcv_saddr = LOOPBACK4_IPV6;
271 273
272 sk->sk_gso_type = SKB_GSO_TCPV6; 274 sk->sk_gso_type = SKB_GSO_TCPV6;
273 __ip6_dst_store(sk, dst, NULL); 275 __ip6_dst_store(sk, dst, NULL, NULL);
274 276
275 icsk->icsk_ext_hdr_len = 0; 277 icsk->icsk_ext_hdr_len = 0;
276 if (np->opt) 278 if (np->opt)
@@ -374,6 +376,7 @@ static void tcp_v6_err(struct sk_buff *skb, struct inet6_skb_parm *opt,
374 fl.oif = sk->sk_bound_dev_if; 376 fl.oif = sk->sk_bound_dev_if;
375 fl.fl_ip_dport = inet->dport; 377 fl.fl_ip_dport = inet->dport;
376 fl.fl_ip_sport = inet->sport; 378 fl.fl_ip_sport = inet->sport;
379 security_skb_classify_flow(skb, &fl);
377 380
378 if ((err = ip6_dst_lookup(sk, &dst, &fl))) { 381 if ((err = ip6_dst_lookup(sk, &dst, &fl))) {
379 sk->sk_err_soft = -err; 382 sk->sk_err_soft = -err;
@@ -467,6 +470,7 @@ static int tcp_v6_send_synack(struct sock *sk, struct request_sock *req,
467 fl.oif = treq->iif; 470 fl.oif = treq->iif;
468 fl.fl_ip_dport = inet_rsk(req)->rmt_port; 471 fl.fl_ip_dport = inet_rsk(req)->rmt_port;
469 fl.fl_ip_sport = inet_sk(sk)->sport; 472 fl.fl_ip_sport = inet_sk(sk)->sport;
473 security_req_classify_flow(req, &fl);
470 474
471 if (dst == NULL) { 475 if (dst == NULL) {
472 opt = np->opt; 476 opt = np->opt;
@@ -541,7 +545,7 @@ static void tcp_v6_send_check(struct sock *sk, int len, struct sk_buff *skb)
541 struct ipv6_pinfo *np = inet6_sk(sk); 545 struct ipv6_pinfo *np = inet6_sk(sk);
542 struct tcphdr *th = skb->h.th; 546 struct tcphdr *th = skb->h.th;
543 547
544 if (skb->ip_summed == CHECKSUM_HW) { 548 if (skb->ip_summed == CHECKSUM_PARTIAL) {
545 th->check = ~csum_ipv6_magic(&np->saddr, &np->daddr, len, IPPROTO_TCP, 0); 549 th->check = ~csum_ipv6_magic(&np->saddr, &np->daddr, len, IPPROTO_TCP, 0);
546 skb->csum = offsetof(struct tcphdr, check); 550 skb->csum = offsetof(struct tcphdr, check);
547 } else { 551 } else {
@@ -566,7 +570,7 @@ static int tcp_v6_gso_send_check(struct sk_buff *skb)
566 th->check = ~csum_ipv6_magic(&ipv6h->saddr, &ipv6h->daddr, skb->len, 570 th->check = ~csum_ipv6_magic(&ipv6h->saddr, &ipv6h->daddr, skb->len,
567 IPPROTO_TCP, 0); 571 IPPROTO_TCP, 0);
568 skb->csum = offsetof(struct tcphdr, check); 572 skb->csum = offsetof(struct tcphdr, check);
569 skb->ip_summed = CHECKSUM_HW; 573 skb->ip_summed = CHECKSUM_PARTIAL;
570 return 0; 574 return 0;
571} 575}
572 576
@@ -625,6 +629,7 @@ static void tcp_v6_send_reset(struct sk_buff *skb)
625 fl.oif = inet6_iif(skb); 629 fl.oif = inet6_iif(skb);
626 fl.fl_ip_dport = t1->dest; 630 fl.fl_ip_dport = t1->dest;
627 fl.fl_ip_sport = t1->source; 631 fl.fl_ip_sport = t1->source;
632 security_skb_classify_flow(skb, &fl);
628 633
629 /* sk = NULL, but it is safe for now. RST socket required. */ 634 /* sk = NULL, but it is safe for now. RST socket required. */
630 if (!ip6_dst_lookup(NULL, &buff->dst, &fl)) { 635 if (!ip6_dst_lookup(NULL, &buff->dst, &fl)) {
@@ -691,6 +696,7 @@ static void tcp_v6_send_ack(struct sk_buff *skb, u32 seq, u32 ack, u32 win, u32
691 fl.oif = inet6_iif(skb); 696 fl.oif = inet6_iif(skb);
692 fl.fl_ip_dport = t1->dest; 697 fl.fl_ip_dport = t1->dest;
693 fl.fl_ip_sport = t1->source; 698 fl.fl_ip_sport = t1->source;
699 security_skb_classify_flow(skb, &fl);
694 700
695 if (!ip6_dst_lookup(NULL, &buff->dst, &fl)) { 701 if (!ip6_dst_lookup(NULL, &buff->dst, &fl)) {
696 if (xfrm_lookup(&buff->dst, &fl, NULL, 0) >= 0) { 702 if (xfrm_lookup(&buff->dst, &fl, NULL, 0) >= 0) {
@@ -820,6 +826,8 @@ static int tcp_v6_conn_request(struct sock *sk, struct sk_buff *skb)
820 826
821 tcp_rsk(req)->snt_isn = isn; 827 tcp_rsk(req)->snt_isn = isn;
822 828
829 security_inet_conn_request(sk, skb, req);
830
823 if (tcp_v6_send_synack(sk, req, NULL)) 831 if (tcp_v6_send_synack(sk, req, NULL))
824 goto drop; 832 goto drop;
825 833
@@ -923,6 +931,7 @@ static struct sock * tcp_v6_syn_recv_sock(struct sock *sk, struct sk_buff *skb,
923 fl.oif = sk->sk_bound_dev_if; 931 fl.oif = sk->sk_bound_dev_if;
924 fl.fl_ip_dport = inet_rsk(req)->rmt_port; 932 fl.fl_ip_dport = inet_rsk(req)->rmt_port;
925 fl.fl_ip_sport = inet_sk(sk)->sport; 933 fl.fl_ip_sport = inet_sk(sk)->sport;
934 security_req_classify_flow(req, &fl);
926 935
927 if (ip6_dst_lookup(sk, &dst, &fl)) 936 if (ip6_dst_lookup(sk, &dst, &fl))
928 goto out; 937 goto out;
@@ -945,7 +954,7 @@ static struct sock * tcp_v6_syn_recv_sock(struct sock *sk, struct sk_buff *skb,
945 */ 954 */
946 955
947 newsk->sk_gso_type = SKB_GSO_TCPV6; 956 newsk->sk_gso_type = SKB_GSO_TCPV6;
948 __ip6_dst_store(newsk, dst, NULL); 957 __ip6_dst_store(newsk, dst, NULL, NULL);
949 958
950 newtcp6sk = (struct tcp6_sock *)newsk; 959 newtcp6sk = (struct tcp6_sock *)newsk;
951 inet_sk(newsk)->pinet6 = &newtcp6sk->inet6; 960 inet_sk(newsk)->pinet6 = &newtcp6sk->inet6;
@@ -1024,7 +1033,7 @@ out:
1024 1033
1025static int tcp_v6_checksum_init(struct sk_buff *skb) 1034static int tcp_v6_checksum_init(struct sk_buff *skb)
1026{ 1035{
1027 if (skb->ip_summed == CHECKSUM_HW) { 1036 if (skb->ip_summed == CHECKSUM_COMPLETE) {
1028 if (!tcp_v6_check(skb->h.th,skb->len,&skb->nh.ipv6h->saddr, 1037 if (!tcp_v6_check(skb->h.th,skb->len,&skb->nh.ipv6h->saddr,
1029 &skb->nh.ipv6h->daddr,skb->csum)) { 1038 &skb->nh.ipv6h->daddr,skb->csum)) {
1030 skb->ip_summed = CHECKSUM_UNNECESSARY; 1039 skb->ip_summed = CHECKSUM_UNNECESSARY;
@@ -1066,7 +1075,7 @@ static int tcp_v6_do_rcv(struct sock *sk, struct sk_buff *skb)
1066 if (skb->protocol == htons(ETH_P_IP)) 1075 if (skb->protocol == htons(ETH_P_IP))
1067 return tcp_v4_do_rcv(sk, skb); 1076 return tcp_v4_do_rcv(sk, skb);
1068 1077
1069 if (sk_filter(sk, skb, 0)) 1078 if (sk_filter(sk, skb))
1070 goto discard; 1079 goto discard;
1071 1080
1072 /* 1081 /*
@@ -1223,7 +1232,7 @@ process:
1223 if (!xfrm6_policy_check(sk, XFRM_POLICY_IN, skb)) 1232 if (!xfrm6_policy_check(sk, XFRM_POLICY_IN, skb))
1224 goto discard_and_relse; 1233 goto discard_and_relse;
1225 1234
1226 if (sk_filter(sk, skb, 0)) 1235 if (sk_filter(sk, skb))
1227 goto discard_and_relse; 1236 goto discard_and_relse;
1228 1237
1229 skb->dev = NULL; 1238 skb->dev = NULL;
diff --git a/net/ipv6/udp.c b/net/ipv6/udp.c
index 3d54f246411e..9662561701d1 100644
--- a/net/ipv6/udp.c
+++ b/net/ipv6/udp.c
@@ -61,81 +61,9 @@
61 61
62DEFINE_SNMP_STAT(struct udp_mib, udp_stats_in6) __read_mostly; 62DEFINE_SNMP_STAT(struct udp_mib, udp_stats_in6) __read_mostly;
63 63
64/* Grrr, addr_type already calculated by caller, but I don't want 64static inline int udp_v6_get_port(struct sock *sk, unsigned short snum)
65 * to add some silly "cookie" argument to this method just for that.
66 */
67static int udp_v6_get_port(struct sock *sk, unsigned short snum)
68{ 65{
69 struct sock *sk2; 66 return udp_get_port(sk, snum, ipv6_rcv_saddr_equal);
70 struct hlist_node *node;
71
72 write_lock_bh(&udp_hash_lock);
73 if (snum == 0) {
74 int best_size_so_far, best, result, i;
75
76 if (udp_port_rover > sysctl_local_port_range[1] ||
77 udp_port_rover < sysctl_local_port_range[0])
78 udp_port_rover = sysctl_local_port_range[0];
79 best_size_so_far = 32767;
80 best = result = udp_port_rover;
81 for (i = 0; i < UDP_HTABLE_SIZE; i++, result++) {
82 int size;
83 struct hlist_head *list;
84
85 list = &udp_hash[result & (UDP_HTABLE_SIZE - 1)];
86 if (hlist_empty(list)) {
87 if (result > sysctl_local_port_range[1])
88 result = sysctl_local_port_range[0] +
89 ((result - sysctl_local_port_range[0]) &
90 (UDP_HTABLE_SIZE - 1));
91 goto gotit;
92 }
93 size = 0;
94 sk_for_each(sk2, node, list)
95 if (++size >= best_size_so_far)
96 goto next;
97 best_size_so_far = size;
98 best = result;
99 next:;
100 }
101 result = best;
102 for(i = 0; i < (1 << 16) / UDP_HTABLE_SIZE; i++, result += UDP_HTABLE_SIZE) {
103 if (result > sysctl_local_port_range[1])
104 result = sysctl_local_port_range[0]
105 + ((result - sysctl_local_port_range[0]) &
106 (UDP_HTABLE_SIZE - 1));
107 if (!udp_lport_inuse(result))
108 break;
109 }
110 if (i >= (1 << 16) / UDP_HTABLE_SIZE)
111 goto fail;
112gotit:
113 udp_port_rover = snum = result;
114 } else {
115 sk_for_each(sk2, node,
116 &udp_hash[snum & (UDP_HTABLE_SIZE - 1)]) {
117 if (inet_sk(sk2)->num == snum &&
118 sk2 != sk &&
119 (!sk2->sk_bound_dev_if ||
120 !sk->sk_bound_dev_if ||
121 sk2->sk_bound_dev_if == sk->sk_bound_dev_if) &&
122 (!sk2->sk_reuse || !sk->sk_reuse) &&
123 ipv6_rcv_saddr_equal(sk, sk2))
124 goto fail;
125 }
126 }
127
128 inet_sk(sk)->num = snum;
129 if (sk_unhashed(sk)) {
130 sk_add_node(sk, &udp_hash[snum & (UDP_HTABLE_SIZE - 1)]);
131 sock_prot_inc_use(sk->sk_prot);
132 }
133 write_unlock_bh(&udp_hash_lock);
134 return 0;
135
136fail:
137 write_unlock_bh(&udp_hash_lock);
138 return 1;
139} 67}
140 68
141static void udp_v6_hash(struct sock *sk) 69static void udp_v6_hash(struct sock *sk)
@@ -345,6 +273,8 @@ out:
345 273
346static inline int udpv6_queue_rcv_skb(struct sock * sk, struct sk_buff *skb) 274static inline int udpv6_queue_rcv_skb(struct sock * sk, struct sk_buff *skb)
347{ 275{
276 int rc;
277
348 if (!xfrm6_policy_check(sk, XFRM_POLICY_IN, skb)) { 278 if (!xfrm6_policy_check(sk, XFRM_POLICY_IN, skb)) {
349 kfree_skb(skb); 279 kfree_skb(skb);
350 return -1; 280 return -1;
@@ -356,7 +286,10 @@ static inline int udpv6_queue_rcv_skb(struct sock * sk, struct sk_buff *skb)
356 return 0; 286 return 0;
357 } 287 }
358 288
359 if (sock_queue_rcv_skb(sk,skb)<0) { 289 if ((rc = sock_queue_rcv_skb(sk,skb)) < 0) {
290 /* Note that an ENOMEM error is charged twice */
291 if (rc == -ENOMEM)
292 UDP6_INC_STATS_BH(UDP_MIB_RCVBUFERRORS);
360 UDP6_INC_STATS_BH(UDP_MIB_INERRORS); 293 UDP6_INC_STATS_BH(UDP_MIB_INERRORS);
361 kfree_skb(skb); 294 kfree_skb(skb);
362 return 0; 295 return 0;
@@ -475,7 +408,7 @@ static int udpv6_rcv(struct sk_buff **pskb)
475 uh = skb->h.uh; 408 uh = skb->h.uh;
476 } 409 }
477 410
478 if (skb->ip_summed == CHECKSUM_HW && 411 if (skb->ip_summed == CHECKSUM_COMPLETE &&
479 !csum_ipv6_magic(saddr, daddr, ulen, IPPROTO_UDP, skb->csum)) 412 !csum_ipv6_magic(saddr, daddr, ulen, IPPROTO_UDP, skb->csum))
480 skb->ip_summed = CHECKSUM_UNNECESSARY; 413 skb->ip_summed = CHECKSUM_UNNECESSARY;
481 414
@@ -782,6 +715,8 @@ do_udp_sendmsg:
782 connected = 0; 715 connected = 0;
783 } 716 }
784 717
718 security_sk_classify_flow(sk, fl);
719
785 err = ip6_sk_dst_lookup(sk, &dst, fl); 720 err = ip6_sk_dst_lookup(sk, &dst, fl);
786 if (err) 721 if (err)
787 goto out; 722 goto out;
@@ -840,7 +775,12 @@ do_append_data:
840 if (connected) { 775 if (connected) {
841 ip6_dst_store(sk, dst, 776 ip6_dst_store(sk, dst,
842 ipv6_addr_equal(&fl->fl6_dst, &np->daddr) ? 777 ipv6_addr_equal(&fl->fl6_dst, &np->daddr) ?
843 &np->daddr : NULL); 778 &np->daddr : NULL,
779#ifdef CONFIG_IPV6_SUBTREES
780 ipv6_addr_equal(&fl->fl6_src, &np->saddr) ?
781 &np->saddr :
782#endif
783 NULL);
844 } else { 784 } else {
845 dst_release(dst); 785 dst_release(dst);
846 } 786 }
@@ -855,6 +795,16 @@ out:
855 UDP6_INC_STATS_USER(UDP_MIB_OUTDATAGRAMS); 795 UDP6_INC_STATS_USER(UDP_MIB_OUTDATAGRAMS);
856 return len; 796 return len;
857 } 797 }
798 /*
799 * ENOBUFS = no kernel mem, SOCK_NOSPACE = no sndbuf space. Reporting
800 * ENOBUFS might not be good (it's not tunable per se), but otherwise
801 * we don't have a good statistic (IpOutDiscards but it can be too many
802 * things). We could add another new stat but at least for now that
803 * seems like overkill.
804 */
805 if (err == -ENOBUFS || test_bit(SOCK_NOSPACE, &sk->sk_socket->flags)) {
806 UDP6_INC_STATS_USER(UDP_MIB_SNDBUFERRORS);
807 }
858 return err; 808 return err;
859 809
860do_confirm: 810do_confirm:
diff --git a/net/ipv6/xfrm6_input.c b/net/ipv6/xfrm6_input.c
index 0405d74ff910..a40a05789013 100644
--- a/net/ipv6/xfrm6_input.c
+++ b/net/ipv6/xfrm6_input.c
@@ -72,7 +72,7 @@ int xfrm6_rcv_spi(struct sk_buff *skb, u32 spi)
72 if (x->mode->input(x, skb)) 72 if (x->mode->input(x, skb))
73 goto drop; 73 goto drop;
74 74
75 if (x->props.mode) { /* XXX */ 75 if (x->props.mode == XFRM_MODE_TUNNEL) { /* XXX */
76 decaps = 1; 76 decaps = 1;
77 break; 77 break;
78 } 78 }
@@ -138,3 +138,111 @@ int xfrm6_rcv(struct sk_buff **pskb)
138{ 138{
139 return xfrm6_rcv_spi(*pskb, 0); 139 return xfrm6_rcv_spi(*pskb, 0);
140} 140}
141
142int xfrm6_input_addr(struct sk_buff *skb, xfrm_address_t *daddr,
143 xfrm_address_t *saddr, u8 proto)
144{
145 struct xfrm_state *x = NULL;
146 int wildcard = 0;
147 struct in6_addr any;
148 xfrm_address_t *xany;
149 struct xfrm_state *xfrm_vec_one = NULL;
150 int nh = 0;
151 int i = 0;
152
153 ipv6_addr_set(&any, 0, 0, 0, 0);
154 xany = (xfrm_address_t *)&any;
155
156 for (i = 0; i < 3; i++) {
157 xfrm_address_t *dst, *src;
158 switch (i) {
159 case 0:
160 dst = daddr;
161 src = saddr;
162 break;
163 case 1:
164 /* lookup state with wild-card source address */
165 wildcard = 1;
166 dst = daddr;
167 src = xany;
168 break;
169 case 2:
170 default:
171 /* lookup state with wild-card addresses */
172 wildcard = 1; /* XXX */
173 dst = xany;
174 src = xany;
175 break;
176 }
177
178 x = xfrm_state_lookup_byaddr(dst, src, proto, AF_INET6);
179 if (!x)
180 continue;
181
182 spin_lock(&x->lock);
183
184 if (wildcard) {
185 if ((x->props.flags & XFRM_STATE_WILDRECV) == 0) {
186 spin_unlock(&x->lock);
187 xfrm_state_put(x);
188 x = NULL;
189 continue;
190 }
191 }
192
193 if (unlikely(x->km.state != XFRM_STATE_VALID)) {
194 spin_unlock(&x->lock);
195 xfrm_state_put(x);
196 x = NULL;
197 continue;
198 }
199 if (xfrm_state_check_expire(x)) {
200 spin_unlock(&x->lock);
201 xfrm_state_put(x);
202 x = NULL;
203 continue;
204 }
205
206 nh = x->type->input(x, skb);
207 if (nh <= 0) {
208 spin_unlock(&x->lock);
209 xfrm_state_put(x);
210 x = NULL;
211 continue;
212 }
213
214 x->curlft.bytes += skb->len;
215 x->curlft.packets++;
216
217 spin_unlock(&x->lock);
218
219 xfrm_vec_one = x;
220 break;
221 }
222
223 if (!xfrm_vec_one)
224 goto drop;
225
226 /* Allocate new secpath or COW existing one. */
227 if (!skb->sp || atomic_read(&skb->sp->refcnt) != 1) {
228 struct sec_path *sp;
229 sp = secpath_dup(skb->sp);
230 if (!sp)
231 goto drop;
232 if (skb->sp)
233 secpath_put(skb->sp);
234 skb->sp = sp;
235 }
236
237 if (1 + skb->sp->len > XFRM_MAX_DEPTH)
238 goto drop;
239
240 skb->sp->xvec[skb->sp->len] = xfrm_vec_one;
241 skb->sp->len ++;
242
243 return 1;
244drop:
245 if (xfrm_vec_one)
246 xfrm_state_put(xfrm_vec_one);
247 return -1;
248}
diff --git a/net/ipv6/xfrm6_mode_ro.c b/net/ipv6/xfrm6_mode_ro.c
new file mode 100644
index 000000000000..6031c16d46ca
--- /dev/null
+++ b/net/ipv6/xfrm6_mode_ro.c
@@ -0,0 +1,93 @@
1/*
2 * xfrm6_mode_ro.c - Route optimization mode for IPv6.
3 *
4 * Copyright (C)2003-2006 Helsinki University of Technology
5 * Copyright (C)2003-2006 USAGI/WIDE Project
6 *
7 * This program is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License as published by
9 * the Free Software Foundation; either version 2 of the License, or
10 * (at your option) any later version.
11 *
12 * This program is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU General Public License for more details.
16 *
17 * You should have received a copy of the GNU General Public License
18 * along with this program; if not, write to the Free Software
19 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
20 */
21/*
22 * Authors:
23 * Noriaki TAKAMIYA @USAGI
24 * Masahide NAKAMURA @USAGI
25 */
26
27#include <linux/init.h>
28#include <linux/kernel.h>
29#include <linux/module.h>
30#include <linux/skbuff.h>
31#include <linux/stringify.h>
32#include <net/ipv6.h>
33#include <net/xfrm.h>
34
35/* Add route optimization header space.
36 *
37 * The IP header and mutable extension headers will be moved forward to make
38 * space for the route optimization header.
39 *
40 * On exit, skb->h will be set to the start of the encapsulation header to be
41 * filled in by x->type->output and skb->nh will be set to the nextheader field
42 * of the extension header directly preceding the encapsulation header, or in
43 * its absence, that of the top IP header. The value of skb->data will always
44 * point to the top IP header.
45 */
46static int xfrm6_ro_output(struct xfrm_state *x, struct sk_buff *skb)
47{
48 struct ipv6hdr *iph;
49 u8 *prevhdr;
50 int hdr_len;
51
52 skb_push(skb, x->props.header_len);
53 iph = skb->nh.ipv6h;
54
55 hdr_len = x->type->hdr_offset(x, skb, &prevhdr);
56 skb->nh.raw = prevhdr - x->props.header_len;
57 skb->h.raw = skb->data + hdr_len;
58 memmove(skb->data, iph, hdr_len);
59 return 0;
60}
61
62/*
63 * Do nothing about routing optimization header unlike IPsec.
64 */
65static int xfrm6_ro_input(struct xfrm_state *x, struct sk_buff *skb)
66{
67 return 0;
68}
69
70static struct xfrm_mode xfrm6_ro_mode = {
71 .input = xfrm6_ro_input,
72 .output = xfrm6_ro_output,
73 .owner = THIS_MODULE,
74 .encap = XFRM_MODE_ROUTEOPTIMIZATION,
75};
76
77static int __init xfrm6_ro_init(void)
78{
79 return xfrm_register_mode(&xfrm6_ro_mode, AF_INET6);
80}
81
82static void __exit xfrm6_ro_exit(void)
83{
84 int err;
85
86 err = xfrm_unregister_mode(&xfrm6_ro_mode, AF_INET6);
87 BUG_ON(err);
88}
89
90module_init(xfrm6_ro_init);
91module_exit(xfrm6_ro_exit);
92MODULE_LICENSE("GPL");
93MODULE_ALIAS_XFRM_MODE(AF_INET6, XFRM_MODE_ROUTEOPTIMIZATION);
diff --git a/net/ipv6/xfrm6_mode_transport.c b/net/ipv6/xfrm6_mode_transport.c
index 711d713e36d8..3a4b39b12bad 100644
--- a/net/ipv6/xfrm6_mode_transport.c
+++ b/net/ipv6/xfrm6_mode_transport.c
@@ -25,9 +25,8 @@
25 * its absence, that of the top IP header. The value of skb->data will always 25 * its absence, that of the top IP header. The value of skb->data will always
26 * point to the top IP header. 26 * point to the top IP header.
27 */ 27 */
28static int xfrm6_transport_output(struct sk_buff *skb) 28static int xfrm6_transport_output(struct xfrm_state *x, struct sk_buff *skb)
29{ 29{
30 struct xfrm_state *x = skb->dst->xfrm;
31 struct ipv6hdr *iph; 30 struct ipv6hdr *iph;
32 u8 *prevhdr; 31 u8 *prevhdr;
33 int hdr_len; 32 int hdr_len;
@@ -35,7 +34,7 @@ static int xfrm6_transport_output(struct sk_buff *skb)
35 skb_push(skb, x->props.header_len); 34 skb_push(skb, x->props.header_len);
36 iph = skb->nh.ipv6h; 35 iph = skb->nh.ipv6h;
37 36
38 hdr_len = ip6_find_1stfragopt(skb, &prevhdr); 37 hdr_len = x->type->hdr_offset(x, skb, &prevhdr);
39 skb->nh.raw = prevhdr - x->props.header_len; 38 skb->nh.raw = prevhdr - x->props.header_len;
40 skb->h.raw = skb->data + hdr_len; 39 skb->h.raw = skb->data + hdr_len;
41 memmove(skb->data, iph, hdr_len); 40 memmove(skb->data, iph, hdr_len);
diff --git a/net/ipv6/xfrm6_mode_tunnel.c b/net/ipv6/xfrm6_mode_tunnel.c
index 8af79be2edca..5e7d8a7d6414 100644
--- a/net/ipv6/xfrm6_mode_tunnel.c
+++ b/net/ipv6/xfrm6_mode_tunnel.c
@@ -37,10 +37,9 @@ static inline void ipip6_ecn_decapsulate(struct sk_buff *skb)
37 * its absence, that of the top IP header. The value of skb->data will always 37 * its absence, that of the top IP header. The value of skb->data will always
38 * point to the top IP header. 38 * point to the top IP header.
39 */ 39 */
40static int xfrm6_tunnel_output(struct sk_buff *skb) 40static int xfrm6_tunnel_output(struct xfrm_state *x, struct sk_buff *skb)
41{ 41{
42 struct dst_entry *dst = skb->dst; 42 struct dst_entry *dst = skb->dst;
43 struct xfrm_state *x = dst->xfrm;
44 struct ipv6hdr *iph, *top_iph; 43 struct ipv6hdr *iph, *top_iph;
45 int dsfield; 44 int dsfield;
46 45
diff --git a/net/ipv6/xfrm6_output.c b/net/ipv6/xfrm6_output.c
index c8c8b44a0f58..c260ea104c52 100644
--- a/net/ipv6/xfrm6_output.c
+++ b/net/ipv6/xfrm6_output.c
@@ -17,6 +17,12 @@
17#include <net/ipv6.h> 17#include <net/ipv6.h>
18#include <net/xfrm.h> 18#include <net/xfrm.h>
19 19
20int xfrm6_find_1stfragopt(struct xfrm_state *x, struct sk_buff *skb,
21 u8 **prevhdr)
22{
23 return ip6_find_1stfragopt(skb, prevhdr);
24}
25
20static int xfrm6_tunnel_check_size(struct sk_buff *skb) 26static int xfrm6_tunnel_check_size(struct sk_buff *skb)
21{ 27{
22 int mtu, ret = 0; 28 int mtu, ret = 0;
@@ -41,13 +47,13 @@ static int xfrm6_output_one(struct sk_buff *skb)
41 struct xfrm_state *x = dst->xfrm; 47 struct xfrm_state *x = dst->xfrm;
42 int err; 48 int err;
43 49
44 if (skb->ip_summed == CHECKSUM_HW) { 50 if (skb->ip_summed == CHECKSUM_PARTIAL) {
45 err = skb_checksum_help(skb, 0); 51 err = skb_checksum_help(skb);
46 if (err) 52 if (err)
47 goto error_nolock; 53 goto error_nolock;
48 } 54 }
49 55
50 if (x->props.mode) { 56 if (x->props.mode == XFRM_MODE_TUNNEL) {
51 err = xfrm6_tunnel_check_size(skb); 57 err = xfrm6_tunnel_check_size(skb);
52 if (err) 58 if (err)
53 goto error_nolock; 59 goto error_nolock;
@@ -59,7 +65,7 @@ static int xfrm6_output_one(struct sk_buff *skb)
59 if (err) 65 if (err)
60 goto error; 66 goto error;
61 67
62 err = x->mode->output(skb); 68 err = x->mode->output(x, skb);
63 if (err) 69 if (err)
64 goto error; 70 goto error;
65 71
@@ -69,6 +75,8 @@ static int xfrm6_output_one(struct sk_buff *skb)
69 75
70 x->curlft.bytes += skb->len; 76 x->curlft.bytes += skb->len;
71 x->curlft.packets++; 77 x->curlft.packets++;
78 if (x->props.mode == XFRM_MODE_ROUTEOPTIMIZATION)
79 x->lastused = (u64)xtime.tv_sec;
72 80
73 spin_unlock_bh(&x->lock); 81 spin_unlock_bh(&x->lock);
74 82
@@ -80,7 +88,7 @@ static int xfrm6_output_one(struct sk_buff *skb)
80 } 88 }
81 dst = skb->dst; 89 dst = skb->dst;
82 x = dst->xfrm; 90 x = dst->xfrm;
83 } while (x && !x->props.mode); 91 } while (x && (x->props.mode != XFRM_MODE_TUNNEL));
84 92
85 IP6CB(skb)->flags |= IP6SKB_XFRM_TRANSFORMED; 93 IP6CB(skb)->flags |= IP6SKB_XFRM_TRANSFORMED;
86 err = 0; 94 err = 0;
diff --git a/net/ipv6/xfrm6_policy.c b/net/ipv6/xfrm6_policy.c
index 73cd250aecbb..6a252e2134d1 100644
--- a/net/ipv6/xfrm6_policy.c
+++ b/net/ipv6/xfrm6_policy.c
@@ -18,6 +18,9 @@
18#include <net/ip.h> 18#include <net/ip.h>
19#include <net/ipv6.h> 19#include <net/ipv6.h>
20#include <net/ip6_route.h> 20#include <net/ip6_route.h>
21#ifdef CONFIG_IPV6_MIP6
22#include <net/mip6.h>
23#endif
21 24
22static struct dst_ops xfrm6_dst_ops; 25static struct dst_ops xfrm6_dst_ops;
23static struct xfrm_policy_afinfo xfrm6_policy_afinfo; 26static struct xfrm_policy_afinfo xfrm6_policy_afinfo;
@@ -31,6 +34,26 @@ static int xfrm6_dst_lookup(struct xfrm_dst **dst, struct flowi *fl)
31 return err; 34 return err;
32} 35}
33 36
37static int xfrm6_get_saddr(xfrm_address_t *saddr, xfrm_address_t *daddr)
38{
39 struct rt6_info *rt;
40 struct flowi fl_tunnel = {
41 .nl_u = {
42 .ip6_u = {
43 .daddr = *(struct in6_addr *)&daddr->a6,
44 },
45 },
46 };
47
48 if (!xfrm6_dst_lookup((struct xfrm_dst **)&rt, &fl_tunnel)) {
49 ipv6_get_saddr(&rt->u.dst, (struct in6_addr *)&daddr->a6,
50 (struct in6_addr *)&saddr->a6);
51 dst_release(&rt->u.dst);
52 return 0;
53 }
54 return -EHOSTUNREACH;
55}
56
34static struct dst_entry * 57static struct dst_entry *
35__xfrm6_find_bundle(struct flowi *fl, struct xfrm_policy *policy) 58__xfrm6_find_bundle(struct flowi *fl, struct xfrm_policy *policy)
36{ 59{
@@ -50,7 +73,9 @@ __xfrm6_find_bundle(struct flowi *fl, struct xfrm_policy *policy)
50 xdst->u.rt6.rt6i_src.plen); 73 xdst->u.rt6.rt6i_src.plen);
51 if (ipv6_addr_equal(&xdst->u.rt6.rt6i_dst.addr, &fl_dst_prefix) && 74 if (ipv6_addr_equal(&xdst->u.rt6.rt6i_dst.addr, &fl_dst_prefix) &&
52 ipv6_addr_equal(&xdst->u.rt6.rt6i_src.addr, &fl_src_prefix) && 75 ipv6_addr_equal(&xdst->u.rt6.rt6i_src.addr, &fl_src_prefix) &&
53 xfrm_bundle_ok(xdst, fl, AF_INET6)) { 76 xfrm_bundle_ok(xdst, fl, AF_INET6,
77 (xdst->u.rt6.rt6i_dst.plen != 128 ||
78 xdst->u.rt6.rt6i_src.plen != 128))) {
54 dst_clone(dst); 79 dst_clone(dst);
55 break; 80 break;
56 } 81 }
@@ -59,6 +84,40 @@ __xfrm6_find_bundle(struct flowi *fl, struct xfrm_policy *policy)
59 return dst; 84 return dst;
60} 85}
61 86
87static inline struct in6_addr*
88__xfrm6_bundle_addr_remote(struct xfrm_state *x, struct in6_addr *addr)
89{
90 return (x->type->remote_addr) ?
91 (struct in6_addr*)x->type->remote_addr(x, (xfrm_address_t *)addr) :
92 (struct in6_addr*)&x->id.daddr;
93}
94
95static inline struct in6_addr*
96__xfrm6_bundle_addr_local(struct xfrm_state *x, struct in6_addr *addr)
97{
98 return (x->type->local_addr) ?
99 (struct in6_addr*)x->type->local_addr(x, (xfrm_address_t *)addr) :
100 (struct in6_addr*)&x->props.saddr;
101}
102
103static inline void
104__xfrm6_bundle_len_inc(int *len, int *nflen, struct xfrm_state *x)
105{
106 if (x->type->flags & XFRM_TYPE_NON_FRAGMENT)
107 *nflen += x->props.header_len;
108 else
109 *len += x->props.header_len;
110}
111
112static inline void
113__xfrm6_bundle_len_dec(int *len, int *nflen, struct xfrm_state *x)
114{
115 if (x->type->flags & XFRM_TYPE_NON_FRAGMENT)
116 *nflen -= x->props.header_len;
117 else
118 *len -= x->props.header_len;
119}
120
62/* Allocate chain of dst_entry's, attach known xfrm's, calculate 121/* Allocate chain of dst_entry's, attach known xfrm's, calculate
63 * all the metrics... Shortly, bundle a bundle. 122 * all the metrics... Shortly, bundle a bundle.
64 */ 123 */
@@ -83,6 +142,7 @@ __xfrm6_bundle_create(struct xfrm_policy *policy, struct xfrm_state **xfrm, int
83 int i; 142 int i;
84 int err = 0; 143 int err = 0;
85 int header_len = 0; 144 int header_len = 0;
145 int nfheader_len = 0;
86 int trailer_len = 0; 146 int trailer_len = 0;
87 147
88 dst = dst_prev = NULL; 148 dst = dst_prev = NULL;
@@ -109,17 +169,18 @@ __xfrm6_bundle_create(struct xfrm_policy *policy, struct xfrm_state **xfrm, int
109 169
110 xdst = (struct xfrm_dst *)dst1; 170 xdst = (struct xfrm_dst *)dst1;
111 xdst->route = &rt->u.dst; 171 xdst->route = &rt->u.dst;
172 xdst->genid = xfrm[i]->genid;
112 if (rt->rt6i_node) 173 if (rt->rt6i_node)
113 xdst->route_cookie = rt->rt6i_node->fn_sernum; 174 xdst->route_cookie = rt->rt6i_node->fn_sernum;
114 175
115 dst1->next = dst_prev; 176 dst1->next = dst_prev;
116 dst_prev = dst1; 177 dst_prev = dst1;
117 if (xfrm[i]->props.mode) { 178 if (xfrm[i]->props.mode != XFRM_MODE_TRANSPORT) {
118 remote = (struct in6_addr*)&xfrm[i]->id.daddr; 179 remote = __xfrm6_bundle_addr_remote(xfrm[i], remote);
119 local = (struct in6_addr*)&xfrm[i]->props.saddr; 180 local = __xfrm6_bundle_addr_local(xfrm[i], local);
120 tunnel = 1; 181 tunnel = 1;
121 } 182 }
122 header_len += xfrm[i]->props.header_len; 183 __xfrm6_bundle_len_inc(&header_len, &nfheader_len, xfrm[i]);
123 trailer_len += xfrm[i]->props.trailer_len; 184 trailer_len += xfrm[i]->props.trailer_len;
124 185
125 if (tunnel) { 186 if (tunnel) {
@@ -154,6 +215,7 @@ __xfrm6_bundle_create(struct xfrm_policy *policy, struct xfrm_state **xfrm, int
154 dst_prev->flags |= DST_HOST; 215 dst_prev->flags |= DST_HOST;
155 dst_prev->lastuse = jiffies; 216 dst_prev->lastuse = jiffies;
156 dst_prev->header_len = header_len; 217 dst_prev->header_len = header_len;
218 dst_prev->nfheader_len = nfheader_len;
157 dst_prev->trailer_len = trailer_len; 219 dst_prev->trailer_len = trailer_len;
158 memcpy(&dst_prev->metrics, &x->route->metrics, sizeof(dst_prev->metrics)); 220 memcpy(&dst_prev->metrics, &x->route->metrics, sizeof(dst_prev->metrics));
159 221
@@ -172,7 +234,7 @@ __xfrm6_bundle_create(struct xfrm_policy *policy, struct xfrm_state **xfrm, int
172 x->u.rt6.rt6i_src = rt0->rt6i_src; 234 x->u.rt6.rt6i_src = rt0->rt6i_src;
173 x->u.rt6.rt6i_idev = rt0->rt6i_idev; 235 x->u.rt6.rt6i_idev = rt0->rt6i_idev;
174 in6_dev_hold(rt0->rt6i_idev); 236 in6_dev_hold(rt0->rt6i_idev);
175 header_len -= x->u.dst.xfrm->props.header_len; 237 __xfrm6_bundle_len_dec(&header_len, &nfheader_len, x->u.dst.xfrm);
176 trailer_len -= x->u.dst.xfrm->props.trailer_len; 238 trailer_len -= x->u.dst.xfrm->props.trailer_len;
177 } 239 }
178 240
@@ -232,6 +294,18 @@ _decode_session6(struct sk_buff *skb, struct flowi *fl)
232 fl->proto = nexthdr; 294 fl->proto = nexthdr;
233 return; 295 return;
234 296
297#ifdef CONFIG_IPV6_MIP6
298 case IPPROTO_MH:
299 if (pskb_may_pull(skb, skb->nh.raw + offset + 3 - skb->data)) {
300 struct ip6_mh *mh;
301 mh = (struct ip6_mh *)exthdr;
302
303 fl->fl_mh_type = mh->ip6mh_type;
304 }
305 fl->proto = nexthdr;
306 return;
307#endif
308
235 /* XXX Why are there these headers? */ 309 /* XXX Why are there these headers? */
236 case IPPROTO_AH: 310 case IPPROTO_AH:
237 case IPPROTO_ESP: 311 case IPPROTO_ESP:
@@ -308,6 +382,7 @@ static struct xfrm_policy_afinfo xfrm6_policy_afinfo = {
308 .family = AF_INET6, 382 .family = AF_INET6,
309 .dst_ops = &xfrm6_dst_ops, 383 .dst_ops = &xfrm6_dst_ops,
310 .dst_lookup = xfrm6_dst_lookup, 384 .dst_lookup = xfrm6_dst_lookup,
385 .get_saddr = xfrm6_get_saddr,
311 .find_bundle = __xfrm6_find_bundle, 386 .find_bundle = __xfrm6_find_bundle,
312 .bundle_create = __xfrm6_bundle_create, 387 .bundle_create = __xfrm6_bundle_create,
313 .decode_session = _decode_session6, 388 .decode_session = _decode_session6,
diff --git a/net/ipv6/xfrm6_state.c b/net/ipv6/xfrm6_state.c
index b33296b3f6de..711bfafb2472 100644
--- a/net/ipv6/xfrm6_state.c
+++ b/net/ipv6/xfrm6_state.c
@@ -42,102 +42,135 @@ __xfrm6_init_tempsel(struct xfrm_state *x, struct flowi *fl,
42 memcpy(&x->props.saddr, &tmpl->saddr, sizeof(x->props.saddr)); 42 memcpy(&x->props.saddr, &tmpl->saddr, sizeof(x->props.saddr));
43 if (ipv6_addr_any((struct in6_addr*)&x->props.saddr)) 43 if (ipv6_addr_any((struct in6_addr*)&x->props.saddr))
44 memcpy(&x->props.saddr, saddr, sizeof(x->props.saddr)); 44 memcpy(&x->props.saddr, saddr, sizeof(x->props.saddr));
45 if (tmpl->mode && ipv6_addr_any((struct in6_addr*)&x->props.saddr)) {
46 struct rt6_info *rt;
47 struct flowi fl_tunnel = {
48 .nl_u = {
49 .ip6_u = {
50 .daddr = *(struct in6_addr *)daddr,
51 }
52 }
53 };
54 if (!xfrm_dst_lookup((struct xfrm_dst **)&rt,
55 &fl_tunnel, AF_INET6)) {
56 ipv6_get_saddr(&rt->u.dst, (struct in6_addr *)daddr,
57 (struct in6_addr *)&x->props.saddr);
58 dst_release(&rt->u.dst);
59 }
60 }
61 x->props.mode = tmpl->mode; 45 x->props.mode = tmpl->mode;
62 x->props.reqid = tmpl->reqid; 46 x->props.reqid = tmpl->reqid;
63 x->props.family = AF_INET6; 47 x->props.family = AF_INET6;
64} 48}
65 49
66static struct xfrm_state * 50static int
67__xfrm6_state_lookup(xfrm_address_t *daddr, u32 spi, u8 proto) 51__xfrm6_state_sort(struct xfrm_state **dst, struct xfrm_state **src, int n)
68{ 52{
69 unsigned h = __xfrm6_spi_hash(daddr, spi, proto); 53 int i;
70 struct xfrm_state *x; 54 int j = 0;
71 55
72 list_for_each_entry(x, xfrm6_state_afinfo.state_byspi+h, byspi) { 56 /* Rule 1: select IPsec transport except AH */
73 if (x->props.family == AF_INET6 && 57 for (i = 0; i < n; i++) {
74 spi == x->id.spi && 58 if (src[i]->props.mode == XFRM_MODE_TRANSPORT &&
75 ipv6_addr_equal((struct in6_addr *)daddr, (struct in6_addr *)x->id.daddr.a6) && 59 src[i]->id.proto != IPPROTO_AH) {
76 proto == x->id.proto) { 60 dst[j++] = src[i];
77 xfrm_state_hold(x); 61 src[i] = NULL;
78 return x; 62 }
63 }
64 if (j == n)
65 goto end;
66
67 /* Rule 2: select MIPv6 RO or inbound trigger */
68#ifdef CONFIG_IPV6_MIP6
69 for (i = 0; i < n; i++) {
70 if (src[i] &&
71 (src[i]->props.mode == XFRM_MODE_ROUTEOPTIMIZATION ||
72 src[i]->props.mode == XFRM_MODE_IN_TRIGGER)) {
73 dst[j++] = src[i];
74 src[i] = NULL;
75 }
76 }
77 if (j == n)
78 goto end;
79#endif
80
81 /* Rule 3: select IPsec transport AH */
82 for (i = 0; i < n; i++) {
83 if (src[i] &&
84 src[i]->props.mode == XFRM_MODE_TRANSPORT &&
85 src[i]->id.proto == IPPROTO_AH) {
86 dst[j++] = src[i];
87 src[i] = NULL;
79 } 88 }
80 } 89 }
81 return NULL; 90 if (j == n)
91 goto end;
92
93 /* Rule 4: select IPsec tunnel */
94 for (i = 0; i < n; i++) {
95 if (src[i] &&
96 src[i]->props.mode == XFRM_MODE_TUNNEL) {
97 dst[j++] = src[i];
98 src[i] = NULL;
99 }
100 }
101 if (likely(j == n))
102 goto end;
103
104 /* Final rule */
105 for (i = 0; i < n; i++) {
106 if (src[i]) {
107 dst[j++] = src[i];
108 src[i] = NULL;
109 }
110 }
111
112 end:
113 return 0;
82} 114}
83 115
84static struct xfrm_state * 116static int
85__xfrm6_find_acq(u8 mode, u32 reqid, u8 proto, 117__xfrm6_tmpl_sort(struct xfrm_tmpl **dst, struct xfrm_tmpl **src, int n)
86 xfrm_address_t *daddr, xfrm_address_t *saddr,
87 int create)
88{ 118{
89 struct xfrm_state *x, *x0; 119 int i;
90 unsigned h = __xfrm6_dst_hash(daddr); 120 int j = 0;
91 121
92 x0 = NULL; 122 /* Rule 1: select IPsec transport */
93 123 for (i = 0; i < n; i++) {
94 list_for_each_entry(x, xfrm6_state_afinfo.state_bydst+h, bydst) { 124 if (src[i]->mode == XFRM_MODE_TRANSPORT) {
95 if (x->props.family == AF_INET6 && 125 dst[j++] = src[i];
96 ipv6_addr_equal((struct in6_addr *)daddr, (struct in6_addr *)x->id.daddr.a6) && 126 src[i] = NULL;
97 mode == x->props.mode && 127 }
98 proto == x->id.proto &&
99 ipv6_addr_equal((struct in6_addr *)saddr, (struct in6_addr *)x->props.saddr.a6) &&
100 reqid == x->props.reqid &&
101 x->km.state == XFRM_STATE_ACQ &&
102 !x->id.spi) {
103 x0 = x;
104 break;
105 }
106 } 128 }
107 if (!x0 && create && (x0 = xfrm_state_alloc()) != NULL) { 129 if (j == n)
108 ipv6_addr_copy((struct in6_addr *)x0->sel.daddr.a6, 130 goto end;
109 (struct in6_addr *)daddr); 131
110 ipv6_addr_copy((struct in6_addr *)x0->sel.saddr.a6, 132 /* Rule 2: select MIPv6 RO or inbound trigger */
111 (struct in6_addr *)saddr); 133#ifdef CONFIG_IPV6_MIP6
112 x0->sel.prefixlen_d = 128; 134 for (i = 0; i < n; i++) {
113 x0->sel.prefixlen_s = 128; 135 if (src[i] &&
114 ipv6_addr_copy((struct in6_addr *)x0->props.saddr.a6, 136 (src[i]->mode == XFRM_MODE_ROUTEOPTIMIZATION ||
115 (struct in6_addr *)saddr); 137 src[i]->mode == XFRM_MODE_IN_TRIGGER)) {
116 x0->km.state = XFRM_STATE_ACQ; 138 dst[j++] = src[i];
117 ipv6_addr_copy((struct in6_addr *)x0->id.daddr.a6, 139 src[i] = NULL;
118 (struct in6_addr *)daddr); 140 }
119 x0->id.proto = proto;
120 x0->props.family = AF_INET6;
121 x0->props.mode = mode;
122 x0->props.reqid = reqid;
123 x0->lft.hard_add_expires_seconds = XFRM_ACQ_EXPIRES;
124 xfrm_state_hold(x0);
125 x0->timer.expires = jiffies + XFRM_ACQ_EXPIRES*HZ;
126 add_timer(&x0->timer);
127 xfrm_state_hold(x0);
128 list_add_tail(&x0->bydst, xfrm6_state_afinfo.state_bydst+h);
129 wake_up(&km_waitq);
130 } 141 }
131 if (x0) 142 if (j == n)
132 xfrm_state_hold(x0); 143 goto end;
133 return x0; 144#endif
145
146 /* Rule 3: select IPsec tunnel */
147 for (i = 0; i < n; i++) {
148 if (src[i] &&
149 src[i]->mode == XFRM_MODE_TUNNEL) {
150 dst[j++] = src[i];
151 src[i] = NULL;
152 }
153 }
154 if (likely(j == n))
155 goto end;
156
157 /* Final rule */
158 for (i = 0; i < n; i++) {
159 if (src[i]) {
160 dst[j++] = src[i];
161 src[i] = NULL;
162 }
163 }
164
165 end:
166 return 0;
134} 167}
135 168
136static struct xfrm_state_afinfo xfrm6_state_afinfo = { 169static struct xfrm_state_afinfo xfrm6_state_afinfo = {
137 .family = AF_INET6, 170 .family = AF_INET6,
138 .init_tempsel = __xfrm6_init_tempsel, 171 .init_tempsel = __xfrm6_init_tempsel,
139 .state_lookup = __xfrm6_state_lookup, 172 .tmpl_sort = __xfrm6_tmpl_sort,
140 .find_acq = __xfrm6_find_acq, 173 .state_sort = __xfrm6_state_sort,
141}; 174};
142 175
143void __init xfrm6_state_init(void) 176void __init xfrm6_state_init(void)
diff --git a/net/ipv6/xfrm6_tunnel.c b/net/ipv6/xfrm6_tunnel.c
index c8f9369c2a87..59685ee8f700 100644
--- a/net/ipv6/xfrm6_tunnel.c
+++ b/net/ipv6/xfrm6_tunnel.c
@@ -307,7 +307,7 @@ static int xfrm6_tunnel_err(struct sk_buff *skb, struct inet6_skb_parm *opt,
307 307
308static int xfrm6_tunnel_init_state(struct xfrm_state *x) 308static int xfrm6_tunnel_init_state(struct xfrm_state *x)
309{ 309{
310 if (!x->props.mode) 310 if (x->props.mode != XFRM_MODE_TUNNEL)
311 return -EINVAL; 311 return -EINVAL;
312 312
313 if (x->encap) 313 if (x->encap)