Skip to content

Commit c4f3db1

Browse files
Florian Westphalummakynes
authored andcommitted
netfilter: conntrack: add and use nf_l4proto_log_invalid
We currently pass down the l4 protocol to the conntrack ->packet() function, but the only user of this is the debug info decision. Same information can be derived from struct nf_conn. As a first step, add and use a new log function for this, similar to nf_ct_helper_log(). Add __cold annotation -- invalid packets should be infrequent so gcc can consider all call paths that lead to such a function as unlikely. Signed-off-by: Florian Westphal <[email protected]> Signed-off-by: Pablo Neira Ayuso <[email protected]>
1 parent 2420770 commit c4f3db1

File tree

8 files changed

+82
-52
lines changed

8 files changed

+82
-52
lines changed

include/net/netfilter/nf_conntrack_l4proto.h

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -152,8 +152,18 @@ extern const struct nla_policy nf_ct_port_nla_policy[];
152152
#define LOG_INVALID(net, proto) \
153153
((net)->ct.sysctl_log_invalid == (proto) || \
154154
(net)->ct.sysctl_log_invalid == IPPROTO_RAW)
155+
156+
__printf(5, 6) __cold
157+
void nf_l4proto_log_invalid(const struct sk_buff *skb,
158+
struct net *net,
159+
u16 pf, u8 protonum,
160+
const char *fmt, ...);
155161
#else
156162
static inline int LOG_INVALID(struct net *net, int proto) { return 0; }
163+
164+
static inline __printf(5, 6) __cold
165+
void nf_l4proto_log_invalid(const struct sk_buff *skb, struct net *net,
166+
u16 pf, u8 protonum, const char *fmt, ...) {}
157167
#endif /* CONFIG_SYSCTL */
158168

159169
#endif /*_NF_CONNTRACK_PROTOCOL_H*/

net/ipv4/netfilter/nf_conntrack_proto_icmp.c

Lines changed: 9 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -165,6 +165,12 @@ icmp_error_message(struct net *net, struct nf_conn *tmpl, struct sk_buff *skb,
165165
return NF_ACCEPT;
166166
}
167167

