10 #include <linux/types.h>
12 #include <linux/netfilter.h>
13 #include <linux/module.h>
15 #include <linux/icmp.h>
16 #include <linux/sysctl.h>
20 #include <linux/netfilter_ipv4.h>
32 static bool ipv4_pkt_to_tuple(
const struct sk_buff *
skb,
unsigned int nhoff,
42 tuple->
src.u3.ip = ap[0];
43 tuple->
dst.u3.ip = ap[1];
51 tuple->
src.u3.ip = orig->
dst.u3.ip;
52 tuple->
dst.u3.ip = orig->
src.u3.ip;
57 static int ipv4_print_tuple(
struct seq_file *
s,
61 &tuple->
src.u3.ip, &tuple->
dst.u3.ip);
64 static int ipv4_get_l4proto(
const struct sk_buff *skb,
unsigned int nhoff,
65 unsigned int *dataoff,
u_int8_t *protonum)
67 const struct iphdr *iph;
70 iph = skb_header_pointer(skb, nhoff,
sizeof(_iph), &_iph);
79 *dataoff = nhoff + (iph->ihl << 2);
80 *protonum = iph->protocol;
83 if (*dataoff > skb->
len) {
84 pr_debug(
"nf_conntrack_ipv4: bogus IPv4 packet: "
85 "nhoff %u, ihl %u, skblen %u\n",
86 nhoff, iph->ihl << 2, skb->
len);
93 static unsigned int ipv4_helper(
unsigned int hooknum,
106 ct = nf_ct_get(skb, &ctinfo);
110 help = nfct_help(ct);
119 ret = helper->
help(skb, skb_network_offset(skb) + ip_hdrlen(skb),
123 "nf_ct_%s: dropping packet", helper->
name);
128 static unsigned int ipv4_confirm(
unsigned int hooknum,
137 ct = nf_ct_get(skb, &ctinfo);
143 !nf_is_loopback_packet(skb)) {
148 !seq_adjust(skb, ct, ctinfo, ip_hdrlen(skb))) {
155 return nf_conntrack_confirm(skb);
158 static unsigned int ipv4_conntrack_in(
unsigned int hooknum,
167 static unsigned int ipv4_conntrack_local(
unsigned int hooknum,
174 if (skb->
len <
sizeof(
struct iphdr) ||
175 ip_hdrlen(skb) <
sizeof(
struct iphdr))
182 static struct nf_hook_ops ipv4_conntrack_ops[]
__read_mostly = {
184 .hook = ipv4_conntrack_in,
191 .hook = ipv4_conntrack_local,
205 .hook = ipv4_confirm,
219 .hook = ipv4_confirm,
227 #if defined(CONFIG_SYSCTL) && defined(CONFIG_NF_CONNTRACK_PROC_COMPAT)
228 static int log_invalid_proto_min = 0;
229 static int log_invalid_proto_max = 255;
231 static ctl_table ip_ct_sysctl_table[] = {
234 .maxlen =
sizeof(
int),
239 .procname =
"ip_conntrack_count",
240 .maxlen =
sizeof(
int),
245 .procname =
"ip_conntrack_buckets",
246 .maxlen =
sizeof(
unsigned int),
251 .procname =
"ip_conntrack_checksum",
252 .maxlen =
sizeof(
int),
257 .procname =
"ip_conntrack_log_invalid",
258 .maxlen =
sizeof(
unsigned int),
261 .extra1 = &log_invalid_proto_min,
262 .extra2 = &log_invalid_proto_max,
273 getorigdst(
struct sock *
sk,
int optval,
void __user *
user,
int *len)
275 const struct inet_sock *inet = inet_sk(sk);
279 memset(&tuple, 0,
sizeof(tuple));
280 tuple.
src.u3.ip = inet->inet_rcv_saddr;
282 tuple.
dst.u3.ip = inet->inet_daddr;
289 pr_debug(
"SO_ORIGINAL_DST: Not a TCP/SCTP socket\n");
293 if ((
unsigned int) *len <
sizeof(
struct sockaddr_in)) {
294 pr_debug(
"SO_ORIGINAL_DST: len %d not %Zu\n",
302 struct nf_conn *ct = nf_ct_tuplehash_to_ctrack(h);
306 .tuple.dst.u.tcp.port;
309 memset(sin.sin_zero, 0,
sizeof(sin.sin_zero));
311 pr_debug(
"SO_ORIGINAL_DST: %pI4 %u\n",
312 &sin.sin_addr.s_addr,
ntohs(sin.sin_port));
319 pr_debug(
"SO_ORIGINAL_DST: Can't find %pI4/%u-%pI4/%u.\n",
325 #if defined(CONFIG_NF_CT_NETLINK) || defined(CONFIG_NF_CT_NETLINK_MODULE)
327 #include <linux/netfilter/nfnetlink.h>
330 static int ipv4_tuple_to_nlattr(
struct sk_buff *skb,
335 goto nla_put_failure;
347 static int ipv4_nlattr_to_tuple(
struct nlattr *
tb[],
354 t->
dst.u3.ip = nla_get_be32(tb[CTA_IP_V4_DST]);
359 static int ipv4_nlattr_tuple_size(
void)
365 static struct nf_sockopt_ops so_getorigdst = {
373 static int ipv4_init_net(
struct net *
net)
375 #if defined(CONFIG_SYSCTL) && defined(CONFIG_NF_CONNTRACK_PROC_COMPAT)
376 struct nf_ip_net *in = &net->ct.nf_ct_proto;
377 in->ctl_table =
kmemdup(ip_ct_sysctl_table,
378 sizeof(ip_ct_sysctl_table),
384 in->ctl_table[1].data = &net->ct.
count;
385 in->ctl_table[2].data = &net->ct.htable_size;
386 in->ctl_table[3].data = &net->ct.sysctl_checksum;
387 in->ctl_table[4].data = &net->ct.sysctl_log_invalid;
395 .pkt_to_tuple = ipv4_pkt_to_tuple,
396 .invert_tuple = ipv4_invert_tuple,
397 .print_tuple = ipv4_print_tuple,
398 .get_l4proto = ipv4_get_l4proto,
399 #if defined(CONFIG_NF_CT_NETLINK) || defined(CONFIG_NF_CT_NETLINK_MODULE)
400 .tuple_to_nlattr = ipv4_tuple_to_nlattr,
401 .nlattr_tuple_size = ipv4_nlattr_tuple_size,
402 .nlattr_to_tuple = ipv4_nlattr_to_tuple,
403 .nla_policy = ipv4_nla_policy,
405 #if defined(CONFIG_SYSCTL) && defined(CONFIG_NF_CONNTRACK_PROC_COMPAT)
406 .ctl_table_path =
"net/ipv4/netfilter",
408 .init_net = ipv4_init_net,
413 &nf_conntrack_htable_size, 0600);
419 static int ipv4_net_init(
struct net *net)
424 &nf_conntrack_l4proto_tcp4);
426 pr_err(
"nf_conntrack_l4proto_tcp4 :protocol register failed\n");
430 &nf_conntrack_l4proto_udp4);
432 pr_err(
"nf_conntrack_l4proto_udp4 :protocol register failed\n");
436 &nf_conntrack_l4proto_icmp);
438 pr_err(
"nf_conntrack_l4proto_icmp4 :protocol register failed\n");
442 &nf_conntrack_l3proto_ipv4);
444 pr_err(
"nf_conntrack_l3proto_ipv4 :protocol register failed\n");
450 &nf_conntrack_l4proto_icmp);
453 &nf_conntrack_l4proto_udp4);
456 &nf_conntrack_l4proto_tcp4);
461 static void ipv4_net_exit(
struct net *net)
464 &nf_conntrack_l3proto_ipv4);
466 &nf_conntrack_l4proto_icmp);
468 &nf_conntrack_l4proto_udp4);
470 &nf_conntrack_l4proto_tcp4);
474 .init = ipv4_net_init,
475 .exit = ipv4_net_exit,
478 static int __init nf_conntrack_l3proto_ipv4_init(
void)
493 pr_err(
"nf_conntrack_ipv4: can't register pernet ops\n");
494 goto cleanup_sockopt;
500 pr_err(
"nf_conntrack_ipv4: can't register hooks.\n");
503 #if defined(CONFIG_PROC_FS) && defined(CONFIG_NF_CONNTRACK_PROC_COMPAT)
509 #if defined(CONFIG_PROC_FS) && defined(CONFIG_NF_CONNTRACK_PROC_COMPAT)
520 static void __exit nf_conntrack_l3proto_ipv4_fini(
void)
523 #if defined(CONFIG_PROC_FS) && defined(CONFIG_NF_CONNTRACK_PROC_COMPAT)