Commit b20ab9cc authored by Pablo Neira Ayuso's avatar Pablo Neira Ayuso

netfilter: nf_ct_helper: better logging for dropped packets

Connection tracking helpers have to drop packets under exceptional
situations. Currently, the user gets the following logging message
in case that happens:

	nf_ct_%s: dropping packet ...

However, depending on the helper, there are different reasons why a
packet can be dropped.

This patch modifies the existing code to provide more specific
error message in the scope of each helper to help users to debug
the reason why the packet has been dropped, ie:

	nf_ct_%s: dropping packet: reason ...

Thanks to Joe Perches for many formatting suggestions.
Signed-off-by: default avatarPablo Neira Ayuso <pablo@netfilter.org>
parent 38124328
...@@ -100,6 +100,10 @@ struct nf_ct_helper_expectfn { ...@@ -100,6 +100,10 @@ struct nf_ct_helper_expectfn {
void (*expectfn)(struct nf_conn *ct, struct nf_conntrack_expect *exp); void (*expectfn)(struct nf_conn *ct, struct nf_conntrack_expect *exp);
}; };
__printf(3,4)
void nf_ct_helper_log(struct sk_buff *skb, const struct nf_conn *ct,
const char *fmt, ...);
void nf_ct_helper_expectfn_register(struct nf_ct_helper_expectfn *n); void nf_ct_helper_expectfn_register(struct nf_ct_helper_expectfn *n);
void nf_ct_helper_expectfn_unregister(struct nf_ct_helper_expectfn *n); void nf_ct_helper_expectfn_unregister(struct nf_ct_helper_expectfn *n);
struct nf_ct_helper_expectfn * struct nf_ct_helper_expectfn *
......
...@@ -100,7 +100,6 @@ static unsigned int ipv4_helper(unsigned int hooknum, ...@@ -100,7 +100,6 @@ static unsigned int ipv4_helper(unsigned int hooknum,
enum ip_conntrack_info ctinfo; enum ip_conntrack_info ctinfo;
const struct nf_conn_help *help; const struct nf_conn_help *help;
const struct nf_conntrack_helper *helper; const struct nf_conntrack_helper *helper;
unsigned int ret;
/* This is where we call the helper: as the packet goes out. */ /* This is where we call the helper: as the packet goes out. */
ct = nf_ct_get(skb, &ctinfo); ct = nf_ct_get(skb, &ctinfo);
...@@ -116,13 +115,8 @@ static unsigned int ipv4_helper(unsigned int hooknum, ...@@ -116,13 +115,8 @@ static unsigned int ipv4_helper(unsigned int hooknum,
if (!helper) if (!helper)
return NF_ACCEPT; return NF_ACCEPT;
ret = helper->help(skb, skb_network_offset(skb) + ip_hdrlen(skb), return helper->help(skb, skb_network_offset(skb) + ip_hdrlen(skb),
ct, ctinfo); ct, ctinfo);
if (ret != NF_ACCEPT && (ret & NF_VERDICT_MASK) != NF_QUEUE) {
nf_log_packet(NFPROTO_IPV4, hooknum, skb, in, out, NULL,
"nf_ct_%s: dropping packet", helper->name);
}
return ret;
} }
static unsigned int ipv4_confirm(unsigned int hooknum, static unsigned int ipv4_confirm(unsigned int hooknum,
......
...@@ -104,7 +104,6 @@ static unsigned int ipv6_helper(unsigned int hooknum, ...@@ -104,7 +104,6 @@ static unsigned int ipv6_helper(unsigned int hooknum,
const struct nf_conn_help *help; const struct nf_conn_help *help;
const struct nf_conntrack_helper *helper; const struct nf_conntrack_helper *helper;
enum ip_conntrack_info ctinfo; enum ip_conntrack_info ctinfo;
unsigned int ret;
__be16 frag_off; __be16 frag_off;
int protoff; int protoff;
u8 nexthdr; u8 nexthdr;
...@@ -130,12 +129,7 @@ static unsigned int ipv6_helper(unsigned int hooknum, ...@@ -130,12 +129,7 @@ static unsigned int ipv6_helper(unsigned int hooknum,
return NF_ACCEPT; return NF_ACCEPT;
} }
ret = helper->help(skb, protoff, ct, ctinfo); return helper->help(skb, protoff, ct, ctinfo);
if (ret != NF_ACCEPT && (ret & NF_VERDICT_MASK) != NF_QUEUE) {
nf_log_packet(NFPROTO_IPV6, hooknum, skb, in, out, NULL,
"nf_ct_%s: dropping packet", helper->name);
}
return ret;
} }
static unsigned int ipv6_confirm(unsigned int hooknum, static unsigned int ipv6_confirm(unsigned int hooknum,
......
...@@ -145,6 +145,7 @@ static int amanda_help(struct sk_buff *skb, ...@@ -145,6 +145,7 @@ static int amanda_help(struct sk_buff *skb,
exp = nf_ct_expect_alloc(ct); exp = nf_ct_expect_alloc(ct);
if (exp == NULL) { if (exp == NULL) {
nf_ct_helper_log(skb, ct, "cannot alloc expectation");
ret = NF_DROP; ret = NF_DROP;
goto out; goto out;
} }
...@@ -158,8 +159,10 @@ static int amanda_help(struct sk_buff *skb, ...@@ -158,8 +159,10 @@ static int amanda_help(struct sk_buff *skb,
if (nf_nat_amanda && ct->status & IPS_NAT_MASK) if (nf_nat_amanda && ct->status & IPS_NAT_MASK)
ret = nf_nat_amanda(skb, ctinfo, protoff, ret = nf_nat_amanda(skb, ctinfo, protoff,
off - dataoff, len, exp); off - dataoff, len, exp);
else if (nf_ct_expect_related(exp) != 0) else if (nf_ct_expect_related(exp) != 0) {
nf_ct_helper_log(skb, ct, "cannot add expectation");
ret = NF_DROP; ret = NF_DROP;
}
nf_ct_expect_put(exp); nf_ct_expect_put(exp);
} }
......
...@@ -435,8 +435,8 @@ static int help(struct sk_buff *skb, ...@@ -435,8 +435,8 @@ static int help(struct sk_buff *skb,
connection tracking, not packet filtering. connection tracking, not packet filtering.
However, it is necessary for accurate tracking in However, it is necessary for accurate tracking in
this case. */ this case. */
pr_debug("conntrack_ftp: partial %s %u+%u\n", nf_ct_helper_log(skb, ct, "partial matching of `%s'",
search[dir][i].pattern, ntohl(th->seq), datalen); search[dir][i].pattern);
ret = NF_DROP; ret = NF_DROP;
goto out; goto out;
} else if (found == 0) { /* No match */ } else if (found == 0) { /* No match */
...@@ -450,6 +450,7 @@ static int help(struct sk_buff *skb, ...@@ -450,6 +450,7 @@ static int help(struct sk_buff *skb,
exp = nf_ct_expect_alloc(ct); exp = nf_ct_expect_alloc(ct);
if (exp == NULL) { if (exp == NULL) {
nf_ct_helper_log(skb, ct, "cannot alloc expectation");
ret = NF_DROP; ret = NF_DROP;
goto out; goto out;
} }
...@@ -500,9 +501,10 @@ static int help(struct sk_buff *skb, ...@@ -500,9 +501,10 @@ static int help(struct sk_buff *skb,
protoff, matchoff, matchlen, exp); protoff, matchoff, matchlen, exp);
else { else {
/* Can't expect this? Best to drop packet now. */ /* Can't expect this? Best to drop packet now. */
if (nf_ct_expect_related(exp) != 0) if (nf_ct_expect_related(exp) != 0) {
nf_ct_helper_log(skb, ct, "cannot add expectation");
ret = NF_DROP; ret = NF_DROP;
else } else
ret = NF_ACCEPT; ret = NF_ACCEPT;
} }
......
...@@ -623,7 +623,7 @@ static int h245_help(struct sk_buff *skb, unsigned int protoff, ...@@ -623,7 +623,7 @@ static int h245_help(struct sk_buff *skb, unsigned int protoff,
drop: drop:
spin_unlock_bh(&nf_h323_lock); spin_unlock_bh(&nf_h323_lock);
net_info_ratelimited("nf_ct_h245: packet dropped\n"); nf_ct_helper_log(skb, ct, "cannot process H.245 message");
return NF_DROP; return NF_DROP;
} }
...@@ -1197,7 +1197,7 @@ static int q931_help(struct sk_buff *skb, unsigned int protoff, ...@@ -1197,7 +1197,7 @@ static int q931_help(struct sk_buff *skb, unsigned int protoff,
drop: drop:
spin_unlock_bh(&nf_h323_lock); spin_unlock_bh(&nf_h323_lock);
net_info_ratelimited("nf_ct_q931: packet dropped\n"); nf_ct_helper_log(skb, ct, "cannot process Q.931 message");
return NF_DROP; return NF_DROP;
} }
...@@ -1795,7 +1795,7 @@ static int ras_help(struct sk_buff *skb, unsigned int protoff, ...@@ -1795,7 +1795,7 @@ static int ras_help(struct sk_buff *skb, unsigned int protoff,
drop: drop:
spin_unlock_bh(&nf_h323_lock); spin_unlock_bh(&nf_h323_lock);
net_info_ratelimited("nf_ct_ras: packet dropped\n"); nf_ct_helper_log(skb, ct, "cannot process RAS message");
return NF_DROP; return NF_DROP;
} }
......
...@@ -28,6 +28,7 @@ ...@@ -28,6 +28,7 @@
#include <net/netfilter/nf_conntrack_helper.h> #include <net/netfilter/nf_conntrack_helper.h>
#include <net/netfilter/nf_conntrack_core.h> #include <net/netfilter/nf_conntrack_core.h>
#include <net/netfilter/nf_conntrack_extend.h> #include <net/netfilter/nf_conntrack_extend.h>
#include <net/netfilter/nf_log.h>
static DEFINE_MUTEX(nf_ct_helper_mutex); static DEFINE_MUTEX(nf_ct_helper_mutex);
struct hlist_head *nf_ct_helper_hash __read_mostly; struct hlist_head *nf_ct_helper_hash __read_mostly;
...@@ -332,6 +333,24 @@ nf_ct_helper_expectfn_find_by_symbol(const void *symbol) ...@@ -332,6 +333,24 @@ nf_ct_helper_expectfn_find_by_symbol(const void *symbol)
} }
EXPORT_SYMBOL_GPL(nf_ct_helper_expectfn_find_by_symbol); EXPORT_SYMBOL_GPL(nf_ct_helper_expectfn_find_by_symbol);
__printf(3, 4)
void nf_ct_helper_log(struct sk_buff *skb, const struct nf_conn *ct,
const char *fmt, ...)
{
const struct nf_conn_help *help;
const struct nf_conntrack_helper *helper;
/* Called from the helper function, this call never fails */
help = nfct_help(ct);
/* rcu_read_lock()ed by nf_hook_slow */
helper = rcu_dereference(help->helper);
nf_log_packet(nf_ct_l3num(ct), 0, skb, NULL, NULL, NULL,
"nf_ct_%s: dropping packet: %s ", helper->name, fmt);
}
EXPORT_SYMBOL_GPL(nf_ct_helper_log);
int nf_conntrack_helper_register(struct nf_conntrack_helper *me) int nf_conntrack_helper_register(struct nf_conntrack_helper *me)
{ {
int ret = 0; int ret = 0;
......
...@@ -194,6 +194,8 @@ static int help(struct sk_buff *skb, unsigned int protoff, ...@@ -194,6 +194,8 @@ static int help(struct sk_buff *skb, unsigned int protoff,
exp = nf_ct_expect_alloc(ct); exp = nf_ct_expect_alloc(ct);
if (exp == NULL) { if (exp == NULL) {
nf_ct_helper_log(skb, ct,
"cannot alloc expectation");
ret = NF_DROP; ret = NF_DROP;
goto out; goto out;
} }
...@@ -210,8 +212,11 @@ static int help(struct sk_buff *skb, unsigned int protoff, ...@@ -210,8 +212,11 @@ static int help(struct sk_buff *skb, unsigned int protoff,
addr_beg_p - ib_ptr, addr_beg_p - ib_ptr,
addr_end_p - addr_beg_p, addr_end_p - addr_beg_p,
exp); exp);
else if (nf_ct_expect_related(exp) != 0) else if (nf_ct_expect_related(exp) != 0) {
nf_ct_helper_log(skb, ct,
"cannot add expectation");
ret = NF_DROP; ret = NF_DROP;
}
nf_ct_expect_put(exp); nf_ct_expect_put(exp);
goto out; goto out;
} }
......
...@@ -138,6 +138,7 @@ static int help(struct sk_buff *skb, ...@@ -138,6 +138,7 @@ static int help(struct sk_buff *skb,
exp = nf_ct_expect_alloc(ct); exp = nf_ct_expect_alloc(ct);
if (exp == NULL) { if (exp == NULL) {
nf_ct_helper_log(skb, ct, "cannot alloc expectation");
ret = NF_DROP; ret = NF_DROP;
goto out; goto out;
} }
...@@ -151,8 +152,10 @@ static int help(struct sk_buff *skb, ...@@ -151,8 +152,10 @@ static int help(struct sk_buff *skb,
nf_ct_dump_tuple(&exp->tuple); nf_ct_dump_tuple(&exp->tuple);
/* Can't expect this? Best to drop packet now. */ /* Can't expect this? Best to drop packet now. */
if (nf_ct_expect_related(exp) != 0) if (nf_ct_expect_related(exp) != 0) {
nf_ct_helper_log(skb, ct, "cannot add expectation");
ret = NF_DROP; ret = NF_DROP;
}
nf_ct_expect_put(exp); nf_ct_expect_put(exp);
......
...@@ -1095,8 +1095,10 @@ static int process_sdp(struct sk_buff *skb, unsigned int protoff, ...@@ -1095,8 +1095,10 @@ static int process_sdp(struct sk_buff *skb, unsigned int protoff,
port = simple_strtoul(*dptr + mediaoff, NULL, 10); port = simple_strtoul(*dptr + mediaoff, NULL, 10);
if (port == 0) if (port == 0)
continue; continue;
if (port < 1024 || port > 65535) if (port < 1024 || port > 65535) {
nf_ct_helper_log(skb, ct, "wrong port %u", port);
return NF_DROP; return NF_DROP;
}
/* The media description overrides the session description. */ /* The media description overrides the session description. */
maddr_len = 0; maddr_len = 0;
...@@ -1107,15 +1109,20 @@ static int process_sdp(struct sk_buff *skb, unsigned int protoff, ...@@ -1107,15 +1109,20 @@ static int process_sdp(struct sk_buff *skb, unsigned int protoff,
memcpy(&rtp_addr, &maddr, sizeof(rtp_addr)); memcpy(&rtp_addr, &maddr, sizeof(rtp_addr));
} else if (caddr_len) } else if (caddr_len)
memcpy(&rtp_addr, &caddr, sizeof(rtp_addr)); memcpy(&rtp_addr, &caddr, sizeof(rtp_addr));
else else {
nf_ct_helper_log(skb, ct, "cannot parse SDP message");
return NF_DROP; return NF_DROP;
}
ret = set_expected_rtp_rtcp(skb, protoff, dataoff, ret = set_expected_rtp_rtcp(skb, protoff, dataoff,
dptr, datalen, dptr, datalen,
&rtp_addr, htons(port), t->class, &rtp_addr, htons(port), t->class,
mediaoff, medialen); mediaoff, medialen);
if (ret != NF_ACCEPT) if (ret != NF_ACCEPT) {
nf_ct_helper_log(skb, ct,
"cannot add expectation for voice");
return ret; return ret;
}
/* Update media connection address if present */ /* Update media connection address if present */
if (maddr_len && nf_nat_sdp_addr && ct->status & IPS_NAT_MASK) { if (maddr_len && nf_nat_sdp_addr && ct->status & IPS_NAT_MASK) {
...@@ -1123,8 +1130,10 @@ static int process_sdp(struct sk_buff *skb, unsigned int protoff, ...@@ -1123,8 +1130,10 @@ static int process_sdp(struct sk_buff *skb, unsigned int protoff,
dptr, datalen, mediaoff, dptr, datalen, mediaoff,
SDP_HDR_CONNECTION, SDP_HDR_MEDIA, SDP_HDR_CONNECTION, SDP_HDR_MEDIA,
&rtp_addr); &rtp_addr);
if (ret != NF_ACCEPT) if (ret != NF_ACCEPT) {
nf_ct_helper_log(skb, ct, "cannot mangle SDP");
return ret; return ret;
}
} }
i++; i++;
} }
...@@ -1258,9 +1267,10 @@ static int process_register_request(struct sk_buff *skb, unsigned int protoff, ...@@ -1258,9 +1267,10 @@ static int process_register_request(struct sk_buff *skb, unsigned int protoff,
ret = ct_sip_parse_header_uri(ct, *dptr, NULL, *datalen, ret = ct_sip_parse_header_uri(ct, *dptr, NULL, *datalen,
SIP_HDR_CONTACT, NULL, SIP_HDR_CONTACT, NULL,
&matchoff, &matchlen, &daddr, &port); &matchoff, &matchlen, &daddr, &port);
if (ret < 0) if (ret < 0) {
nf_ct_helper_log(skb, ct, "cannot parse contact");
return NF_DROP; return NF_DROP;
else if (ret == 0) } else if (ret == 0)
return NF_ACCEPT; return NF_ACCEPT;
/* We don't support third-party registrations */ /* We don't support third-party registrations */
...@@ -1273,8 +1283,10 @@ static int process_register_request(struct sk_buff *skb, unsigned int protoff, ...@@ -1273,8 +1283,10 @@ static int process_register_request(struct sk_buff *skb, unsigned int protoff,
if (ct_sip_parse_numerical_param(ct, *dptr, if (ct_sip_parse_numerical_param(ct, *dptr,
matchoff + matchlen, *datalen, matchoff + matchlen, *datalen,
"expires=", NULL, NULL, &expires) < 0) "expires=", NULL, NULL, &expires) < 0) {
nf_ct_helper_log(skb, ct, "cannot parse expires");
return NF_DROP; return NF_DROP;
}
if (expires == 0) { if (expires == 0) {
ret = NF_ACCEPT; ret = NF_ACCEPT;
...@@ -1282,8 +1294,10 @@ static int process_register_request(struct sk_buff *skb, unsigned int protoff, ...@@ -1282,8 +1294,10 @@ static int process_register_request(struct sk_buff *skb, unsigned int protoff,
} }
exp = nf_ct_expect_alloc(ct); exp = nf_ct_expect_alloc(ct);
if (!exp) if (!exp) {
nf_ct_helper_log(skb, ct, "cannot alloc expectation");
return NF_DROP; return NF_DROP;
}
saddr = NULL; saddr = NULL;
if (sip_direct_signalling) if (sip_direct_signalling)
...@@ -1300,9 +1314,10 @@ static int process_register_request(struct sk_buff *skb, unsigned int protoff, ...@@ -1300,9 +1314,10 @@ static int process_register_request(struct sk_buff *skb, unsigned int protoff,
ret = nf_nat_sip_expect(skb, protoff, dataoff, dptr, datalen, ret = nf_nat_sip_expect(skb, protoff, dataoff, dptr, datalen,
exp, matchoff, matchlen); exp, matchoff, matchlen);
else { else {
if (nf_ct_expect_related(exp) != 0) if (nf_ct_expect_related(exp) != 0) {
nf_ct_helper_log(skb, ct, "cannot add expectation");
ret = NF_DROP; ret = NF_DROP;
else } else
ret = NF_ACCEPT; ret = NF_ACCEPT;
} }
nf_ct_expect_put(exp); nf_ct_expect_put(exp);
...@@ -1356,9 +1371,10 @@ static int process_register_response(struct sk_buff *skb, unsigned int protoff, ...@@ -1356,9 +1371,10 @@ static int process_register_response(struct sk_buff *skb, unsigned int protoff,
SIP_HDR_CONTACT, &in_contact, SIP_HDR_CONTACT, &in_contact,
&matchoff, &matchlen, &matchoff, &matchlen,
&addr, &port); &addr, &port);
if (ret < 0) if (ret < 0) {
nf_ct_helper_log(skb, ct, "cannot parse contact");
return NF_DROP; return NF_DROP;
else if (ret == 0) } else if (ret == 0)
break; break;
/* We don't support third-party registrations */ /* We don't support third-party registrations */
...@@ -1373,8 +1389,10 @@ static int process_register_response(struct sk_buff *skb, unsigned int protoff, ...@@ -1373,8 +1389,10 @@ static int process_register_response(struct sk_buff *skb, unsigned int protoff,
matchoff + matchlen, matchoff + matchlen,
*datalen, "expires=", *datalen, "expires=",
NULL, NULL, &c_expires); NULL, NULL, &c_expires);
if (ret < 0) if (ret < 0) {
nf_ct_helper_log(skb, ct, "cannot parse expires");
return NF_DROP; return NF_DROP;
}
if (c_expires == 0) if (c_expires == 0)
break; break;
if (refresh_signalling_expectation(ct, &addr, proto, port, if (refresh_signalling_expectation(ct, &addr, proto, port,
...@@ -1408,15 +1426,21 @@ static int process_sip_response(struct sk_buff *skb, unsigned int protoff, ...@@ -1408,15 +1426,21 @@ static int process_sip_response(struct sk_buff *skb, unsigned int protoff,
if (*datalen < strlen("SIP/2.0 200")) if (*datalen < strlen("SIP/2.0 200"))
return NF_ACCEPT; return NF_ACCEPT;
code = simple_strtoul(*dptr + strlen("SIP/2.0 "), NULL, 10); code = simple_strtoul(*dptr + strlen("SIP/2.0 "), NULL, 10);
if (!code) if (!code) {
nf_ct_helper_log(skb, ct, "cannot get code");
return NF_DROP; return NF_DROP;
}
if (ct_sip_get_header(ct, *dptr, 0, *datalen, SIP_HDR_CSEQ, if (ct_sip_get_header(ct, *dptr, 0, *datalen, SIP_HDR_CSEQ,
&matchoff, &matchlen) <= 0) &matchoff, &matchlen) <= 0) {
nf_ct_helper_log(skb, ct, "cannot parse cseq");
return NF_DROP; return NF_DROP;
}
cseq = simple_strtoul(*dptr + matchoff, NULL, 10); cseq = simple_strtoul(*dptr + matchoff, NULL, 10);
if (!cseq) if (!cseq) {
nf_ct_helper_log(skb, ct, "cannot get cseq");
return NF_DROP; return NF_DROP;
}
matchend = matchoff + matchlen + 1; matchend = matchoff + matchlen + 1;
for (i = 0; i < ARRAY_SIZE(sip_handlers); i++) { for (i = 0; i < ARRAY_SIZE(sip_handlers); i++) {
...@@ -1471,11 +1495,15 @@ static int process_sip_request(struct sk_buff *skb, unsigned int protoff, ...@@ -1471,11 +1495,15 @@ static int process_sip_request(struct sk_buff *skb, unsigned int protoff,
continue; continue;
if (ct_sip_get_header(ct, *dptr, 0, *datalen, SIP_HDR_CSEQ, if (ct_sip_get_header(ct, *dptr, 0, *datalen, SIP_HDR_CSEQ,
&matchoff, &matchlen) <= 0) &matchoff, &matchlen) <= 0) {
nf_ct_helper_log(skb, ct, "cannot parse cseq");
return NF_DROP; return NF_DROP;
}
cseq = simple_strtoul(*dptr + matchoff, NULL, 10); cseq = simple_strtoul(*dptr + matchoff, NULL, 10);
if (!cseq) if (!cseq) {
nf_ct_helper_log(skb, ct, "cannot get cseq");
return NF_DROP; return NF_DROP;
}
return handler->request(skb, protoff, dataoff, dptr, datalen, return handler->request(skb, protoff, dataoff, dptr, datalen,
cseq); cseq);
...@@ -1498,8 +1526,10 @@ static int process_sip_msg(struct sk_buff *skb, struct nf_conn *ct, ...@@ -1498,8 +1526,10 @@ static int process_sip_msg(struct sk_buff *skb, struct nf_conn *ct,
if (ret == NF_ACCEPT && ct->status & IPS_NAT_MASK) { if (ret == NF_ACCEPT && ct->status & IPS_NAT_MASK) {
nf_nat_sip = rcu_dereference(nf_nat_sip_hook); nf_nat_sip = rcu_dereference(nf_nat_sip_hook);
if (nf_nat_sip && !nf_nat_sip(skb, protoff, dataoff, if (nf_nat_sip && !nf_nat_sip(skb, protoff, dataoff,
dptr, datalen)) dptr, datalen)) {
nf_ct_helper_log(skb, ct, "cannot NAT SIP message");
ret = NF_DROP; ret = NF_DROP;
}
} }
return ret; return ret;
...@@ -1563,11 +1593,14 @@ static int sip_help_tcp(struct sk_buff *skb, unsigned int protoff, ...@@ -1563,11 +1593,14 @@ static int sip_help_tcp(struct sk_buff *skb, unsigned int protoff,
end += strlen("\r\n\r\n") + clen; end += strlen("\r\n\r\n") + clen;
msglen = origlen = end - dptr; msglen = origlen = end - dptr;
if (msglen > datalen) if (msglen > datalen) {
nf_ct_helper_log(skb, ct, "incomplete/bad SIP message");
return NF_DROP; return NF_DROP;
}
ret = process_sip_msg(skb, ct, protoff, dataoff, ret = process_sip_msg(skb, ct, protoff, dataoff,
&dptr, &msglen); &dptr, &msglen);
/* process_sip_* functions report why this packet is dropped */
if (ret != NF_ACCEPT) if (ret != NF_ACCEPT)
break; break;
diff = msglen - origlen; diff = msglen - origlen;
......
...@@ -60,8 +60,10 @@ static int tftp_help(struct sk_buff *skb, ...@@ -60,8 +60,10 @@ static int tftp_help(struct sk_buff *skb,
nf_ct_dump_tuple(&ct->tuplehash[IP_CT_DIR_REPLY].tuple); nf_ct_dump_tuple(&ct->tuplehash[IP_CT_DIR_REPLY].tuple);
exp = nf_ct_expect_alloc(ct); exp = nf_ct_expect_alloc(ct);
if (exp == NULL) if (exp == NULL) {
nf_ct_helper_log(skb, ct, "cannot alloc expectation");
return NF_DROP; return NF_DROP;
}
tuple = &ct->tuplehash[IP_CT_DIR_REPLY].tuple; tuple = &ct->tuplehash[IP_CT_DIR_REPLY].tuple;
nf_ct_expect_init(exp, NF_CT_EXPECT_CLASS_DEFAULT, nf_ct_expect_init(exp, NF_CT_EXPECT_CLASS_DEFAULT,
nf_ct_l3num(ct), nf_ct_l3num(ct),
...@@ -74,8 +76,10 @@ static int tftp_help(struct sk_buff *skb, ...@@ -74,8 +76,10 @@ static int tftp_help(struct sk_buff *skb,
nf_nat_tftp = rcu_dereference(nf_nat_tftp_hook); nf_nat_tftp = rcu_dereference(nf_nat_tftp_hook);
if (nf_nat_tftp && ct->status & IPS_NAT_MASK) if (nf_nat_tftp && ct->status & IPS_NAT_MASK)
ret = nf_nat_tftp(skb, ctinfo, exp); ret = nf_nat_tftp(skb, ctinfo, exp);
else if (nf_ct_expect_related(exp) != 0) else if (nf_ct_expect_related(exp) != 0) {
nf_ct_helper_log(skb, ct, "cannot add expectation");
ret = NF_DROP; ret = NF_DROP;
}
nf_ct_expect_put(exp); nf_ct_expect_put(exp);
break; break;
case TFTP_OPCODE_DATA: case TFTP_OPCODE_DATA:
......
...@@ -56,15 +56,19 @@ static unsigned int help(struct sk_buff *skb, ...@@ -56,15 +56,19 @@ static unsigned int help(struct sk_buff *skb,
} }
} }
if (port == 0) if (port == 0) {
nf_ct_helper_log(skb, exp->master, "all ports in use");
return NF_DROP; return NF_DROP;
}
sprintf(buffer, "%u", port); sprintf(buffer, "%u", port);
ret = nf_nat_mangle_udp_packet(skb, exp->master, ctinfo, ret = nf_nat_mangle_udp_packet(skb, exp->master, ctinfo,
protoff, matchoff, matchlen, protoff, matchoff, matchlen,
buffer, strlen(buffer)); buffer, strlen(buffer));
if (ret != NF_ACCEPT) if (ret != NF_ACCEPT) {
nf_ct_helper_log(skb, exp->master, "cannot mangle packet");
nf_ct_unexpect_related(exp); nf_ct_unexpect_related(exp);
}
return ret; return ret;
} }
......
...@@ -96,8 +96,10 @@ static unsigned int nf_nat_ftp(struct sk_buff *skb, ...@@ -96,8 +96,10 @@ static unsigned int nf_nat_ftp(struct sk_buff *skb,
} }
} }
if (port == 0) if (port == 0) {
nf_ct_helper_log(skb, ct, "all ports in use");
return NF_DROP; return NF_DROP;
}
buflen = nf_nat_ftp_fmt_cmd(ct, type, buffer, sizeof(buffer), buflen = nf_nat_ftp_fmt_cmd(ct, type, buffer, sizeof(buffer),
&newaddr, port); &newaddr, port);
...@@ -113,6 +115,7 @@ static unsigned int nf_nat_ftp(struct sk_buff *skb, ...@@ -113,6 +115,7 @@ static unsigned int nf_nat_ftp(struct sk_buff *skb,
return NF_ACCEPT; return NF_ACCEPT;
out: out:
nf_ct_helper_log(skb, ct, "cannot mangle packet");
nf_ct_unexpect_related(exp); nf_ct_unexpect_related(exp);
return NF_DROP; return NF_DROP;
} }
......
...@@ -56,14 +56,18 @@ static unsigned int help(struct sk_buff *skb, ...@@ -56,14 +56,18 @@ static unsigned int help(struct sk_buff *skb,
} }
} }
if (port == 0) if (port == 0) {
nf_ct_helper_log(skb, exp->master, "all ports in use");
return NF_DROP; return NF_DROP;
}
ret = nf_nat_mangle_tcp_packet(skb, exp->master, ctinfo, ret = nf_nat_mangle_tcp_packet(skb, exp->master, ctinfo,
protoff, matchoff, matchlen, buffer, protoff, matchoff, matchlen, buffer,
strlen(buffer)); strlen(buffer));
if (ret != NF_ACCEPT) if (ret != NF_ACCEPT) {
nf_ct_helper_log(skb, exp->master, "cannot mangle packet");
nf_ct_unexpect_related(exp); nf_ct_unexpect_related(exp);
}
return ret; return ret;
} }
......
...@@ -159,8 +159,10 @@ static unsigned int nf_nat_sip(struct sk_buff *skb, unsigned int protoff, ...@@ -159,8 +159,10 @@ static unsigned int nf_nat_sip(struct sk_buff *skb, unsigned int protoff,
&matchoff, &matchlen, &matchoff, &matchlen,
&addr, &port) > 0 && &addr, &port) > 0 &&
!map_addr(skb, protoff, dataoff, dptr, datalen, !map_addr(skb, protoff, dataoff, dptr, datalen,
matchoff, matchlen, &addr, port)) matchoff, matchlen, &addr, port)) {
nf_ct_helper_log(skb, ct, "cannot mangle SIP message");
return NF_DROP; return NF_DROP;
}
request = 1; request = 1;
} else } else
request = 0; request = 0;
...@@ -193,8 +195,10 @@ static unsigned int nf_nat_sip(struct sk_buff *skb, unsigned int protoff, ...@@ -193,8 +195,10 @@ static unsigned int nf_nat_sip(struct sk_buff *skb, unsigned int protoff,
olen = *datalen; olen = *datalen;
if (!map_addr(skb, protoff, dataoff, dptr, datalen, if (!map_addr(skb, protoff, dataoff, dptr, datalen,
matchoff, matchlen, &addr, port)) matchoff, matchlen, &addr, port)) {
nf_ct_helper_log(skb, ct, "cannot mangle Via header");
return NF_DROP; return NF_DROP;
}
matchend = matchoff + matchlen + *datalen - olen; matchend = matchoff + matchlen + *datalen - olen;
...@@ -209,8 +213,10 @@ static unsigned int nf_nat_sip(struct sk_buff *skb, unsigned int protoff, ...@@ -209,8 +213,10 @@ static unsigned int nf_nat_sip(struct sk_buff *skb, unsigned int protoff,
&ct->tuplehash[!dir].tuple.dst.u3, &ct->tuplehash[!dir].tuple.dst.u3,
true); true);
if (!mangle_packet(skb, protoff, dataoff, dptr, datalen, if (!mangle_packet(skb, protoff, dataoff, dptr, datalen,
poff, plen, buffer, buflen)) poff, plen, buffer, buflen)) {
nf_ct_helper_log(skb, ct, "cannot mangle maddr");
return NF_DROP; return NF_DROP;
}
} }
/* The received= parameter (RFC 2361) contains the address /* The received= parameter (RFC 2361) contains the address
...@@ -225,6 +231,7 @@ static unsigned int nf_nat_sip(struct sk_buff *skb, unsigned int protoff, ...@@ -225,6 +231,7 @@ static unsigned int nf_nat_sip(struct sk_buff *skb, unsigned int protoff,
false); false);
if (!mangle_packet(skb, protoff, dataoff, dptr, datalen, if (!mangle_packet(skb, protoff, dataoff, dptr, datalen,
poff, plen, buffer, buflen)) poff, plen, buffer, buflen))
nf_ct_helper_log(skb, ct, "cannot mangle received");
return NF_DROP; return NF_DROP;
} }
...@@ -238,8 +245,10 @@ static unsigned int nf_nat_sip(struct sk_buff *skb, unsigned int protoff, ...@@ -238,8 +245,10 @@ static unsigned int nf_nat_sip(struct sk_buff *skb, unsigned int protoff,
__be16 p = ct->tuplehash[!dir].tuple.src.u.udp.port; __be16 p = ct->tuplehash[!dir].tuple.src.u.udp.port;
buflen = sprintf(buffer, "%u", ntohs(p)); buflen = sprintf(buffer, "%u", ntohs(p));
if (!mangle_packet(skb, protoff, dataoff, dptr, datalen, if (!mangle_packet(skb, protoff, dataoff, dptr, datalen,
poff, plen, buffer, buflen)) poff, plen, buffer, buflen)) {
nf_ct_helper_log(skb, ct, "cannot mangle rport");
return NF_DROP; return NF_DROP;
}
} }
} }
...@@ -253,27 +262,35 @@ static unsigned int nf_nat_sip(struct sk_buff *skb, unsigned int protoff, ...@@ -253,27 +262,35 @@ static unsigned int nf_nat_sip(struct sk_buff *skb, unsigned int protoff,
&addr, &port) > 0) { &addr, &port) > 0) {
if (!map_addr(skb, protoff, dataoff, dptr, datalen, if (!map_addr(skb, protoff, dataoff, dptr, datalen,
matchoff, matchlen, matchoff, matchlen,
&addr, port)) &addr, port)) {
nf_ct_helper_log(skb, ct, "cannot mangle contact");
return NF_DROP; return NF_DROP;
}
} }
if (!map_sip_addr(skb, protoff, dataoff, dptr, datalen, SIP_HDR_FROM) || if (!map_sip_addr(skb, protoff, dataoff, dptr, datalen, SIP_HDR_FROM) ||
!map_sip_addr(skb, protoff, dataoff, dptr, datalen, SIP_HDR_TO)) !map_sip_addr(skb, protoff, dataoff, dptr, datalen, SIP_HDR_TO)) {
nf_ct_helper_log(skb, ct, "cannot mangle SIP from/to");
return NF_DROP; return NF_DROP;
}
/* Mangle destination port for Cisco phones, then fix up checksums */ /* Mangle destination port for Cisco phones, then fix up checksums */
if (dir == IP_CT_DIR_REPLY && ct_sip_info->forced_dport) { if (dir == IP_CT_DIR_REPLY && ct_sip_info->forced_dport) {
struct udphdr *uh; struct udphdr *uh;
if (!skb_make_writable(skb, skb->len)) if (!skb_make_writable(skb, skb->len)) {
nf_ct_helper_log(skb, ct, "cannot mangle packet");
return NF_DROP; return NF_DROP;
}
uh = (void *)skb->data + protoff; uh = (void *)skb->data + protoff;
uh->dest = ct_sip_info->forced_dport; uh->dest = ct_sip_info->forced_dport;
if (!nf_nat_mangle_udp_packet(skb, ct, ctinfo, protoff, if (!nf_nat_mangle_udp_packet(skb, ct, ctinfo, protoff,
0, 0, NULL, 0)) 0, 0, NULL, 0)) {
nf_ct_helper_log(skb, ct, "cannot mangle packet");
return NF_DROP; return NF_DROP;
}
} }
return NF_ACCEPT; return NF_ACCEPT;
...@@ -372,15 +389,19 @@ static unsigned int nf_nat_sip_expect(struct sk_buff *skb, unsigned int protoff, ...@@ -372,15 +389,19 @@ static unsigned int nf_nat_sip_expect(struct sk_buff *skb, unsigned int protoff,
} }
} }
if (port == 0) if (port == 0) {
nf_ct_helper_log(skb, ct, "all ports in use for SIP");
return NF_DROP; return NF_DROP;
}
if (!nf_inet_addr_cmp(&exp->tuple.dst.u3, &exp->saved_addr) || if (!nf_inet_addr_cmp(&exp->tuple.dst.u3, &exp->saved_addr) ||
exp->tuple.dst.u.udp.port != exp->saved_proto.udp.port) { exp->tuple.dst.u.udp.port != exp->saved_proto.udp.port) {
buflen = sip_sprintf_addr_port(ct, buffer, &newaddr, port); buflen = sip_sprintf_addr_port(ct, buffer, &newaddr, port);
if (!mangle_packet(skb, protoff, dataoff, dptr, datalen, if (!mangle_packet(skb, protoff, dataoff, dptr, datalen,
matchoff, matchlen, buffer, buflen)) matchoff, matchlen, buffer, buflen)) {
nf_ct_helper_log(skb, ct, "cannot mangle packet");
goto err; goto err;
}
} }
return NF_ACCEPT; return NF_ACCEPT;
...@@ -573,14 +594,18 @@ static unsigned int nf_nat_sdp_media(struct sk_buff *skb, unsigned int protoff, ...@@ -573,14 +594,18 @@ static unsigned int nf_nat_sdp_media(struct sk_buff *skb, unsigned int protoff,
} }
} }
if (port == 0) if (port == 0) {
nf_ct_helper_log(skb, ct, "all ports in use for SDP media");
goto err1; goto err1;
}
/* Update media port. */ /* Update media port. */
if (rtp_exp->tuple.dst.u.udp.port != rtp_exp->saved_proto.udp.port && if (rtp_exp->tuple.dst.u.udp.port != rtp_exp->saved_proto.udp.port &&
!nf_nat_sdp_port(skb, protoff, dataoff, dptr, datalen, !nf_nat_sdp_port(skb, protoff, dataoff, dptr, datalen,
mediaoff, medialen, port)) mediaoff, medialen, port)) {
nf_ct_helper_log(skb, ct, "cannot mangle SDP message");
goto err2; goto err2;
}
return NF_ACCEPT; return NF_ACCEPT;
......
...@@ -28,8 +28,10 @@ static unsigned int help(struct sk_buff *skb, ...@@ -28,8 +28,10 @@ static unsigned int help(struct sk_buff *skb,
= ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple.src.u.udp.port; = ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple.src.u.udp.port;
exp->dir = IP_CT_DIR_REPLY; exp->dir = IP_CT_DIR_REPLY;
exp->expectfn = nf_nat_follow_master; exp->expectfn = nf_nat_follow_master;
if (nf_ct_expect_related(exp) != 0) if (nf_ct_expect_related(exp) != 0) {
nf_ct_helper_log(skb, exp->master, "cannot add expectation");
return NF_DROP; return NF_DROP;
}
return NF_ACCEPT; return NF_ACCEPT;
} }
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment