mirror of
				https://github.com/torvalds/linux.git
				synced 2025-11-04 02:30:34 +02:00 
			
		
		
		
	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 <fw@strlen.de> Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>
This commit is contained in:
		
							parent
							
								
									2420770b3f
								
							
						
					
					
						commit
						c4f3db1595
					
				
					 8 changed files with 82 additions and 52 deletions
				
			
		| 
						 | 
					@ -152,8 +152,18 @@ extern const struct nla_policy nf_ct_port_nla_policy[];
 | 
				
			||||||
#define LOG_INVALID(net, proto)				\
 | 
					#define LOG_INVALID(net, proto)				\
 | 
				
			||||||
	((net)->ct.sysctl_log_invalid == (proto) ||	\
 | 
						((net)->ct.sysctl_log_invalid == (proto) ||	\
 | 
				
			||||||
	 (net)->ct.sysctl_log_invalid == IPPROTO_RAW)
 | 
						 (net)->ct.sysctl_log_invalid == IPPROTO_RAW)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					__printf(5, 6) __cold
 | 
				
			||||||
 | 
					void nf_l4proto_log_invalid(const struct sk_buff *skb,
 | 
				
			||||||
 | 
								    struct net *net,
 | 
				
			||||||
 | 
								    u16 pf, u8 protonum,
 | 
				
			||||||
 | 
								    const char *fmt, ...);
 | 
				
			||||||
#else
 | 
					#else
 | 
				
			||||||
static inline int LOG_INVALID(struct net *net, int proto) { return 0; }
 | 
					static inline int LOG_INVALID(struct net *net, int proto) { return 0; }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static inline __printf(5, 6) __cold
 | 
				
			||||||
 | 
					void nf_l4proto_log_invalid(const struct sk_buff *skb, struct net *net,
 | 
				
			||||||
 | 
								    u16 pf, u8 protonum, const char *fmt, ...) {}
 | 
				
			||||||
