On Wed, Aug 22, 2018 at 03:10:17PM +0200, Ahmed Abdelsalam wrote: [...] > diff --git a/net/ipv6/netfilter/ip6t_SEG6.c b/net/ipv6/netfilter/ip6t_SEG6.c > new file mode 100644 > index 000000000000..0adfb98ccaf2 > --- /dev/null > +++ b/net/ipv6/netfilter/ip6t_SEG6.c > @@ -0,0 +1,120 @@ > +/** > + * IPv6 Segment Routing target module (SEG6). > + * > + * Author: > + * Ahmed Abdelsalam <amsalam20@xxxxxxxxx> > + * > + * This program is free software; you can redistribute it and/or > + * modify it under the terms of the GNU General Public License > + * as published by the Free Software Foundation; either version 2 > + * of the License, or (at your option) any later version. > + */ > + > +#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt > + > +#include <linux/gfp.h> > +#include <linux/module.h> > +#include <linux/skbuff.h> > +#include <linux/icmpv6.h> > +#include <linux/netdevice.h> > +#include <linux/netfilter/x_tables.h> > +#include <linux/netfilter_ipv6/ip6_tables.h> > +#include <linux/netfilter_ipv6/ip6t_SEG6.h> > + > +#include <net/flow.h> > +#include <net/seg6.h> > +#include <net/ip6_route.h> > + > +static int seg6_go_next(struct sk_buff *skb, struct ipv6_sr_hdr *srh) > +{ > + if (srh->segments_left == 0) > + return NF_DROP; > + seg6_advance_nextseg(srh, &ipv6_hdr(skb)->daddr); > + seg6_lookup_nexthop(skb, NULL, 0); > + dst_input(skb); > + return NF_STOLEN; > +} > + > +static int seg6_skip_next(struct sk_buff *skb, struct ipv6_sr_hdr *srh) > +{ > + if (srh->segments_left < 2) > + return NF_DROP; > + seg6_advance_nextseg(srh, &ipv6_hdr(skb)->daddr); > + seg6_advance_nextseg(srh, &ipv6_hdr(skb)->daddr); > + seg6_lookup_nexthop(skb, NULL, 0); > + dst_input(skb); > + return NF_STOLEN; > +} > + > +static int seg6_go_last(struct sk_buff *skb, struct ipv6_sr_hdr *srh) > +{ > + if (srh->segments_left == 0) > + return NF_DROP; > + srh->segments_left = 1; > + seg6_advance_nextseg(srh, &ipv6_hdr(skb)->daddr); > + seg6_lookup_nexthop(skb, NULL, 0); > + dst_input(skb); > + return NF_STOLEN; > +} > + > +static unsigned int > +seg6_tg6(struct sk_buff *skb, const struct xt_action_param *par) > +{ > + struct ipv6_sr_hdr *srh; > + const struct ip6t_seg6_info *seg6 = par->targinfo; > + > + srh = seg6_get_srh(skb); > + if (!srh) > + return NF_DROP; > + > + switch (seg6->action) { > + case IP6T_SEG6_GO_NEXT: > + return seg6_go_next(skb, srh); > + case IP6T_SEG6_SKIP_NEXT: > + return seg6_skip_next(skb, srh); > + case IP6T_SEG6_GO_LAST: > + return seg6_go_last(skb, srh); > + } > + > + return NF_DROP; > +} > + > +static int seg6_check(const struct xt_tgchk_param *par) > +{ > + const struct ip6t_seg6_info *seg6 = par->targinfo; > + > + switch (seg6->action) { > + case IP6T_SEG6_GO_NEXT: > + case IP6T_SEG6_SKIP_NEXT: > + case IP6T_SEG6_GO_LAST: > + return 0; > + default: > + return -EOPNOTSUPP; > + } > +} > + > +static struct xt_target seg6_tg6_reg __read_mostly = { > + .name = "SEG6", > + .family = NFPROTO_IPV6, > + .target = seg6_tg6, > + .targetsize = sizeof(struct ip6t_seg6_info), There is no .hook_mask here, can you really use this target from any netfilter hook? This is also mangling the IPv6 dst field, which breaks ongoing conntracking/NAT, so I suspect at least you need to restrict this to PREROUTING/raw table? Or this explicit needs a rule with -j NOTRACK? Probably this extension would fit better in the ingress hook? If you could post realistic example ruleset that would help understand how you plan to use this, or even configuration example where this extension is used. Interaction of this module with other existing netfilter extensions is broken, I'd appreciate an explanation. Thanks.