[NETFILTER]: nf_conntrack: Introduces nf_ct_get_tuplepr and uses it
nf_ct_get_tuple() requires the offset to transport header and that bothers callers such as icmp[v6] l4proto modules. This introduces new function to simplify them. 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>
This commit is contained in:
Родитель
ffc3069048
Коммит
e2a3123fbe
|
@ -186,6 +186,10 @@ extern void nf_conntrack_hash_insert(struct nf_conn *ct);
|
||||||
|
|
||||||
extern void nf_conntrack_flush(void);
|
extern void nf_conntrack_flush(void);
|
||||||
|
|
||||||
|
extern int nf_ct_get_tuplepr(const struct sk_buff *skb,
|
||||||
|
unsigned int nhoff,
|
||||||
|
u_int16_t l3num,
|
||||||
|
struct nf_conntrack_tuple *tuple);
|
||||||
extern int nf_ct_invert_tuplepr(struct nf_conntrack_tuple *inverse,
|
extern int nf_ct_invert_tuplepr(struct nf_conntrack_tuple *inverse,
|
||||||
const struct nf_conntrack_tuple *orig);
|
const struct nf_conntrack_tuple *orig);
|
||||||
|
|
||||||
|
|
|
@ -136,40 +136,22 @@ icmp_error_message(struct sk_buff *skb,
|
||||||
unsigned int hooknum)
|
unsigned int hooknum)
|
||||||
{
|
{
|
||||||
struct nf_conntrack_tuple innertuple, origtuple;
|
struct nf_conntrack_tuple innertuple, origtuple;
|
||||||
struct {
|
|
||||||
struct icmphdr icmp;
|
|
||||||
struct iphdr ip;
|
|
||||||
} _in, *inside;
|
|
||||||
struct nf_conntrack_l4proto *innerproto;
|
struct nf_conntrack_l4proto *innerproto;
|
||||||
struct nf_conntrack_tuple_hash *h;
|
struct nf_conntrack_tuple_hash *h;
|
||||||
int dataoff;
|
|
||||||
|
|
||||||
NF_CT_ASSERT(skb->nfct == NULL);
|
NF_CT_ASSERT(skb->nfct == NULL);
|
||||||
|
|
||||||
/* Not enough header? */
|
/* Are they talking about one of our connections? */
|
||||||
inside = skb_header_pointer(skb, ip_hdrlen(skb), sizeof(_in), &_in);
|
if (!nf_ct_get_tuplepr(skb,
|
||||||
if (inside == NULL)
|
skb_network_offset(skb) + ip_hdrlen(skb)
|
||||||
return -NF_ACCEPT;
|
+ sizeof(struct icmphdr),
|
||||||
|
PF_INET, &origtuple)) {
|
||||||
/* Ignore ICMP's containing fragments (shouldn't happen) */
|
pr_debug("icmp_error_message: failed to get tuple\n");
|
||||||
if (inside->ip.frag_off & htons(IP_OFFSET)) {
|
|
||||||
pr_debug("icmp_error_message: fragment of proto %u\n",
|
|
||||||
inside->ip.protocol);
|
|
||||||
return -NF_ACCEPT;
|
return -NF_ACCEPT;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* rcu_read_lock()ed by nf_hook_slow */
|
/* rcu_read_lock()ed by nf_hook_slow */
|
||||||
innerproto = __nf_ct_l4proto_find(PF_INET, inside->ip.protocol);
|
innerproto = __nf_ct_l4proto_find(PF_INET, origtuple.dst.protonum);
|
||||||
|
|
||||||
dataoff = ip_hdrlen(skb) + sizeof(inside->icmp);
|
|
||||||
/* Are they talking about one of our connections? */
|
|
||||||
if (!nf_ct_get_tuple(skb, dataoff, dataoff + inside->ip.ihl*4, PF_INET,
|
|
||||||
inside->ip.protocol, &origtuple,
|
|
||||||
&nf_conntrack_l3proto_ipv4, innerproto)) {
|
|
||||||
pr_debug("icmp_error_message: ! get_tuple p=%u",
|
|
||||||
inside->ip.protocol);
|
|
||||||
return -NF_ACCEPT;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Ordinarily, we'd expect the inverted tupleproto, but it's
|
/* Ordinarily, we'd expect the inverted tupleproto, but it's
|
||||||
been preserved inside the ICMP. */
|
been preserved inside the ICMP. */
|
||||||
|
|
|
@ -136,48 +136,22 @@ icmpv6_error_message(struct sk_buff *skb,
|
||||||
{
|
{
|
||||||
struct nf_conntrack_tuple intuple, origtuple;
|
struct nf_conntrack_tuple intuple, origtuple;
|
||||||
struct nf_conntrack_tuple_hash *h;
|
struct nf_conntrack_tuple_hash *h;
|
||||||
struct icmp6hdr _hdr, *hp;
|
|
||||||
unsigned int inip6off;
|
|
||||||
struct nf_conntrack_l4proto *inproto;
|
struct nf_conntrack_l4proto *inproto;
|
||||||
u_int8_t inprotonum;
|
|
||||||
unsigned int inprotoff;
|
|
||||||
|
|
||||||
NF_CT_ASSERT(skb->nfct == NULL);
|
NF_CT_ASSERT(skb->nfct == NULL);
|
||||||
|
|
||||||
hp = skb_header_pointer(skb, icmp6off, sizeof(_hdr), &_hdr);
|
/* Are they talking about one of our connections? */
|
||||||
if (hp == NULL) {
|
if (!nf_ct_get_tuplepr(skb,
|
||||||
pr_debug("icmpv6_error: Can't get ICMPv6 hdr.\n");
|
skb_network_offset(skb)
|
||||||
return -NF_ACCEPT;
|
+ sizeof(struct ipv6hdr)
|
||||||
}
|
+ sizeof(struct icmp6hdr),
|
||||||
|
PF_INET6, &origtuple)) {
|
||||||
inip6off = icmp6off + sizeof(_hdr);
|
pr_debug("icmpv6_error: Can't get tuple\n");
|
||||||
if (skb_copy_bits(skb, inip6off+offsetof(struct ipv6hdr, nexthdr),
|
|
||||||
&inprotonum, sizeof(inprotonum)) != 0) {
|
|
||||||
pr_debug("icmpv6_error: Can't get nexthdr in inner IPv6 "
|
|
||||||
"header.\n");
|
|
||||||
return -NF_ACCEPT;
|
|
||||||
}
|
|
||||||
inprotoff = nf_ct_ipv6_skip_exthdr(skb,
|
|
||||||
inip6off + sizeof(struct ipv6hdr),
|
|
||||||
&inprotonum,
|
|
||||||
skb->len - inip6off
|
|
||||||
- sizeof(struct ipv6hdr));
|
|
||||||
|
|
||||||
if ((inprotoff > skb->len) || (inprotonum == NEXTHDR_FRAGMENT)) {
|
|
||||||
pr_debug("icmpv6_error: Can't get protocol header in ICMPv6 "
|
|
||||||
"payload.\n");
|
|
||||||
return -NF_ACCEPT;
|
return -NF_ACCEPT;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* rcu_read_lock()ed by nf_hook_slow */
|
/* rcu_read_lock()ed by nf_hook_slow */
|
||||||
inproto = __nf_ct_l4proto_find(PF_INET6, inprotonum);
|
inproto = __nf_ct_l4proto_find(PF_INET6, origtuple.dst.protonum);
|
||||||
|
|
||||||
/* Are they talking about one of our connections? */
|
|
||||||
if (!nf_ct_get_tuple(skb, inip6off, inprotoff, PF_INET6, inprotonum,
|
|
||||||
&origtuple, &nf_conntrack_l3proto_ipv6, inproto)) {
|
|
||||||
pr_debug("icmpv6_error: Can't get tuple\n");
|
|
||||||
return -NF_ACCEPT;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Ordinarily, we'd expect the inverted tupleproto, but it's
|
/* Ordinarily, we'd expect the inverted tupleproto, but it's
|
||||||
been preserved inside the ICMP. */
|
been preserved inside the ICMP. */
|
||||||
|
|
|
@ -113,6 +113,36 @@ nf_ct_get_tuple(const struct sk_buff *skb,
|
||||||
}
|
}
|
||||||
EXPORT_SYMBOL_GPL(nf_ct_get_tuple);
|
EXPORT_SYMBOL_GPL(nf_ct_get_tuple);
|
||||||
|
|
||||||
|
int nf_ct_get_tuplepr(const struct sk_buff *skb,
|
||||||
|
unsigned int nhoff,
|
||||||
|
u_int16_t l3num,
|
||||||
|
struct nf_conntrack_tuple *tuple)
|
||||||
|
{
|
||||||
|
struct nf_conntrack_l3proto *l3proto;
|
||||||
|
struct nf_conntrack_l4proto *l4proto;
|
||||||
|
unsigned int protoff;
|
||||||
|
u_int8_t protonum;
|
||||||
|
int ret;
|
||||||
|
|
||||||
|
rcu_read_lock();
|
||||||
|
|
||||||
|
l3proto = __nf_ct_l3proto_find(l3num);
|
||||||
|
ret = l3proto->get_l4proto(skb, nhoff, &protoff, &protonum);
|
||||||
|
if (ret != NF_ACCEPT) {
|
||||||
|
rcu_read_unlock();
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
l4proto = __nf_ct_l4proto_find(l3num, protonum);
|
||||||
|
|
||||||
|
ret = nf_ct_get_tuple(skb, nhoff, protoff, l3num, protonum, tuple,
|
||||||
|
l3proto, l4proto);
|
||||||
|
|
||||||
|
rcu_read_unlock();
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
EXPORT_SYMBOL_GPL(nf_ct_get_tuplepr);
|
||||||
|
|
||||||
int
|
int
|
||||||
nf_ct_invert_tuple(struct nf_conntrack_tuple *inverse,
|
nf_ct_invert_tuple(struct nf_conntrack_tuple *inverse,
|
||||||
const struct nf_conntrack_tuple *orig,
|
const struct nf_conntrack_tuple *orig,
|
||||||
|
|
Загрузка…
Ссылка в новой задаче