168+
static void icmp_error_log(const struct sk_buff *skb, struct net *net,
169+
u8 pf, const char *msg)
170+
{
171+
nf_l4proto_log_invalid(skb, net, pf, IPPROTO_ICMP, "%s", msg);
172+
}
173+
168174
/* Small and modified version of icmp_rcv */
169175
static int
170176
icmp_error(struct net *net, struct nf_conn *tmpl,
@@ -177,18 +183,14 @@ icmp_error(struct net *net, struct nf_conn *tmpl,
177183
/* Not enough header? */
178184
icmph = skb_header_pointer(skb, ip_hdrlen(skb), sizeof(_ih), &_ih);
179185
if (icmph == NULL) {
180-
if (LOG_INVALID(net, IPPROTO_ICMP))
181-
nf_log_packet(net, PF_INET, 0, skb, NULL, NULL,
182-
NULL, "nf_ct_icmp: short packet ");
186+
icmp_error_log(skb, net, pf, "short packet");
183187
return -NF_ACCEPT;
184188
}
185189

186190
/* See ip_conntrack_proto_tcp.c */
187191
if (net->ct.sysctl_checksum && hooknum == NF_INET_PRE_ROUTING &&
188192
nf_ip_checksum(skb, hooknum, dataoff, 0)) {
189-
if (LOG_INVALID(net, IPPROTO_ICMP))
190-
nf_log_packet(net, PF_INET, 0, skb, NULL, NULL, NULL,
191-
"nf_ct_icmp: bad HW ICMP checksum ");
193+
icmp_error_log(skb, net, pf, "bad hw icmp checksum");
192194
return -NF_ACCEPT;
193195
}
194196

@@ -199,9 +201,7 @@ icmp_error(struct net *net, struct nf_conn *tmpl,
199201
* discarded.
200202
*/
201203
if (icmph->type > NR_ICMP_TYPES) {
202-
if (LOG_INVALID(net, IPPROTO_ICMP))
203-
nf_log_packet(net, PF_INET, 0, skb, NULL, NULL, NULL,
204-
"nf_ct_icmp: invalid ICMP type ");
204+
icmp_error_log(skb, net, pf, "invalid icmp type");
205205
return -NF_ACCEPT;
206206
}
207207

net/ipv6/netfilter/nf_conntrack_proto_icmpv6.c

Lines changed: 8 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -176,6 +176,12 @@ icmpv6_error_message(struct net *net, struct nf_conn *tmpl,
176176
return NF_ACCEPT;
177177
}
178178

179+
static void icmpv6_error_log(const struct sk_buff *skb, struct net *net,
180+
u8 pf, const char *msg)
181+
{
182+
nf_l4proto_log_invalid(skb, net, pf, IPPROTO_ICMPV6, "%s", msg);
183+
}
184+
179185
static int
180186
icmpv6_error(struct net *net, struct nf_conn *tmpl,
181187
struct sk_buff *skb, unsigned int dataoff,
@@ -187,17 +193,13 @@ icmpv6_error(struct net *net, struct nf_conn *tmpl,
187193

188194
icmp6h = skb_header_pointer(skb, dataoff, sizeof(_ih), &_ih);
189195
if (icmp6h == NULL) {
190-
if (LOG_INVALID(net, IPPROTO_ICMPV6))
191-
nf_log_packet(net, PF_INET6, 0, skb, NULL, NULL, NULL,
192-
"nf_ct_icmpv6: short packet ");
196+
icmpv6_error_log(skb, net, pf, "short packet");
193197
return -NF_ACCEPT;
194198
}
195199

196200
if (net->ct.sysctl_checksum && hooknum == NF_INET_PRE_ROUTING &&
197201
nf_ip6_checksum(skb, hooknum, dataoff, IPPROTO_ICMPV6)) {
198-
if (LOG_INVALID(net, IPPROTO_ICMPV6))
199-
nf_log_packet(net, PF_INET6, 0, skb, NULL, NULL, NULL,
200-
"nf_ct_icmpv6: ICMPv6 checksum failed ");
202+
icmpv6_error_log(skb, net, pf, "ICMPv6 checksum failed");
201203
return -NF_ACCEPT;
202204
}
203205

net/netfilter/nf_conntrack_proto.c

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,7 @@
2727
#include <net/netfilter/nf_conntrack_l3proto.h>
2828
#include <net/netfilter/nf_conntrack_l4proto.h>
2929
#include <net/netfilter/nf_conntrack_core.h>
30+
#include <net/netfilter/nf_log.h>
3031

3132
static struct nf_conntrack_l4proto __rcu **nf_ct_protos[NFPROTO_NUMPROTO] __read_mostly;
3233
struct nf_conntrack_l3proto __rcu *nf_ct_l3protos[NFPROTO_NUMPROTO] __read_mostly;
@@ -63,6 +64,29 @@ nf_ct_unregister_sysctl(struct ctl_table_header **header,
6364
*header = NULL;
6465
*table = NULL;
6566
}
67+
68+
__printf(5, 6)
69+
void nf_l4proto_log_invalid(const struct sk_buff *skb,
70+
struct net *net,
71+
u16 pf, u8 protonum,
72+
const char *fmt, ...)
73+
{
74+
struct va_format vaf;
75+
va_list args;
76+
77+
if (net->ct.sysctl_log_invalid != protonum ||
78+
net->ct.sysctl_log_invalid != IPPROTO_RAW)
79+
return;
80+
81+
va_start(args, fmt);
82+
vaf.fmt = fmt;
83+
vaf.va = &args;
84+
85+
nf_log_packet(net, pf, 0, skb, NULL, NULL, NULL,
86+
"nf_ct_proto_%d: %pV ", protonum, &vaf);
87+
va_end(args);
88+
}
89+
EXPORT_SYMBOL_GPL(nf_l4proto_log_invalid);
6690
#endif
6791

6892
const struct nf_conntrack_l4proto *

net/netfilter/nf_conntrack_proto_dccp.c

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -604,8 +604,7 @@ static int dccp_error(struct net *net, struct nf_conn *tmpl,
604604
return NF_ACCEPT;
605605

606606
out_invalid:
607-
if (LOG_INVALID(net, IPPROTO_DCCP))
608-
nf_log_packet(net, pf, 0, skb, NULL, NULL, NULL, "%s", msg);
607+
nf_l4proto_log_invalid(skb, net, pf, IPPROTO_DCCP, "%s", msg);
609608
return -NF_ACCEPT;
610609
}
611610

net/netfilter/nf_conntrack_proto_sctp.c

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -522,8 +522,7 @@ static int sctp_error(struct net *net, struct nf_conn *tpl, struct sk_buff *skb,
522522
}
523523
return NF_ACCEPT;
524524
out_invalid:
525-
if (LOG_INVALID(net, IPPROTO_SCTP))
526-
nf_log_packet(net, pf, 0, skb, NULL, NULL, NULL, "%s", logmsg);
525+
nf_l4proto_log_invalid(skb, net, pf, IPPROTO_SCTP, "%s", logmsg);
527526
return -NF_ACCEPT;
528527
}
529528

net/netfilter/nf_conntrack_proto_tcp.c

Lines changed: 10 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -738,6 +738,12 @@ static const u8 tcp_valid_flags[(TCPHDR_FIN|TCPHDR_SYN|TCPHDR_RST|TCPHDR_ACK|
738738
[TCPHDR_ACK|TCPHDR_URG] = 1,
739739
};
740740

741+
static void tcp_error_log(const struct sk_buff *skb, struct net *net,
742+
u8 pf, const char *msg)
743+
{
744+
nf_l4proto_log_invalid(skb, net, pf, IPPROTO_TCP, "%s", msg);
745+
}
746+
741747
/* Protect conntrack agaist broken packets. Code taken from ipt_unclean.c. */
742748
static int tcp_error(struct net *net, struct nf_conn *tmpl,
743749
struct sk_buff *skb,
@@ -753,17 +759,13 @@ static int tcp_error(struct net *net, struct nf_conn *tmpl,
753759
/* Smaller that minimal TCP header? */
754760
th = skb_header_pointer(skb, dataoff, sizeof(_tcph), &_tcph);
755761
if (th == NULL) {
756-
if (LOG_INVALID(net, IPPROTO_TCP))
757-
nf_log_packet(net, pf, 0, skb, NULL, NULL, NULL,
758-
"nf_ct_tcp: short packet ");
762+
tcp_error_log(skb, net, pf, "short packet");
759763
return -NF_ACCEPT;
760764
}
761765

762766
/* Not whole TCP header or malformed packet */
763767
if (th->doff*4 < sizeof(struct tcphdr) || tcplen < th->doff*4) {
764-
if (LOG_INVALID(net, IPPROTO_TCP))
765-
nf_log_packet(net, pf, 0, skb, NULL, NULL, NULL,
766-
"nf_ct_tcp: truncated/malformed packet ");
768+
tcp_error_log(skb, net, pf, "truncated packet");
767769
return -NF_ACCEPT;
768770
}
769771

@@ -774,18 +776,14 @@ static int tcp_error(struct net *net, struct nf_conn *tmpl,
774776
/* FIXME: Source route IP option packets --RR */
775777
if (net->ct.sysctl_checksum && hooknum == NF_INET_PRE_ROUTING &&
776778
nf_checksum(skb, hooknum, dataoff, IPPROTO_TCP, pf)) {
777-
if (LOG_INVALID(net, IPPROTO_TCP))
778-
nf_log_packet(net, pf, 0, skb, NULL, NULL, NULL,
779-
"nf_ct_tcp: bad TCP checksum ");
779+
tcp_error_log(skb, net, pf, "bad checksum");
780780
return -NF_ACCEPT;
781781
}
782782

783783
/* Check TCP flags. */
784784
tcpflags = (tcp_flag_byte(th) & ~(TCPHDR_ECE|TCPHDR_CWR|TCPHDR_PSH));
785785
if (!tcp_valid_flags[tcpflags]) {
786-
if (LOG_INVALID(net, IPPROTO_TCP))
787-
nf_log_packet(net, pf, 0, skb, NULL, NULL, NULL,
788-
"nf_ct_tcp: invalid TCP flag combination ");
786+
tcp_error_log(skb, net, pf, "invalid tcp flag combination");
789787
return -NF_ACCEPT;
790788
}
791789

net/netfilter/nf_conntrack_proto_udp.c

Lines changed: 19 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -99,6 +99,12 @@ static bool udp_new(struct nf_conn *ct, const struct sk_buff *skb,
9999
}
100100

101101
#ifdef CONFIG_NF_CT_PROTO_UDPLITE
102+
static void udplite_error_log(const struct sk_buff *skb, struct net *net,
103+
u8 pf, const char *msg)
104+
{
105+
nf_l4proto_log_invalid(skb, net, pf, IPPROTO_UDPLITE, "%s", msg);
106+
}
107+
102108
static int udplite_error(struct net *net, struct nf_conn *tmpl,
103109
struct sk_buff *skb,
104110
unsigned int dataoff,
@@ -112,44 +118,42 @@ static int udplite_error(struct net *net, struct nf_conn *tmpl,
112118
/* Header is too small? */
113119
hdr = skb_header_pointer(skb, dataoff, sizeof(_hdr), &_hdr);
114120
if (!hdr) {
115-
if (LOG_INVALID(net, IPPROTO_UDPLITE))
116-
nf_log_packet(net, pf, 0, skb, NULL, NULL, NULL,
117-
"nf_ct_udplite: short packet ");
121+
udplite_error_log(skb, net, pf, "short packet");
118122
return -NF_ACCEPT;
119123
}
120124

121125
cscov = ntohs(hdr->len);
122126
if (cscov == 0) {
123127
cscov = udplen;
124128
} else if (cscov < sizeof(*hdr) || cscov > udplen) {
125-
if (LOG_INVALID(net, IPPROTO_UDPLITE))
126-
nf_log_packet(net, pf, 0, skb, NULL, NULL, NULL,
127-
"nf_ct_udplite: invalid checksum coverage ");
129+
udplite_error_log(skb, net, pf, "invalid checksum coverage");
128130
return -NF_ACCEPT;
129131
}
130132

131133
/* UDPLITE mandates checksums */
132134
if (!hdr->check) {
133-
if (LOG_INVALID(net, IPPROTO_UDPLITE))
134-
nf_log_packet(net, pf, 0, skb, NULL, NULL, NULL,
135-
"nf_ct_udplite: checksum missing ");
135+
udplite_error_log(skb, net, pf, "checksum missing");
136136
return -NF_ACCEPT;
137137
}
138138

139139
/* Checksum invalid? Ignore. */
140140
if (net->ct.sysctl_checksum && hooknum == NF_INET_PRE_ROUTING &&
141141
nf_checksum_partial(skb, hooknum, dataoff, cscov, IPPROTO_UDP,
142142
pf)) {
143-
if (LOG_INVALID(net, IPPROTO_UDPLITE))
144-
nf_log_packet(net, pf, 0, skb, NULL, NULL, NULL,
145-
"nf_ct_udplite: bad UDPLite checksum ");
143+
udplite_error_log(skb, net, pf, "bad checksum");
146144
return -NF_ACCEPT;
147145
}
148146

149147
return NF_ACCEPT;
150148
}
151149
#endif
152150

151+
static void udp_error_log(const struct sk_buff *skb, struct net *net,
152+
u8 pf, const char *msg)
153+
{
154+
nf_l4proto_log_invalid(skb, net, pf, IPPROTO_UDP, "%s", msg);
155+
}
156+
153157
static int udp_error(struct net *net, struct nf_conn *tmpl, struct sk_buff *skb,
154158
unsigned int dataoff,
155159
u_int8_t pf,
@@ -162,17 +166,13 @@ static int udp_error(struct net *net, struct nf_conn *tmpl, struct sk_buff *skb,
162166
/* Header is too small? */
163167
hdr = skb_header_pointer(skb, dataoff, sizeof(_hdr), &_hdr);
164168
if (hdr == NULL) {
165-
if (LOG_INVALID(net, IPPROTO_UDP))
166-
nf_log_packet(net, pf, 0, skb, NULL, NULL, NULL,
167-
"nf_ct_udp: short packet ");
169+
udp_error_log(skb, net, pf, "short packet");
168170
return -NF_ACCEPT;
169171
}
170172

171173
/* Truncated/malformed packets */
172174
if (ntohs(hdr->len) > udplen || ntohs(hdr->len) < sizeof(*hdr)) {
173-
if (LOG_INVALID(net, IPPROTO_UDP))
174-
nf_log_packet(net, pf, 0, skb, NULL, NULL, NULL,
175-
"nf_ct_udp: truncated/malformed packet ");
175+
udp_error_log(skb, net, pf, "truncated/malformed packet");
176176
return -NF_ACCEPT;
177177
}
178178

@@ -186,9 +186,7 @@ static int udp_error(struct net *net, struct nf_conn *tmpl, struct sk_buff *skb,
186186
* FIXME: Source route IP option packets --RR */
187187
if (net->ct.sysctl_checksum && hooknum == NF_INET_PRE_ROUTING &&
188188
nf_checksum(skb, hooknum, dataoff, IPPROTO_UDP, pf)) {
189-
if (LOG_INVALID(net, IPPROTO_UDP))
190-
nf_log_packet(net, pf, 0, skb, NULL, NULL, NULL,
191-
"nf_ct_udp: bad UDP checksum ");
189+
udp_error_log(skb, net, pf, "bad checksum");
192190
return -NF_ACCEPT;
193191
}
194192

0 commit comments

Comments
 (0)