aboutsummaryrefslogtreecommitdiffstats
path: root/net/ipv6
diff options
context:
space:
mode:
Diffstat (limited to 'net/ipv6')
-rw-r--r--net/ipv6/datagram.c8
-rw-r--r--net/ipv6/ip6_output.c4
-rw-r--r--net/ipv6/ping.c3
-rw-r--r--net/ipv6/protocol.c4
-rw-r--r--net/ipv6/raw.c4
-rw-r--r--net/ipv6/sit.c50
-rw-r--r--net/ipv6/tcpv6_offload.c32
-rw-r--r--net/ipv6/udp.c4
8 files changed, 70 insertions, 39 deletions
diff --git a/net/ipv6/datagram.c b/net/ipv6/datagram.c
index a454b0ff57c7..8dfe1f4d3c1a 100644
--- a/net/ipv6/datagram.c
+++ b/net/ipv6/datagram.c
@@ -318,7 +318,7 @@ void ipv6_local_rxpmtu(struct sock *sk, struct flowi6 *fl6, u32 mtu)
318/* 318/*
319 * Handle MSG_ERRQUEUE 319 * Handle MSG_ERRQUEUE
320 */ 320 */
321int ipv6_recv_error(struct sock *sk, struct msghdr *msg, int len) 321int ipv6_recv_error(struct sock *sk, struct msghdr *msg, int len, int *addr_len)
322{ 322{
323 struct ipv6_pinfo *np = inet6_sk(sk); 323 struct ipv6_pinfo *np = inet6_sk(sk);
324 struct sock_exterr_skb *serr; 324 struct sock_exterr_skb *serr;
@@ -369,6 +369,7 @@ int ipv6_recv_error(struct sock *sk, struct msghdr *msg, int len)
369 &sin->sin6_addr); 369 &sin->sin6_addr);
370 sin->sin6_scope_id = 0; 370 sin->sin6_scope_id = 0;
371 } 371 }
372 *addr_len = sizeof(*sin);
372 } 373 }
373 374
374 memcpy(&errhdr.ee, &serr->ee, sizeof(struct sock_extended_err)); 375 memcpy(&errhdr.ee, &serr->ee, sizeof(struct sock_extended_err));
@@ -377,6 +378,7 @@ int ipv6_recv_error(struct sock *sk, struct msghdr *msg, int len)
377 if (serr->ee.ee_origin != SO_EE_ORIGIN_LOCAL) { 378 if (serr->ee.ee_origin != SO_EE_ORIGIN_LOCAL) {
378 sin->sin6_family = AF_INET6; 379 sin->sin6_family = AF_INET6;
379 sin->sin6_flowinfo = 0; 380 sin->sin6_flowinfo = 0;
381 sin->sin6_port = 0;
380 if (skb->protocol == htons(ETH_P_IPV6)) { 382 if (skb->protocol == htons(ETH_P_IPV6)) {
381 sin->sin6_addr = ipv6_hdr(skb)->saddr; 383 sin->sin6_addr = ipv6_hdr(skb)->saddr;
382 if (np->rxopt.all) 384 if (np->rxopt.all)
@@ -423,7 +425,8 @@ EXPORT_SYMBOL_GPL(ipv6_recv_error);
423/* 425/*
424 * Handle IPV6_RECVPATHMTU 426 * Handle IPV6_RECVPATHMTU
425 */ 427 */
426int ipv6_recv_rxpmtu(struct sock *sk, struct msghdr *msg, int len) 428int ipv6_recv_rxpmtu(struct sock *sk, struct msghdr *msg, int len,
429 int *addr_len)
427{ 430{
428 struct ipv6_pinfo *np = inet6_sk(sk); 431 struct ipv6_pinfo *np = inet6_sk(sk);
429 struct sk_buff *skb; 432 struct sk_buff *skb;
@@ -457,6 +460,7 @@ int ipv6_recv_rxpmtu(struct sock *sk, struct msghdr *msg, int len)
457 sin->sin6_port = 0; 460 sin->sin6_port = 0;
458 sin->sin6_scope_id = mtu_info.ip6m_addr.sin6_scope_id; 461 sin->sin6_scope_id = mtu_info.ip6m_addr.sin6_scope_id;
459 sin->sin6_addr = mtu_info.ip6m_addr.sin6_addr; 462 sin->sin6_addr = mtu_info.ip6m_addr.sin6_addr;
463 *addr_len = sizeof(*sin);
460 } 464 }
461 465
462 put_cmsg(msg, SOL_IPV6, IPV6_PATHMTU, sizeof(mtu_info), &mtu_info); 466 put_cmsg(msg, SOL_IPV6, IPV6_PATHMTU, sizeof(mtu_info), &mtu_info);
diff --git a/net/ipv6/ip6_output.c b/net/ipv6/ip6_output.c
index 59df872e2f4d..4acdb63495db 100644
--- a/net/ipv6/ip6_output.c
+++ b/net/ipv6/ip6_output.c
@@ -116,8 +116,8 @@ static int ip6_finish_output2(struct sk_buff *skb)
116 } 116 }
117 rcu_read_unlock_bh(); 117 rcu_read_unlock_bh();
118 118
119 IP6_INC_STATS_BH(dev_net(dst->dev), 119 IP6_INC_STATS(dev_net(dst->dev),
120 ip6_dst_idev(dst), IPSTATS_MIB_OUTNOROUTES); 120 ip6_dst_idev(dst), IPSTATS_MIB_OUTNOROUTES);
121 kfree_skb(skb); 121 kfree_skb(skb);
122 return -EINVAL; 122 return -EINVAL;
123} 123}
diff --git a/net/ipv6/ping.c b/net/ipv6/ping.c
index 8815e31a87fe..a83243c3d656 100644
--- a/net/ipv6/ping.c
+++ b/net/ipv6/ping.c
@@ -57,7 +57,8 @@ static struct inet_protosw pingv6_protosw = {
57 57
58 58
59/* Compatibility glue so we can support IPv6 when it's compiled as a module */ 59/* Compatibility glue so we can support IPv6 when it's compiled as a module */
60static int dummy_ipv6_recv_error(struct sock *sk, struct msghdr *msg, int len) 60static int dummy_ipv6_recv_error(struct sock *sk, struct msghdr *msg, int len,
61 int *addr_len)
61{ 62{
62 return -EAFNOSUPPORT; 63 return -EAFNOSUPPORT;
63} 64}
diff --git a/net/ipv6/protocol.c b/net/ipv6/protocol.c
index 22d1bd4670da..e048cf1bb6a2 100644
--- a/net/ipv6/protocol.c
+++ b/net/ipv6/protocol.c
@@ -36,10 +36,6 @@ int inet6_add_protocol(const struct inet6_protocol *prot, unsigned char protocol
36} 36}
37EXPORT_SYMBOL(inet6_add_protocol); 37EXPORT_SYMBOL(inet6_add_protocol);
38 38
39/*
40 * Remove a protocol from the hash tables.
41 */
42
43int inet6_del_protocol(const struct inet6_protocol *prot, unsigned char protocol) 39int inet6_del_protocol(const struct inet6_protocol *prot, unsigned char protocol)
44{ 40{
45 int ret; 41 int ret;
diff --git a/net/ipv6/raw.c b/net/ipv6/raw.c
index e24ff1df0401..7fb4e14c467f 100644
--- a/net/ipv6/raw.c
+++ b/net/ipv6/raw.c
@@ -466,10 +466,10 @@ static int rawv6_recvmsg(struct kiocb *iocb, struct sock *sk,
466 return -EOPNOTSUPP; 466 return -EOPNOTSUPP;
467 467
468 if (flags & MSG_ERRQUEUE) 468 if (flags & MSG_ERRQUEUE)
469 return ipv6_recv_error(sk, msg, len); 469 return ipv6_recv_error(sk, msg, len, addr_len);
470 470
471 if (np->rxpmtu && np->rxopt.bits.rxpmtu) 471 if (np->rxpmtu && np->rxopt.bits.rxpmtu)
472 return ipv6_recv_rxpmtu(sk, msg, len); 472 return ipv6_recv_rxpmtu(sk, msg, len, addr_len);
473 473
474 skb = skb_recv_datagram(sk, flags, noblock, &err); 474 skb = skb_recv_datagram(sk, flags, noblock, &err);
475 if (!skb) 475 if (!skb)
diff --git a/net/ipv6/sit.c b/net/ipv6/sit.c
index 1b4a4a953675..366fbba3359a 100644
--- a/net/ipv6/sit.c
+++ b/net/ipv6/sit.c
@@ -478,14 +478,44 @@ static void ipip6_tunnel_uninit(struct net_device *dev)
478 dev_put(dev); 478 dev_put(dev);
479} 479}
480 480
481/* Generate icmpv6 with type/code ICMPV6_DEST_UNREACH/ICMPV6_ADDR_UNREACH
482 * if sufficient data bytes are available
483 */
484static int ipip6_err_gen_icmpv6_unreach(struct sk_buff *skb)
485{
486 const struct iphdr *iph = (const struct iphdr *) skb->data;
487 struct rt6_info *rt;
488 struct sk_buff *skb2;
489
490 if (!pskb_may_pull(skb, iph->ihl * 4 + sizeof(struct ipv6hdr) + 8))
491 return 1;
492
493 skb2 = skb_clone(skb, GFP_ATOMIC);
494
495 if (!skb2)
496 return 1;
497
498 skb_dst_drop(skb2);
499 skb_pull(skb2, iph->ihl * 4);
500 skb_reset_network_header(skb2);
501
502 rt = rt6_lookup(dev_net(skb->dev), &ipv6_hdr(skb2)->saddr, NULL, 0, 0);
503
504 if (rt && rt->dst.dev)
505 skb2->dev = rt->dst.dev;
506
507 icmpv6_send(skb2, ICMPV6_DEST_UNREACH, ICMPV6_ADDR_UNREACH, 0);
508
509 if (rt)
510 ip6_rt_put(rt);
511
512 kfree_skb(skb2);
513
514 return 0;
515}
481 516
482static int ipip6_err(struct sk_buff *skb, u32 info) 517static int ipip6_err(struct sk_buff *skb, u32 info)
483{ 518{
484
485/* All the routers (except for Linux) return only
486 8 bytes of packet payload. It means, that precise relaying of
487 ICMP in the real Internet is absolutely infeasible.
488 */
489 const struct iphdr *iph = (const struct iphdr *)skb->data; 519 const struct iphdr *iph = (const struct iphdr *)skb->data;
490 const int type = icmp_hdr(skb)->type; 520 const int type = icmp_hdr(skb)->type;
491 const int code = icmp_hdr(skb)->code; 521 const int code = icmp_hdr(skb)->code;
@@ -500,7 +530,6 @@ static int ipip6_err(struct sk_buff *skb, u32 info)
500 case ICMP_DEST_UNREACH: 530 case ICMP_DEST_UNREACH:
501 switch (code) { 531 switch (code) {
502 case ICMP_SR_FAILED: 532 case ICMP_SR_FAILED:
503 case ICMP_PORT_UNREACH:
504 /* Impossible event. */ 533 /* Impossible event. */
505 return 0; 534 return 0;
506 default: 535 default:
@@ -545,6 +574,9 @@ static int ipip6_err(struct sk_buff *skb, u32 info)
545 goto out; 574 goto out;
546 575
547 err = 0; 576 err = 0;
577 if (!ipip6_err_gen_icmpv6_unreach(skb))
578 goto out;
579
548 if (t->parms.iph.ttl == 0 && type == ICMP_TIME_EXCEEDED) 580 if (t->parms.iph.ttl == 0 && type == ICMP_TIME_EXCEEDED)
549 goto out; 581 goto out;
550 582
@@ -919,7 +951,7 @@ static netdev_tx_t ipip6_tunnel_xmit(struct sk_buff *skb,
919 if (!new_skb) { 951 if (!new_skb) {
920 ip_rt_put(rt); 952 ip_rt_put(rt);
921 dev->stats.tx_dropped++; 953 dev->stats.tx_dropped++;
922 dev_kfree_skb(skb); 954 kfree_skb(skb);
923 return NETDEV_TX_OK; 955 return NETDEV_TX_OK;
924 } 956 }
925 if (skb->sk) 957 if (skb->sk)
@@ -945,7 +977,7 @@ static netdev_tx_t ipip6_tunnel_xmit(struct sk_buff *skb,
945tx_error_icmp: 977tx_error_icmp:
946 dst_link_failure(skb); 978 dst_link_failure(skb);
947tx_error: 979tx_error:
948 dev_kfree_skb(skb); 980 kfree_skb(skb);
949out: 981out:
950 dev->stats.tx_errors++; 982 dev->stats.tx_errors++;
951 return NETDEV_TX_OK; 983 return NETDEV_TX_OK;
@@ -985,7 +1017,7 @@ static netdev_tx_t sit_tunnel_xmit(struct sk_buff *skb,
985 1017
986tx_err: 1018tx_err:
987 dev->stats.tx_errors++; 1019 dev->stats.tx_errors++;
988 dev_kfree_skb(skb); 1020 kfree_skb(skb);
989 return NETDEV_TX_OK; 1021 return NETDEV_TX_OK;
990 1022
991} 1023}
diff --git a/net/ipv6/tcpv6_offload.c b/net/ipv6/tcpv6_offload.c
index c1097c798900..6d18157dc32c 100644
--- a/net/ipv6/tcpv6_offload.c
+++ b/net/ipv6/tcpv6_offload.c
@@ -37,34 +37,32 @@ static struct sk_buff **tcp6_gro_receive(struct sk_buff **head,
37{ 37{
38 const struct ipv6hdr *iph = skb_gro_network_header(skb); 38 const struct ipv6hdr *iph = skb_gro_network_header(skb);
39 __wsum wsum; 39 __wsum wsum;
40 __sum16 sum; 40
41 /* Don't bother verifying checksum if we're going to flush anyway. */
42 if (NAPI_GRO_CB(skb)->flush)
43 goto skip_csum;
44
45 wsum = skb->csum;
41 46
42 switch (skb->ip_summed) { 47 switch (skb->ip_summed) {
48 case CHECKSUM_NONE:
49 wsum = skb_checksum(skb, skb_gro_offset(skb), skb_gro_len(skb),
50 wsum);
51
52 /* fall through */
53
43 case CHECKSUM_COMPLETE: 54 case CHECKSUM_COMPLETE:
44 if (!tcp_v6_check(skb_gro_len(skb), &iph->saddr, &iph->daddr, 55 if (!tcp_v6_check(skb_gro_len(skb), &iph->saddr, &iph->daddr,
45 skb->csum)) { 56 wsum)) {
46 skb->ip_summed = CHECKSUM_UNNECESSARY; 57 skb->ip_summed = CHECKSUM_UNNECESSARY;
47 break; 58 break;
48 } 59 }
49flush: 60
50 NAPI_GRO_CB(skb)->flush = 1; 61 NAPI_GRO_CB(skb)->flush = 1;
51 return NULL; 62 return NULL;
52
53 case CHECKSUM_NONE:
54 wsum = ~csum_unfold(csum_ipv6_magic(&iph->saddr, &iph->daddr,
55 skb_gro_len(skb),
56 IPPROTO_TCP, 0));
57 sum = csum_fold(skb_checksum(skb,
58 skb_gro_offset(skb),
59 skb_gro_len(skb),
60 wsum));
61 if (sum)
62 goto flush;
63
64 skb->ip_summed = CHECKSUM_UNNECESSARY;
65 break;
66 } 63 }
67 64
65skip_csum:
68 return tcp_gro_receive(head, skb); 66 return tcp_gro_receive(head, skb);
69} 67}
70 68
diff --git a/net/ipv6/udp.c b/net/ipv6/udp.c
index 81eb8cf8389b..bcd5699313c3 100644
--- a/net/ipv6/udp.c
+++ b/net/ipv6/udp.c
@@ -393,10 +393,10 @@ int udpv6_recvmsg(struct kiocb *iocb, struct sock *sk,
393 bool slow; 393 bool slow;
394 394
395 if (flags & MSG_ERRQUEUE) 395 if (flags & MSG_ERRQUEUE)
396 return ipv6_recv_error(sk, msg, len); 396 return ipv6_recv_error(sk, msg, len, addr_len);
397 397
398 if (np->rxpmtu && np->rxopt.bits.rxpmtu) 398 if (np->rxpmtu && np->rxopt.bits.rxpmtu)
399 return ipv6_recv_rxpmtu(sk, msg, len); 399 return ipv6_recv_rxpmtu(sk, msg, len, addr_len);
400 400
401try_again: 401try_again:
402 skb = __skb_recv_datagram(sk, flags | (noblock ? MSG_DONTWAIT : 0), 402 skb = __skb_recv_datagram(sk, flags | (noblock ? MSG_DONTWAIT : 0),