15 #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
18 #include <linux/ipv6.h>
19 #include <linux/module.h>
23 #include <linux/string.h>
24 #include <linux/ctype.h>
25 #include <linux/list.h>
26 #include <linux/random.h>
28 #include <linux/bitops.h>
31 #include <linux/slab.h>
35 #include <linux/netfilter/x_tables.h>
45 static unsigned int ip_list_tot = 100;
46 static unsigned int ip_pkt_list_tot = 20;
47 static unsigned int ip_list_hash_size = 0;
48 static unsigned int ip_list_perms = 0644;
49 static unsigned int ip_list_uid = 0;
50 static unsigned int ip_list_gid = 0;
58 MODULE_PARM_DESC(ip_pkt_list_tot,
"number of packets per IP address to remember (max. 255)");
59 MODULE_PARM_DESC(ip_list_hash_size,
"size of hash table used to look up IPs");
60 MODULE_PARM_DESC(ip_list_perms,
"permissions on /proc/net/xt_recent/* files");
61 MODULE_PARM_DESC(ip_list_uid,
"default owner of /proc/net/xt_recent/* files");
62 MODULE_PARM_DESC(ip_list_gid,
"default owning group of /proc/net/xt_recent/* files");
92 static int recent_net_id;
101 #ifdef CONFIG_PROC_FS
108 static inline unsigned int recent_entry_hash4(
const union nf_inet_addr *
addr)
111 (ip_list_hash_size - 1);
114 static inline unsigned int recent_entry_hash6(
const union nf_inet_addr *addr)
117 (ip_list_hash_size - 1);
129 h = recent_entry_hash4(addrp);
131 h = recent_entry_hash6(addrp);
134 if (e->family == family &&
136 (ttl == e->ttl || ttl == 0 || e->ttl == 0))
165 recent_entry_remove(t, e);
174 if (t->
entries >= ip_list_tot) {
176 recent_entry_remove(t, e);
178 e =
kmalloc(
sizeof(*e) +
sizeof(e->
stamps[0]) * ip_pkt_list_tot,
199 e->
index %= ip_pkt_list_tot;
222 for (i = 0; i < ip_list_hash_size; i++)
224 recent_entry_remove(t, e);
231 struct recent_net *recent_net = recent_pernet(net);
240 const struct iphdr *iph = ip_hdr(skb);
249 const struct ipv6hdr *iph = ipv6_hdr(skb);
260 if (par->
out != NULL && skb->
sk == NULL)
263 spin_lock_bh(&recent_lock);
264 t = recent_table_lookup(recent_net, info->
name);
266 nf_inet_addr_mask(&addr, &addr_mask, &t->
mask);
268 e = recent_entry_lookup(t, &addr_mask, par->
family,
273 e = recent_entry_init(t, &addr_mask, par->
family, ttl);
283 recent_entry_remove(t, e);
287 unsigned int i, hits = 0;
289 for (i = 0; i < e->
nstamps; i++) {
300 recent_entry_reap(t, time);
305 recent_entry_update(t, e);
309 spin_unlock_bh(&recent_lock);
316 struct recent_net *recent_net = recent_pernet(par->
net);
318 #ifdef CONFIG_PROC_FS
328 hash_rnd_inited =
true;
331 pr_info(
"Unsupported user space flags (%08x)\n",
346 pr_info(
"hitcount (%u) is larger than "
347 "packets to be remembered (%u)\n",
351 if (info->
name[0] ==
'\0' ||
356 t = recent_table_lookup(recent_net, info->
name);
363 t = kzalloc(
sizeof(*t) +
sizeof(t->
iphash[0]) * ip_list_hash_size,
374 for (i = 0; i < ip_list_hash_size; i++)
375 INIT_LIST_HEAD(&t->
iphash[i]);
376 #ifdef CONFIG_PROC_FS
379 if (!uid_valid(uid) || !gid_valid(gid)) {
394 spin_lock_bh(&recent_lock);
396 spin_unlock_bh(&recent_lock);
405 const struct xt_recent_mtinfo_v0 *info_v0 = par->
matchinfo;
411 memset(info_v1.mask.all, 0xFF,
sizeof(info_v1.mask.all));
413 return recent_mt_check(par, &info_v1);
418 return recent_mt_check(par, par->
matchinfo);
423 struct recent_net *recent_net = recent_pernet(par->
net);
428 t = recent_table_lookup(recent_net, info->
name);
430 spin_lock_bh(&recent_lock);
432 spin_unlock_bh(&recent_lock);
433 #ifdef CONFIG_PROC_FS
436 recent_table_flush(t);
442 #ifdef CONFIG_PROC_FS
443 struct recent_iter_state {
448 static void *recent_seq_start(
struct seq_file *seq, loff_t *
pos)
451 struct recent_iter_state *
st =
seq->private;
456 spin_lock_bh(&recent_lock);
458 for (st->bucket = 0; st->bucket < ip_list_hash_size; st->bucket++)
467 struct recent_iter_state *st = seq->private;
472 while (head == &t->
iphash[st->bucket]) {
473 if (++st->bucket >= ip_list_hash_size)
475 head = t->
iphash[st->bucket].next;
481 static void recent_seq_stop(
struct seq_file *
s,
void *v)
484 spin_unlock_bh(&recent_lock);
487 static int recent_seq_show(
struct seq_file *seq,
void *v)
492 i = (e->
index - 1) % ip_pkt_list_tot;
494 seq_printf(seq,
"src=%pI4 ttl: %u last_seen: %lu oldest_pkt: %u",
497 seq_printf(seq,
"src=%pI6 ttl: %u last_seen: %lu oldest_pkt: %u",
499 for (i = 0; i < e->
nstamps; i++)
506 .
start = recent_seq_start,
507 .next = recent_seq_next,
508 .stop = recent_seq_stop,
509 .show = recent_seq_show,
515 struct recent_iter_state *
st;
521 st->table = pde->
data;
526 recent_mt_proc_write(
struct file *file,
const char __user *
input,
527 size_t size, loff_t *loff)
532 char buf[
sizeof(
"+b335:1d35:1e55:dead:c0de:1715:5afe:c0de")];
540 if (size >
sizeof(
buf))
550 spin_lock_bh(&recent_lock);
551 recent_table_flush(t);
552 spin_unlock_bh(&recent_lock);
561 pr_info(
"Need \"+ip\", \"-ip\" or \"/\"\n");
567 if (
strnchr(c, size,
':') != NULL) {
569 succ =
in6_pton(c, size, (
void *)&addr,
'\n', NULL);
572 succ =
in4_pton(c, size, (
void *)&addr,
'\n', NULL);
576 pr_info(
"illegal address written to procfs\n");
580 spin_lock_bh(&recent_lock);
581 e = recent_entry_lookup(t, &addr, family, 0);
584 recent_entry_init(t, &addr, family, 0);
587 recent_entry_update(t, e);
589 recent_entry_remove(t, e);
591 spin_unlock_bh(&recent_lock);
598 .
open = recent_seq_open,
600 .write = recent_mt_proc_write,
606 static int __net_init recent_proc_net_init(
struct net *net)
608 struct recent_net *recent_net = recent_pernet(net);
611 if (!recent_net->xt_recent)
616 static void __net_exit recent_proc_net_exit(
struct net *net)
621 static inline int recent_proc_net_init(
struct net *net)
626 static inline void recent_proc_net_exit(
struct net *net)
631 static int __net_init recent_net_init(
struct net *net)
633 struct recent_net *recent_net = recent_pernet(net);
635 INIT_LIST_HEAD(&recent_net->
tables);
636 return recent_proc_net_init(net);
639 static void __net_exit recent_net_exit(
struct net *net)
641 struct recent_net *recent_net = recent_pernet(net);
644 recent_proc_net_exit(net);
648 .init = recent_net_init,
649 .exit = recent_net_exit,
650 .id = &recent_net_id,
651 .size =
sizeof(
struct recent_net),
661 .checkentry = recent_mt_check_v0,
662 .destroy = recent_mt_destroy,
671 .checkentry = recent_mt_check_v0,
672 .destroy = recent_mt_destroy,
681 .checkentry = recent_mt_check_v1,
682 .destroy = recent_mt_destroy,
691 .checkentry = recent_mt_check_v1,
692 .destroy = recent_mt_destroy,
697 static int __init recent_mt_init(
void)
701 if (!ip_list_tot || !ip_pkt_list_tot || ip_pkt_list_tot > 255)
703 ip_list_hash_size = 1 << fls(ip_list_tot);
714 static void __exit recent_mt_exit(
void)