Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

[NETFILTER]: nf_conntrack: make l3proto->prepare() generic and renames it

The icmp[v6] l4proto modules parse headers in ICMP[v6] error to get tuple.
But they have to find the offset to transport protocol header before that.
Their processings are almost same as prepare() of l3proto modules.
This makes prepare() more generic to simplify icmp[v6] l4proto module
later.

Signed-off-by: Yasuyuki Kozakai <yasuyuki.kozakai@toshiba.co.jp>
Signed-off-by: Patrick McHardy <kaber@trash.net>
Signed-off-by: David S. Miller <davem@davemloft.net>

authored by

Yasuyuki Kozakai and committed by
David S. Miller
ffc30690 d87d8469

+40 -30
+1 -1
include/net/netfilter/ipv6/nf_conntrack_ipv6.h
··· 7 7 extern struct nf_conntrack_l4proto nf_conntrack_l4proto_udp6; 8 8 extern struct nf_conntrack_l4proto nf_conntrack_l4proto_icmpv6; 9 9 10 - extern int nf_ct_ipv6_skip_exthdr(struct sk_buff *skb, int start, 10 + extern int nf_ct_ipv6_skip_exthdr(const struct sk_buff *skb, int start, 11 11 u8 *nexthdrp, int len); 12 12 13 13 extern int nf_ct_frag6_init(void);
+3 -3
include/net/netfilter/nf_conntrack_l3proto.h
··· 58 58 59 59 /* 60 60 * Called before tracking. 61 - * *dataoff: offset of protocol header (TCP, UDP,...) in *pskb 61 + * *dataoff: offset of protocol header (TCP, UDP,...) in skb 62 62 * *protonum: protocol number 63 63 */ 64 - int (*prepare)(struct sk_buff **pskb, unsigned int hooknum, 65 - unsigned int *dataoff, u_int8_t *protonum); 64 + int (*get_l4proto)(const struct sk_buff *skb, unsigned int nhoff, 65 + unsigned int *dataoff, u_int8_t *protonum); 66 66 67 67 int (*tuple_to_nfattr)(struct sk_buff *skb, 68 68 const struct nf_conntrack_tuple *t);
+14 -9
net/ipv4/netfilter/nf_conntrack_l3proto_ipv4.c
··· 78 78 return skb; 79 79 } 80 80 81 - static int 82 - ipv4_prepare(struct sk_buff **pskb, unsigned int hooknum, unsigned int *dataoff, 83 - u_int8_t *protonum) 81 + static int ipv4_get_l4proto(const struct sk_buff *skb, unsigned int nhoff, 82 + unsigned int *dataoff, u_int8_t *protonum) 84 83 { 84 + struct iphdr _iph, *iph; 85 + 86 + iph = skb_header_pointer(skb, nhoff, sizeof(_iph), &_iph); 87 + if (iph == NULL) 88 + return -NF_DROP; 89 + 85 90 /* Never happen */ 86 - if (ip_hdr(*pskb)->frag_off & htons(IP_OFFSET)) { 91 + if (iph->frag_off & htons(IP_OFFSET)) { 87 92 if (net_ratelimit()) { 88 - printk(KERN_ERR "ipv4_prepare: Frag of proto %u (hook=%u)\n", 89 - ip_hdr(*pskb)->protocol, hooknum); 93 + printk(KERN_ERR "ipv4_get_l4proto: Frag of proto %u\n", 94 + iph->protocol); 90 95 } 91 96 return -NF_DROP; 92 97 } 93 98 94 - *dataoff = skb_network_offset(*pskb) + ip_hdrlen(*pskb); 95 - *protonum = ip_hdr(*pskb)->protocol; 99 + *dataoff = nhoff + (iph->ihl << 2); 100 + *protonum = iph->protocol; 96 101 97 102 return NF_ACCEPT; 98 103 } ··· 412 407 .invert_tuple = ipv4_invert_tuple, 413 408 .print_tuple = ipv4_print_tuple, 414 409 .print_conntrack = ipv4_print_conntrack, 415 - .prepare = ipv4_prepare, 410 + .get_l4proto = ipv4_get_l4proto, 416 411 #if defined(CONFIG_NF_CT_NETLINK) || defined(CONFIG_NF_CT_NETLINK_MODULE) 417 412 .tuple_to_nfattr = ipv4_tuple_to_nfattr, 418 413 .nfattr_to_tuple = ipv4_nfattr_to_tuple,
+16 -11
net/ipv6/netfilter/nf_conntrack_l3proto_ipv6.c
··· 86 86 * - Note also special handling of AUTH header. Thanks to IPsec wizards. 87 87 */ 88 88 89 - int nf_ct_ipv6_skip_exthdr(struct sk_buff *skb, int start, u8 *nexthdrp, 89 + int nf_ct_ipv6_skip_exthdr(const struct sk_buff *skb, int start, u8 *nexthdrp, 90 90 int len) 91 91 { 92 92 u8 nexthdr = *nexthdrp; ··· 117 117 return start; 118 118 } 119 119 120 - static int 121 - ipv6_prepare(struct sk_buff **pskb, unsigned int hooknum, unsigned int *dataoff, 122 - u_int8_t *protonum) 120 + static int ipv6_get_l4proto(const struct sk_buff *skb, unsigned int nhoff, 121 + unsigned int *dataoff, u_int8_t *protonum) 123 122 { 124 - unsigned int extoff = (u8 *)(ipv6_hdr(*pskb) + 1) - (*pskb)->data; 125 - unsigned char pnum = ipv6_hdr(*pskb)->nexthdr; 126 - int protoff = nf_ct_ipv6_skip_exthdr(*pskb, extoff, &pnum, 127 - (*pskb)->len - extoff); 123 + unsigned int extoff = nhoff + sizeof(struct ipv6hdr); 124 + unsigned char pnum; 125 + int protoff; 126 + 127 + if (skb_copy_bits(skb, nhoff + offsetof(struct ipv6hdr, nexthdr), 128 + &pnum, sizeof(pnum)) != 0) { 129 + pr_debug("ip6_conntrack_core: can't get nexthdr\n"); 130 + return -NF_ACCEPT; 131 + } 132 + protoff = nf_ct_ipv6_skip_exthdr(skb, extoff, &pnum, skb->len - extoff); 128 133 /* 129 - * (protoff == (*pskb)->len) mean that the packet doesn't have no data 134 + * (protoff == skb->len) mean that the packet doesn't have no data 130 135 * except of IPv6 & ext headers. but it's tracked anyway. - YK 131 136 */ 132 - if ((protoff < 0) || (protoff > (*pskb)->len)) { 137 + if ((protoff < 0) || (protoff > skb->len)) { 133 138 pr_debug("ip6_conntrack_core: can't find proto in pkt\n"); 134 139 return -NF_ACCEPT; 135 140 } ··· 380 375 .invert_tuple = ipv6_invert_tuple, 381 376 .print_tuple = ipv6_print_tuple, 382 377 .print_conntrack = ipv6_print_conntrack, 383 - .prepare = ipv6_prepare, 378 + .get_l4proto = ipv6_get_l4proto, 384 379 #if defined(CONFIG_NF_CT_NETLINK) || defined(CONFIG_NF_CT_NETLINK_MODULE) 385 380 .tuple_to_nfattr = ipv6_tuple_to_nfattr, 386 381 .nfattr_to_tuple = ipv6_nfattr_to_tuple,
+3 -2
net/netfilter/nf_conntrack_core.c
··· 622 622 623 623 /* rcu_read_lock()ed by nf_hook_slow */ 624 624 l3proto = __nf_ct_l3proto_find((u_int16_t)pf); 625 - 626 - if ((ret = l3proto->prepare(pskb, hooknum, &dataoff, &protonum)) <= 0) { 625 + ret = l3proto->get_l4proto(*pskb, skb_network_offset(*pskb), 626 + &dataoff, &protonum); 627 + if (ret <= 0) { 627 628 pr_debug("not prepared to track yet or error occured\n"); 628 629 NF_CT_STAT_INC_ATOMIC(error); 629 630 NF_CT_STAT_INC_ATOMIC(invalid);
+3 -4
net/netfilter/nf_conntrack_l3proto_generic.c
··· 61 61 return 0; 62 62 } 63 63 64 - static int 65 - generic_prepare(struct sk_buff **pskb, unsigned int hooknum, 66 - unsigned int *dataoff, u_int8_t *protonum) 64 + static int generic_get_l4proto(const struct sk_buff *skb, unsigned int nhoff, 65 + unsigned int *dataoff, u_int8_t *protonum) 67 66 { 68 67 /* Never track !!! */ 69 68 return -NF_ACCEPT; ··· 76 77 .invert_tuple = generic_invert_tuple, 77 78 .print_tuple = generic_print_tuple, 78 79 .print_conntrack = generic_print_conntrack, 79 - .prepare = generic_prepare, 80 + .get_l4proto = generic_get_l4proto, 80 81 }; 81 82 EXPORT_SYMBOL_GPL(nf_conntrack_l3proto_generic);