aboutsummaryrefslogtreecommitdiffstats
path: root/net/ipv6
diff options
context:
space:
mode:
Diffstat (limited to 'net/ipv6')
-rw-r--r--net/ipv6/af_inet6.c20
-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.c42
-rw-r--r--net/ipv6/ip6_tunnel.c6
-rw-r--r--net/ipv6/ip6mr.c5
-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/proc.c4
-rw-r--r--net/ipv6/raw.c5
-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/udp.c146
-rw-r--r--net/ipv6/xfrm6_policy.c38
17 files changed, 268 insertions, 116 deletions
diff --git a/net/ipv6/af_inet6.c b/net/ipv6/af_inet6.c
index 45f9a2a42d56..a123a328aeb3 100644
--- a/net/ipv6/af_inet6.c
+++ b/net/ipv6/af_inet6.c
@@ -774,6 +774,11 @@ static struct sk_buff *ipv6_gso_segment(struct sk_buff *skb, int features)
774 struct sk_buff *segs = ERR_PTR(-EINVAL); 774 struct sk_buff *segs = ERR_PTR(-EINVAL);
775 struct ipv6hdr *ipv6h; 775 struct ipv6hdr *ipv6h;
776 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;
777 782
778 if (!(features & NETIF_F_V6_CSUM)) 783 if (!(features & NETIF_F_V6_CSUM))
779 features &= ~NETIF_F_SG; 784 features &= ~NETIF_F_SG;
@@ -793,10 +798,9 @@ static struct sk_buff *ipv6_gso_segment(struct sk_buff *skb, int features)
793 __skb_pull(skb, sizeof(*ipv6h)); 798 __skb_pull(skb, sizeof(*ipv6h));
794 segs = ERR_PTR(-EPROTONOSUPPORT); 799 segs = ERR_PTR(-EPROTONOSUPPORT);
795 800
801 proto = ipv6_gso_pull_exthdrs(skb, ipv6h->nexthdr);
796 rcu_read_lock(); 802 rcu_read_lock();
797 ops = rcu_dereference(inet6_protos[ 803 ops = rcu_dereference(inet6_protos[proto]);
798 ipv6_gso_pull_exthdrs(skb, ipv6h->nexthdr)]);
799
800 if (likely(ops && ops->gso_segment)) { 804 if (likely(ops && ops->gso_segment)) {
801 skb_reset_transport_header(skb); 805 skb_reset_transport_header(skb);
802 segs = ops->gso_segment(skb, features); 806 segs = ops->gso_segment(skb, features);
@@ -810,6 +814,16 @@ static struct sk_buff *ipv6_gso_segment(struct sk_buff *skb, int features)
810 ipv6h = ipv6_hdr(skb); 814 ipv6h = ipv6_hdr(skb);
811 ipv6h->payload_len = htons(skb->len - skb->mac_len - 815 ipv6h->payload_len = htons(skb->len - skb->mac_len -
812 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 }
813 } 827 }
814 828
815out: 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..a931229856b6 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
@@ -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..19c8dec2ead9 100644
--- a/net/ipv6/ip6mr.c
+++ b/net/ipv6/ip6mr.c
@@ -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/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/raw.c b/net/ipv6/raw.c
index d6c3c1c34b2d..506841030fbe 100644
--- a/net/ipv6/raw.c
+++ b/net/ipv6/raw.c
@@ -877,11 +877,8 @@ static int rawv6_sendmsg(struct kiocb *iocb, struct sock *sk,
877 hlimit = ip6_dst_hoplimit(dst); 877 hlimit = ip6_dst_hoplimit(dst);
878 } 878 }
879 879
880 if (tclass < 0) { 880 if (tclass < 0)
881 tclass = np->tclass; 881 tclass = np->tclass;
882 if (tclass < 0)
883 tclass = 0;
884 }
885 882
886 if (msg->msg_flags&MSG_CONFIRM) 883 if (msg->msg_flags&MSG_CONFIRM)
887 goto do_confirm; 884 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/udp.c b/net/ipv6/udp.c
index 33b59bd92c4d..20d2ffc15f0d 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,6 +722,7 @@ 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);
681out: 727out:
682 up->len = 0; 728 up->len = 0;
@@ -900,11 +946,8 @@ do_udp_sendmsg:
900 hlimit = ip6_dst_hoplimit(dst); 946 hlimit = ip6_dst_hoplimit(dst);
901 } 947 }
902 948
903 if (tclass < 0) { 949 if (tclass < 0)
904 tclass = np->tclass; 950 tclass = np->tclass;
905 if (tclass < 0)
906 tclass = 0;
907 }
908 951
909 if (msg->msg_flags&MSG_CONFIRM) 952 if (msg->msg_flags&MSG_CONFIRM)
910 goto do_confirm; 953 goto do_confirm;
@@ -1032,9 +1075,102 @@ int compat_udpv6_getsockopt(struct sock *sk, int level, int optname,
1032} 1075}
1033#endif 1076#endif
1034 1077
1078static int udp6_ufo_send_check(struct sk_buff *skb)
1079{
1080 struct ipv6hdr *ipv6h;
1081 struct udphdr *uh;
1082
1083 if (!pskb_may_pull(skb, sizeof(*uh)))
1084 return -EINVAL;
1085
1086 ipv6h = ipv6_hdr(skb);
1087 uh = udp_hdr(skb);
1088
1089 uh->check = ~csum_ipv6_magic(&ipv6h->saddr, &ipv6h->daddr, skb->len,
1090 IPPROTO_UDP, 0);
1091 skb->csum_start = skb_transport_header(skb) - skb->head;
1092 skb->csum_offset = offsetof(struct udphdr, check);
1093 skb->ip_summed = CHECKSUM_PARTIAL;
1094 return 0;
1095}
1096
1097static struct sk_buff *udp6_ufo_fragment(struct sk_buff *skb, int features)
1098{
1099 struct sk_buff *segs = ERR_PTR(-EINVAL);
1100 unsigned int mss;
1101 unsigned int unfrag_ip6hlen, unfrag_len;
1102 struct frag_hdr *fptr;
1103 u8 *mac_start, *prevhdr;
1104 u8 nexthdr;
1105 u8 frag_hdr_sz = sizeof(struct frag_hdr);
1106 int offset;
1107 __wsum csum;
1108
1109 mss = skb_shinfo(skb)->gso_size;
1110 if (unlikely(skb->len <= mss))
1111 goto out;
1112
1113 if (skb_gso_ok(skb, features | NETIF_F_GSO_ROBUST)) {
1114 /* Packet is from an untrusted source, reset gso_segs. */
1115 int type = skb_shinfo(skb)->gso_type;
1116
1117 if (unlikely(type & ~(SKB_GSO_UDP | SKB_GSO_DODGY) ||
1118 !(type & (SKB_GSO_UDP))))
1119 goto out;
1120
1121 skb_shinfo(skb)->gso_segs = DIV_ROUND_UP(skb->len, mss);
1122
1123 segs = NULL;
1124 goto out;
1125 }
1126
1127 /* Do software UFO. Complete and fill in the UDP checksum as HW cannot
1128 * do checksum of UDP packets sent as multiple IP fragments.
1129 */
1130 offset = skb->csum_start - skb_headroom(skb);
1131 csum = skb_checksum(skb, offset, skb->len- offset, 0);
1132 offset += skb->csum_offset;
1133 *(__sum16 *)(skb->data + offset) = csum_fold(csum);
1134 skb->ip_summed = CHECKSUM_NONE;
1135
1136 /* Check if there is enough headroom to insert fragment header. */
1137 if ((skb_headroom(skb) < frag_hdr_sz) &&
1138 pskb_expand_head(skb, frag_hdr_sz, 0, GFP_ATOMIC))
1139 goto out;
1140
1141 /* Find the unfragmentable header and shift it left by frag_hdr_sz
1142 * bytes to insert fragment header.
1143 */
1144 unfrag_ip6hlen = ip6_find_1stfragopt(skb, &prevhdr);
1145 nexthdr = *prevhdr;
1146 *prevhdr = NEXTHDR_FRAGMENT;
1147 unfrag_len = skb_network_header(skb) - skb_mac_header(skb) +
1148 unfrag_ip6hlen;
1149 mac_start = skb_mac_header(skb);
1150 memmove(mac_start-frag_hdr_sz, mac_start, unfrag_len);
1151
1152 skb->mac_header -= frag_hdr_sz;
1153 skb->network_header -= frag_hdr_sz;
1154
1155 fptr = (struct frag_hdr *)(skb_network_header(skb) + unfrag_ip6hlen);
1156 fptr->nexthdr = nexthdr;
1157 fptr->reserved = 0;
1158 ipv6_select_ident(fptr);
1159
1160 /* Fragment the skb. ipv6 header and the remaining fields of the
1161 * fragment header are updated in ipv6_gso_segment()
1162 */
1163 segs = skb_segment(skb, features);
1164
1165out:
1166 return segs;
1167}
1168
1035static struct inet6_protocol udpv6_protocol = { 1169static struct inet6_protocol udpv6_protocol = {
1036 .handler = udpv6_rcv, 1170 .handler = udpv6_rcv,
1037 .err_handler = udpv6_err, 1171 .err_handler = udpv6_err,
1172 .gso_send_check = udp6_ufo_send_check,
1173 .gso_segment = udp6_ufo_fragment,
1038 .flags = INET6_PROTO_NOPOLICY|INET6_PROTO_FINAL, 1174 .flags = INET6_PROTO_NOPOLICY|INET6_PROTO_FINAL,
1039}; 1175};
1040 1176
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();