aboutsummaryrefslogtreecommitdiffstats
path: root/net/ipv6
diff options
context:
space:
mode:
Diffstat (limited to 'net/ipv6')
-rw-r--r--net/ipv6/addrconf.c12
-rw-r--r--net/ipv6/af_inet6.c24
-rw-r--r--net/ipv6/icmp.c17
-rw-r--r--net/ipv6/ip6_fib.c16
-rw-r--r--net/ipv6/ip6_input.c6
-rw-r--r--net/ipv6/ip6_output.c44
-rw-r--r--net/ipv6/ip6_tunnel.c6
-rw-r--r--net/ipv6/ip6mr.c11
-rw-r--r--net/ipv6/ipv6_sockglue.c5
-rw-r--r--net/ipv6/mcast.c1
-rw-r--r--net/ipv6/ndisc.c24
-rw-r--r--net/ipv6/netfilter/ip6_tables.c48
-rw-r--r--net/ipv6/netfilter/ip6t_eui64.c9
-rw-r--r--net/ipv6/netfilter/ip6table_filter.c10
-rw-r--r--net/ipv6/netfilter/ip6table_mangle.c16
-rw-r--r--net/ipv6/netfilter/ip6table_raw.c10
-rw-r--r--net/ipv6/netfilter/ip6table_security.c12
-rw-r--r--net/ipv6/netfilter/nf_conntrack_l3proto_ipv6.c18
-rw-r--r--net/ipv6/proc.c4
-rw-r--r--net/ipv6/protocol.c15
-rw-r--r--net/ipv6/raw.c9
-rw-r--r--net/ipv6/route.c34
-rw-r--r--net/ipv6/sit.c11
-rw-r--r--net/ipv6/sysctl_net_ipv6.c4
-rw-r--r--net/ipv6/tcp_ipv6.c21
-rw-r--r--net/ipv6/udp.c158
-rw-r--r--net/ipv6/xfrm6_policy.c38
27 files changed, 377 insertions, 206 deletions
diff --git a/net/ipv6/addrconf.c b/net/ipv6/addrconf.c
index 43b3c9f89c12..c9b369034a40 100644
--- a/net/ipv6/addrconf.c
+++ b/net/ipv6/addrconf.c
@@ -1371,12 +1371,14 @@ struct inet6_ifaddr *ipv6_get_ifaddr(struct net *net, const struct in6_addr *add
1371 1371
1372/* Gets referenced address, destroys ifaddr */ 1372/* Gets referenced address, destroys ifaddr */
1373 1373
1374static void addrconf_dad_stop(struct inet6_ifaddr *ifp) 1374static void addrconf_dad_stop(struct inet6_ifaddr *ifp, int dad_failed)
1375{ 1375{
1376 if (ifp->flags&IFA_F_PERMANENT) { 1376 if (ifp->flags&IFA_F_PERMANENT) {
1377 spin_lock_bh(&ifp->lock); 1377 spin_lock_bh(&ifp->lock);
1378 addrconf_del_timer(ifp); 1378 addrconf_del_timer(ifp);
1379 ifp->flags |= IFA_F_TENTATIVE; 1379 ifp->flags |= IFA_F_TENTATIVE;
1380 if (dad_failed)
1381 ifp->flags |= IFA_F_DADFAILED;
1380 spin_unlock_bh(&ifp->lock); 1382 spin_unlock_bh(&ifp->lock);
1381 in6_ifa_put(ifp); 1383 in6_ifa_put(ifp);
1382#ifdef CONFIG_IPV6_PRIVACY 1384#ifdef CONFIG_IPV6_PRIVACY
@@ -1422,7 +1424,7 @@ void addrconf_dad_failure(struct inet6_ifaddr *ifp)
1422 } 1424 }
1423 } 1425 }
1424 1426
1425 addrconf_dad_stop(ifp); 1427 addrconf_dad_stop(ifp, 1);
1426} 1428}
1427 1429
1428/* Join to solicited addr multicast group. */ 1430/* Join to solicited addr multicast group. */
@@ -2778,7 +2780,7 @@ static void addrconf_dad_start(struct inet6_ifaddr *ifp, u32 flags)
2778 idev->cnf.accept_dad < 1 || 2780 idev->cnf.accept_dad < 1 ||
2779 !(ifp->flags&IFA_F_TENTATIVE) || 2781 !(ifp->flags&IFA_F_TENTATIVE) ||
2780 ifp->flags & IFA_F_NODAD) { 2782 ifp->flags & IFA_F_NODAD) {
2781 ifp->flags &= ~(IFA_F_TENTATIVE|IFA_F_OPTIMISTIC); 2783 ifp->flags &= ~(IFA_F_TENTATIVE|IFA_F_OPTIMISTIC|IFA_F_DADFAILED);
2782 spin_unlock_bh(&ifp->lock); 2784 spin_unlock_bh(&ifp->lock);
2783 read_unlock_bh(&idev->lock); 2785 read_unlock_bh(&idev->lock);
2784 2786
@@ -2795,7 +2797,7 @@ static void addrconf_dad_start(struct inet6_ifaddr *ifp, u32 flags)
2795 * - otherwise, kill it. 2797 * - otherwise, kill it.
2796 */ 2798 */
2797 in6_ifa_hold(ifp); 2799 in6_ifa_hold(ifp);
2798 addrconf_dad_stop(ifp); 2800 addrconf_dad_stop(ifp, 0);
2799 return; 2801 return;
2800 } 2802 }
2801 2803
@@ -2829,7 +2831,7 @@ static void addrconf_dad_timer(unsigned long data)
2829 * DAD was successful 2831 * DAD was successful
2830 */ 2832 */
2831 2833
2832 ifp->flags &= ~(IFA_F_TENTATIVE|IFA_F_OPTIMISTIC); 2834 ifp->flags &= ~(IFA_F_TENTATIVE|IFA_F_OPTIMISTIC|IFA_F_DADFAILED);
2833 spin_unlock_bh(&ifp->lock); 2835 spin_unlock_bh(&ifp->lock);
2834 read_unlock_bh(&idev->lock); 2836 read_unlock_bh(&idev->lock);
2835 2837
diff --git a/net/ipv6/af_inet6.c b/net/ipv6/af_inet6.c
index caa0278d30a9..a123a328aeb3 100644
--- a/net/ipv6/af_inet6.c
+++ b/net/ipv6/af_inet6.c
@@ -306,8 +306,10 @@ int inet6_bind(struct socket *sock, struct sockaddr *uaddr, int addr_len)
306 v4addr != htonl(INADDR_ANY) && 306 v4addr != htonl(INADDR_ANY) &&
307 chk_addr_ret != RTN_LOCAL && 307 chk_addr_ret != RTN_LOCAL &&
308 chk_addr_ret != RTN_MULTICAST && 308 chk_addr_ret != RTN_MULTICAST &&
309 chk_addr_ret != RTN_BROADCAST) 309 chk_addr_ret != RTN_BROADCAST) {
310 err = -EADDRNOTAVAIL;
310 goto out; 311 goto out;
312 }
311 } else { 313 } else {
312 if (addr_type != IPV6_ADDR_ANY) { 314 if (addr_type != IPV6_ADDR_ANY) {
313 struct net_device *dev = NULL; 315 struct net_device *dev = NULL;
@@ -772,6 +774,11 @@ static struct sk_buff *ipv6_gso_segment(struct sk_buff *skb, int features)
772 struct sk_buff *segs = ERR_PTR(-EINVAL); 774 struct sk_buff *segs = ERR_PTR(-EINVAL);
773 struct ipv6hdr *ipv6h; 775 struct ipv6hdr *ipv6h;
774 struct inet6_protocol *ops; 776 struct inet6_protocol *ops;
777 int proto;
778 struct frag_hdr *fptr;
779 unsigned int unfrag_ip6hlen;
780 u8 *prevhdr;
781 int offset = 0;
775 782
776 if (!(features & NETIF_F_V6_CSUM)) 783 if (!(features & NETIF_F_V6_CSUM))
777 features &= ~NETIF_F_SG; 784 features &= ~NETIF_F_SG;
@@ -791,10 +798,9 @@ static struct sk_buff *ipv6_gso_segment(struct sk_buff *skb, int features)
791 __skb_pull(skb, sizeof(*ipv6h)); 798 __skb_pull(skb, sizeof(*ipv6h));
792 segs = ERR_PTR(-EPROTONOSUPPORT); 799 segs = ERR_PTR(-EPROTONOSUPPORT);
793 800
801 proto = ipv6_gso_pull_exthdrs(skb, ipv6h->nexthdr);
794 rcu_read_lock(); 802 rcu_read_lock();
795 ops = rcu_dereference(inet6_protos[ 803 ops = rcu_dereference(inet6_protos[proto]);
796 ipv6_gso_pull_exthdrs(skb, ipv6h->nexthdr)]);
797
798 if (likely(ops && ops->gso_segment)) { 804 if (likely(ops && ops->gso_segment)) {
799 skb_reset_transport_header(skb); 805 skb_reset_transport_header(skb);
800 segs = ops->gso_segment(skb, features); 806 segs = ops->gso_segment(skb, features);
@@ -808,6 +814,16 @@ static struct sk_buff *ipv6_gso_segment(struct sk_buff *skb, int features)
808 ipv6h = ipv6_hdr(skb); 814 ipv6h = ipv6_hdr(skb);
809 ipv6h->payload_len = htons(skb->len - skb->mac_len - 815 ipv6h->payload_len = htons(skb->len - skb->mac_len -
810 sizeof(*ipv6h)); 816 sizeof(*ipv6h));
817 if (proto == IPPROTO_UDP) {
818 unfrag_ip6hlen = ip6_find_1stfragopt(skb, &prevhdr);
819 fptr = (struct frag_hdr *)(skb_network_header(skb) +
820 unfrag_ip6hlen);
821 fptr->frag_off = htons(offset);
822 if (skb->next != NULL)
823 fptr->frag_off |= htons(IP6_MF);
824 offset += (ntohs(ipv6h->payload_len) -
825 sizeof(struct frag_hdr));
826 }
811 } 827 }
812 828
813out: 829out:
diff --git a/net/ipv6/icmp.c b/net/ipv6/icmp.c
index eab62a7a8f06..e2325f6a05fb 100644
--- a/net/ipv6/icmp.c
+++ b/net/ipv6/icmp.c
@@ -323,7 +323,7 @@ void icmpv6_send(struct sk_buff *skb, u8 type, u8 code, __u32 info,
323 int iif = 0; 323 int iif = 0;
324 int addr_type = 0; 324 int addr_type = 0;
325 int len; 325 int len;
326 int hlimit, tclass; 326 int hlimit;
327 int err = 0; 327 int err = 0;
328 328
329 if ((u8 *)hdr < skb->head || 329 if ((u8 *)hdr < skb->head ||
@@ -469,10 +469,6 @@ route_done:
469 if (hlimit < 0) 469 if (hlimit < 0)
470 hlimit = ip6_dst_hoplimit(dst); 470 hlimit = ip6_dst_hoplimit(dst);
471 471
472 tclass = np->tclass;
473 if (tclass < 0)
474 tclass = 0;
475
476 msg.skb = skb; 472 msg.skb = skb;
477 msg.offset = skb_network_offset(skb); 473 msg.offset = skb_network_offset(skb);
478 msg.type = type; 474 msg.type = type;
@@ -488,8 +484,8 @@ route_done:
488 484
489 err = ip6_append_data(sk, icmpv6_getfrag, &msg, 485 err = ip6_append_data(sk, icmpv6_getfrag, &msg,
490 len + sizeof(struct icmp6hdr), 486 len + sizeof(struct icmp6hdr),
491 sizeof(struct icmp6hdr), 487 sizeof(struct icmp6hdr), hlimit,
492 hlimit, tclass, NULL, &fl, (struct rt6_info*)dst, 488 np->tclass, NULL, &fl, (struct rt6_info*)dst,
493 MSG_DONTWAIT); 489 MSG_DONTWAIT);
494 if (err) { 490 if (err) {
495 ip6_flush_pending_frames(sk); 491 ip6_flush_pending_frames(sk);
@@ -522,7 +518,6 @@ static void icmpv6_echo_reply(struct sk_buff *skb)
522 struct dst_entry *dst; 518 struct dst_entry *dst;
523 int err = 0; 519 int err = 0;
524 int hlimit; 520 int hlimit;
525 int tclass;
526 521
527 saddr = &ipv6_hdr(skb)->daddr; 522 saddr = &ipv6_hdr(skb)->daddr;
528 523
@@ -562,10 +557,6 @@ static void icmpv6_echo_reply(struct sk_buff *skb)
562 if (hlimit < 0) 557 if (hlimit < 0)
563 hlimit = ip6_dst_hoplimit(dst); 558 hlimit = ip6_dst_hoplimit(dst);
564 559
565 tclass = np->tclass;
566 if (tclass < 0)
567 tclass = 0;
568
569 idev = in6_dev_get(skb->dev); 560 idev = in6_dev_get(skb->dev);
570 561
571 msg.skb = skb; 562 msg.skb = skb;
@@ -573,7 +564,7 @@ static void icmpv6_echo_reply(struct sk_buff *skb)
573 msg.type = ICMPV6_ECHO_REPLY; 564 msg.type = ICMPV6_ECHO_REPLY;
574 565
575 err = ip6_append_data(sk, icmpv6_getfrag, &msg, skb->len + sizeof(struct icmp6hdr), 566 err = ip6_append_data(sk, icmpv6_getfrag, &msg, skb->len + sizeof(struct icmp6hdr),
576 sizeof(struct icmp6hdr), hlimit, tclass, NULL, &fl, 567 sizeof(struct icmp6hdr), hlimit, np->tclass, NULL, &fl,
577 (struct rt6_info*)dst, MSG_DONTWAIT); 568 (struct rt6_info*)dst, MSG_DONTWAIT);
578 569
579 if (err) { 570 if (err) {
diff --git a/net/ipv6/ip6_fib.c b/net/ipv6/ip6_fib.c
index 52ee1dced2ff..0e93ca56eb69 100644
--- a/net/ipv6/ip6_fib.c
+++ b/net/ipv6/ip6_fib.c
@@ -164,12 +164,6 @@ static __inline__ void rt6_release(struct rt6_info *rt)
164 dst_free(&rt->u.dst); 164 dst_free(&rt->u.dst);
165} 165}
166 166
167#ifdef CONFIG_IPV6_MULTIPLE_TABLES
168#define FIB_TABLE_HASHSZ 256
169#else
170#define FIB_TABLE_HASHSZ 1
171#endif
172
173static void fib6_link_table(struct net *net, struct fib6_table *tb) 167static void fib6_link_table(struct net *net, struct fib6_table *tb)
174{ 168{
175 unsigned int h; 169 unsigned int h;
@@ -180,7 +174,7 @@ static void fib6_link_table(struct net *net, struct fib6_table *tb)
180 */ 174 */
181 rwlock_init(&tb->tb6_lock); 175 rwlock_init(&tb->tb6_lock);
182 176
183 h = tb->tb6_id & (FIB_TABLE_HASHSZ - 1); 177 h = tb->tb6_id & (FIB6_TABLE_HASHSZ - 1);
184 178
185 /* 179 /*
186 * No protection necessary, this is the only list mutatation 180 * No protection necessary, this is the only list mutatation
@@ -231,7 +225,7 @@ struct fib6_table *fib6_get_table(struct net *net, u32 id)
231 225
232 if (id == 0) 226 if (id == 0)
233 id = RT6_TABLE_MAIN; 227 id = RT6_TABLE_MAIN;
234 h = id & (FIB_TABLE_HASHSZ - 1); 228 h = id & (FIB6_TABLE_HASHSZ - 1);
235 rcu_read_lock(); 229 rcu_read_lock();
236 head = &net->ipv6.fib_table_hash[h]; 230 head = &net->ipv6.fib_table_hash[h];
237 hlist_for_each_entry_rcu(tb, node, head, tb6_hlist) { 231 hlist_for_each_entry_rcu(tb, node, head, tb6_hlist) {
@@ -382,7 +376,7 @@ static int inet6_dump_fib(struct sk_buff *skb, struct netlink_callback *cb)
382 arg.net = net; 376 arg.net = net;
383 w->args = &arg; 377 w->args = &arg;
384 378
385 for (h = s_h; h < FIB_TABLE_HASHSZ; h++, s_e = 0) { 379 for (h = s_h; h < FIB6_TABLE_HASHSZ; h++, s_e = 0) {
386 e = 0; 380 e = 0;
387 head = &net->ipv6.fib_table_hash[h]; 381 head = &net->ipv6.fib_table_hash[h];
388 hlist_for_each_entry(tb, node, head, tb6_hlist) { 382 hlist_for_each_entry(tb, node, head, tb6_hlist) {
@@ -1368,7 +1362,7 @@ void fib6_clean_all(struct net *net, int (*func)(struct rt6_info *, void *arg),
1368 unsigned int h; 1362 unsigned int h;
1369 1363
1370 rcu_read_lock(); 1364 rcu_read_lock();
1371 for (h = 0; h < FIB_TABLE_HASHSZ; h++) { 1365 for (h = 0; h < FIB6_TABLE_HASHSZ; h++) {
1372 head = &net->ipv6.fib_table_hash[h]; 1366 head = &net->ipv6.fib_table_hash[h];
1373 hlist_for_each_entry_rcu(table, node, head, tb6_hlist) { 1367 hlist_for_each_entry_rcu(table, node, head, tb6_hlist) {
1374 write_lock_bh(&table->tb6_lock); 1368 write_lock_bh(&table->tb6_lock);
@@ -1483,7 +1477,7 @@ static int fib6_net_init(struct net *net)
1483 if (!net->ipv6.rt6_stats) 1477 if (!net->ipv6.rt6_stats)
1484 goto out_timer; 1478 goto out_timer;
1485 1479
1486 net->ipv6.fib_table_hash = kcalloc(FIB_TABLE_HASHSZ, 1480 net->ipv6.fib_table_hash = kcalloc(FIB6_TABLE_HASHSZ,
1487 sizeof(*net->ipv6.fib_table_hash), 1481 sizeof(*net->ipv6.fib_table_hash),
1488 GFP_KERNEL); 1482 GFP_KERNEL);
1489 if (!net->ipv6.fib_table_hash) 1483 if (!net->ipv6.fib_table_hash)
diff --git a/net/ipv6/ip6_input.c b/net/ipv6/ip6_input.c
index 6d6a4277c677..2d9cbaa67edb 100644
--- a/net/ipv6/ip6_input.c
+++ b/net/ipv6/ip6_input.c
@@ -63,7 +63,7 @@ int ipv6_rcv(struct sk_buff *skb, struct net_device *dev, struct packet_type *pt
63 63
64 if (skb->pkt_type == PACKET_OTHERHOST) { 64 if (skb->pkt_type == PACKET_OTHERHOST) {
65 kfree_skb(skb); 65 kfree_skb(skb);
66 return 0; 66 return NET_RX_DROP;
67 } 67 }
68 68
69 rcu_read_lock(); 69 rcu_read_lock();
@@ -133,7 +133,7 @@ int ipv6_rcv(struct sk_buff *skb, struct net_device *dev, struct packet_type *pt
133 if (ipv6_parse_hopopts(skb) < 0) { 133 if (ipv6_parse_hopopts(skb) < 0) {
134 IP6_INC_STATS_BH(net, idev, IPSTATS_MIB_INHDRERRORS); 134 IP6_INC_STATS_BH(net, idev, IPSTATS_MIB_INHDRERRORS);
135 rcu_read_unlock(); 135 rcu_read_unlock();
136 return 0; 136 return NET_RX_DROP;
137 } 137 }
138 } 138 }
139 139
@@ -149,7 +149,7 @@ err:
149drop: 149drop:
150 rcu_read_unlock(); 150 rcu_read_unlock();
151 kfree_skb(skb); 151 kfree_skb(skb);
152 return 0; 152 return NET_RX_DROP;
153} 153}
154 154
155/* 155/*
diff --git a/net/ipv6/ip6_output.c b/net/ipv6/ip6_output.c
index 87f8419a68fd..cd48801a8d6f 100644
--- a/net/ipv6/ip6_output.c
+++ b/net/ipv6/ip6_output.c
@@ -57,18 +57,6 @@
57 57
58static int ip6_fragment(struct sk_buff *skb, int (*output)(struct sk_buff *)); 58static int ip6_fragment(struct sk_buff *skb, int (*output)(struct sk_buff *));
59 59
60static __inline__ void ipv6_select_ident(struct sk_buff *skb, struct frag_hdr *fhdr)
61{
62 static u32 ipv6_fragmentation_id = 1;
63 static DEFINE_SPINLOCK(ip6_id_lock);
64
65 spin_lock_bh(&ip6_id_lock);
66 fhdr->identification = htonl(ipv6_fragmentation_id);
67 if (++ipv6_fragmentation_id == 0)
68 ipv6_fragmentation_id = 1;
69 spin_unlock_bh(&ip6_id_lock);
70}
71
72int __ip6_local_out(struct sk_buff *skb) 60int __ip6_local_out(struct sk_buff *skb)
73{ 61{
74 int len; 62 int len;
@@ -206,7 +194,8 @@ int ip6_xmit(struct sock *sk, struct sk_buff *skb, struct flowi *fl,
206 struct ipv6hdr *hdr; 194 struct ipv6hdr *hdr;
207 u8 proto = fl->proto; 195 u8 proto = fl->proto;
208 int seg_len = skb->len; 196 int seg_len = skb->len;
209 int hlimit, tclass; 197 int hlimit = -1;
198 int tclass = 0;
210 u32 mtu; 199 u32 mtu;
211 200
212 if (opt) { 201 if (opt) {
@@ -249,19 +238,13 @@ int ip6_xmit(struct sock *sk, struct sk_buff *skb, struct flowi *fl,
249 /* 238 /*
250 * Fill in the IPv6 header 239 * Fill in the IPv6 header
251 */ 240 */
252 241 if (np) {
253 hlimit = -1; 242 tclass = np->tclass;
254 if (np)
255 hlimit = np->hop_limit; 243 hlimit = np->hop_limit;
244 }
256 if (hlimit < 0) 245 if (hlimit < 0)
257 hlimit = ip6_dst_hoplimit(dst); 246 hlimit = ip6_dst_hoplimit(dst);
258 247
259 tclass = -1;
260 if (np)
261 tclass = np->tclass;
262 if (tclass < 0)
263 tclass = 0;
264
265 *(__be32 *)hdr = htonl(0x60000000 | (tclass << 20)) | fl->fl6_flowlabel; 248 *(__be32 *)hdr = htonl(0x60000000 | (tclass << 20)) | fl->fl6_flowlabel;
266 249
267 hdr->payload_len = htons(seg_len); 250 hdr->payload_len = htons(seg_len);
@@ -706,7 +689,7 @@ static int ip6_fragment(struct sk_buff *skb, int (*output)(struct sk_buff *))
706 skb_reset_network_header(skb); 689 skb_reset_network_header(skb);
707 memcpy(skb_network_header(skb), tmp_hdr, hlen); 690 memcpy(skb_network_header(skb), tmp_hdr, hlen);
708 691
709 ipv6_select_ident(skb, fh); 692 ipv6_select_ident(fh);
710 fh->nexthdr = nexthdr; 693 fh->nexthdr = nexthdr;
711 fh->reserved = 0; 694 fh->reserved = 0;
712 fh->frag_off = htons(IP6_MF); 695 fh->frag_off = htons(IP6_MF);
@@ -844,7 +827,7 @@ slow_path:
844 fh->nexthdr = nexthdr; 827 fh->nexthdr = nexthdr;
845 fh->reserved = 0; 828 fh->reserved = 0;
846 if (!frag_id) { 829 if (!frag_id) {
847 ipv6_select_ident(skb, fh); 830 ipv6_select_ident(fh);
848 frag_id = fh->identification; 831 frag_id = fh->identification;
849 } else 832 } else
850 fh->identification = frag_id; 833 fh->identification = frag_id;
@@ -1087,11 +1070,13 @@ static inline int ip6_ufo_append_data(struct sock *sk,
1087 if (!err) { 1070 if (!err) {
1088 struct frag_hdr fhdr; 1071 struct frag_hdr fhdr;
1089 1072
1090 /* specify the length of each IP datagram fragment*/ 1073 /* Specify the length of each IPv6 datagram fragment.
1091 skb_shinfo(skb)->gso_size = mtu - fragheaderlen - 1074 * It has to be a multiple of 8.
1092 sizeof(struct frag_hdr); 1075 */
1076 skb_shinfo(skb)->gso_size = (mtu - fragheaderlen -
1077 sizeof(struct frag_hdr)) & ~7;
1093 skb_shinfo(skb)->gso_type = SKB_GSO_UDP; 1078 skb_shinfo(skb)->gso_type = SKB_GSO_UDP;
1094 ipv6_select_ident(skb, &fhdr); 1079 ipv6_select_ident(&fhdr);
1095 skb_shinfo(skb)->ip6_frag_id = fhdr.identification; 1080 skb_shinfo(skb)->ip6_frag_id = fhdr.identification;
1096 __skb_queue_tail(&sk->sk_write_queue, skb); 1081 __skb_queue_tail(&sk->sk_write_queue, skb);
1097 1082
@@ -1526,7 +1511,7 @@ int ip6_push_pending_frames(struct sock *sk)
1526 err = ip6_local_out(skb); 1511 err = ip6_local_out(skb);
1527 if (err) { 1512 if (err) {
1528 if (err > 0) 1513 if (err > 0)
1529 err = np->recverr ? net_xmit_errno(err) : 0; 1514 err = net_xmit_errno(err);
1530 if (err) 1515 if (err)
1531 goto error; 1516 goto error;
1532 } 1517 }
@@ -1535,6 +1520,7 @@ out:
1535 ip6_cork_release(inet, np); 1520 ip6_cork_release(inet, np);
1536 return err; 1521 return err;
1537error: 1522error:
1523 IP6_INC_STATS(net, rt->rt6i_idev, IPSTATS_MIB_OUTDISCARDS);
1538 goto out; 1524 goto out;
1539} 1525}
1540 1526
diff --git a/net/ipv6/ip6_tunnel.c b/net/ipv6/ip6_tunnel.c
index 51f410e7775a..7d25bbe32110 100644
--- a/net/ipv6/ip6_tunnel.c
+++ b/net/ipv6/ip6_tunnel.c
@@ -1036,7 +1036,7 @@ ip6ip6_tnl_xmit(struct sk_buff *skb, struct net_device *dev)
1036 return 0; 1036 return 0;
1037} 1037}
1038 1038
1039static int 1039static netdev_tx_t
1040ip6_tnl_xmit(struct sk_buff *skb, struct net_device *dev) 1040ip6_tnl_xmit(struct sk_buff *skb, struct net_device *dev)
1041{ 1041{
1042 struct ip6_tnl *t = netdev_priv(dev); 1042 struct ip6_tnl *t = netdev_priv(dev);
@@ -1063,14 +1063,14 @@ ip6_tnl_xmit(struct sk_buff *skb, struct net_device *dev)
1063 goto tx_err; 1063 goto tx_err;
1064 1064
1065 t->recursion--; 1065 t->recursion--;
1066 return 0; 1066 return NETDEV_TX_OK;
1067 1067
1068tx_err: 1068tx_err:
1069 stats->tx_errors++; 1069 stats->tx_errors++;
1070 stats->tx_dropped++; 1070 stats->tx_dropped++;
1071 kfree_skb(skb); 1071 kfree_skb(skb);
1072 t->recursion--; 1072 t->recursion--;
1073 return 0; 1073 return NETDEV_TX_OK;
1074} 1074}
1075 1075
1076static void ip6_tnl_set_cap(struct ip6_tnl *t) 1076static void ip6_tnl_set_cap(struct ip6_tnl *t)
diff --git a/net/ipv6/ip6mr.c b/net/ipv6/ip6mr.c
index c769f155c698..5c8d73730c75 100644
--- a/net/ipv6/ip6mr.c
+++ b/net/ipv6/ip6mr.c
@@ -204,7 +204,7 @@ static int ip6mr_vif_seq_show(struct seq_file *seq, void *v)
204 return 0; 204 return 0;
205} 205}
206 206
207static struct seq_operations ip6mr_vif_seq_ops = { 207static const struct seq_operations ip6mr_vif_seq_ops = {
208 .start = ip6mr_vif_seq_start, 208 .start = ip6mr_vif_seq_start,
209 .next = ip6mr_vif_seq_next, 209 .next = ip6mr_vif_seq_next,
210 .stop = ip6mr_vif_seq_stop, 210 .stop = ip6mr_vif_seq_stop,
@@ -217,7 +217,7 @@ static int ip6mr_vif_open(struct inode *inode, struct file *file)
217 sizeof(struct ipmr_vif_iter)); 217 sizeof(struct ipmr_vif_iter));
218} 218}
219 219
220static struct file_operations ip6mr_vif_fops = { 220static const struct file_operations ip6mr_vif_fops = {
221 .owner = THIS_MODULE, 221 .owner = THIS_MODULE,
222 .open = ip6mr_vif_open, 222 .open = ip6mr_vif_open,
223 .read = seq_read, 223 .read = seq_read,
@@ -341,7 +341,7 @@ static int ipmr_mfc_open(struct inode *inode, struct file *file)
341 sizeof(struct ipmr_mfc_iter)); 341 sizeof(struct ipmr_mfc_iter));
342} 342}
343 343
344static struct file_operations ip6mr_mfc_fops = { 344static const struct file_operations ip6mr_mfc_fops = {
345 .owner = THIS_MODULE, 345 .owner = THIS_MODULE,
346 .open = ipmr_mfc_open, 346 .open = ipmr_mfc_open,
347 .read = seq_read, 347 .read = seq_read,
@@ -416,7 +416,8 @@ static struct inet6_protocol pim6_protocol = {
416 416
417/* Service routines creating virtual interfaces: PIMREG */ 417/* Service routines creating virtual interfaces: PIMREG */
418 418
419static int reg_vif_xmit(struct sk_buff *skb, struct net_device *dev) 419static netdev_tx_t reg_vif_xmit(struct sk_buff *skb,
420 struct net_device *dev)
420{ 421{
421 struct net *net = dev_net(dev); 422 struct net *net = dev_net(dev);
422 423
@@ -427,7 +428,7 @@ static int reg_vif_xmit(struct sk_buff *skb, struct net_device *dev)
427 MRT6MSG_WHOLEPKT); 428 MRT6MSG_WHOLEPKT);
428 read_unlock(&mrt_lock); 429 read_unlock(&mrt_lock);
429 kfree_skb(skb); 430 kfree_skb(skb);
430 return 0; 431 return NETDEV_TX_OK;
431} 432}
432 433
433static const struct net_device_ops reg_vif_netdev_ops = { 434static const struct net_device_ops reg_vif_netdev_ops = {
diff --git a/net/ipv6/ipv6_sockglue.c b/net/ipv6/ipv6_sockglue.c
index a7fdf9a27f15..f5e0682b402d 100644
--- a/net/ipv6/ipv6_sockglue.c
+++ b/net/ipv6/ipv6_sockglue.c
@@ -315,6 +315,9 @@ static int do_ipv6_setsockopt(struct sock *sk, int level, int optname,
315 goto e_inval; 315 goto e_inval;
316 if (val < -1 || val > 0xff) 316 if (val < -1 || val > 0xff)
317 goto e_inval; 317 goto e_inval;
318 /* RFC 3542, 6.5: default traffic class of 0x0 */
319 if (val == -1)
320 val = 0;
318 np->tclass = val; 321 np->tclass = val;
319 retv = 0; 322 retv = 0;
320 break; 323 break;
@@ -1037,8 +1040,6 @@ static int do_ipv6_getsockopt(struct sock *sk, int level, int optname,
1037 1040
1038 case IPV6_TCLASS: 1041 case IPV6_TCLASS:
1039 val = np->tclass; 1042 val = np->tclass;
1040 if (val < 0)
1041 val = 0;
1042 break; 1043 break;
1043 1044
1044 case IPV6_RECVTCLASS: 1045 case IPV6_RECVTCLASS:
diff --git a/net/ipv6/mcast.c b/net/ipv6/mcast.c
index 4b264ed40a8c..71c3dacec1ed 100644
--- a/net/ipv6/mcast.c
+++ b/net/ipv6/mcast.c
@@ -2107,7 +2107,6 @@ static int ip6_mc_add_src(struct inet6_dev *idev, struct in6_addr *pmca,
2107 for (j=0; j<i; j++) 2107 for (j=0; j<i; j++)
2108 (void) ip6_mc_del1_src(pmc, sfmode, &psfsrc[i]); 2108 (void) ip6_mc_del1_src(pmc, sfmode, &psfsrc[i]);
2109 } else if (isexclude != (pmc->mca_sfcount[MCAST_EXCLUDE] != 0)) { 2109 } else if (isexclude != (pmc->mca_sfcount[MCAST_EXCLUDE] != 0)) {
2110 struct inet6_dev *idev = pmc->idev;
2111 struct ip6_sf_list *psf; 2110 struct ip6_sf_list *psf;
2112 2111
2113 /* filter mode change */ 2112 /* filter mode change */
diff --git a/net/ipv6/ndisc.c b/net/ipv6/ndisc.c
index 9eb68e92cc18..7015478797f6 100644
--- a/net/ipv6/ndisc.c
+++ b/net/ipv6/ndisc.c
@@ -98,7 +98,7 @@ static int pndisc_constructor(struct pneigh_entry *n);
98static void pndisc_destructor(struct pneigh_entry *n); 98static void pndisc_destructor(struct pneigh_entry *n);
99static void pndisc_redo(struct sk_buff *skb); 99static void pndisc_redo(struct sk_buff *skb);
100 100
101static struct neigh_ops ndisc_generic_ops = { 101static const struct neigh_ops ndisc_generic_ops = {
102 .family = AF_INET6, 102 .family = AF_INET6,
103 .solicit = ndisc_solicit, 103 .solicit = ndisc_solicit,
104 .error_report = ndisc_error_report, 104 .error_report = ndisc_error_report,
@@ -108,7 +108,7 @@ static struct neigh_ops ndisc_generic_ops = {
108 .queue_xmit = dev_queue_xmit, 108 .queue_xmit = dev_queue_xmit,
109}; 109};
110 110
111static struct neigh_ops ndisc_hh_ops = { 111static const struct neigh_ops ndisc_hh_ops = {
112 .family = AF_INET6, 112 .family = AF_INET6,
113 .solicit = ndisc_solicit, 113 .solicit = ndisc_solicit,
114 .error_report = ndisc_error_report, 114 .error_report = ndisc_error_report,
@@ -119,7 +119,7 @@ static struct neigh_ops ndisc_hh_ops = {
119}; 119};
120 120
121 121
122static struct neigh_ops ndisc_direct_ops = { 122static const struct neigh_ops ndisc_direct_ops = {
123 .family = AF_INET6, 123 .family = AF_INET6,
124 .output = dev_queue_xmit, 124 .output = dev_queue_xmit,
125 .connected_output = dev_queue_xmit, 125 .connected_output = dev_queue_xmit,
@@ -955,8 +955,8 @@ static void ndisc_recv_na(struct sk_buff *skb)
955 */ 955 */
956 if (skb->pkt_type != PACKET_LOOPBACK) 956 if (skb->pkt_type != PACKET_LOOPBACK)
957 ND_PRINTK1(KERN_WARNING 957 ND_PRINTK1(KERN_WARNING
958 "ICMPv6 NA: someone advertises our address on %s!\n", 958 "ICMPv6 NA: someone advertises our address %pI6 on %s!\n",
959 ifp->idev->dev->name); 959 &ifp->addr, ifp->idev->dev->name);
960 in6_ifa_put(ifp); 960 in6_ifa_put(ifp);
961 return; 961 return;
962 } 962 }
@@ -1151,10 +1151,6 @@ static void ndisc_router_discovery(struct sk_buff *skb)
1151 skb->dev->name); 1151 skb->dev->name);
1152 return; 1152 return;
1153 } 1153 }
1154 if (in6_dev->cnf.forwarding || !in6_dev->cnf.accept_ra) {
1155 in6_dev_put(in6_dev);
1156 return;
1157 }
1158 1154
1159 if (!ndisc_parse_options(opt, optlen, &ndopts)) { 1155 if (!ndisc_parse_options(opt, optlen, &ndopts)) {
1160 in6_dev_put(in6_dev); 1156 in6_dev_put(in6_dev);
@@ -1163,6 +1159,10 @@ static void ndisc_router_discovery(struct sk_buff *skb)
1163 return; 1159 return;
1164 } 1160 }
1165 1161
1162 /* skip route and link configuration on routers */
1163 if (in6_dev->cnf.forwarding || !in6_dev->cnf.accept_ra)
1164 goto skip_linkparms;
1165
1166#ifdef CONFIG_IPV6_NDISC_NODETYPE 1166#ifdef CONFIG_IPV6_NDISC_NODETYPE
1167 /* skip link-specific parameters from interior routers */ 1167 /* skip link-specific parameters from interior routers */
1168 if (skb->ndisc_nodetype == NDISC_NODETYPE_NODEFAULT) 1168 if (skb->ndisc_nodetype == NDISC_NODETYPE_NODEFAULT)
@@ -1283,9 +1283,7 @@ skip_defrtr:
1283 } 1283 }
1284 } 1284 }
1285 1285
1286#ifdef CONFIG_IPV6_NDISC_NODETYPE
1287skip_linkparms: 1286skip_linkparms:
1288#endif
1289 1287
1290 /* 1288 /*
1291 * Process options. 1289 * Process options.
@@ -1312,6 +1310,10 @@ skip_linkparms:
1312 NEIGH_UPDATE_F_ISROUTER); 1310 NEIGH_UPDATE_F_ISROUTER);
1313 } 1311 }
1314 1312
1313 /* skip route and link configuration on routers */
1314 if (in6_dev->cnf.forwarding || !in6_dev->cnf.accept_ra)
1315 goto out;
1316
1315#ifdef CONFIG_IPV6_ROUTE_INFO 1317#ifdef CONFIG_IPV6_ROUTE_INFO
1316 if (in6_dev->cnf.accept_ra_rtr_pref && ndopts.nd_opts_ri) { 1318 if (in6_dev->cnf.accept_ra_rtr_pref && ndopts.nd_opts_ri) {
1317 struct nd_opt_hdr *p; 1319 struct nd_opt_hdr *p;
diff --git a/net/ipv6/netfilter/ip6_tables.c b/net/ipv6/netfilter/ip6_tables.c
index ced1f2c0cb65..cc9f8ef303fd 100644
--- a/net/ipv6/netfilter/ip6_tables.c
+++ b/net/ipv6/netfilter/ip6_tables.c
@@ -8,7 +8,7 @@
8 * it under the terms of the GNU General Public License version 2 as 8 * it under the terms of the GNU General Public License version 2 as
9 * published by the Free Software Foundation. 9 * published by the Free Software Foundation.
10 */ 10 */
11 11#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
12#include <linux/capability.h> 12#include <linux/capability.h>
13#include <linux/in.h> 13#include <linux/in.h>
14#include <linux/skbuff.h> 14#include <linux/skbuff.h>
@@ -222,16 +222,11 @@ get_entry(void *base, unsigned int offset)
222 222
223/* All zeroes == unconditional rule. */ 223/* All zeroes == unconditional rule. */
224/* Mildly perf critical (only if packet tracing is on) */ 224/* Mildly perf critical (only if packet tracing is on) */
225static inline int 225static inline bool unconditional(const struct ip6t_ip6 *ipv6)
226unconditional(const struct ip6t_ip6 *ipv6)
227{ 226{
228 unsigned int i; 227 static const struct ip6t_ip6 uncond;
229
230 for (i = 0; i < sizeof(*ipv6); i++)
231 if (((char *)ipv6)[i])
232 break;
233 228
234 return (i == sizeof(*ipv6)); 229 return memcmp(ipv6, &uncond, sizeof(uncond)) == 0;
235} 230}
236 231
237#if defined(CONFIG_NETFILTER_XT_TARGET_TRACE) || \ 232#if defined(CONFIG_NETFILTER_XT_TARGET_TRACE) || \
@@ -745,6 +740,21 @@ find_check_entry(struct ip6t_entry *e, const char *name, unsigned int size,
745 return ret; 740 return ret;
746} 741}
747 742
743static bool check_underflow(struct ip6t_entry *e)
744{
745 const struct ip6t_entry_target *t;
746 unsigned int verdict;
747
748 if (!unconditional(&e->ipv6))
749 return false;
750 t = ip6t_get_target(e);
751 if (strcmp(t->u.user.name, XT_STANDARD_TARGET) != 0)
752 return false;
753 verdict = ((struct ip6t_standard_target *)t)->verdict;
754 verdict = -verdict - 1;
755 return verdict == NF_DROP || verdict == NF_ACCEPT;
756}
757
748static int 758static int
749check_entry_size_and_hooks(struct ip6t_entry *e, 759check_entry_size_and_hooks(struct ip6t_entry *e,
750 struct xt_table_info *newinfo, 760 struct xt_table_info *newinfo,
@@ -752,6 +762,7 @@ check_entry_size_and_hooks(struct ip6t_entry *e,
752 unsigned char *limit, 762 unsigned char *limit,
753 const unsigned int *hook_entries, 763 const unsigned int *hook_entries,
754 const unsigned int *underflows, 764 const unsigned int *underflows,
765 unsigned int valid_hooks,
755 unsigned int *i) 766 unsigned int *i)
756{ 767{
757 unsigned int h; 768 unsigned int h;
@@ -771,15 +782,21 @@ check_entry_size_and_hooks(struct ip6t_entry *e,
771 782
772 /* Check hooks & underflows */ 783 /* Check hooks & underflows */
773 for (h = 0; h < NF_INET_NUMHOOKS; h++) { 784 for (h = 0; h < NF_INET_NUMHOOKS; h++) {
785 if (!(valid_hooks & (1 << h)))
786 continue;
774 if ((unsigned char *)e - base == hook_entries[h]) 787 if ((unsigned char *)e - base == hook_entries[h])
775 newinfo->hook_entry[h] = hook_entries[h]; 788 newinfo->hook_entry[h] = hook_entries[h];
776 if ((unsigned char *)e - base == underflows[h]) 789 if ((unsigned char *)e - base == underflows[h]) {
790 if (!check_underflow(e)) {
791 pr_err("Underflows must be unconditional and "
792 "use the STANDARD target with "
793 "ACCEPT/DROP\n");
794 return -EINVAL;
795 }
777 newinfo->underflow[h] = underflows[h]; 796 newinfo->underflow[h] = underflows[h];
797 }
778 } 798 }
779 799
780 /* FIXME: underflows must be unconditional, standard verdicts
781 < 0 (not IP6T_RETURN). --RR */
782
783 /* Clear counters and comefrom */ 800 /* Clear counters and comefrom */
784 e->counters = ((struct xt_counters) { 0, 0 }); 801 e->counters = ((struct xt_counters) { 0, 0 });
785 e->comefrom = 0; 802 e->comefrom = 0;
@@ -842,7 +859,7 @@ translate_table(const char *name,
842 newinfo, 859 newinfo,
843 entry0, 860 entry0,
844 entry0 + size, 861 entry0 + size,
845 hook_entries, underflows, &i); 862 hook_entries, underflows, valid_hooks, &i);
846 if (ret != 0) 863 if (ret != 0)
847 return ret; 864 return ret;
848 865
@@ -2083,7 +2100,8 @@ do_ip6t_get_ctl(struct sock *sk, int cmd, void __user *user, int *len)
2083 return ret; 2100 return ret;
2084} 2101}
2085 2102
2086struct xt_table *ip6t_register_table(struct net *net, struct xt_table *table, 2103struct xt_table *ip6t_register_table(struct net *net,
2104 const struct xt_table *table,
2087 const struct ip6t_replace *repl) 2105 const struct ip6t_replace *repl)
2088{ 2106{
2089 int ret; 2107 int ret;
diff --git a/net/ipv6/netfilter/ip6t_eui64.c b/net/ipv6/netfilter/ip6t_eui64.c
index db610bacbcce..ca287f6d2bce 100644
--- a/net/ipv6/netfilter/ip6t_eui64.c
+++ b/net/ipv6/netfilter/ip6t_eui64.c
@@ -23,7 +23,6 @@ static bool
23eui64_mt6(const struct sk_buff *skb, const struct xt_match_param *par) 23eui64_mt6(const struct sk_buff *skb, const struct xt_match_param *par)
24{ 24{
25 unsigned char eui64[8]; 25 unsigned char eui64[8];
26 int i = 0;
27 26
28 if (!(skb_mac_header(skb) >= skb->head && 27 if (!(skb_mac_header(skb) >= skb->head &&
29 skb_mac_header(skb) + ETH_HLEN <= skb->data) && 28 skb_mac_header(skb) + ETH_HLEN <= skb->data) &&
@@ -42,12 +41,8 @@ eui64_mt6(const struct sk_buff *skb, const struct xt_match_param *par)
42 eui64[4] = 0xfe; 41 eui64[4] = 0xfe;
43 eui64[0] ^= 0x02; 42 eui64[0] ^= 0x02;
44 43
45 i = 0; 44 if (!memcmp(ipv6_hdr(skb)->saddr.s6_addr + 8, eui64,
46 while (ipv6_hdr(skb)->saddr.s6_addr[8 + i] == eui64[i] 45 sizeof(eui64)))
47 && i < 8)
48 i++;
49
50 if (i == 8)
51 return true; 46 return true;
52 } 47 }
53 } 48 }
diff --git a/net/ipv6/netfilter/ip6table_filter.c b/net/ipv6/netfilter/ip6table_filter.c
index ef5a0a32bf8e..6f4383ad86f9 100644
--- a/net/ipv6/netfilter/ip6table_filter.c
+++ b/net/ipv6/netfilter/ip6table_filter.c
@@ -51,11 +51,11 @@ static struct
51 .term = IP6T_ERROR_INIT, /* ERROR */ 51 .term = IP6T_ERROR_INIT, /* ERROR */
52}; 52};
53 53
54static struct xt_table packet_filter = { 54static const struct xt_table packet_filter = {
55 .name = "filter", 55 .name = "filter",
56 .valid_hooks = FILTER_VALID_HOOKS, 56 .valid_hooks = FILTER_VALID_HOOKS,
57 .me = THIS_MODULE, 57 .me = THIS_MODULE,
58 .af = AF_INET6, 58 .af = NFPROTO_IPV6,
59}; 59};
60 60
61/* The work comes in here from netfilter.c. */ 61/* The work comes in here from netfilter.c. */
@@ -95,21 +95,21 @@ static struct nf_hook_ops ip6t_ops[] __read_mostly = {
95 { 95 {
96 .hook = ip6t_in_hook, 96 .hook = ip6t_in_hook,
97 .owner = THIS_MODULE, 97 .owner = THIS_MODULE,
98 .pf = PF_INET6, 98 .pf = NFPROTO_IPV6,
99 .hooknum = NF_INET_LOCAL_IN, 99 .hooknum = NF_INET_LOCAL_IN,
100 .priority = NF_IP6_PRI_FILTER, 100 .priority = NF_IP6_PRI_FILTER,
101 }, 101 },
102 { 102 {
103 .hook = ip6t_in_hook, 103 .hook = ip6t_in_hook,
104 .owner = THIS_MODULE, 104 .owner = THIS_MODULE,
105 .pf = PF_INET6, 105 .pf = NFPROTO_IPV6,
106 .hooknum = NF_INET_FORWARD, 106 .hooknum = NF_INET_FORWARD,
107 .priority = NF_IP6_PRI_FILTER, 107 .priority = NF_IP6_PRI_FILTER,
108 }, 108 },
109 { 109 {
110 .hook = ip6t_local_out_hook, 110 .hook = ip6t_local_out_hook,
111 .owner = THIS_MODULE, 111 .owner = THIS_MODULE,
112 .pf = PF_INET6, 112 .pf = NFPROTO_IPV6,
113 .hooknum = NF_INET_LOCAL_OUT, 113 .hooknum = NF_INET_LOCAL_OUT,
114 .priority = NF_IP6_PRI_FILTER, 114 .priority = NF_IP6_PRI_FILTER,
115 }, 115 },
diff --git a/net/ipv6/netfilter/ip6table_mangle.c b/net/ipv6/netfilter/ip6table_mangle.c
index ab0d398a2ba7..0ad91433ed61 100644
--- a/net/ipv6/netfilter/ip6table_mangle.c
+++ b/net/ipv6/netfilter/ip6table_mangle.c
@@ -21,7 +21,7 @@ MODULE_DESCRIPTION("ip6tables mangle table");
21 (1 << NF_INET_LOCAL_OUT) | \ 21 (1 << NF_INET_LOCAL_OUT) | \
22 (1 << NF_INET_POST_ROUTING)) 22 (1 << NF_INET_POST_ROUTING))
23 23
24static struct 24static const struct
25{ 25{
26 struct ip6t_replace repl; 26 struct ip6t_replace repl;
27 struct ip6t_standard entries[5]; 27 struct ip6t_standard entries[5];
@@ -57,11 +57,11 @@ static struct
57 .term = IP6T_ERROR_INIT, /* ERROR */ 57 .term = IP6T_ERROR_INIT, /* ERROR */
58}; 58};
59 59
60static struct xt_table packet_mangler = { 60static const struct xt_table packet_mangler = {
61 .name = "mangle", 61 .name = "mangle",
62 .valid_hooks = MANGLE_VALID_HOOKS, 62 .valid_hooks = MANGLE_VALID_HOOKS,
63 .me = THIS_MODULE, 63 .me = THIS_MODULE,
64 .af = AF_INET6, 64 .af = NFPROTO_IPV6,
65}; 65};
66 66
67/* The work comes in here from netfilter.c. */ 67/* The work comes in here from netfilter.c. */
@@ -136,35 +136,35 @@ static struct nf_hook_ops ip6t_ops[] __read_mostly = {
136 { 136 {
137 .hook = ip6t_in_hook, 137 .hook = ip6t_in_hook,
138 .owner = THIS_MODULE, 138 .owner = THIS_MODULE,
139 .pf = PF_INET6, 139 .pf = NFPROTO_IPV6,
140 .hooknum = NF_INET_PRE_ROUTING, 140 .hooknum = NF_INET_PRE_ROUTING,
141 .priority = NF_IP6_PRI_MANGLE, 141 .priority = NF_IP6_PRI_MANGLE,
142 }, 142 },
143 { 143 {
144 .hook = ip6t_in_hook, 144 .hook = ip6t_in_hook,
145 .owner = THIS_MODULE, 145 .owner = THIS_MODULE,
146 .pf = PF_INET6, 146 .pf = NFPROTO_IPV6,
147 .hooknum = NF_INET_LOCAL_IN, 147 .hooknum = NF_INET_LOCAL_IN,
148 .priority = NF_IP6_PRI_MANGLE, 148 .priority = NF_IP6_PRI_MANGLE,
149 }, 149 },
150 { 150 {
151 .hook = ip6t_in_hook, 151 .hook = ip6t_in_hook,
152 .owner = THIS_MODULE, 152 .owner = THIS_MODULE,
153 .pf = PF_INET6, 153 .pf = NFPROTO_IPV6,
154 .hooknum = NF_INET_FORWARD, 154 .hooknum = NF_INET_FORWARD,
155 .priority = NF_IP6_PRI_MANGLE, 155 .priority = NF_IP6_PRI_MANGLE,
156 }, 156 },
157 { 157 {
158 .hook = ip6t_local_out_hook, 158 .hook = ip6t_local_out_hook,
159 .owner = THIS_MODULE, 159 .owner = THIS_MODULE,
160 .pf = PF_INET6, 160 .pf = NFPROTO_IPV6,
161 .hooknum = NF_INET_LOCAL_OUT, 161 .hooknum = NF_INET_LOCAL_OUT,
162 .priority = NF_IP6_PRI_MANGLE, 162 .priority = NF_IP6_PRI_MANGLE,
163 }, 163 },
164 { 164 {
165 .hook = ip6t_post_routing_hook, 165 .hook = ip6t_post_routing_hook,
166 .owner = THIS_MODULE, 166 .owner = THIS_MODULE,
167 .pf = PF_INET6, 167 .pf = NFPROTO_IPV6,
168 .hooknum = NF_INET_POST_ROUTING, 168 .hooknum = NF_INET_POST_ROUTING,
169 .priority = NF_IP6_PRI_MANGLE, 169 .priority = NF_IP6_PRI_MANGLE,
170 }, 170 },
diff --git a/net/ipv6/netfilter/ip6table_raw.c b/net/ipv6/netfilter/ip6table_raw.c
index 4b792b6ca321..ed1a1180f3b3 100644
--- a/net/ipv6/netfilter/ip6table_raw.c
+++ b/net/ipv6/netfilter/ip6table_raw.c
@@ -8,7 +8,7 @@
8 8
9#define RAW_VALID_HOOKS ((1 << NF_INET_PRE_ROUTING) | (1 << NF_INET_LOCAL_OUT)) 9#define RAW_VALID_HOOKS ((1 << NF_INET_PRE_ROUTING) | (1 << NF_INET_LOCAL_OUT))
10 10
11static struct 11static const struct
12{ 12{
13 struct ip6t_replace repl; 13 struct ip6t_replace repl;
14 struct ip6t_standard entries[2]; 14 struct ip6t_standard entries[2];
@@ -35,11 +35,11 @@ static struct
35 .term = IP6T_ERROR_INIT, /* ERROR */ 35 .term = IP6T_ERROR_INIT, /* ERROR */
36}; 36};
37 37
38static struct xt_table packet_raw = { 38static const struct xt_table packet_raw = {
39 .name = "raw", 39 .name = "raw",
40 .valid_hooks = RAW_VALID_HOOKS, 40 .valid_hooks = RAW_VALID_HOOKS,
41 .me = THIS_MODULE, 41 .me = THIS_MODULE,
42 .af = AF_INET6, 42 .af = NFPROTO_IPV6,
43}; 43};
44 44
45/* The work comes in here from netfilter.c. */ 45/* The work comes in here from netfilter.c. */
@@ -68,14 +68,14 @@ ip6t_local_out_hook(unsigned int hook,
68static struct nf_hook_ops ip6t_ops[] __read_mostly = { 68static struct nf_hook_ops ip6t_ops[] __read_mostly = {
69 { 69 {
70 .hook = ip6t_pre_routing_hook, 70 .hook = ip6t_pre_routing_hook,
71 .pf = PF_INET6, 71 .pf = NFPROTO_IPV6,
72 .hooknum = NF_INET_PRE_ROUTING, 72 .hooknum = NF_INET_PRE_ROUTING,
73 .priority = NF_IP6_PRI_FIRST, 73 .priority = NF_IP6_PRI_FIRST,
74 .owner = THIS_MODULE, 74 .owner = THIS_MODULE,
75 }, 75 },
76 { 76 {
77 .hook = ip6t_local_out_hook, 77 .hook = ip6t_local_out_hook,
78 .pf = PF_INET6, 78 .pf = NFPROTO_IPV6,
79 .hooknum = NF_INET_LOCAL_OUT, 79 .hooknum = NF_INET_LOCAL_OUT,
80 .priority = NF_IP6_PRI_FIRST, 80 .priority = NF_IP6_PRI_FIRST,
81 .owner = THIS_MODULE, 81 .owner = THIS_MODULE,
diff --git a/net/ipv6/netfilter/ip6table_security.c b/net/ipv6/netfilter/ip6table_security.c
index 0ea37ff15d56..41b444c60934 100644
--- a/net/ipv6/netfilter/ip6table_security.c
+++ b/net/ipv6/netfilter/ip6table_security.c
@@ -26,7 +26,7 @@ MODULE_DESCRIPTION("ip6tables security table, for MAC rules");
26 (1 << NF_INET_FORWARD) | \ 26 (1 << NF_INET_FORWARD) | \
27 (1 << NF_INET_LOCAL_OUT) 27 (1 << NF_INET_LOCAL_OUT)
28 28
29static struct 29static const struct
30{ 30{
31 struct ip6t_replace repl; 31 struct ip6t_replace repl;
32 struct ip6t_standard entries[3]; 32 struct ip6t_standard entries[3];
@@ -56,11 +56,11 @@ static struct
56 .term = IP6T_ERROR_INIT, /* ERROR */ 56 .term = IP6T_ERROR_INIT, /* ERROR */
57}; 57};
58 58
59static struct xt_table security_table = { 59static const struct xt_table security_table = {
60 .name = "security", 60 .name = "security",
61 .valid_hooks = SECURITY_VALID_HOOKS, 61 .valid_hooks = SECURITY_VALID_HOOKS,
62 .me = THIS_MODULE, 62 .me = THIS_MODULE,
63 .af = AF_INET6, 63 .af = NFPROTO_IPV6,
64}; 64};
65 65
66static unsigned int 66static unsigned int
@@ -101,21 +101,21 @@ static struct nf_hook_ops ip6t_ops[] __read_mostly = {
101 { 101 {
102 .hook = ip6t_local_in_hook, 102 .hook = ip6t_local_in_hook,
103 .owner = THIS_MODULE, 103 .owner = THIS_MODULE,
104 .pf = PF_INET6, 104 .pf = NFPROTO_IPV6,
105 .hooknum = NF_INET_LOCAL_IN, 105 .hooknum = NF_INET_LOCAL_IN,
106 .priority = NF_IP6_PRI_SECURITY, 106 .priority = NF_IP6_PRI_SECURITY,
107 }, 107 },
108 { 108 {
109 .hook = ip6t_forward_hook, 109 .hook = ip6t_forward_hook,
110 .owner = THIS_MODULE, 110 .owner = THIS_MODULE,
111 .pf = PF_INET6, 111 .pf = NFPROTO_IPV6,
112 .hooknum = NF_INET_FORWARD, 112 .hooknum = NF_INET_FORWARD,
113 .priority = NF_IP6_PRI_SECURITY, 113 .priority = NF_IP6_PRI_SECURITY,
114 }, 114 },
115 { 115 {
116 .hook = ip6t_local_out_hook, 116 .hook = ip6t_local_out_hook,
117 .owner = THIS_MODULE, 117 .owner = THIS_MODULE,
118 .pf = PF_INET6, 118 .pf = NFPROTO_IPV6,
119 .hooknum = NF_INET_LOCAL_OUT, 119 .hooknum = NF_INET_LOCAL_OUT,
120 .priority = NF_IP6_PRI_SECURITY, 120 .priority = NF_IP6_PRI_SECURITY,
121 }, 121 },
diff --git a/net/ipv6/netfilter/nf_conntrack_l3proto_ipv6.c b/net/ipv6/netfilter/nf_conntrack_l3proto_ipv6.c
index 2a15c2d66c69..5f2ec208a8c3 100644
--- a/net/ipv6/netfilter/nf_conntrack_l3proto_ipv6.c
+++ b/net/ipv6/netfilter/nf_conntrack_l3proto_ipv6.c
@@ -27,6 +27,7 @@
27#include <net/netfilter/nf_conntrack_l3proto.h> 27#include <net/netfilter/nf_conntrack_l3proto.h>
28#include <net/netfilter/nf_conntrack_core.h> 28#include <net/netfilter/nf_conntrack_core.h>
29#include <net/netfilter/ipv6/nf_conntrack_ipv6.h> 29#include <net/netfilter/ipv6/nf_conntrack_ipv6.h>
30#include <net/netfilter/nf_log.h>
30 31
31static bool ipv6_pkt_to_tuple(const struct sk_buff *skb, unsigned int nhoff, 32static bool ipv6_pkt_to_tuple(const struct sk_buff *skb, unsigned int nhoff,
32 struct nf_conntrack_tuple *tuple) 33 struct nf_conntrack_tuple *tuple)
@@ -176,8 +177,11 @@ static unsigned int ipv6_confirm(unsigned int hooknum,
176 } 177 }
177 178
178 ret = helper->help(skb, protoff, ct, ctinfo); 179 ret = helper->help(skb, protoff, ct, ctinfo);
179 if (ret != NF_ACCEPT) 180 if (ret != NF_ACCEPT) {
181 nf_log_packet(NFPROTO_IPV6, hooknum, skb, in, out, NULL,
182 "nf_ct_%s: dropping packet", helper->name);
180 return ret; 183 return ret;
184 }
181out: 185out:
182 /* We've seen it coming out the other side: confirm it */ 186 /* We've seen it coming out the other side: confirm it */
183 return nf_conntrack_confirm(skb); 187 return nf_conntrack_confirm(skb);
@@ -265,42 +269,42 @@ static struct nf_hook_ops ipv6_conntrack_ops[] __read_mostly = {
265 { 269 {
266 .hook = ipv6_defrag, 270 .hook = ipv6_defrag,
267 .owner = THIS_MODULE, 271 .owner = THIS_MODULE,
268 .pf = PF_INET6, 272 .pf = NFPROTO_IPV6,
269 .hooknum = NF_INET_PRE_ROUTING, 273 .hooknum = NF_INET_PRE_ROUTING,
270 .priority = NF_IP6_PRI_CONNTRACK_DEFRAG, 274 .priority = NF_IP6_PRI_CONNTRACK_DEFRAG,
271 }, 275 },
272 { 276 {
273 .hook = ipv6_conntrack_in, 277 .hook = ipv6_conntrack_in,
274 .owner = THIS_MODULE, 278 .owner = THIS_MODULE,
275 .pf = PF_INET6, 279 .pf = NFPROTO_IPV6,
276 .hooknum = NF_INET_PRE_ROUTING, 280 .hooknum = NF_INET_PRE_ROUTING,
277 .priority = NF_IP6_PRI_CONNTRACK, 281 .priority = NF_IP6_PRI_CONNTRACK,
278 }, 282 },
279 { 283 {
280 .hook = ipv6_conntrack_local, 284 .hook = ipv6_conntrack_local,
281 .owner = THIS_MODULE, 285 .owner = THIS_MODULE,
282 .pf = PF_INET6, 286 .pf = NFPROTO_IPV6,
283 .hooknum = NF_INET_LOCAL_OUT, 287 .hooknum = NF_INET_LOCAL_OUT,
284 .priority = NF_IP6_PRI_CONNTRACK, 288 .priority = NF_IP6_PRI_CONNTRACK,
285 }, 289 },
286 { 290 {
287 .hook = ipv6_defrag, 291 .hook = ipv6_defrag,
288 .owner = THIS_MODULE, 292 .owner = THIS_MODULE,
289 .pf = PF_INET6, 293 .pf = NFPROTO_IPV6,
290 .hooknum = NF_INET_LOCAL_OUT, 294 .hooknum = NF_INET_LOCAL_OUT,
291 .priority = NF_IP6_PRI_CONNTRACK_DEFRAG, 295 .priority = NF_IP6_PRI_CONNTRACK_DEFRAG,
292 }, 296 },
293 { 297 {
294 .hook = ipv6_confirm, 298 .hook = ipv6_confirm,
295 .owner = THIS_MODULE, 299 .owner = THIS_MODULE,
296 .pf = PF_INET6, 300 .pf = NFPROTO_IPV6,
297 .hooknum = NF_INET_POST_ROUTING, 301 .hooknum = NF_INET_POST_ROUTING,
298 .priority = NF_IP6_PRI_LAST, 302 .priority = NF_IP6_PRI_LAST,
299 }, 303 },
300 { 304 {
301 .hook = ipv6_confirm, 305 .hook = ipv6_confirm,
302 .owner = THIS_MODULE, 306 .owner = THIS_MODULE,
303 .pf = PF_INET6, 307 .pf = NFPROTO_IPV6,
304 .hooknum = NF_INET_LOCAL_IN, 308 .hooknum = NF_INET_LOCAL_IN,
305 .priority = NF_IP6_PRI_LAST-1, 309 .priority = NF_IP6_PRI_LAST-1,
306 }, 310 },
diff --git a/net/ipv6/proc.c b/net/ipv6/proc.c
index 590ddefb7ffc..c9605c3ad91f 100644
--- a/net/ipv6/proc.c
+++ b/net/ipv6/proc.c
@@ -101,7 +101,7 @@ static struct snmp_mib snmp6_icmp6_list[] = {
101}; 101};
102 102
103/* RFC 4293 v6 ICMPMsgStatsTable; named items for RFC 2466 compatibility */ 103/* RFC 4293 v6 ICMPMsgStatsTable; named items for RFC 2466 compatibility */
104static char *icmp6type2name[256] = { 104static const char *const icmp6type2name[256] = {
105 [ICMPV6_DEST_UNREACH] = "DestUnreachs", 105 [ICMPV6_DEST_UNREACH] = "DestUnreachs",
106 [ICMPV6_PKT_TOOBIG] = "PktTooBigs", 106 [ICMPV6_PKT_TOOBIG] = "PktTooBigs",
107 [ICMPV6_TIME_EXCEED] = "TimeExcds", 107 [ICMPV6_TIME_EXCEED] = "TimeExcds",
@@ -144,7 +144,7 @@ static void snmp6_seq_show_icmpv6msg(struct seq_file *seq, void **mib)
144 /* print by name -- deprecated items */ 144 /* print by name -- deprecated items */
145 for (i = 0; i < ICMP6MSG_MIB_MAX; i++) { 145 for (i = 0; i < ICMP6MSG_MIB_MAX; i++) {
146 int icmptype; 146 int icmptype;
147 char *p; 147 const char *p;
148 148
149 icmptype = i & 0xff; 149 icmptype = i & 0xff;
150 p = icmp6type2name[icmptype]; 150 p = icmp6type2name[icmptype];
diff --git a/net/ipv6/protocol.c b/net/ipv6/protocol.c
index 9ab789159913..568864f722ca 100644
--- a/net/ipv6/protocol.c
+++ b/net/ipv6/protocol.c
@@ -20,20 +20,9 @@
20 * - Removed unused variable 'inet6_protocol_base' 20 * - Removed unused variable 'inet6_protocol_base'
21 * - Modified inet6_del_protocol() to correctly maintain copy bit. 21 * - Modified inet6_del_protocol() to correctly maintain copy bit.
22 */ 22 */
23 23#include <linux/module.h>
24#include <linux/errno.h>
25#include <linux/types.h>
26#include <linux/socket.h>
27#include <linux/sockios.h>
28#include <linux/net.h>
29#include <linux/in6.h>
30#include <linux/netdevice.h> 24#include <linux/netdevice.h>
31#include <linux/if_arp.h> 25#include <linux/spinlock.h>
32
33#include <net/sock.h>
34#include <net/snmp.h>
35
36#include <net/ipv6.h>
37#include <net/protocol.h> 26#include <net/protocol.h>
38 27
39struct inet6_protocol *inet6_protos[MAX_INET_PROTOS]; 28struct inet6_protocol *inet6_protos[MAX_INET_PROTOS];
diff --git a/net/ipv6/raw.c b/net/ipv6/raw.c
index d6c3c1c34b2d..7d675b8d82d3 100644
--- a/net/ipv6/raw.c
+++ b/net/ipv6/raw.c
@@ -642,7 +642,7 @@ static int rawv6_send_hdrinc(struct sock *sk, void *from, int length,
642 err = NF_HOOK(PF_INET6, NF_INET_LOCAL_OUT, skb, NULL, rt->u.dst.dev, 642 err = NF_HOOK(PF_INET6, NF_INET_LOCAL_OUT, skb, NULL, rt->u.dst.dev,
643 dst_output); 643 dst_output);
644 if (err > 0) 644 if (err > 0)
645 err = np->recverr ? net_xmit_errno(err) : 0; 645 err = net_xmit_errno(err);
646 if (err) 646 if (err)
647 goto error; 647 goto error;
648out: 648out:
@@ -653,6 +653,8 @@ error_fault:
653 kfree_skb(skb); 653 kfree_skb(skb);
654error: 654error:
655 IP6_INC_STATS(sock_net(sk), rt->rt6i_idev, IPSTATS_MIB_OUTDISCARDS); 655 IP6_INC_STATS(sock_net(sk), rt->rt6i_idev, IPSTATS_MIB_OUTDISCARDS);
656 if (err == -ENOBUFS && !np->recverr)
657 err = 0;
656 return err; 658 return err;
657} 659}
658 660
@@ -877,11 +879,8 @@ static int rawv6_sendmsg(struct kiocb *iocb, struct sock *sk,
877 hlimit = ip6_dst_hoplimit(dst); 879 hlimit = ip6_dst_hoplimit(dst);
878 } 880 }
879 881
880 if (tclass < 0) { 882 if (tclass < 0)
881 tclass = np->tclass; 883 tclass = np->tclass;
882 if (tclass < 0)
883 tclass = 0;
884 }
885 884
886 if (msg->msg_flags&MSG_CONFIRM) 885 if (msg->msg_flags&MSG_CONFIRM)
887 goto do_confirm; 886 goto do_confirm;
diff --git a/net/ipv6/route.c b/net/ipv6/route.c
index 1473ee0a1f51..9ccfef345560 100644
--- a/net/ipv6/route.c
+++ b/net/ipv6/route.c
@@ -665,7 +665,7 @@ static struct rt6_info *rt6_alloc_cow(struct rt6_info *ort, struct in6_addr *dad
665 net->ipv6.sysctl.ip6_rt_gc_elasticity = 1; 665 net->ipv6.sysctl.ip6_rt_gc_elasticity = 1;
666 net->ipv6.sysctl.ip6_rt_gc_min_interval = 0; 666 net->ipv6.sysctl.ip6_rt_gc_min_interval = 0;
667 667
668 ip6_dst_gc(net->ipv6.ip6_dst_ops); 668 ip6_dst_gc(&net->ipv6.ip6_dst_ops);
669 669
670 net->ipv6.sysctl.ip6_rt_gc_elasticity = 670 net->ipv6.sysctl.ip6_rt_gc_elasticity =
671 saved_rt_elasticity; 671 saved_rt_elasticity;
@@ -970,7 +970,7 @@ struct dst_entry *icmp6_dst_alloc(struct net_device *dev,
970 if (unlikely(idev == NULL)) 970 if (unlikely(idev == NULL))
971 return NULL; 971 return NULL;
972 972
973 rt = ip6_dst_alloc(net->ipv6.ip6_dst_ops); 973 rt = ip6_dst_alloc(&net->ipv6.ip6_dst_ops);
974 if (unlikely(rt == NULL)) { 974 if (unlikely(rt == NULL)) {
975 in6_dev_put(idev); 975 in6_dev_put(idev);
976 goto out; 976 goto out;
@@ -1060,7 +1060,7 @@ static void icmp6_clean_all(int (*func)(struct rt6_info *rt, void *arg),
1060static int ip6_dst_gc(struct dst_ops *ops) 1060static int ip6_dst_gc(struct dst_ops *ops)
1061{ 1061{
1062 unsigned long now = jiffies; 1062 unsigned long now = jiffies;
1063 struct net *net = ops->dst_net; 1063 struct net *net = container_of(ops, struct net, ipv6.ip6_dst_ops);
1064 int rt_min_interval = net->ipv6.sysctl.ip6_rt_gc_min_interval; 1064 int rt_min_interval = net->ipv6.sysctl.ip6_rt_gc_min_interval;
1065 int rt_max_size = net->ipv6.sysctl.ip6_rt_max_size; 1065 int rt_max_size = net->ipv6.sysctl.ip6_rt_max_size;
1066 int rt_elasticity = net->ipv6.sysctl.ip6_rt_gc_elasticity; 1066 int rt_elasticity = net->ipv6.sysctl.ip6_rt_gc_elasticity;
@@ -1154,7 +1154,7 @@ int ip6_route_add(struct fib6_config *cfg)
1154 goto out; 1154 goto out;
1155 } 1155 }
1156 1156
1157 rt = ip6_dst_alloc(net->ipv6.ip6_dst_ops); 1157 rt = ip6_dst_alloc(&net->ipv6.ip6_dst_ops);
1158 1158
1159 if (rt == NULL) { 1159 if (rt == NULL) {
1160 err = -ENOMEM; 1160 err = -ENOMEM;
@@ -1643,7 +1643,7 @@ out:
1643static struct rt6_info * ip6_rt_copy(struct rt6_info *ort) 1643static struct rt6_info * ip6_rt_copy(struct rt6_info *ort)
1644{ 1644{
1645 struct net *net = dev_net(ort->rt6i_dev); 1645 struct net *net = dev_net(ort->rt6i_dev);
1646 struct rt6_info *rt = ip6_dst_alloc(net->ipv6.ip6_dst_ops); 1646 struct rt6_info *rt = ip6_dst_alloc(&net->ipv6.ip6_dst_ops);
1647 1647
1648 if (rt) { 1648 if (rt) {
1649 rt->u.dst.input = ort->u.dst.input; 1649 rt->u.dst.input = ort->u.dst.input;
@@ -1923,7 +1923,7 @@ struct rt6_info *addrconf_dst_alloc(struct inet6_dev *idev,
1923 int anycast) 1923 int anycast)
1924{ 1924{
1925 struct net *net = dev_net(idev->dev); 1925 struct net *net = dev_net(idev->dev);
1926 struct rt6_info *rt = ip6_dst_alloc(net->ipv6.ip6_dst_ops); 1926 struct rt6_info *rt = ip6_dst_alloc(&net->ipv6.ip6_dst_ops);
1927 struct neighbour *neigh; 1927 struct neighbour *neigh;
1928 1928
1929 if (rt == NULL) 1929 if (rt == NULL)
@@ -2501,7 +2501,7 @@ static int rt6_stats_seq_show(struct seq_file *seq, void *v)
2501 net->ipv6.rt6_stats->fib_rt_alloc, 2501 net->ipv6.rt6_stats->fib_rt_alloc,
2502 net->ipv6.rt6_stats->fib_rt_entries, 2502 net->ipv6.rt6_stats->fib_rt_entries,
2503 net->ipv6.rt6_stats->fib_rt_cache, 2503 net->ipv6.rt6_stats->fib_rt_cache,
2504 atomic_read(&net->ipv6.ip6_dst_ops->entries), 2504 atomic_read(&net->ipv6.ip6_dst_ops.entries),
2505 net->ipv6.rt6_stats->fib_discarded_routes); 2505 net->ipv6.rt6_stats->fib_discarded_routes);
2506 2506
2507 return 0; 2507 return 0;
@@ -2637,7 +2637,7 @@ struct ctl_table *ipv6_route_sysctl_init(struct net *net)
2637 2637
2638 if (table) { 2638 if (table) {
2639 table[0].data = &net->ipv6.sysctl.flush_delay; 2639 table[0].data = &net->ipv6.sysctl.flush_delay;
2640 table[1].data = &net->ipv6.ip6_dst_ops->gc_thresh; 2640 table[1].data = &net->ipv6.ip6_dst_ops.gc_thresh;
2641 table[2].data = &net->ipv6.sysctl.ip6_rt_max_size; 2641 table[2].data = &net->ipv6.sysctl.ip6_rt_max_size;
2642 table[3].data = &net->ipv6.sysctl.ip6_rt_gc_min_interval; 2642 table[3].data = &net->ipv6.sysctl.ip6_rt_gc_min_interval;
2643 table[4].data = &net->ipv6.sysctl.ip6_rt_gc_timeout; 2643 table[4].data = &net->ipv6.sysctl.ip6_rt_gc_timeout;
@@ -2655,12 +2655,8 @@ static int ip6_route_net_init(struct net *net)
2655{ 2655{
2656 int ret = -ENOMEM; 2656 int ret = -ENOMEM;
2657 2657
2658 net->ipv6.ip6_dst_ops = kmemdup(&ip6_dst_ops_template, 2658 memcpy(&net->ipv6.ip6_dst_ops, &ip6_dst_ops_template,
2659 sizeof(*net->ipv6.ip6_dst_ops), 2659 sizeof(net->ipv6.ip6_dst_ops));
2660 GFP_KERNEL);
2661 if (!net->ipv6.ip6_dst_ops)
2662 goto out;
2663 net->ipv6.ip6_dst_ops->dst_net = hold_net(net);
2664 2660
2665 net->ipv6.ip6_null_entry = kmemdup(&ip6_null_entry_template, 2661 net->ipv6.ip6_null_entry = kmemdup(&ip6_null_entry_template,
2666 sizeof(*net->ipv6.ip6_null_entry), 2662 sizeof(*net->ipv6.ip6_null_entry),
@@ -2669,7 +2665,7 @@ static int ip6_route_net_init(struct net *net)
2669 goto out_ip6_dst_ops; 2665 goto out_ip6_dst_ops;
2670 net->ipv6.ip6_null_entry->u.dst.path = 2666 net->ipv6.ip6_null_entry->u.dst.path =
2671 (struct dst_entry *)net->ipv6.ip6_null_entry; 2667 (struct dst_entry *)net->ipv6.ip6_null_entry;
2672 net->ipv6.ip6_null_entry->u.dst.ops = net->ipv6.ip6_dst_ops; 2668 net->ipv6.ip6_null_entry->u.dst.ops = &net->ipv6.ip6_dst_ops;
2673 2669
2674#ifdef CONFIG_IPV6_MULTIPLE_TABLES 2670#ifdef CONFIG_IPV6_MULTIPLE_TABLES
2675 net->ipv6.ip6_prohibit_entry = kmemdup(&ip6_prohibit_entry_template, 2671 net->ipv6.ip6_prohibit_entry = kmemdup(&ip6_prohibit_entry_template,
@@ -2679,7 +2675,7 @@ static int ip6_route_net_init(struct net *net)
2679 goto out_ip6_null_entry; 2675 goto out_ip6_null_entry;
2680 net->ipv6.ip6_prohibit_entry->u.dst.path = 2676 net->ipv6.ip6_prohibit_entry->u.dst.path =
2681 (struct dst_entry *)net->ipv6.ip6_prohibit_entry; 2677 (struct dst_entry *)net->ipv6.ip6_prohibit_entry;
2682 net->ipv6.ip6_prohibit_entry->u.dst.ops = net->ipv6.ip6_dst_ops; 2678 net->ipv6.ip6_prohibit_entry->u.dst.ops = &net->ipv6.ip6_dst_ops;
2683 2679
2684 net->ipv6.ip6_blk_hole_entry = kmemdup(&ip6_blk_hole_entry_template, 2680 net->ipv6.ip6_blk_hole_entry = kmemdup(&ip6_blk_hole_entry_template,
2685 sizeof(*net->ipv6.ip6_blk_hole_entry), 2681 sizeof(*net->ipv6.ip6_blk_hole_entry),
@@ -2688,7 +2684,7 @@ static int ip6_route_net_init(struct net *net)
2688 goto out_ip6_prohibit_entry; 2684 goto out_ip6_prohibit_entry;
2689 net->ipv6.ip6_blk_hole_entry->u.dst.path = 2685 net->ipv6.ip6_blk_hole_entry->u.dst.path =
2690 (struct dst_entry *)net->ipv6.ip6_blk_hole_entry; 2686 (struct dst_entry *)net->ipv6.ip6_blk_hole_entry;
2691 net->ipv6.ip6_blk_hole_entry->u.dst.ops = net->ipv6.ip6_dst_ops; 2687 net->ipv6.ip6_blk_hole_entry->u.dst.ops = &net->ipv6.ip6_dst_ops;
2692#endif 2688#endif
2693 2689
2694 net->ipv6.sysctl.flush_delay = 0; 2690 net->ipv6.sysctl.flush_delay = 0;
@@ -2717,8 +2713,6 @@ out_ip6_null_entry:
2717 kfree(net->ipv6.ip6_null_entry); 2713 kfree(net->ipv6.ip6_null_entry);
2718#endif 2714#endif
2719out_ip6_dst_ops: 2715out_ip6_dst_ops:
2720 release_net(net->ipv6.ip6_dst_ops->dst_net);
2721 kfree(net->ipv6.ip6_dst_ops);
2722 goto out; 2716 goto out;
2723} 2717}
2724 2718
@@ -2733,8 +2727,6 @@ static void ip6_route_net_exit(struct net *net)
2733 kfree(net->ipv6.ip6_prohibit_entry); 2727 kfree(net->ipv6.ip6_prohibit_entry);
2734 kfree(net->ipv6.ip6_blk_hole_entry); 2728 kfree(net->ipv6.ip6_blk_hole_entry);
2735#endif 2729#endif
2736 release_net(net->ipv6.ip6_dst_ops->dst_net);
2737 kfree(net->ipv6.ip6_dst_ops);
2738} 2730}
2739 2731
2740static struct pernet_operations ip6_route_net_ops = { 2732static struct pernet_operations ip6_route_net_ops = {
diff --git a/net/ipv6/sit.c b/net/ipv6/sit.c
index 98b7327d0949..0ae4f6448187 100644
--- a/net/ipv6/sit.c
+++ b/net/ipv6/sit.c
@@ -609,7 +609,8 @@ static inline __be32 try_6to4(struct in6_addr *v6dst)
609 * and that skb is filled properly by that function. 609 * and that skb is filled properly by that function.
610 */ 610 */
611 611
612static int ipip6_tunnel_xmit(struct sk_buff *skb, struct net_device *dev) 612static netdev_tx_t ipip6_tunnel_xmit(struct sk_buff *skb,
613 struct net_device *dev)
613{ 614{
614 struct ip_tunnel *tunnel = netdev_priv(dev); 615 struct ip_tunnel *tunnel = netdev_priv(dev);
615 struct net_device_stats *stats = &tunnel->dev->stats; 616 struct net_device_stats *stats = &tunnel->dev->stats;
@@ -753,7 +754,7 @@ static int ipip6_tunnel_xmit(struct sk_buff *skb, struct net_device *dev)
753 stats->tx_dropped++; 754 stats->tx_dropped++;
754 dev_kfree_skb(skb); 755 dev_kfree_skb(skb);
755 tunnel->recursion--; 756 tunnel->recursion--;
756 return 0; 757 return NETDEV_TX_OK;
757 } 758 }
758 if (skb->sk) 759 if (skb->sk)
759 skb_set_owner_w(new_skb, skb->sk); 760 skb_set_owner_w(new_skb, skb->sk);
@@ -778,7 +779,7 @@ static int ipip6_tunnel_xmit(struct sk_buff *skb, struct net_device *dev)
778 iph->version = 4; 779 iph->version = 4;
779 iph->ihl = sizeof(struct iphdr)>>2; 780 iph->ihl = sizeof(struct iphdr)>>2;
780 if (mtu > IPV6_MIN_MTU) 781 if (mtu > IPV6_MIN_MTU)
781 iph->frag_off = htons(IP_DF); 782 iph->frag_off = tiph->frag_off;
782 else 783 else
783 iph->frag_off = 0; 784 iph->frag_off = 0;
784 785
@@ -794,7 +795,7 @@ static int ipip6_tunnel_xmit(struct sk_buff *skb, struct net_device *dev)
794 795
795 IPTUNNEL_XMIT(); 796 IPTUNNEL_XMIT();
796 tunnel->recursion--; 797 tunnel->recursion--;
797 return 0; 798 return NETDEV_TX_OK;
798 799
799tx_error_icmp: 800tx_error_icmp:
800 dst_link_failure(skb); 801 dst_link_failure(skb);
@@ -802,7 +803,7 @@ tx_error:
802 stats->tx_errors++; 803 stats->tx_errors++;
803 dev_kfree_skb(skb); 804 dev_kfree_skb(skb);
804 tunnel->recursion--; 805 tunnel->recursion--;
805 return 0; 806 return NETDEV_TX_OK;
806} 807}
807 808
808static void ipip6_tunnel_bind_dev(struct net_device *dev) 809static void ipip6_tunnel_bind_dev(struct net_device *dev)
diff --git a/net/ipv6/sysctl_net_ipv6.c b/net/ipv6/sysctl_net_ipv6.c
index a031034720b4..0dc6a4e5ed4a 100644
--- a/net/ipv6/sysctl_net_ipv6.c
+++ b/net/ipv6/sysctl_net_ipv6.c
@@ -40,7 +40,7 @@ static ctl_table ipv6_table_template[] = {
40 { .ctl_name = 0 } 40 { .ctl_name = 0 }
41}; 41};
42 42
43static ctl_table ipv6_table[] = { 43static ctl_table ipv6_rotable[] = {
44 { 44 {
45 .ctl_name = NET_IPV6_MLD_MAX_MSF, 45 .ctl_name = NET_IPV6_MLD_MAX_MSF,
46 .procname = "mld_max_msf", 46 .procname = "mld_max_msf",
@@ -130,7 +130,7 @@ int ipv6_sysctl_register(void)
130{ 130{
131 int err = -ENOMEM; 131 int err = -ENOMEM;
132 132
133 ip6_header = register_net_sysctl_rotable(net_ipv6_ctl_path, ipv6_table); 133 ip6_header = register_net_sysctl_rotable(net_ipv6_ctl_path, ipv6_rotable);
134 if (ip6_header == NULL) 134 if (ip6_header == NULL)
135 goto out; 135 goto out;
136 136
diff --git a/net/ipv6/tcp_ipv6.c b/net/ipv6/tcp_ipv6.c
index d849dd53b788..3aae0f217d61 100644
--- a/net/ipv6/tcp_ipv6.c
+++ b/net/ipv6/tcp_ipv6.c
@@ -75,11 +75,11 @@ static void tcp_v6_reqsk_send_ack(struct sock *sk, struct sk_buff *skb,
75 75
76static int tcp_v6_do_rcv(struct sock *sk, struct sk_buff *skb); 76static int tcp_v6_do_rcv(struct sock *sk, struct sk_buff *skb);
77 77
78static struct inet_connection_sock_af_ops ipv6_mapped; 78static const struct inet_connection_sock_af_ops ipv6_mapped;
79static struct inet_connection_sock_af_ops ipv6_specific; 79static const struct inet_connection_sock_af_ops ipv6_specific;
80#ifdef CONFIG_TCP_MD5SIG 80#ifdef CONFIG_TCP_MD5SIG
81static struct tcp_sock_af_ops tcp_sock_ipv6_specific; 81static const struct tcp_sock_af_ops tcp_sock_ipv6_specific;
82static struct tcp_sock_af_ops tcp_sock_ipv6_mapped_specific; 82static const struct tcp_sock_af_ops tcp_sock_ipv6_mapped_specific;
83#else 83#else
84static struct tcp_md5sig_key *tcp_v6_md5_do_lookup(struct sock *sk, 84static struct tcp_md5sig_key *tcp_v6_md5_do_lookup(struct sock *sk,
85 struct in6_addr *addr) 85 struct in6_addr *addr)
@@ -591,7 +591,7 @@ static int tcp_v6_md5_do_add(struct sock *sk, struct in6_addr *peer,
591 } 591 }
592 sk->sk_route_caps &= ~NETIF_F_GSO_MASK; 592 sk->sk_route_caps &= ~NETIF_F_GSO_MASK;
593 } 593 }
594 if (tcp_alloc_md5sig_pool() == NULL) { 594 if (tcp_alloc_md5sig_pool(sk) == NULL) {
595 kfree(newkey); 595 kfree(newkey);
596 return -ENOMEM; 596 return -ENOMEM;
597 } 597 }
@@ -894,7 +894,7 @@ struct request_sock_ops tcp6_request_sock_ops __read_mostly = {
894}; 894};
895 895
896#ifdef CONFIG_TCP_MD5SIG 896#ifdef CONFIG_TCP_MD5SIG
897static struct tcp_request_sock_ops tcp_request_sock_ipv6_ops = { 897static const struct tcp_request_sock_ops tcp_request_sock_ipv6_ops = {
898 .md5_lookup = tcp_v6_reqsk_md5_lookup, 898 .md5_lookup = tcp_v6_reqsk_md5_lookup,
899 .calc_md5_hash = tcp_v6_md5_hash_skb, 899 .calc_md5_hash = tcp_v6_md5_hash_skb,
900}; 900};
@@ -1003,6 +1003,7 @@ static void tcp_v6_send_response(struct sk_buff *skb, u32 seq, u32 ack, u32 win,
1003 skb_reserve(buff, MAX_HEADER + sizeof(struct ipv6hdr) + tot_len); 1003 skb_reserve(buff, MAX_HEADER + sizeof(struct ipv6hdr) + tot_len);
1004 1004
1005 t1 = (struct tcphdr *) skb_push(buff, tot_len); 1005 t1 = (struct tcphdr *) skb_push(buff, tot_len);
1006 skb_reset_transport_header(skb);
1006 1007
1007 /* Swap the send and the receive. */ 1008 /* Swap the send and the receive. */
1008 memset(t1, 0, sizeof(*t1)); 1009 memset(t1, 0, sizeof(*t1));
@@ -1760,7 +1761,7 @@ static int tcp_v6_remember_stamp(struct sock *sk)
1760 return 0; 1761 return 0;
1761} 1762}
1762 1763
1763static struct inet_connection_sock_af_ops ipv6_specific = { 1764static const struct inet_connection_sock_af_ops ipv6_specific = {
1764 .queue_xmit = inet6_csk_xmit, 1765 .queue_xmit = inet6_csk_xmit,
1765 .send_check = tcp_v6_send_check, 1766 .send_check = tcp_v6_send_check,
1766 .rebuild_header = inet6_sk_rebuild_header, 1767 .rebuild_header = inet6_sk_rebuild_header,
@@ -1780,7 +1781,7 @@ static struct inet_connection_sock_af_ops ipv6_specific = {
1780}; 1781};
1781 1782
1782#ifdef CONFIG_TCP_MD5SIG 1783#ifdef CONFIG_TCP_MD5SIG
1783static struct tcp_sock_af_ops tcp_sock_ipv6_specific = { 1784static const struct tcp_sock_af_ops tcp_sock_ipv6_specific = {
1784 .md5_lookup = tcp_v6_md5_lookup, 1785 .md5_lookup = tcp_v6_md5_lookup,
1785 .calc_md5_hash = tcp_v6_md5_hash_skb, 1786 .calc_md5_hash = tcp_v6_md5_hash_skb,
1786 .md5_add = tcp_v6_md5_add_func, 1787 .md5_add = tcp_v6_md5_add_func,
@@ -1792,7 +1793,7 @@ static struct tcp_sock_af_ops tcp_sock_ipv6_specific = {
1792 * TCP over IPv4 via INET6 API 1793 * TCP over IPv4 via INET6 API
1793 */ 1794 */
1794 1795
1795static struct inet_connection_sock_af_ops ipv6_mapped = { 1796static const struct inet_connection_sock_af_ops ipv6_mapped = {
1796 .queue_xmit = ip_queue_xmit, 1797 .queue_xmit = ip_queue_xmit,
1797 .send_check = tcp_v4_send_check, 1798 .send_check = tcp_v4_send_check,
1798 .rebuild_header = inet_sk_rebuild_header, 1799 .rebuild_header = inet_sk_rebuild_header,
@@ -1812,7 +1813,7 @@ static struct inet_connection_sock_af_ops ipv6_mapped = {
1812}; 1813};
1813 1814
1814#ifdef CONFIG_TCP_MD5SIG 1815#ifdef CONFIG_TCP_MD5SIG
1815static struct tcp_sock_af_ops tcp_sock_ipv6_mapped_specific = { 1816static const struct tcp_sock_af_ops tcp_sock_ipv6_mapped_specific = {
1816 .md5_lookup = tcp_v4_md5_lookup, 1817 .md5_lookup = tcp_v4_md5_lookup,
1817 .calc_md5_hash = tcp_v4_md5_hash_skb, 1818 .calc_md5_hash = tcp_v4_md5_hash_skb,
1818 .md5_add = tcp_v6_md5_add_func, 1819 .md5_add = tcp_v6_md5_add_func,
diff --git a/net/ipv6/udp.c b/net/ipv6/udp.c
index 33b59bd92c4d..164040613c2e 100644
--- a/net/ipv6/udp.c
+++ b/net/ipv6/udp.c
@@ -638,6 +638,47 @@ static void udp_v6_flush_pending_frames(struct sock *sk)
638 } 638 }
639} 639}
640 640
641/**
642 * udp6_hwcsum_outgoing - handle outgoing HW checksumming
643 * @sk: socket we are sending on
644 * @skb: sk_buff containing the filled-in UDP header
645 * (checksum field must be zeroed out)
646 */
647static void udp6_hwcsum_outgoing(struct sock *sk, struct sk_buff *skb,
648 const struct in6_addr *saddr,
649 const struct in6_addr *daddr, int len)
650{
651 unsigned int offset;
652 struct udphdr *uh = udp_hdr(skb);
653 __wsum csum = 0;
654
655 if (skb_queue_len(&sk->sk_write_queue) == 1) {
656 /* Only one fragment on the socket. */
657 skb->csum_start = skb_transport_header(skb) - skb->head;
658 skb->csum_offset = offsetof(struct udphdr, check);
659 uh->check = ~csum_ipv6_magic(saddr, daddr, len, IPPROTO_UDP, 0);
660 } else {
661 /*
662 * HW-checksum won't work as there are two or more
663 * fragments on the socket so that all csums of sk_buffs
664 * should be together
665 */
666 offset = skb_transport_offset(skb);
667 skb->csum = skb_checksum(skb, offset, skb->len - offset, 0);
668
669 skb->ip_summed = CHECKSUM_NONE;
670
671 skb_queue_walk(&sk->sk_write_queue, skb) {
672 csum = csum_add(csum, skb->csum);
673 }
674
675 uh->check = csum_ipv6_magic(saddr, daddr, len, IPPROTO_UDP,
676 csum);
677 if (uh->check == 0)
678 uh->check = CSUM_MANGLED_0;
679 }
680}
681
641/* 682/*
642 * Sending 683 * Sending
643 */ 684 */
@@ -668,7 +709,11 @@ static int udp_v6_push_pending_frames(struct sock *sk)
668 709
669 if (is_udplite) 710 if (is_udplite)
670 csum = udplite_csum_outgoing(sk, skb); 711 csum = udplite_csum_outgoing(sk, skb);
671 else 712 else if (skb->ip_summed == CHECKSUM_PARTIAL) { /* UDP hardware csum */
713 udp6_hwcsum_outgoing(sk, skb, &fl->fl6_src, &fl->fl6_dst,
714 up->len);
715 goto send;
716 } else
672 csum = udp_csum_outgoing(sk, skb); 717 csum = udp_csum_outgoing(sk, skb);
673 718
674 /* add protocol-dependent pseudo-header */ 719 /* add protocol-dependent pseudo-header */
@@ -677,13 +722,20 @@ static int udp_v6_push_pending_frames(struct sock *sk)
677 if (uh->check == 0) 722 if (uh->check == 0)
678 uh->check = CSUM_MANGLED_0; 723 uh->check = CSUM_MANGLED_0;
679 724
725send:
680 err = ip6_push_pending_frames(sk); 726 err = ip6_push_pending_frames(sk);
727 if (err) {
728 if (err == -ENOBUFS && !inet6_sk(sk)->recverr) {
729 UDP6_INC_STATS_USER(sock_net(sk),
730 UDP_MIB_SNDBUFERRORS, is_udplite);
731 err = 0;
732 }
733 } else
734 UDP6_INC_STATS_USER(sock_net(sk),
735 UDP_MIB_OUTDATAGRAMS, is_udplite);
681out: 736out:
682 up->len = 0; 737 up->len = 0;
683 up->pending = 0; 738 up->pending = 0;
684 if (!err)
685 UDP6_INC_STATS_USER(sock_net(sk),
686 UDP_MIB_OUTDATAGRAMS, is_udplite);
687 return err; 739 return err;
688} 740}
689 741
@@ -900,11 +952,8 @@ do_udp_sendmsg:
900 hlimit = ip6_dst_hoplimit(dst); 952 hlimit = ip6_dst_hoplimit(dst);
901 } 953 }
902 954
903 if (tclass < 0) { 955 if (tclass < 0)
904 tclass = np->tclass; 956 tclass = np->tclass;
905 if (tclass < 0)
906 tclass = 0;
907 }
908 957
909 if (msg->msg_flags&MSG_CONFIRM) 958 if (msg->msg_flags&MSG_CONFIRM)
910 goto do_confirm; 959 goto do_confirm;
@@ -1032,9 +1081,102 @@ int compat_udpv6_getsockopt(struct sock *sk, int level, int optname,
1032} 1081}
1033#endif 1082#endif
1034 1083
1084static int udp6_ufo_send_check(struct sk_buff *skb)
1085{
1086 struct ipv6hdr *ipv6h;
1087 struct udphdr *uh;
1088
1089 if (!pskb_may_pull(skb, sizeof(*uh)))
1090 return -EINVAL;
1091
1092 ipv6h = ipv6_hdr(skb);
1093 uh = udp_hdr(skb);
1094
1095 uh->check = ~csum_ipv6_magic(&ipv6h->saddr, &ipv6h->daddr, skb->len,
1096 IPPROTO_UDP, 0);
1097 skb->csum_start = skb_transport_header(skb) - skb->head;
1098 skb->csum_offset = offsetof(struct udphdr, check);
1099 skb->ip_summed = CHECKSUM_PARTIAL;
1100 return 0;
1101}
1102
1103static struct sk_buff *udp6_ufo_fragment(struct sk_buff *skb, int features)
1104{
1105 struct sk_buff *segs = ERR_PTR(-EINVAL);
1106 unsigned int mss;
1107 unsigned int unfrag_ip6hlen, unfrag_len;
1108 struct frag_hdr *fptr;
1109 u8 *mac_start, *prevhdr;
1110 u8 nexthdr;
1111 u8 frag_hdr_sz = sizeof(struct frag_hdr);
1112 int offset;
1113 __wsum csum;
1114
1115 mss = skb_shinfo(skb)->gso_size;
1116 if (unlikely(skb->len <= mss))
1117 goto out;
1118
1119 if (skb_gso_ok(skb, features | NETIF_F_GSO_ROBUST)) {
1120 /* Packet is from an untrusted source, reset gso_segs. */
1121 int type = skb_shinfo(skb)->gso_type;
1122
1123 if (unlikely(type & ~(SKB_GSO_UDP | SKB_GSO_DODGY) ||
1124 !(type & (SKB_GSO_UDP))))
1125 goto out;
1126
1127 skb_shinfo(skb)->gso_segs = DIV_ROUND_UP(skb->len, mss);
1128
1129 segs = NULL;
1130 goto out;
1131 }
1132
1133 /* Do software UFO. Complete and fill in the UDP checksum as HW cannot
1134 * do checksum of UDP packets sent as multiple IP fragments.
1135 */
1136 offset = skb->csum_start - skb_headroom(skb);
1137 csum = skb_checksum(skb, offset, skb->len- offset, 0);
1138 offset += skb->csum_offset;
1139 *(__sum16 *)(skb->data + offset) = csum_fold(csum);
1140 skb->ip_summed = CHECKSUM_NONE;
1141
1142 /* Check if there is enough headroom to insert fragment header. */
1143 if ((skb_headroom(skb) < frag_hdr_sz) &&
1144 pskb_expand_head(skb, frag_hdr_sz, 0, GFP_ATOMIC))
1145 goto out;
1146
1147 /* Find the unfragmentable header and shift it left by frag_hdr_sz
1148 * bytes to insert fragment header.
1149 */
1150 unfrag_ip6hlen = ip6_find_1stfragopt(skb, &prevhdr);
1151 nexthdr = *prevhdr;
1152 *prevhdr = NEXTHDR_FRAGMENT;
1153 unfrag_len = skb_network_header(skb) - skb_mac_header(skb) +
1154 unfrag_ip6hlen;
1155 mac_start = skb_mac_header(skb);
1156 memmove(mac_start-frag_hdr_sz, mac_start, unfrag_len);
1157
1158 skb->mac_header -= frag_hdr_sz;
1159 skb->network_header -= frag_hdr_sz;
1160
1161 fptr = (struct frag_hdr *)(skb_network_header(skb) + unfrag_ip6hlen);
1162 fptr->nexthdr = nexthdr;
1163 fptr->reserved = 0;
1164 ipv6_select_ident(fptr);
1165
1166 /* Fragment the skb. ipv6 header and the remaining fields of the
1167 * fragment header are updated in ipv6_gso_segment()
1168 */
1169 segs = skb_segment(skb, features);
1170
1171out:
1172 return segs;
1173}
1174
1035static struct inet6_protocol udpv6_protocol = { 1175static struct inet6_protocol udpv6_protocol = {
1036 .handler = udpv6_rcv, 1176 .handler = udpv6_rcv,
1037 .err_handler = udpv6_err, 1177 .err_handler = udpv6_err,
1178 .gso_send_check = udp6_ufo_send_check,
1179 .gso_segment = udp6_ufo_fragment,
1038 .flags = INET6_PROTO_NOPOLICY|INET6_PROTO_FINAL, 1180 .flags = INET6_PROTO_NOPOLICY|INET6_PROTO_FINAL,
1039}; 1181};
1040 1182
diff --git a/net/ipv6/xfrm6_policy.c b/net/ipv6/xfrm6_policy.c
index 3a3c677bc0f2..8ec3d45cd1d9 100644
--- a/net/ipv6/xfrm6_policy.c
+++ b/net/ipv6/xfrm6_policy.c
@@ -306,9 +306,26 @@ static void xfrm6_policy_fini(void)
306 xfrm_policy_unregister_afinfo(&xfrm6_policy_afinfo); 306 xfrm_policy_unregister_afinfo(&xfrm6_policy_afinfo);
307} 307}
308 308
309#ifdef CONFIG_SYSCTL
310static struct ctl_table xfrm6_policy_table[] = {
311 {
312 .ctl_name = CTL_UNNUMBERED,
313 .procname = "xfrm6_gc_thresh",
314 .data = &xfrm6_dst_ops.gc_thresh,
315 .maxlen = sizeof(int),
316 .mode = 0644,
317 .proc_handler = proc_dointvec,
318 },
319 { }
320};
321
322static struct ctl_table_header *sysctl_hdr;
323#endif
324
309int __init xfrm6_init(void) 325int __init xfrm6_init(void)
310{ 326{
311 int ret; 327 int ret;
328 unsigned int gc_thresh;
312 329
313 ret = xfrm6_policy_init(); 330 ret = xfrm6_policy_init();
314 if (ret) 331 if (ret)
@@ -317,6 +334,23 @@ int __init xfrm6_init(void)
317 ret = xfrm6_state_init(); 334 ret = xfrm6_state_init();
318 if (ret) 335 if (ret)
319 goto out_policy; 336 goto out_policy;
337 /*
338 * We need a good default value for the xfrm6 gc threshold.
339 * In ipv4 we set it to the route hash table size * 8, which
340 * is half the size of the maximaum route cache for ipv4. It
341 * would be good to do the same thing for v6, except the table is
342 * constructed differently here. Here each table for a net namespace
343 * can have FIB_TABLE_HASHSZ entries, so lets go with the same
344 * computation that we used for ipv4 here. Also, lets keep the initial
345 * gc_thresh to a minimum of 1024, since, the ipv6 route cache defaults
346 * to that as a minimum as well
347 */
348 gc_thresh = FIB6_TABLE_HASHSZ * 8;
349 xfrm6_dst_ops.gc_thresh = (gc_thresh < 1024) ? 1024 : gc_thresh;
350#ifdef CONFIG_SYSCTL
351 sysctl_hdr = register_net_sysctl_table(&init_net, net_ipv6_ctl_path,
352 xfrm6_policy_table);
353#endif
320out: 354out:
321 return ret; 355 return ret;
322out_policy: 356out_policy:
@@ -326,6 +360,10 @@ out_policy:
326 360
327void xfrm6_fini(void) 361void xfrm6_fini(void)
328{ 362{
363#ifdef CONFIG_SYSCTL
364 if (sysctl_hdr)
365 unregister_net_sysctl_table(sysctl_hdr);
366#endif
329 //xfrm6_input_fini(); 367 //xfrm6_input_fini();
330 xfrm6_policy_fini(); 368 xfrm6_policy_fini();
331 xfrm6_state_fini(); 369 xfrm6_state_fini();