Commit f8f626754ebeca613cf1af2e6f890cfde0e74d5b

Authored by Jesse Gross
1 parent c061853381

ipv6: Move ipv6_find_hdr() out of Netfilter code.

Open vSwitch will soon also use ipv6_find_hdr() so this moves it
out of Netfilter-specific code into a more common location.

Signed-off-by: Jesse Gross <jesse@nicira.com>

Showing 5 changed files with 116 additions and 116 deletions Side-by-side Diff

include/linux/netfilter_ipv6/ip6_tables.h
... ... @@ -47,15 +47,6 @@
47 47 (nexthdr == IPPROTO_DSTOPTS);
48 48 }
49 49  
50   -enum {
51   - IP6T_FH_F_FRAG = (1 << 0),
52   - IP6T_FH_F_AUTH = (1 << 1),
53   -};
54   -
55   -/* find specified header and get offset to it */
56   -extern int ipv6_find_hdr(const struct sk_buff *skb, unsigned int *offset,
57   - int target, unsigned short *fragoff, int *fragflg);
58   -
59 50 #ifdef CONFIG_COMPAT
60 51 #include <net/compat.h>
61 52  
... ... @@ -630,6 +630,15 @@
630 630  
631 631 extern bool ipv6_ext_hdr(u8 nexthdr);
632 632  
  633 +enum {
  634 + IP6_FH_F_FRAG = (1 << 0),
  635 + IP6_FH_F_AUTH = (1 << 1),
  636 +};
  637 +
  638 +/* find specified header and get offset to it */
  639 +extern int ipv6_find_hdr(const struct sk_buff *skb, unsigned int *offset,
  640 + int target, unsigned short *fragoff, int *fragflg);
  641 +
633 642 extern int ipv6_find_tlv(struct sk_buff *skb, int offset, int type);
634 643  
635 644 extern struct in6_addr *fl6_update_dst(struct flowi6 *fl6,
net/ipv6/exthdrs_core.c
... ... @@ -111,4 +111,107 @@
111 111 return start;
112 112 }
113 113 EXPORT_SYMBOL(ipv6_skip_exthdr);
  114 +
  115 +/*
  116 + * find the offset to specified header or the protocol number of last header
  117 + * if target < 0. "last header" is transport protocol header, ESP, or
  118 + * "No next header".
  119 + *
  120 + * Note that *offset is used as input/output parameter. an if it is not zero,
  121 + * then it must be a valid offset to an inner IPv6 header. This can be used
  122 + * to explore inner IPv6 header, eg. ICMPv6 error messages.
  123 + *
  124 + * If target header is found, its offset is set in *offset and return protocol
  125 + * number. Otherwise, return -1.
  126 + *
  127 + * If the first fragment doesn't contain the final protocol header or
  128 + * NEXTHDR_NONE it is considered invalid.
  129 + *
  130 + * Note that non-1st fragment is special case that "the protocol number
  131 + * of last header" is "next header" field in Fragment header. In this case,
  132 + * *offset is meaningless and fragment offset is stored in *fragoff if fragoff
  133 + * isn't NULL.
  134 + *
  135 + * if flags is not NULL and it's a fragment, then the frag flag IP6_FH_F_FRAG
  136 + * will be set. If it's an AH header, the IP6_FH_F_AUTH flag is set and
  137 + * target < 0, then this function will stop at the AH header.
  138 + */
  139 +int ipv6_find_hdr(const struct sk_buff *skb, unsigned int *offset,
  140 + int target, unsigned short *fragoff, int *flags)
  141 +{
  142 + unsigned int start = skb_network_offset(skb) + sizeof(struct ipv6hdr);
  143 + u8 nexthdr = ipv6_hdr(skb)->nexthdr;
  144 + unsigned int len;
  145 +
  146 + if (fragoff)
  147 + *fragoff = 0;
  148 +
  149 + if (*offset) {
  150 + struct ipv6hdr _ip6, *ip6;
  151 +
  152 + ip6 = skb_header_pointer(skb, *offset, sizeof(_ip6), &_ip6);
  153 + if (!ip6 || (ip6->version != 6)) {
  154 + printk(KERN_ERR "IPv6 header not found\n");
  155 + return -EBADMSG;
  156 + }
  157 + start = *offset + sizeof(struct ipv6hdr);
  158 + nexthdr = ip6->nexthdr;
  159 + }
  160 + len = skb->len - start;
  161 +
  162 + while (nexthdr != target) {
  163 + struct ipv6_opt_hdr _hdr, *hp;
  164 + unsigned int hdrlen;
  165 +
  166 + if ((!ipv6_ext_hdr(nexthdr)) || nexthdr == NEXTHDR_NONE) {
  167 + if (target < 0)
  168 + break;
  169 + return -ENOENT;
  170 + }
  171 +
  172 + hp = skb_header_pointer(skb, start, sizeof(_hdr), &_hdr);
  173 + if (hp == NULL)
  174 + return -EBADMSG;
  175 + if (nexthdr == NEXTHDR_FRAGMENT) {
  176 + unsigned short _frag_off;
  177 + __be16 *fp;
  178 +
  179 + if (flags) /* Indicate that this is a fragment */
  180 + *flags |= IP6_FH_F_FRAG;
  181 + fp = skb_header_pointer(skb,
  182 + start+offsetof(struct frag_hdr,
  183 + frag_off),
  184 + sizeof(_frag_off),
  185 + &_frag_off);
  186 + if (fp == NULL)
  187 + return -EBADMSG;
  188 +
  189 + _frag_off = ntohs(*fp) & ~0x7;
  190 + if (_frag_off) {
  191 + if (target < 0 &&
  192 + ((!ipv6_ext_hdr(hp->nexthdr)) ||
  193 + hp->nexthdr == NEXTHDR_NONE)) {
  194 + if (fragoff)
  195 + *fragoff = _frag_off;
  196 + return hp->nexthdr;
  197 + }
  198 + return -ENOENT;
  199 + }
  200 + hdrlen = 8;
  201 + } else if (nexthdr == NEXTHDR_AUTH) {
  202 + if (flags && (*flags & IP6_FH_F_AUTH) && (target < 0))
  203 + break;
  204 + hdrlen = (hp->hdrlen + 2) << 2;
  205 + } else
  206 + hdrlen = ipv6_optlen(hp);
  207 +
  208 + nexthdr = hp->nexthdr;
  209 + len -= hdrlen;
  210 + start += hdrlen;
  211 + }
  212 +
  213 + *offset = start;
  214 + return nexthdr;
  215 +}
  216 +EXPORT_SYMBOL(ipv6_find_hdr);
