aboutsummaryrefslogtreecommitdiffstats
path: root/net/ipv6
diff options
context:
space:
mode:
authorVlad Yasevich <vyasevic@redhat.com>2012-11-15 03:49:20 -0500
committerDavid S. Miller <davem@davemloft.net>2012-11-15 17:39:23 -0500
commit3c73a0368e995f047c14388a05dcfba599053bef (patch)
tree1c5d8d505ec43c325ebc200ddd124f9c131e6558 /net/ipv6
parent2207afc8bfd80d596b524d4feb6b27f5ce359d59 (diff)
ipv6: Update ipv6 static library with newly needed functions
UDP offload needs some additional functions to be in the static kernel for it work correclty. Move those functions into the core. Signed-off-by: Vlad Yasevich <vyasevic@redhat.com> Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'net/ipv6')
-rw-r--r--net/ipv6/Makefile2
-rw-r--r--net/ipv6/exthdrs.c44
-rw-r--r--net/ipv6/exthdrs_core.c44
-rw-r--r--net/ipv6/ip6_output.c65
-rw-r--r--net/ipv6/output_core.c76
5 files changed, 121 insertions, 110 deletions
diff --git a/net/ipv6/Makefile b/net/ipv6/Makefile
index 7f250773ecc9..cdca302f395c 100644
--- a/net/ipv6/Makefile
+++ b/net/ipv6/Makefile
@@ -41,6 +41,6 @@ obj-$(CONFIG_IPV6_SIT) += sit.o
41obj-$(CONFIG_IPV6_TUNNEL) += ip6_tunnel.o 41obj-$(CONFIG_IPV6_TUNNEL) += ip6_tunnel.o
42obj-$(CONFIG_IPV6_GRE) += ip6_gre.o 42obj-$(CONFIG_IPV6_GRE) += ip6_gre.o
43 43
44obj-y += addrconf_core.o exthdrs_core.o 44obj-y += addrconf_core.o exthdrs_core.o output_core.o
45 45
46obj-$(subst m,y,$(CONFIG_IPV6)) += inet6_hashtables.o 46obj-$(subst m,y,$(CONFIG_IPV6)) += inet6_hashtables.o
diff --git a/net/ipv6/exthdrs.c b/net/ipv6/exthdrs.c
index 70fbf6bc5a87..a786a20ad823 100644
--- a/net/ipv6/exthdrs.c
+++ b/net/ipv6/exthdrs.c
@@ -50,50 +50,6 @@
50#include <asm/uaccess.h> 50#include <asm/uaccess.h>
51#include "ip6_offload.h" 51#include "ip6_offload.h"
52 52
53int ipv6_find_tlv(struct sk_buff *skb, int offset, int type)
54{
55 const unsigned char *nh = skb_network_header(skb);
56 int packet_len = skb->tail - skb->network_header;
57 struct ipv6_opt_hdr *hdr;
58 int len;
59
60 if (offset + 2 > packet_len)
61 goto bad;
62 hdr = (struct ipv6_opt_hdr *)(nh + offset);
63 len = ((hdr->hdrlen + 1) << 3);
64
65 if (offset + len > packet_len)
66 goto bad;
67
68 offset += 2;
69 len -= 2;
70
71 while (len > 0) {
72 int opttype = nh[offset];
73 int optlen;
74
75 if (opttype == type)
76 return offset;
77
78 switch (opttype) {
79 case IPV6_TLV_PAD1:
80 optlen = 1;
81 break;
82 default:
83 optlen = nh[offset + 1] + 2;
84 if (optlen > len)
85 goto bad;
86 break;
87 }
88 offset += optlen;
89 len -= optlen;
90 }
91 /* not_found */
92 bad:
93 return -1;
94}
95EXPORT_SYMBOL_GPL(ipv6_find_tlv);
96
97/* 53/*
98 * Parsing tlv encoded headers. 54 * Parsing tlv encoded headers.
99 * 55 *
diff --git a/net/ipv6/exthdrs_core.c b/net/ipv6/exthdrs_core.c
index f73d59a14131..e7d756e19d1d 100644
--- a/net/ipv6/exthdrs_core.c
+++ b/net/ipv6/exthdrs_core.c
@@ -111,3 +111,47 @@ int ipv6_skip_exthdr(const struct sk_buff *skb, int start, u8 *nexthdrp,
111 return start; 111 return start;
112} 112}
113EXPORT_SYMBOL(ipv6_skip_exthdr); 113EXPORT_SYMBOL(ipv6_skip_exthdr);
114
115int ipv6_find_tlv(struct sk_buff *skb, int offset, int type)
116{
117 const unsigned char *nh = skb_network_header(skb);
118 int packet_len = skb->tail - skb->network_header;
119 struct ipv6_opt_hdr *hdr;
120 int len;
121
122 if (offset + 2 > packet_len)
123 goto bad;
124 hdr = (struct ipv6_opt_hdr *)(nh + offset);
125 len = ((hdr->hdrlen + 1) << 3);
126
127 if (offset + len > packet_len)
128 goto bad;
129
130 offset += 2;
131 len -= 2;
132
133 while (len > 0) {
134 int opttype = nh[offset];
135 int optlen;
136
137 if (opttype == type)
138 return offset;
139
140 switch (opttype) {
141 case IPV6_TLV_PAD1:
142 optlen = 1;
143 break;
144 default:
145 optlen = nh[offset + 1] + 2;
146 if (optlen > len)
147 goto bad;
148 break;
149 }
150 offset += optlen;
151 len -= optlen;
152 }
153 /* not_found */
154 bad:
155 return -1;
156}
157EXPORT_SYMBOL_GPL(ipv6_find_tlv);
diff --git a/net/ipv6/ip6_output.c b/net/ipv6/ip6_output.c
index 3deaa4e2e8e2..5552d13ae92f 100644
--- a/net/ipv6/ip6_output.c
+++ b/net/ipv6/ip6_output.c
@@ -544,71 +544,6 @@ static void ip6_copy_metadata(struct sk_buff *to, struct sk_buff *from)
544 skb_copy_secmark(to, from); 544 skb_copy_secmark(to, from);
545} 545}
546 546
547int ip6_find_1stfragopt(struct sk_buff *skb, u8 **nexthdr)
548{
549 u16 offset = sizeof(struct ipv6hdr);
550 struct ipv6_opt_hdr *exthdr =
551 (struct ipv6_opt_hdr *)(ipv6_hdr(skb) + 1);
552 unsigned int packet_len = skb->tail - skb->network_header;
553 int found_rhdr = 0;
554 *nexthdr = &ipv6_hdr(skb)->nexthdr;
555
556 while (offset + 1 <= packet_len) {
557
558 switch (**nexthdr) {
559
560 case NEXTHDR_HOP:
561 break;
562 case NEXTHDR_ROUTING:
563 found_rhdr = 1;
564 break;
565 case NEXTHDR_DEST:
566#if IS_ENABLED(CONFIG_IPV6_MIP6)
567 if (ipv6_find_tlv(skb, offset, IPV6_TLV_HAO) >= 0)
568 break;
569#endif
570 if (found_rhdr)
571 return offset;
572 break;
573 default :
574 return offset;
575 }
576
577 offset += ipv6_optlen(exthdr);
578 *nexthdr = &exthdr->nexthdr;
579 exthdr = (struct ipv6_opt_hdr *)(skb_network_header(skb) +
580 offset);
581 }
582
583 return offset;
584}
585
586void ipv6_select_ident(struct frag_hdr *fhdr, struct rt6_info *rt)
587{
588 static atomic_t ipv6_fragmentation_id;
589 int old, new;
590
591 if (rt && !(rt->dst.flags & DST_NOPEER)) {
592 struct inet_peer *peer;
593 struct net *net;
594
595 net = dev_net(rt->dst.dev);
596 peer = inet_getpeer_v6(net->ipv6.peers, &rt->rt6i_dst.addr, 1);
597 if (peer) {
598 fhdr->identification = htonl(inet_getid(peer, 0));
599 inet_putpeer(peer);
600 return;
601 }
602 }
603 do {
604 old = atomic_read(&ipv6_fragmentation_id);
605 new = old + 1;
606 if (!new)
607 new = 1;
608 } while (atomic_cmpxchg(&ipv6_fragmentation_id, old, new) != old);
609 fhdr->identification = htonl(new);
610}
611
612int ip6_fragment(struct sk_buff *skb, int (*output)(struct sk_buff *)) 547int ip6_fragment(struct sk_buff *skb, int (*output)(struct sk_buff *))
613{ 548{
614 struct sk_buff *frag; 549 struct sk_buff *frag;
diff --git a/net/ipv6/output_core.c b/net/ipv6/output_core.c
new file mode 100644
index 000000000000..c2e73e647e44
--- /dev/null
+++ b/net/ipv6/output_core.c
@@ -0,0 +1,76 @@
1/*
2 * IPv6 library code, needed by static components when full IPv6 support is
3 * not configured or static. These functions are needed by GSO/GRO implementation.
4 */
5#include <linux/export.h>
6#include <net/ipv6.h>
7#include <net/ip6_fib.h>
8
9void ipv6_select_ident(struct frag_hdr *fhdr, struct rt6_info *rt)
10{
11 static atomic_t ipv6_fragmentation_id;
12 int old, new;
13
14#if IS_ENABLED(CONFIG_IPV6)
15 if (rt && !(rt->dst.flags & DST_NOPEER)) {
16 struct inet_peer *peer;
17 struct net *net;
18
19 net = dev_net(rt->dst.dev);
20 peer = inet_getpeer_v6(net->ipv6.peers, &rt->rt6i_dst.addr, 1);
21 if (peer) {
22 fhdr->identification = htonl(inet_getid(peer, 0));
23 inet_putpeer(peer);
24 return;
25 }
26 }
27#endif
28 do {
29 old = atomic_read(&ipv6_fragmentation_id);
30 new = old + 1;
31 if (!new)
32 new = 1;
33 } while (atomic_cmpxchg(&ipv6_fragmentation_id, old, new) != old);
34 fhdr->identification = htonl(new);
35}
36EXPORT_SYMBOL(ipv6_select_ident);
37
38int ip6_find_1stfragopt(struct sk_buff *skb, u8 **nexthdr)
39{
40 u16 offset = sizeof(struct ipv6hdr);
41 struct ipv6_opt_hdr *exthdr =
42 (struct ipv6_opt_hdr *)(ipv6_hdr(skb) + 1);
43 unsigned int packet_len = skb->tail - skb->network_header;
44 int found_rhdr = 0;
45 *nexthdr = &ipv6_hdr(skb)->nexthdr;
46
47 while (offset + 1 <= packet_len) {
48
49 switch (**nexthdr) {
50
51 case NEXTHDR_HOP:
52 break;
53 case NEXTHDR_ROUTING:
54 found_rhdr = 1;
55 break;
56 case NEXTHDR_DEST:
57#if IS_ENABLED(CONFIG_IPV6_MIP6)
58 if (ipv6_find_tlv(skb, offset, IPV6_TLV_HAO) >= 0)
59 break;
60#endif
61 if (found_rhdr)
62 return offset;
63 break;
64 default :
65 return offset;
66 }
67
68 offset += ipv6_optlen(exthdr);
69 *nexthdr = &exthdr->nexthdr;
70 exthdr = (struct ipv6_opt_hdr *)(skb_network_header(skb) +
71 offset);
72 }
73
74 return offset;
75}
76EXPORT_SYMBOL(ip6_find_1stfragopt);