#endif /* CONFIG_SYSCTL */
 | 
					#endif /* CONFIG_SYSCTL */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#endif /*_NF_CONNTRACK_PROTOCOL_H*/
 | 
					#endif /*_NF_CONNTRACK_PROTOCOL_H*/
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -165,6 +165,12 @@ icmp_error_message(struct net *net, struct nf_conn *tmpl, struct sk_buff *skb,
 | 
				
			||||||
	return NF_ACCEPT;
 | 
						return NF_ACCEPT;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static void icmp_error_log(const struct sk_buff *skb, struct net *net,
 | 
				
			||||||
 | 
								   u8 pf, const char *msg)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						nf_l4proto_log_invalid(skb, net, pf, IPPROTO_ICMP, "%s", msg);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/* Small and modified version of icmp_rcv */
 | 
					/* Small and modified version of icmp_rcv */
 | 
				
			||||||
static int
 | 
					static int
 | 
				
			||||||
icmp_error(struct net *net, struct nf_conn *tmpl,
 | 
					icmp_error(struct net *net, struct nf_conn *tmpl,
 | 
				
			||||||
| 
						 | 
					@ -177,18 +183,14 @@ icmp_error(struct net *net, struct nf_conn *tmpl,
 | 
				
			||||||
	/* Not enough header? */
 | 
						/* Not enough header? */
 | 
				
			||||||
	icmph = skb_header_pointer(skb, ip_hdrlen(skb), sizeof(_ih), &_ih);
 | 
						icmph = skb_header_pointer(skb, ip_hdrlen(skb), sizeof(_ih), &_ih);
 | 
				
			||||||
	if (icmph == NULL) {
 | 
						if (icmph == NULL) {
 | 
				
			||||||
		if (LOG_INVALID(net, IPPROTO_ICMP))
 | 
							icmp_error_log(skb, net, pf, "short packet");
 | 
				
			||||||
			nf_log_packet(net, PF_INET, 0, skb, NULL, NULL,
 | 
					 | 
				
			||||||
				      NULL, "nf_ct_icmp: short packet ");
 | 
					 | 
				
			||||||
		return -NF_ACCEPT;
 | 
							return -NF_ACCEPT;
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	/* See ip_conntrack_proto_tcp.c */
 | 
						/* See ip_conntrack_proto_tcp.c */
 | 
				
			||||||
	if (net->ct.sysctl_checksum && hooknum == NF_INET_PRE_ROUTING &&
 | 
						if (net->ct.sysctl_checksum && hooknum == NF_INET_PRE_ROUTING &&
 | 
				
			||||||
	    nf_ip_checksum(skb, hooknum, dataoff, 0)) {
 | 
						    nf_ip_checksum(skb, hooknum, dataoff, 0)) {
 | 
				
			||||||
		if (LOG_INVALID(net, IPPROTO_ICMP))
 | 
							icmp_error_log(skb, net, pf, "bad hw icmp checksum");
 | 
				
			||||||
			nf_log_packet(net, PF_INET, 0, skb, NULL, NULL, NULL,
 | 
					 | 
				
			||||||
				      "nf_ct_icmp: bad HW ICMP checksum ");
 | 
					 | 
				
			||||||
		return -NF_ACCEPT;
 | 
							return -NF_ACCEPT;
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -199,9 +201,7 @@ icmp_error(struct net *net, struct nf_conn *tmpl,
 | 
				
			||||||
	 *		  discarded.
 | 
						 *		  discarded.
 | 
				
			||||||
	 */
 | 
						 */
 | 
				
			||||||
	if (icmph->type > NR_ICMP_TYPES) {
 | 
						if (icmph->type > NR_ICMP_TYPES) {
 | 
				
			||||||
		if (LOG_INVALID(net, IPPROTO_ICMP))
 | 
							icmp_error_log(skb, net, pf, "invalid icmp type");
 | 
				
			||||||
			nf_log_packet(net, PF_INET, 0, skb, NULL, NULL, NULL,
 | 
					 | 
				
			||||||
				      "nf_ct_icmp: invalid ICMP type ");
 | 
					 | 
				
			||||||
		return -NF_ACCEPT;
 | 
							return -NF_ACCEPT;
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -176,6 +176,12 @@ icmpv6_error_message(struct net *net, struct nf_conn *tmpl,
 | 
				
			||||||
	return NF_ACCEPT;
 | 
						return NF_ACCEPT;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static void icmpv6_error_log(const struct sk_buff *skb, struct net *net,
 | 
				
			||||||
 | 
								     u8 pf, const char *msg)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						nf_l4proto_log_invalid(skb, net, pf, IPPROTO_ICMPV6, "%s", msg);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static int
 | 
					static int
 | 
				
			||||||
icmpv6_error(struct net *net, struct nf_conn *tmpl,
 | 
					icmpv6_error(struct net *net, struct nf_conn *tmpl,
 | 
				
			||||||
	     struct sk_buff *skb, unsigned int dataoff,
 | 
						     struct sk_buff *skb, unsigned int dataoff,
 | 
				
			||||||
| 
						 | 
					@ -187,17 +193,13 @@ icmpv6_error(struct net *net, struct nf_conn *tmpl,
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	icmp6h = skb_header_pointer(skb, dataoff, sizeof(_ih), &_ih);
 | 
						icmp6h = skb_header_pointer(skb, dataoff, sizeof(_ih), &_ih);
 | 
				
			||||||
	if (icmp6h == NULL) {
 | 
						if (icmp6h == NULL) {
 | 
				
			||||||
		if (LOG_INVALID(net, IPPROTO_ICMPV6))
 | 
							icmpv6_error_log(skb, net, pf, "short packet");
 | 
				
			||||||
			nf_log_packet(net, PF_INET6, 0, skb, NULL, NULL, NULL,
 | 
					 | 
				
			||||||
			      "nf_ct_icmpv6: short packet ");
 | 
					 | 
				
			||||||
		return -NF_ACCEPT;
 | 
							return -NF_ACCEPT;
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if (net->ct.sysctl_checksum && hooknum == NF_INET_PRE_ROUTING &&
 | 
						if (net->ct.sysctl_checksum && hooknum == NF_INET_PRE_ROUTING &&
 | 
				
			||||||
	    nf_ip6_checksum(skb, hooknum, dataoff, IPPROTO_ICMPV6)) {
 | 
						    nf_ip6_checksum(skb, hooknum, dataoff, IPPROTO_ICMPV6)) {
 | 
				
			||||||
		if (LOG_INVALID(net, IPPROTO_ICMPV6))
 | 
							icmpv6_error_log(skb, net, pf, "ICMPv6 checksum failed");
 | 
				
			||||||
			nf_log_packet(net, PF_INET6, 0, skb, NULL, NULL, NULL,
 | 
					 | 
				
			||||||
				      "nf_ct_icmpv6: ICMPv6 checksum failed ");
 | 
					 | 
				
			||||||
		return -NF_ACCEPT;
 | 
							return -NF_ACCEPT;
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -27,6 +27,7 @@
 | 
				
			||||||
#include <net/netfilter/nf_conntrack_l3proto.h>
 | 
					#include <net/netfilter/nf_conntrack_l3proto.h>
 | 
				
			||||||
#include <net/netfilter/nf_conntrack_l4proto.h>
 | 
					#include <net/netfilter/nf_conntrack_l4proto.h>
 | 
				
			||||||
#include <net/netfilter/nf_conntrack_core.h>
 | 
					#include <net/netfilter/nf_conntrack_core.h>
 | 
				
			||||||
 | 
					#include <net/netfilter/nf_log.h>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static struct nf_conntrack_l4proto __rcu **nf_ct_protos[NFPROTO_NUMPROTO] __read_mostly;
 | 
					static struct nf_conntrack_l4proto __rcu **nf_ct_protos[NFPROTO_NUMPROTO] __read_mostly;
 | 
				
			||||||
struct nf_conntrack_l3proto __rcu *nf_ct_l3protos[NFPROTO_NUMPROTO] __read_mostly;
 | 
					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,
 | 
				
			||||||
	*header = NULL;
 | 
						*header = NULL;
 | 
				
			||||||
	*table = NULL;
 | 
						*table = NULL;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					__printf(5, 6)
 | 
				
			||||||
 | 
					void nf_l4proto_log_invalid(const struct sk_buff *skb,
 | 
				
			||||||
 | 
								    struct net *net,
 | 
				
			||||||
 | 
								    u16 pf, u8 protonum,
 | 
				
			||||||
 | 
								    const char *fmt, ...)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						struct va_format vaf;
 | 
				
			||||||
 | 
						va_list args;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if (net->ct.sysctl_log_invalid != protonum ||
 | 
				
			||||||
 | 
						    net->ct.sysctl_log_invalid != IPPROTO_RAW)
 | 
				
			||||||
 | 
							return;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						va_start(args, fmt);
 | 
				
			||||||
 | 
						vaf.fmt = fmt;
 | 
				
			||||||
 | 
						vaf.va = &args;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						nf_log_packet(net, pf, 0, skb, NULL, NULL, NULL,
 | 
				
			||||||
 | 
							      "nf_ct_proto_%d: %pV ", protonum, &vaf);
 | 
				
			||||||
 | 
						va_end(args);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					EXPORT_SYMBOL_GPL(nf_l4proto_log_invalid);
 | 
				
			||||||
#endif
 | 
					#endif
 | 
				
			||||||
 | 
					
 | 
				
			||||||
const struct nf_conntrack_l4proto *
 | 
					const struct nf_conntrack_l4proto *
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -604,8 +604,7 @@ static int dccp_error(struct net *net, struct nf_conn *tmpl,
 | 
				
			||||||
	return NF_ACCEPT;
 | 
						return NF_ACCEPT;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
out_invalid:
 | 
					out_invalid:
 | 
				
			||||||
	if (LOG_INVALID(net, IPPROTO_DCCP))
 | 
						nf_l4proto_log_invalid(skb, net, pf, IPPROTO_DCCP, "%s", msg);
 | 
				
			||||||
		nf_log_packet(net, pf, 0, skb, NULL, NULL, NULL, "%s", msg);
 | 
					 | 
				
			||||||
	return -NF_ACCEPT;
 | 
						return -NF_ACCEPT;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -522,8 +522,7 @@ static int sctp_error(struct net *net, struct nf_conn *tpl, struct sk_buff *skb,
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	return NF_ACCEPT;
 | 
						return NF_ACCEPT;
 | 
				
			||||||
out_invalid:
 | 
					out_invalid:
 | 
				
			||||||
	if (LOG_INVALID(net, IPPROTO_SCTP))
 | 
						nf_l4proto_log_invalid(skb, net, pf, IPPROTO_SCTP, "%s", logmsg);
 | 
				
			||||||
		nf_log_packet(net, pf, 0, skb, NULL, NULL, NULL, "%s", logmsg);
 | 
					 | 
				
			||||||
	return -NF_ACCEPT;
 | 
						return -NF_ACCEPT;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -738,6 +738,12 @@ static const u8 tcp_valid_flags[(TCPHDR_FIN|TCPHDR_SYN|TCPHDR_RST|TCPHDR_ACK|
 | 
				
			||||||
	[TCPHDR_ACK|TCPHDR_URG]			= 1,
 | 
						[TCPHDR_ACK|TCPHDR_URG]			= 1,
 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static void tcp_error_log(const struct sk_buff *skb, struct net *net,
 | 
				
			||||||
 | 
								  u8 pf, const char *msg)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						nf_l4proto_log_invalid(skb, net, pf, IPPROTO_TCP, "%s", msg);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/* Protect conntrack agaist broken packets. Code taken from ipt_unclean.c.  */
 | 
					/* Protect conntrack agaist broken packets. Code taken from ipt_unclean.c.  */
 | 
				
			||||||
static int tcp_error(struct net *net, struct nf_conn *tmpl,
 | 
					static int tcp_error(struct net *net, struct nf_conn *tmpl,
 | 
				
			||||||
		     struct sk_buff *skb,
 | 
							     struct sk_buff *skb,
 | 
				
			||||||
| 
						 | 
					@ -753,17 +759,13 @@ static int tcp_error(struct net *net, struct nf_conn *tmpl,
 | 
				
			||||||
	/* Smaller that minimal TCP header? */
 | 
						/* Smaller that minimal TCP header? */
 | 
				
			||||||
	th = skb_header_pointer(skb, dataoff, sizeof(_tcph), &_tcph);
 | 
						th = skb_header_pointer(skb, dataoff, sizeof(_tcph), &_tcph);
 | 
				
			||||||
	if (th == NULL) {
 | 
						if (th == NULL) {
 | 
				
			||||||
		if (LOG_INVALID(net, IPPROTO_TCP))
 | 
							tcp_error_log(skb, net, pf, "short packet");
 | 
				
			||||||
			nf_log_packet(net, pf, 0, skb, NULL, NULL, NULL,
 | 
					 | 
				
			||||||
				"nf_ct_tcp: short packet ");
 | 
					 | 
				
			||||||
		return -NF_ACCEPT;
 | 
							return -NF_ACCEPT;
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	/* Not whole TCP header or malformed packet */
 | 
						/* Not whole TCP header or malformed packet */
 | 
				
			||||||
	if (th->doff*4 < sizeof(struct tcphdr) || tcplen < th->doff*4) {
 | 
						if (th->doff*4 < sizeof(struct tcphdr) || tcplen < th->doff*4) {
 | 
				
			||||||
		if (LOG_INVALID(net, IPPROTO_TCP))
 | 
							tcp_error_log(skb, net, pf, "truncated packet");
 | 
				
			||||||
			nf_log_packet(net, pf, 0, skb, NULL, NULL, NULL,
 | 
					 | 
				
			||||||
				"nf_ct_tcp: truncated/malformed packet ");
 | 
					 | 
				
			||||||
		return -NF_ACCEPT;
 | 
							return -NF_ACCEPT;
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -774,18 +776,14 @@ static int tcp_error(struct net *net, struct nf_conn *tmpl,
 | 
				
			||||||
	/* FIXME: Source route IP option packets --RR */
 | 
						/* FIXME: Source route IP option packets --RR */
 | 
				
			||||||
	if (net->ct.sysctl_checksum && hooknum == NF_INET_PRE_ROUTING &&
 | 
						if (net->ct.sysctl_checksum && hooknum == NF_INET_PRE_ROUTING &&
 | 
				
			||||||
	    nf_checksum(skb, hooknum, dataoff, IPPROTO_TCP, pf)) {
 | 
						    nf_checksum(skb, hooknum, dataoff, IPPROTO_TCP, pf)) {
 | 
				
			||||||
		if (LOG_INVALID(net, IPPROTO_TCP))
 | 
							tcp_error_log(skb, net, pf, "bad checksum");
 | 
				
			||||||
			nf_log_packet(net, pf, 0, skb, NULL, NULL, NULL,
 | 
					 | 
				
			||||||
				  "nf_ct_tcp: bad TCP checksum ");
 | 
					 | 
				
			||||||
		return -NF_ACCEPT;
 | 
							return -NF_ACCEPT;
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	/* Check TCP flags. */
 | 
						/* Check TCP flags. */
 | 
				
			||||||
	tcpflags = (tcp_flag_byte(th) & ~(TCPHDR_ECE|TCPHDR_CWR|TCPHDR_PSH));
 | 
						tcpflags = (tcp_flag_byte(th) & ~(TCPHDR_ECE|TCPHDR_CWR|TCPHDR_PSH));
 | 
				
			||||||
	if (!tcp_valid_flags[tcpflags]) {
 | 
						if (!tcp_valid_flags[tcpflags]) {
 | 
				
			||||||
		if (LOG_INVALID(net, IPPROTO_TCP))
 | 
							tcp_error_log(skb, net, pf, "invalid tcp flag combination");
 | 
				
			||||||
			nf_log_packet(net, pf, 0, skb, NULL, NULL, NULL,
 | 
					 | 
				
			||||||
				  "nf_ct_tcp: invalid TCP flag combination ");
 | 
					 | 
				
			||||||
		return -NF_ACCEPT;
 | 
							return -NF_ACCEPT;
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -99,6 +99,12 @@ static bool udp_new(struct nf_conn *ct, const struct sk_buff *skb,
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#ifdef CONFIG_NF_CT_PROTO_UDPLITE
 | 
					#ifdef CONFIG_NF_CT_PROTO_UDPLITE
 | 
				
			||||||
 | 
					static void udplite_error_log(const struct sk_buff *skb, struct net *net,
 | 
				
			||||||
 | 
								      u8 pf, const char *msg)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						nf_l4proto_log_invalid(skb, net, pf, IPPROTO_UDPLITE, "%s", msg);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static int udplite_error(struct net *net, struct nf_conn *tmpl,
 | 
					static int udplite_error(struct net *net, struct nf_conn *tmpl,
 | 
				
			||||||
			 struct sk_buff *skb,
 | 
								 struct sk_buff *skb,
 | 
				
			||||||
			 unsigned int dataoff,
 | 
								 unsigned int dataoff,
 | 
				
			||||||
| 
						 | 
					@ -112,9 +118,7 @@ static int udplite_error(struct net *net, struct nf_conn *tmpl,
 | 
				
			||||||
	/* Header is too small? */
 | 
						/* Header is too small? */
 | 
				
			||||||
	hdr = skb_header_pointer(skb, dataoff, sizeof(_hdr), &_hdr);
 | 
						hdr = skb_header_pointer(skb, dataoff, sizeof(_hdr), &_hdr);
 | 
				
			||||||
	if (!hdr) {
 | 
						if (!hdr) {
 | 
				
			||||||
		if (LOG_INVALID(net, IPPROTO_UDPLITE))
 | 
							udplite_error_log(skb, net, pf, "short packet");
 | 
				
			||||||
			nf_log_packet(net, pf, 0, skb, NULL, NULL, NULL,
 | 
					 | 
				
			||||||
				      "nf_ct_udplite: short packet ");
 | 
					 | 
				
			||||||
		return -NF_ACCEPT;
 | 
							return -NF_ACCEPT;
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -122,17 +126,13 @@ static int udplite_error(struct net *net, struct nf_conn *tmpl,
 | 
				
			||||||
	if (cscov == 0) {
 | 
						if (cscov == 0) {
 | 
				
			||||||
		cscov = udplen;
 | 
							cscov = udplen;
 | 
				
			||||||
	} else if (cscov < sizeof(*hdr) || cscov > udplen) {
 | 
						} else if (cscov < sizeof(*hdr) || cscov > udplen) {
 | 
				
			||||||
		if (LOG_INVALID(net, IPPROTO_UDPLITE))
 | 
							udplite_error_log(skb, net, pf, "invalid checksum coverage");
 | 
				
			||||||
			nf_log_packet(net, pf, 0, skb, NULL, NULL, NULL,
 | 
					 | 
				
			||||||
				      "nf_ct_udplite: invalid checksum coverage ");
 | 
					 | 
				
			||||||
		return -NF_ACCEPT;
 | 
							return -NF_ACCEPT;
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	/* UDPLITE mandates checksums */
 | 
						/* UDPLITE mandates checksums */
 | 
				
			||||||
	if (!hdr->check) {
 | 
						if (!hdr->check) {
 | 
				
			||||||
		if (LOG_INVALID(net, IPPROTO_UDPLITE))
 | 
							udplite_error_log(skb, net, pf, "checksum missing");
 | 
				
			||||||
			nf_log_packet(net, pf, 0, skb, NULL, NULL, NULL,
 | 
					 | 
				
			||||||
				      "nf_ct_udplite: checksum missing ");
 | 
					 | 
				
			||||||
		return -NF_ACCEPT;
 | 
							return -NF_ACCEPT;
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -140,9 +140,7 @@ static int udplite_error(struct net *net, struct nf_conn *tmpl,
 | 
				
			||||||
	if (net->ct.sysctl_checksum && hooknum == NF_INET_PRE_ROUTING &&
 | 
						if (net->ct.sysctl_checksum && hooknum == NF_INET_PRE_ROUTING &&
 | 
				
			||||||
	    nf_checksum_partial(skb, hooknum, dataoff, cscov, IPPROTO_UDP,
 | 
						    nf_checksum_partial(skb, hooknum, dataoff, cscov, IPPROTO_UDP,
 | 
				
			||||||
				pf)) {
 | 
									pf)) {
 | 
				
			||||||
		if (LOG_INVALID(net, IPPROTO_UDPLITE))
 | 
							udplite_error_log(skb, net, pf, "bad checksum");
 | 
				
			||||||
			nf_log_packet(net, pf, 0, skb, NULL, NULL, NULL,
 | 
					 | 
				
			||||||
				      "nf_ct_udplite: bad UDPLite checksum ");
 | 
					 | 
				
			||||||
		return -NF_ACCEPT;
 | 
							return -NF_ACCEPT;
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -150,6 +148,12 @@ static int udplite_error(struct net *net, struct nf_conn *tmpl,
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
#endif
 | 
					#endif
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static void udp_error_log(const struct sk_buff *skb, struct net *net,
 | 
				
			||||||
 | 
								  u8 pf, const char *msg)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						nf_l4proto_log_invalid(skb, net, pf, IPPROTO_UDP, "%s", msg);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static int udp_error(struct net *net, struct nf_conn *tmpl, struct sk_buff *skb,
 | 
					static int udp_error(struct net *net, struct nf_conn *tmpl, struct sk_buff *skb,
 | 
				
			||||||
		     unsigned int dataoff,
 | 
							     unsigned int dataoff,
 | 
				
			||||||
		     u_int8_t pf,
 | 
							     u_int8_t pf,
 | 
				
			||||||
| 
						 | 
					@ -162,17 +166,13 @@ static int udp_error(struct net *net, struct nf_conn *tmpl, struct sk_buff *skb,
 | 
				
			||||||
	/* Header is too small? */
 | 
						/* Header is too small? */
 | 
				
			||||||
	hdr = skb_header_pointer(skb, dataoff, sizeof(_hdr), &_hdr);
 | 
						hdr = skb_header_pointer(skb, dataoff, sizeof(_hdr), &_hdr);
 | 
				
			||||||
	if (hdr == NULL) {
 | 
						if (hdr == NULL) {
 | 
				
			||||||
		if (LOG_INVALID(net, IPPROTO_UDP))
 | 
							udp_error_log(skb, net, pf, "short packet");
 | 
				
			||||||
			nf_log_packet(net, pf, 0, skb, NULL, NULL, NULL,
 | 
					 | 
				
			||||||
				      "nf_ct_udp: short packet ");
 | 
					 | 
				
			||||||
		return -NF_ACCEPT;
 | 
							return -NF_ACCEPT;
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	/* Truncated/malformed packets */
 | 
						/* Truncated/malformed packets */
 | 
				
			||||||
	if (ntohs(hdr->len) > udplen || ntohs(hdr->len) < sizeof(*hdr)) {
 | 
						if (ntohs(hdr->len) > udplen || ntohs(hdr->len) < sizeof(*hdr)) {
 | 
				
			||||||
		if (LOG_INVALID(net, IPPROTO_UDP))
 | 
							udp_error_log(skb, net, pf, "truncated/malformed packet");
 | 
				
			||||||
			nf_log_packet(net, pf, 0, skb, NULL, NULL, NULL,
 | 
					 | 
				
			||||||
				"nf_ct_udp: truncated/malformed packet ");
 | 
					 | 
				
			||||||
		return -NF_ACCEPT;
 | 
							return -NF_ACCEPT;
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -186,9 +186,7 @@ static int udp_error(struct net *net, struct nf_conn *tmpl, struct sk_buff *skb,
 | 
				
			||||||
	 * FIXME: Source route IP option packets --RR */
 | 
						 * FIXME: Source route IP option packets --RR */
 | 
				
			||||||
	if (net->ct.sysctl_checksum && hooknum == NF_INET_PRE_ROUTING &&
 | 
						if (net->ct.sysctl_checksum && hooknum == NF_INET_PRE_ROUTING &&
 | 
				
			||||||
	    nf_checksum(skb, hooknum, dataoff, IPPROTO_UDP, pf)) {
 | 
						    nf_checksum(skb, hooknum, dataoff, IPPROTO_UDP, pf)) {
 | 
				
			||||||
		if (LOG_INVALID(net, IPPROTO_UDP))
 | 
							udp_error_log(skb, net, pf, "bad checksum");
 | 
				
			||||||
			nf_log_packet(net, pf, 0, skb, NULL, NULL, NULL,
 | 
					 | 
				
			||||||
				"nf_ct_udp: bad UDP checksum ");
 | 
					 | 
				
			||||||
		return -NF_ACCEPT;
 | 
							return -NF_ACCEPT;
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
		Loading…
	
		Reference in a new issue