net/ipv6/netfilter/ip6_tables.c
... ... @@ -2273,112 +2273,9 @@
2273 2273 unregister_pernet_subsys(&ip6_tables_net_ops);
2274 2274 }
2275 2275  
2276   -/*
2277   - * find the offset to specified header or the protocol number of last header
2278   - * if target < 0. "last header" is transport protocol header, ESP, or
2279   - * "No next header".
2280   - *
2281   - * Note that *offset is used as input/output parameter. an if it is not zero,
2282   - * then it must be a valid offset to an inner IPv6 header. This can be used
2283   - * to explore inner IPv6 header, eg. ICMPv6 error messages.
2284   - *
2285   - * If target header is found, its offset is set in *offset and return protocol
2286   - * number. Otherwise, return -1.
2287   - *
2288   - * If the first fragment doesn't contain the final protocol header or
2289   - * NEXTHDR_NONE it is considered invalid.
2290   - *
2291   - * Note that non-1st fragment is special case that "the protocol number
2292   - * of last header" is "next header" field in Fragment header. In this case,
2293   - * *offset is meaningless and fragment offset is stored in *fragoff if fragoff
2294   - * isn't NULL.
2295   - *
2296   - * if flags is not NULL and it's a fragment, then the frag flag IP6T_FH_F_FRAG
2297   - * will be set. If it's an AH header, the IP6T_FH_F_AUTH flag is set and
2298   - * target < 0, then this function will stop at the AH header.
2299   - */
2300   -int ipv6_find_hdr(const struct sk_buff *skb, unsigned int *offset,
2301   - int target, unsigned short *fragoff, int *flags)
2302   -{
2303   - unsigned int start = skb_network_offset(skb) + sizeof(struct ipv6hdr);
2304   - u8 nexthdr = ipv6_hdr(skb)->nexthdr;
2305   - unsigned int len;
2306   -
2307   - if (fragoff)
2308   - *fragoff = 0;
2309   -
2310   - if (*offset) {
2311   - struct ipv6hdr _ip6, *ip6;
2312   -
2313   - ip6 = skb_header_pointer(skb, *offset, sizeof(_ip6), &_ip6);
2314   - if (!ip6 || (ip6->version != 6)) {
2315   - printk(KERN_ERR "IPv6 header not found\n");
2316   - return -EBADMSG;
2317   - }
2318   - start = *offset + sizeof(struct ipv6hdr);
2319   - nexthdr = ip6->nexthdr;
2320   - }
2321   - len = skb->len - start;
2322   -
2323   - while (nexthdr != target) {
2324   - struct ipv6_opt_hdr _hdr, *hp;
2325   - unsigned int hdrlen;
2326   -
2327   - if ((!ipv6_ext_hdr(nexthdr)) || nexthdr == NEXTHDR_NONE) {
2328   - if (target < 0)
2329   - break;
2330   - return -ENOENT;
2331   - }
2332   -
2333   - hp = skb_header_pointer(skb, start, sizeof(_hdr), &_hdr);
2334   - if (hp == NULL)
2335   - return -EBADMSG;
2336   - if (nexthdr == NEXTHDR_FRAGMENT) {
2337   - unsigned short _frag_off;
2338   - __be16 *fp;
2339   -
2340   - if (flags) /* Indicate that this is a fragment */
2341   - *flags |= IP6T_FH_F_FRAG;
2342   - fp = skb_header_pointer(skb,
2343   - start+offsetof(struct frag_hdr,
2344   - frag_off),
2345   - sizeof(_frag_off),
2346   - &_frag_off);
2347   - if (fp == NULL)
2348   - return -EBADMSG;
2349   -
2350   - _frag_off = ntohs(*fp) & ~0x7;
2351   - if (_frag_off) {
2352   - if (target < 0 &&
2353   - ((!ipv6_ext_hdr(hp->nexthdr)) ||
2354   - hp->nexthdr == NEXTHDR_NONE)) {
2355   - if (fragoff)
2356   - *fragoff = _frag_off;
2357   - return hp->nexthdr;
2358   - }
2359   - return -ENOENT;
2360   - }
2361   - hdrlen = 8;
2362   - } else if (nexthdr == NEXTHDR_AUTH) {
2363   - if (flags && (*flags & IP6T_FH_F_AUTH) && (target < 0))
2364   - break;
2365   - hdrlen = (hp->hdrlen + 2) << 2;
2366   - } else
2367   - hdrlen = ipv6_optlen(hp);
2368   -
2369   - nexthdr = hp->nexthdr;
2370   - len -= hdrlen;
2371   - start += hdrlen;
2372   - }
2373   -
2374   - *offset = start;
2375   - return nexthdr;
2376   -}
2377   -
2378 2276 EXPORT_SYMBOL(ip6t_register_table);
2379 2277 EXPORT_SYMBOL(ip6t_unregister_table);
2380 2278 EXPORT_SYMBOL(ip6t_do_table);
2381   -EXPORT_SYMBOL(ipv6_find_hdr);
2382 2279  
2383 2280 module_init(ip6_tables_init);
2384 2281 module_exit(ip6_tables_fini);
net/netfilter/xt_HMARK.c
... ... @@ -167,7 +167,7 @@
167 167 const struct xt_hmark_info *info)
168 168 {
169 169 struct ipv6hdr *ip6, _ip6;
170   - int flag = IP6T_FH_F_AUTH;
  170 + int flag = IP6_FH_F_AUTH;
171 171 unsigned int nhoff = 0;
172 172 u16 fragoff = 0;
173 173 int nexthdr;
... ... @@ -177,7 +177,7 @@
177 177 if (nexthdr < 0)
178 178 return 0;
179 179 /* No need to check for icmp errors on fragments */
180   - if ((flag & IP6T_FH_F_FRAG) || (nexthdr != IPPROTO_ICMPV6))
  180 + if ((flag & IP6_FH_F_FRAG) || (nexthdr != IPPROTO_ICMPV6))
181 181 goto noicmp;
182 182 /* Use inner header in case of ICMP errors */
183 183 if (get_inner6_hdr(skb, &nhoff)) {
... ... @@ -185,7 +185,7 @@
185 185 if (ip6 == NULL)
186 186 return -1;
187 187 /* If AH present, use SPI like in ESP. */
188   - flag = IP6T_FH_F_AUTH;
  188 + flag = IP6_FH_F_AUTH;
189 189 nexthdr = ipv6_find_hdr(skb, &nhoff, -1, &fragoff, &flag);
190 190 if (nexthdr < 0)
191 191 return -1;
... ... @@ -201,7 +201,7 @@
201 201 if (t->proto == IPPROTO_ICMPV6)
202 202 return 0;
203 203  
204   - if (flag & IP6T_FH_F_FRAG)
  204 + if (flag & IP6_FH_F_FRAG)
205 205 return 0;
206 206  
207 207 hmark_set_tuple_ports(skb, nhoff, t, info);