11 #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
12 #include <linux/kernel.h>
14 #include <linux/netdevice.h>
15 #include <linux/capability.h>
16 #include <linux/if_arp.h>
20 #include <linux/module.h>
26 #include <asm/uaccess.h>
28 #include <linux/netfilter/x_tables.h>
29 #include <linux/netfilter_arp/arp_tables.h>
30 #include "../../netfilter/xt_repldata.h"
39 #ifdef DEBUG_ARP_TABLES
40 #define dprintf(format, args...) printk(format , ## args)
42 #define dprintf(format, args...)
45 #ifdef DEBUG_ARP_TABLES_USER
46 #define duprintf(format, args...) printk(format , ## args)
48 #define duprintf(format, args...)
51 #ifdef CONFIG_NETFILTER_DEBUG
52 #define ARP_NF_ASSERT(x) WARN_ON(!(x))
54 #define ARP_NF_ASSERT(x)
64 const char *hdr_addr,
int len)
72 for (i = 0; i < len; i++)
73 ret |= (hdr_addr[i] ^ ap->
addr[i]) & ap->
mask[
i];
83 static unsigned long ifname_compare(
const char *_a,
const char *_b,
const char *_mask)
85 #ifdef CONFIG_HAVE_EFFICIENT_UNALIGNED_ACCESS
86 unsigned long ret = ifname_compare_aligned(_a, _b, _mask);
88 unsigned long ret = 0;
95 ret |= (a[i] ^ b[i]) & mask[
i];
101 static inline int arp_packet_match(
const struct arphdr *
arphdr,
107 const char *arpptr = (
char *)(arphdr + 1);
108 const char *src_devaddr, *tgt_devaddr;
109 __be32 src_ipaddr, tgt_ipaddr;
112 #define FWINV(bool, invflg) ((bool) ^ !!(arpinfo->invflags & (invflg)))
116 dprintf(
"ARP operation field mismatch.\n");
117 dprintf(
"ar_op: %04x info->arpop: %04x info->arpop_mask: %04x\n",
124 dprintf(
"ARP hardware address format mismatch.\n");
125 dprintf(
"ar_hrd: %04x info->arhrd: %04x info->arhrd_mask: %04x\n",
132 dprintf(
"ARP protocol address format mismatch.\n");
133 dprintf(
"ar_pro: %04x info->arpro: %04x info->arpro_mask: %04x\n",
140 dprintf(
"ARP hardware address length mismatch.\n");
141 dprintf(
"ar_hln: %02x info->arhln: %02x info->arhln_mask: %02x\n",
146 src_devaddr = arpptr;
148 memcpy(&src_ipaddr, arpptr,
sizeof(
u32));
149 arpptr +=
sizeof(
u32);
150 tgt_devaddr = arpptr;
152 memcpy(&tgt_ipaddr, arpptr,
sizeof(
u32));
158 dprintf(
"Source or target device address mismatch.\n");
163 if (
FWINV((src_ipaddr & arpinfo->smsk.s_addr) != arpinfo->src.s_addr,
165 FWINV(((tgt_ipaddr & arpinfo->
tmsk.s_addr) != arpinfo->
tgt.s_addr),
167 dprintf(
"Source or target IP address mismatch.\n");
169 dprintf(
"SRC: %pI4. Mask: %pI4. Target: %pI4.%s\n",
171 &arpinfo->smsk.s_addr,
172 &arpinfo->src.s_addr,
174 dprintf(
"TGT: %pI4 Mask: %pI4 Target: %pI4.%s\n",
176 &arpinfo->
tmsk.s_addr,
177 &arpinfo->
tgt.s_addr,
186 dprintf(
"VIA in mismatch (%s vs %s).%s\n",
195 dprintf(
"VIA out mismatch (%s vs %s).%s\n",
205 static inline int arp_checkentry(
const struct arpt_arp *arp)
208 duprintf(
"Unknown flag bits set: %08X\n",
213 duprintf(
"Unknown invflag bits set: %08X\n",
233 return arpt_get_target((
struct arpt_entry *)e);
255 unsigned int verdict =
NF_DROP;
256 const struct arphdr *arp;
258 const char *indev, *outdev;
264 if (!pskb_may_pull(skb, arp_hdr_len(skb->
dev)))
267 indev = in ? in->
name : nulldevname;
268 outdev = out ? out->
name : nulldevname;
271 addend = xt_write_recseq_begin();
275 e =
get_entry(table_base, private->hook_entry[hook]);
276 back =
get_entry(table_base, private->underflow[hook]);
288 if (!arp_packet_match(arp, skb->
dev, indev, outdev, &e->
arp)) {
289 e = arpt_next_entry(e);
295 t = arpt_get_target_c(e);
298 if (!t->
u.
kernel.target->target) {
305 verdict = (
unsigned int)(-v) - 1;
313 != arpt_next_entry(e)) {
316 next->
comefrom = (
void *)back - table_base;
331 verdict = t->
u.
kernel.target->target(skb, &acpar);
337 e = arpt_next_entry(e);
342 xt_write_recseq_end(addend);
352 static inline bool unconditional(
const struct arpt_arp *arp)
354 static const struct arpt_arp uncond;
356 return memcmp(arp, &uncond,
sizeof(uncond)) == 0;
362 static int mark_source_chains(
const struct xt_table_info *newinfo,
363 unsigned int valid_hooks,
void *entry0)
375 if (!(valid_hooks & (1 << hook)))
383 = (
void *)arpt_get_target_c(e);
386 if (e->
comefrom & (1 << NF_ARP_NUMHOOKS)) {
387 pr_notice(
"arptables: loop hook %u pos %u %08X.\n",
392 |= ((1 <<
hook) | (1 << NF_ARP_NUMHOOKS));
400 unsigned int oldpos,
size;
406 "negative verdict (%i)\n",
431 (entry0 + pos + size);
440 if (newpos > newinfo->
size -
443 "bad verdict (%i)\n",
462 duprintf(
"Finished chain %u\n", hook);
467 static inline int check_entry(
const struct arpt_entry *e,
const char *
name)
471 if (!arp_checkentry(&e->
arp)) {
472 duprintf(
"arp_tables: arp check failed %p %s.\n", e, name);
479 t = arpt_get_target_c(e);
486 static inline int check_target(
struct arpt_entry *e,
const char *name)
501 duprintf(
"arp_tables: check failed for `%s'.\n",
509 find_check_entry(
struct arpt_entry *e,
const char *name,
unsigned int size)
515 ret = check_entry(e, name);
519 t = arpt_get_target(e);
522 if (IS_ERR(target)) {
523 duprintf(
"find_check_entry: `%s' not found\n", t->
u.
user.name);
524 ret = PTR_ERR(target);
529 ret = check_target(e, name);
534 module_put(t->
u.
kernel.target->me);
539 static bool check_underflow(
const struct arpt_entry *e)
542 unsigned int verdict;
544 if (!unconditional(&e->
arp))
546 t = arpt_get_target_c(e);
550 verdict = -verdict - 1;
554 static inline int check_entry_size_and_hooks(
struct arpt_entry *e,
556 const unsigned char *base,
557 const unsigned char *
limit,
558 const unsigned int *hook_entries,
559 const unsigned int *underflows,
560 unsigned int valid_hooks)
564 if ((
unsigned long)e % __alignof__(
struct arpt_entry) != 0 ||
565 (
unsigned char *)e +
sizeof(
struct arpt_entry) >= limit) {
572 duprintf(
"checking: element %p size %u\n",
579 if (!(valid_hooks & (1 << h)))
581 if ((
unsigned char *)e - base == hook_entries[h])
583 if ((
unsigned char *)e - base == underflows[h]) {
584 if (!check_underflow(e)) {
585 pr_err(
"Underflows must be unconditional and "
586 "use the STANDARD target with "
600 static inline void cleanup_entry(
struct arpt_entry *e)
605 t = arpt_get_target(e);
610 par.
target->destroy(&par);
611 module_put(par.
target->me);
617 static int translate_table(
struct xt_table_info *newinfo,
void *entry0,
638 ret = check_entry_size_and_hooks(iter, newinfo, entry0,
646 if (
strcmp(arpt_get_target(iter)->
u.user.name,
650 duprintf(
"translate_table: ARPT_ENTRY_ITERATE gives %d\n", ret);
655 duprintf(
"translate_table: %u not %u entries\n",
666 duprintf(
"Invalid hook entry %u %u\n",
670 if (newinfo->
underflow[i] == 0xFFFFFFFF) {
671 duprintf(
"Invalid underflow %u %u\n",
677 if (!mark_source_chains(newinfo, repl->
valid_hooks, entry0)) {
685 ret = find_check_entry(iter, repl->
name, repl->
size);
725 start = read_seqcount_begin(s);
728 }
while (read_seqcount_retry(s, start));
738 unsigned int countersize;
746 countersize =
sizeof(
struct xt_counters) *
private->number;
747 counters =
vzalloc(countersize);
749 if (counters ==
NULL)
757 static int copy_entries_to_user(
unsigned int total_size,
759 void __user *userptr)
761 unsigned int off,
num;
768 counters = alloc_counters(table);
769 if (IS_ERR(counters))
770 return PTR_ERR(counters);
774 if (
copy_to_user(userptr, loc_cpu_entry, total_size) != 0) {
784 e = (
struct arpt_entry *)(loc_cpu_entry + off);
788 sizeof(counters[num])) != 0) {
793 t = arpt_get_target_c(e);
810 static void compat_standard_from_user(
void *
dst,
const void *
src)
816 memcpy(dst, &v,
sizeof(v));
819 static int compat_standard_to_user(
void __user *dst,
const void *src)
828 static int compat_calc_entry(
const struct arpt_entry *e,
833 unsigned int entry_offset;
837 entry_offset = (
void *)e - base;
839 t = arpt_get_target_c(e);
840 off += xt_compat_target_offset(t->
u.
kernel.target);
841 newinfo->
size -= off;
842 ret = xt_compat_add_offset(
NFPROTO_ARP, entry_offset, off);
857 static int compat_table_info(
const struct xt_table_info *info,
864 if (!newinfo || !info)
873 ret = compat_calc_entry(iter, info, loc_cpu_entry, newinfo);
881 static int get_info(
struct net *
net,
void __user *
user,
882 const int *len,
int compat)
889 duprintf(
"length %u != %Zu\n", *len,
903 "arptable_%s", name);
904 if (t && !IS_ERR(t)) {
911 ret = compat_table_info(
private, &
tmp);
916 memset(&info, 0,
sizeof(info));
922 info.num_entries =
private->
number;
923 info.
size =
private->size;
933 ret = t ? PTR_ERR(t) : -
ENOENT;
941 static int get_entries(
struct net *net,
struct arpt_get_entries __user *uptr,
948 if (*len <
sizeof(
get)) {
949 duprintf(
"get_entries: %u < %Zu\n", *len,
sizeof(
get));
955 duprintf(
"get_entries: %u != %Zu\n", *len,
961 if (t && !IS_ERR(t)) {
964 duprintf(
"t->private->number = %u\n",
966 if (
get.size == private->size)
967 ret = copy_entries_to_user(private->size,
968 t, uptr->entrytable);
970 duprintf(
"get_entries: I've got %u not %u!\n",
971 private->size,
get.size);
977 ret = t ? PTR_ERR(t) : -
ENOENT;
982 static int __do_replace(
struct net *net,
const char *name,
983 unsigned int valid_hooks,
985 unsigned int num_counters,
986 void __user *counters_ptr)
992 void *loc_cpu_old_entry;
1003 "arptable_%s", name);
1004 if (!t || IS_ERR(t)) {
1005 ret = t ? PTR_ERR(t) : -
ENOENT;
1006 goto free_newinfo_counters_untrans;
1011 duprintf(
"Valid hook crap: %08X vs %08X\n",
1022 duprintf(
"do_replace: oldnum=%u, initnum=%u, newnum=%u\n",
1037 cleanup_entry(iter);
1050 free_newinfo_counters_untrans:
1056 static
int do_replace(
struct net *net,
const void __user *user,
1062 void *loc_cpu_entry;
1085 ret = translate_table(newinfo, loc_cpu_entry, &
tmp);
1089 duprintf(
"arp_tables: Translated table\n");
1091 ret = __do_replace(net,
tmp.
name,
tmp.valid_hooks, newinfo,
1092 tmp.num_counters,
tmp.counters);
1094 goto free_newinfo_untrans;
1097 free_newinfo_untrans:
1099 cleanup_entry(iter);
1105 static
int do_add_counters(
struct net *net,
const void __user *user,
1106 unsigned int len,
int compat)
1108 unsigned int i, curcpu;
1111 unsigned int num_counters;
1118 void *loc_cpu_entry;
1120 unsigned int addend;
1121 #ifdef CONFIG_COMPAT
1122 struct compat_xt_counters_info compat_tmp;
1126 size =
sizeof(
struct compat_xt_counters_info);
1137 #ifdef CONFIG_COMPAT
1139 num_counters = compat_tmp.num_counters;
1140 name = compat_tmp.name;
1144 num_counters =
tmp.num_counters;
1148 if (len != size + num_counters *
sizeof(
struct xt_counters))
1161 if (!t || IS_ERR(t)) {
1162 ret = t ? PTR_ERR(t) : -
ENOENT;
1168 if (private->number != num_counters) {
1170 goto unlock_up_free;
1176 loc_cpu_entry =
private->entries[curcpu];
1177 addend = xt_write_recseq_begin();
1182 xt_write_recseq_end(addend);
1193 #ifdef CONFIG_COMPAT
1194 static inline void compat_release_entry(
struct compat_arpt_entry *e)
1198 t = compat_arpt_get_target(e);
1199 module_put(t->
u.
kernel.target->me);
1203 check_compat_entry_size_and_hooks(
struct compat_arpt_entry *e,
1206 const unsigned char *base,
1207 const unsigned char *limit,
1208 const unsigned int *hook_entries,
1209 const unsigned int *underflows,
1214 unsigned int entry_offset;
1217 duprintf(
"check_compat_entry_size_and_hooks %p\n", e);
1218 if ((
unsigned long)e % __alignof__(
struct compat_arpt_entry) != 0 ||
1219 (
unsigned char *)e +
sizeof(
struct compat_arpt_entry) >= limit) {
1220 duprintf(
"Bad offset %p, limit = %p\n", e, limit);
1224 if (e->next_offset <
sizeof(
struct compat_arpt_entry) +
1225 sizeof(
struct compat_xt_entry_target)) {
1226 duprintf(
"checking: element %p size %u\n",
1232 ret = check_entry((
struct arpt_entry *)e, name);
1237 entry_offset = (
void *)e - (
void *)base;
1239 t = compat_arpt_get_target(e);
1241 t->
u.
user.revision);
1242 if (IS_ERR(target)) {
1243 duprintf(
"check_compat_entry_size_and_hooks: `%s' not found\n",
1245 ret = PTR_ERR(target);
1250 off += xt_compat_target_offset(target);
1252 ret = xt_compat_add_offset(
NFPROTO_ARP, entry_offset, off);
1254 goto release_target;
1258 if ((
unsigned char *)e - base == hook_entries[h])
1260 if ((
unsigned char *)e - base == underflows[h])
1265 memset(&e->counters, 0,
sizeof(e->counters));
1270 module_put(t->
u.
kernel.target->me);
1276 compat_copy_entry_from_user(
struct compat_arpt_entry *e,
void **dstptr,
1277 unsigned int *size,
const char *name,
1283 unsigned int origsize;
1296 t = compat_arpt_get_target(e);
1298 xt_compat_target_from_user(t, dstptr, size);
1302 if ((
unsigned char *)de - base < newinfo->
hook_entry[
h])
1304 if ((
unsigned char *)de - base < newinfo->
underflow[
h])
1305 newinfo->
underflow[h] -= origsize - *size;
1310 static int translate_compat_table(
const char *name,
1311 unsigned int valid_hooks,
1314 unsigned int total_size,
1315 unsigned int number,
1316 unsigned int *hook_entries,
1317 unsigned int *underflows)
1321 void *
pos, *entry0, *entry1;
1322 struct compat_arpt_entry *iter0;
1338 duprintf(
"translate_compat_table: size %u\n", info->
size);
1344 ret = check_compat_entry_size_and_hooks(iter0, info, &size,
1346 entry0 + total_size,
1357 duprintf(
"translate_compat_table: %u not %u entries\n",
1365 if (!(valid_hooks & (1 << i)))
1368 duprintf(
"Invalid hook entry %u %u\n",
1369 i, hook_entries[i]);
1373 duprintf(
"Invalid underflow %u %u\n",
1384 newinfo->
number = number;
1393 ret = compat_copy_entry_from_user(iter0, &pos, &size,
1394 name, newinfo, entry1);
1404 if (!mark_source_chains(newinfo, valid_hooks, entry1))
1409 ret = check_target(iter1, name);
1413 if (
strcmp(arpt_get_target(iter1)->
u.user.name,
1430 compat_release_entry(iter0);
1435 cleanup_entry(iter1);
1457 compat_release_entry(iter0);
1466 struct compat_arpt_replace {
1475 struct compat_arpt_entry
entries[0];
1478 static int compat_do_replace(
struct net *net,
void __user *user,
1482 struct compat_arpt_replace
tmp;
1484 void *loc_cpu_entry;
1508 ret = translate_compat_table(
tmp.
name,
tmp.valid_hooks,
1509 &newinfo, &loc_cpu_entry,
tmp.size,
1510 tmp.num_entries,
tmp.hook_entry,
1515 duprintf(
"compat_do_replace: Translated table\n");
1517 ret = __do_replace(net,
tmp.
name,
tmp.valid_hooks, newinfo,
1518 tmp.num_counters, compat_ptr(
tmp.counters));
1520 goto free_newinfo_untrans;
1523 free_newinfo_untrans:
1525 cleanup_entry(iter);
1531 static
int compat_do_arpt_set_ctl(
struct sock *
sk,
int cmd,
void __user *user,
1541 ret = compat_do_replace(sock_net(sk), user, len);
1545 ret = do_add_counters(sock_net(sk), user, len, 1);
1549 duprintf(
"do_arpt_set_ctl: unknown request %i\n", cmd);
1556 static int compat_copy_entry_to_user(
struct arpt_entry *e,
void __user **dstptr,
1562 struct compat_arpt_entry
__user *
ce;
1568 ce = (
struct compat_arpt_entry
__user *)*dstptr;
1571 sizeof(counters[i])) != 0)
1574 *dstptr +=
sizeof(
struct compat_arpt_entry);
1579 t = arpt_get_target(e);
1580 ret = xt_compat_target_to_user(t, dstptr, size);
1584 if (
put_user(target_offset, &ce->target_offset) != 0 ||
1585 put_user(next_offset, &ce->next_offset) != 0)
1590 static int compat_copy_entries_to_user(
unsigned int total_size,
1592 void __user *userptr)
1599 void *loc_cpu_entry;
1603 counters = alloc_counters(table);
1604 if (IS_ERR(counters))
1605 return PTR_ERR(counters);
1612 ret = compat_copy_entry_to_user(iter, &pos,
1613 &size, counters, i++);
1621 struct compat_arpt_get_entries {
1624 struct compat_arpt_entry entrytable[0];
1627 static int compat_get_entries(
struct net *net,
1628 struct compat_arpt_get_entries __user *uptr,
1632 struct compat_arpt_get_entries
get;
1635 if (*len <
sizeof(
get)) {
1636 duprintf(
"compat_get_entries: %u < %zu\n", *len,
sizeof(
get));
1641 if (*len !=
sizeof(
struct compat_arpt_get_entries) +
get.size) {
1642 duprintf(
"compat_get_entries: %u != %zu\n",
1643 *len,
sizeof(
get) +
get.size);
1649 if (t && !IS_ERR(t)) {
1653 duprintf(
"t->private->number = %u\n", private->number);
1654 ret = compat_table_info(
private, &info);
1655 if (!ret &&
get.size == info.
size) {
1656 ret = compat_copy_entries_to_user(private->size,
1657 t, uptr->entrytable);
1659 duprintf(
"compat_get_entries: I've got %u not %u!\n",
1660 private->size,
get.size);
1667 ret = t ? PTR_ERR(t) : -
ENOENT;
1673 static int do_arpt_get_ctl(
struct sock *,
int,
void __user *,
int *);
1675 static int compat_do_arpt_get_ctl(
struct sock *sk,
int cmd,
void __user *user,
1685 ret = get_info(sock_net(sk), user, len, 1);
1688 ret = compat_get_entries(sock_net(sk), user, len);
1691 ret = do_arpt_get_ctl(sk, cmd, user, len);
1697 static int do_arpt_set_ctl(
struct sock *sk,
int cmd,
void __user *user,
unsigned int len)
1706 ret = do_replace(sock_net(sk), user, len);
1710 ret = do_add_counters(sock_net(sk), user, len, 0);
1714 duprintf(
"do_arpt_set_ctl: unknown request %i\n", cmd);
1721 static int do_arpt_get_ctl(
struct sock *sk,
int cmd,
void __user *user,
int *len)
1730 ret = get_info(sock_net(sk), user, len, 0);
1734 ret = get_entries(sock_net(sk), user, len);
1740 if (*len !=
sizeof(
rev)) {
1748 rev.name[
sizeof(
rev.name)-1] = 0;
1751 rev.revision, 1, &ret),
1752 "arpt_%s",
rev.name);
1757 duprintf(
"do_arpt_get_ctl: unknown request %i\n", cmd);
1771 void *loc_cpu_entry;
1784 ret = translate_table(newinfo, loc_cpu_entry, repl);
1785 duprintf(
"arpt_register_table: translate table gives %d\n", ret);
1790 if (IS_ERR(new_table)) {
1791 ret = PTR_ERR(new_table);
1799 return ERR_PTR(ret);
1805 void *loc_cpu_entry;
1806 struct module *table_owner = table->
me;
1814 cleanup_entry(iter);
1815 if (private->number > private->initial_entries)
1816 module_put(table_owner);
1824 .targetsize =
sizeof(
int),
1826 #ifdef CONFIG_COMPAT
1828 .compat_from_user = compat_standard_from_user,
1829 .compat_to_user = compat_standard_to_user,
1840 static struct nf_sockopt_ops arpt_sockopts = {
1844 .set = do_arpt_set_ctl,
1845 #ifdef CONFIG_COMPAT
1846 .compat_set = compat_do_arpt_set_ctl,
1850 .get = do_arpt_get_ctl,
1851 #ifdef CONFIG_COMPAT
1852 .compat_get = compat_do_arpt_get_ctl,
1857 static int __net_init arp_tables_net_init(
struct net *net)
1862 static void __net_exit arp_tables_net_exit(
struct net *net)
1868 .init = arp_tables_net_init,
1869 .exit = arp_tables_net_exit,
1872 static int __init arp_tables_init(
void)
1901 static void __exit arp_tables_fini(
void)