Patchwork [v5,1/3] NETFILTER added flags to __ipv6_find_hdr()

login
register
mail settings
Submitter Hans Schillstrom
Date Jan. 2, 2012, 3:06 p.m.
Message ID <1325516801-25488-2-git-send-email-hans.schillstrom@ericsson.com>
Download mbox | patch
Permalink /patch/133855/
State Not Applicable
Delegated to: David Miller
Headers show

Comments

Hans Schillstrom - Jan. 2, 2012, 3:06 p.m.
Two new flags to __ipv6_find_hdr,
One that tells us that this is a fragemnt.
One that stops at AH if any i.e. treat it like a transport header.
i.e. make handling of ESP and AH the same.

Signed-off-by: Hans Schillstrom <hans.schillstrom@ericsson.com>
---
 include/linux/netfilter_ipv6/ip6_tables.h |   16 ++++++++++++++--
 net/ipv6/netfilter/ip6_tables.c           |   19 ++++++++++++++-----
 2 files changed, 28 insertions(+), 7 deletions(-)
Pablo Neira - Jan. 4, 2012, 5:37 p.m.
On Mon, Jan 02, 2012 at 04:06:39PM +0100, Hans Schillstrom wrote:
> Two new flags to __ipv6_find_hdr,
> One that tells us that this is a fragemnt.
> One that stops at AH if any i.e. treat it like a transport header.
> i.e. make handling of ESP and AH the same.
> 
> Signed-off-by: Hans Schillstrom <hans.schillstrom@ericsson.com>
> ---
>  include/linux/netfilter_ipv6/ip6_tables.h |   16 ++++++++++++++--
>  net/ipv6/netfilter/ip6_tables.c           |   19 ++++++++++++++-----
>  2 files changed, 28 insertions(+), 7 deletions(-)
> 
> diff --git a/include/linux/netfilter_ipv6/ip6_tables.h b/include/linux/netfilter_ipv6/ip6_tables.h
> index f549adc..ee0c68e 100644
> --- a/include/linux/netfilter_ipv6/ip6_tables.h
> +++ b/include/linux/netfilter_ipv6/ip6_tables.h
> @@ -288,9 +288,21 @@ extern unsigned int ip6t_do_table(struct sk_buff *skb,
>  
>  /* Check for an extension */
>  extern int ip6t_ext_hdr(u8 nexthdr);
> +enum {
> +	IP6T_FH_FRAG,
> +	IP6T_FH_AUTH,
> +	IP6T_FH_F_FRAG = 1 << IP6T_FH_FRAG,
> +	IP6T_FH_F_AUTH = 1 << IP6T_FH_AUTH,
> +};
>  /* find specified header and get offset to it */
> -extern int ipv6_find_hdr(const struct sk_buff *skb, unsigned int *offset,
> -			 int target, unsigned short *fragoff);
> +extern int __ipv6_find_hdr(const struct sk_buff *skb, unsigned int *offset,
> +			 int target, unsigned short *fragoff, int *fragflg);

Please, don't do this.

the convention in the kernel is to use __function for non-locked
versions of one function.

The number of clients for this function seems small. I'll be very
happy if you send me a patch that changes this interface and that
propagates the changes to other clients of it.
--
To unsubscribe from this list: send the line "unsubscribe netdev" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Hans Schillstrom - Jan. 4, 2012, 8:48 p.m.
On Wednesday, January 04, 2012 18:37:41 Pablo Neira Ayuso wrote:
> On Mon, Jan 02, 2012 at 04:06:39PM +0100, Hans Schillstrom wrote:
> > Two new flags to __ipv6_find_hdr,
> > One that tells us that this is a fragemnt.
> > One that stops at AH if any i.e. treat it like a transport header.
> > i.e. make handling of ESP and AH the same.
> > 
> > Signed-off-by: Hans Schillstrom <hans.schillstrom@ericsson.com>
> > ---
> >  include/linux/netfilter_ipv6/ip6_tables.h |   16 ++++++++++++++--
> >  net/ipv6/netfilter/ip6_tables.c           |   19 ++++++++++++++-----
> >  2 files changed, 28 insertions(+), 7 deletions(-)
> > 
> > diff --git a/include/linux/netfilter_ipv6/ip6_tables.h b/include/linux/netfilter_ipv6/ip6_tables.h
> > index f549adc..ee0c68e 100644
> > --- a/include/linux/netfilter_ipv6/ip6_tables.h
> > +++ b/include/linux/netfilter_ipv6/ip6_tables.h
> > @@ -288,9 +288,21 @@ extern unsigned int ip6t_do_table(struct sk_buff *skb,
> >  
> >  /* Check for an extension */
> >  extern int ip6t_ext_hdr(u8 nexthdr);
> > +enum {
> > +	IP6T_FH_FRAG,
> > +	IP6T_FH_AUTH,
> > +	IP6T_FH_F_FRAG = 1 << IP6T_FH_FRAG,
> > +	IP6T_FH_F_AUTH = 1 << IP6T_FH_AUTH,
> > +};
> >  /* find specified header and get offset to it */
> > -extern int ipv6_find_hdr(const struct sk_buff *skb, unsigned int *offset,
> > -			 int target, unsigned short *fragoff);
> > +extern int __ipv6_find_hdr(const struct sk_buff *skb, unsigned int *offset,
> > +			 int target, unsigned short *fragoff, int *fragflg);
> 
> Please, don't do this.
> 
> the convention in the kernel is to use __function for non-locked
> versions of one function.
> 
> The number of clients for this function seems small. I'll be very
> happy if you send me a patch that changes this interface and that
> propagates the changes to other clients of it.
> 
No problem, I'll fix this.

I have some minor compilation warnings with out nat to fix also in the other patch.

Thanks
Hans
--
To unsubscribe from this list: send the line "unsubscribe netdev" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

Patch

diff --git a/include/linux/netfilter_ipv6/ip6_tables.h b/include/linux/netfilter_ipv6/ip6_tables.h
index f549adc..ee0c68e 100644
--- a/include/linux/netfilter_ipv6/ip6_tables.h
+++ b/include/linux/netfilter_ipv6/ip6_tables.h
@@ -288,9 +288,21 @@  extern unsigned int ip6t_do_table(struct sk_buff *skb,
 
 /* Check for an extension */
 extern int ip6t_ext_hdr(u8 nexthdr);
+enum {
+	IP6T_FH_FRAG,
+	IP6T_FH_AUTH,
+	IP6T_FH_F_FRAG = 1 << IP6T_FH_FRAG,
+	IP6T_FH_F_AUTH = 1 << IP6T_FH_AUTH,
+};
 /* find specified header and get offset to it */
-extern int ipv6_find_hdr(const struct sk_buff *skb, unsigned int *offset,
-			 int target, unsigned short *fragoff);
+extern int __ipv6_find_hdr(const struct sk_buff *skb, unsigned int *offset,
+			 int target, unsigned short *fragoff, int *fragflg);
+
+static inline int ipv6_find_hdr(const struct sk_buff *skb, unsigned int *offset,
+		  int target, unsigned short *fragoff)
+{
+	return __ipv6_find_hdr(skb, offset, target, fragoff, NULL);
+}
 
 #ifdef CONFIG_COMPAT
 #include <net/compat.h>
diff --git a/net/ipv6/netfilter/ip6_tables.c b/net/ipv6/netfilter/ip6_tables.c
index 94874b0..8729bff 100644
--- a/net/ipv6/netfilter/ip6_tables.c
+++ b/net/ipv6/netfilter/ip6_tables.c
@@ -2302,9 +2302,13 @@  static void __exit ip6_tables_fini(void)
  * *offset is meaningless and fragment offset is stored in *fragoff if fragoff
  * isn't NULL.
  *
+ * if flags != NULL AND
+ *    it's a fragment the frag flag "IP6T_FH_F_FRAG" will be set
+ *    it's an AH header and IP6T_FH_F_AUTH is set and target < 0
+ *      stop at AH (i.e. treat is as a transport header)
  */
-int ipv6_find_hdr(const struct sk_buff *skb, unsigned int *offset,
-		  int target, unsigned short *fragoff)
+int __ipv6_find_hdr(const struct sk_buff *skb, unsigned int *offset,
+		  int target, unsigned short *fragoff, int *flags)
 {
 	unsigned int start = skb_network_offset(skb) + sizeof(struct ipv6hdr);
 	u8 nexthdr = ipv6_hdr(skb)->nexthdr;
@@ -2329,6 +2333,9 @@  int ipv6_find_hdr(const struct sk_buff *skb, unsigned int *offset,
 		if (nexthdr == NEXTHDR_FRAGMENT) {
 			unsigned short _frag_off;
 			__be16 *fp;
+
+			if (flags)	/* Indicate that this is a fragment */
+				*flags |= IP6T_FH_F_FRAG;
 			fp = skb_header_pointer(skb,
 						start+offsetof(struct frag_hdr,
 							       frag_off),
@@ -2349,9 +2356,11 @@  int ipv6_find_hdr(const struct sk_buff *skb, unsigned int *offset,
 				return -ENOENT;
 			}
 			hdrlen = 8;
-		} else if (nexthdr == NEXTHDR_AUTH)
+		} else if (nexthdr == NEXTHDR_AUTH) {
+			if (flags && (*flags & IP6T_FH_F_AUTH) && (target < 0))
+				break;
 			hdrlen = (hp->hdrlen + 2) << 2;
-		else
+		} else
 			hdrlen = ipv6_optlen(hp);
 
 		nexthdr = hp->nexthdr;
@@ -2367,7 +2376,7 @@  EXPORT_SYMBOL(ip6t_register_table);
 EXPORT_SYMBOL(ip6t_unregister_table);
 EXPORT_SYMBOL(ip6t_do_table);
 EXPORT_SYMBOL(ip6t_ext_hdr);
-EXPORT_SYMBOL(ipv6_find_hdr);
+EXPORT_SYMBOL(__ipv6_find_hdr);
 
 module_init(ip6_tables_init);
 module_exit(ip6_tables_fini);