11 #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
12 #include <linux/capability.h>
17 #include <linux/netdevice.h>
18 #include <linux/module.h>
19 #include <linux/poison.h>
20 #include <linux/icmpv6.h>
23 #include <asm/uaccess.h>
29 #include <linux/netfilter_ipv6/ip6_tables.h>
30 #include <linux/netfilter/x_tables.h>
32 #include "../../netfilter/xt_repldata.h"
42 #ifdef DEBUG_IP_FIREWALL
43 #define dprintf(format, args...) pr_info(format , ## args)
45 #define dprintf(format, args...)
48 #ifdef DEBUG_IP_FIREWALL_USER
49 #define duprintf(format, args...) pr_info(format , ## args)
51 #define duprintf(format, args...)
54 #ifdef CONFIG_NETFILTER_DEBUG
55 #define IP_NF_ASSERT(x) WARN_ON(!(x))
57 #define IP_NF_ASSERT(x)
88 unsigned int *protoff,
89 int *fragoff,
bool *hotdrop)
92 const struct ipv6hdr *ipv6 = ipv6_hdr(skb);
94 #define FWINV(bool, invflg) ((bool) ^ !!(ip6info->invflags & (invflg)))
96 if (
FWINV(ipv6_masked_addr_cmp(&ipv6->
saddr, &ip6info->smsk,
100 dprintf(
"Source or dest mismatch.\n");
114 dprintf(
"VIA in mismatch (%s vs %s).%s\n",
123 dprintf(
"VIA out mismatch (%s vs %s).%s\n",
134 unsigned short _frag_off;
142 *fragoff = _frag_off;
144 dprintf(
"Packet protocol %hi ?= %s%hi.\n",
149 if (ip6info->
proto == protohdr) {
157 if ((ip6info->
proto != 0) &&
166 ip6_checkentry(
const struct ip6t_ip6 *ipv6)
169 duprintf(
"Unknown flag bits set: %08X\n",
174 duprintf(
"Unknown invflag bits set: %08X\n",
197 static inline bool unconditional(
const struct ip6t_ip6 *ipv6)
199 static const struct ip6t_ip6 uncond;
201 return memcmp(ipv6, &uncond,
sizeof(uncond)) == 0;
207 return ip6t_get_target((
struct ip6t_entry *)e);
210 #if defined(CONFIG_NETFILTER_XT_TARGET_TRACE) || \
211 defined(CONFIG_NETFILTER_XT_TARGET_TRACE_MODULE)
213 static const char *
const hooknames[] = {
221 enum nf_ip_trace_comments {
222 NF_IP6_TRACE_COMMENT_RULE,
223 NF_IP6_TRACE_COMMENT_RETURN,
224 NF_IP6_TRACE_COMMENT_POLICY,
227 static const char *
const comments[] = {
228 [NF_IP6_TRACE_COMMENT_RULE] =
"rule",
229 [NF_IP6_TRACE_COMMENT_RETURN] =
"return",
230 [NF_IP6_TRACE_COMMENT_POLICY] =
"policy",
246 const char *hookname,
const char **chainname,
247 const char **comment,
unsigned int *rulenum)
253 *chainname = t->
target.data;
262 unconditional(&s->
ipv6)) {
264 *comment = *chainname == hookname
265 ? comments[NF_IP6_TRACE_COMMENT_POLICY]
266 : comments[NF_IP6_TRACE_COMMENT_RETURN];
275 static void trace_packet(
const struct sk_buff *skb,
279 const char *tablename,
283 const void *table_base;
285 const char *hookname, *chainname, *comment;
287 unsigned int rulenum = 0;
290 root =
get_entry(table_base, private->hook_entry[hook]);
292 hookname = chainname = hooknames[
hook];
293 comment = comments[NF_IP6_TRACE_COMMENT_RULE];
296 if (get_chainname_rulenum(iter, e, hookname,
297 &chainname, &comment, &rulenum) != 0)
302 tablename, chainname, comment, rulenum);
322 unsigned int verdict =
NF_DROP;
323 const char *indev, *outdev;
324 const void *table_base;
326 unsigned int *stackptr, origptr,
cpu;
332 indev = in ? in->
name : nulldevname;
333 outdev = out ? out->
name : nulldevname;
349 addend = xt_write_recseq_begin();
352 table_base =
private->entries[
cpu];
353 jumpstack = (
struct ip6t_entry **)private->jumpstack[cpu];
357 e =
get_entry(table_base, private->hook_entry[hook]);
365 if (!ip6_packet_match(skb, indev, outdev, &e->
ipv6,
368 e = ip6t_next_entry(e);
375 if (!acpar.
match->match(skb, &acpar))
381 t = ip6t_get_target_c(e);
384 #if defined(CONFIG_NETFILTER_XT_TARGET_TRACE) || \
385 defined(CONFIG_NETFILTER_XT_TARGET_TRACE_MODULE)
388 trace_packet(skb, hook, in, out,
389 table->
name,
private, e);
392 if (!t->
u.
kernel.target->target) {
399 verdict = (
unsigned int)(-v) - 1;
402 if (*stackptr <= origptr)
404 private->underflow[hook]);
406 e = ip6t_next_entry(jumpstack[--*stackptr]);
409 if (table_base + v != ip6t_next_entry(e) &&
411 if (*stackptr >= private->stacksize) {
415 jumpstack[(*stackptr)++] =
e;
425 verdict = t->
u.
kernel.target->target(skb, &acpar);
427 e = ip6t_next_entry(e);
435 xt_write_recseq_end(addend);
438 #ifdef DEBUG_ALLOW_ALL
451 unsigned int valid_hooks,
void *entry0)
461 if (!(valid_hooks & (1 << hook)))
469 = (
void *)ip6t_get_target_c(e);
472 if (e->
comefrom & (1 << NF_INET_NUMHOOKS)) {
473 pr_err(
"iptables: loop hook %u pos %u %08X.\n",
484 unconditional(&e->
ipv6)) || visited) {
485 unsigned int oldpos,
size;
491 "negative verdict (%i)\n",
500 #ifdef DEBUG_IP_FIREWALL_USER
502 & (1 << NF_INET_NUMHOOKS)) {
524 (entry0 + pos + size);
533 if (newpos > newinfo->
size -
536 "bad verdict (%i)\n",
554 duprintf(
"Finished chain %u\n", hook);
568 par.
match->destroy(&par);
569 module_put(par.
match->me);
577 if (!ip6_checkentry(&e->
ipv6)) {
578 duprintf(
"ip_tables: ip check failed %p %s.\n", e, name);
586 t = ip6t_get_target_c(e);
604 duprintf(
"ip_tables: check failed for `%s'.\n",
620 duprintf(
"find_check_match: `%s' not found\n", m->
u.
user.name);
621 return PTR_ERR(match);
631 module_put(m->
u.
kernel.match->me);
635 static int check_target(
struct ip6t_entry *e,
struct net *net,
const char *name)
649 t = ip6t_get_target(e);
653 duprintf(
"ip_tables: check failed for `%s'.\n",
661 find_check_entry(
struct ip6t_entry *e,
struct net *net,
const char *name,
671 ret = check_entry(e, name);
678 mtpar.entryinfo = &e->
ipv6;
682 ret = find_check_match(ematch, &mtpar);
684 goto cleanup_matches;
688 t = ip6t_get_target(e);
691 if (IS_ERR(target)) {
692 duprintf(
"find_check_entry: `%s' not found\n", t->
u.
user.name);
693 ret = PTR_ERR(target);
694 goto cleanup_matches;
698 ret = check_target(e, net, name);
703 module_put(t->
u.
kernel.target->me);
708 cleanup_match(ematch, net);
713 static bool check_underflow(
const struct ip6t_entry *e)
716 unsigned int verdict;
718 if (!unconditional(&e->
ipv6))
720 t = ip6t_get_target_c(e);
724 verdict = -verdict - 1;
729 check_entry_size_and_hooks(
struct ip6t_entry *e,
731 const unsigned char *base,
732 const unsigned char *
limit,
733 const unsigned int *hook_entries,
734 const unsigned int *underflows,
735 unsigned int valid_hooks)
739 if ((
unsigned long)e % __alignof__(
struct ip6t_entry) != 0 ||
740 (
unsigned char *)e +
sizeof(
struct ip6t_entry) >= limit) {
747 duprintf(
"checking: element %p size %u\n",
754 if (!(valid_hooks & (1 << h)))
756 if ((
unsigned char *)e - base == hook_entries[h])
758 if ((
unsigned char *)e - base == underflows[h]) {
759 if (!check_underflow(e)) {
760 pr_err(
"Underflows must be unconditional and "
761 "use the STANDARD target with "
775 static void cleanup_entry(
struct ip6t_entry *e,
struct net *net)
783 cleanup_match(ematch, net);
784 t = ip6t_get_target(e);
787 par.target = t->u.
kernel.target;
788 par.targinfo = t->
data;
792 module_put(par.target->me);
805 newinfo->size = repl->size;
806 newinfo->number = repl->num_entries;
810 newinfo->hook_entry[
i] = 0xFFFFFFFF;
811 newinfo->underflow[
i] = 0xFFFFFFFF;
814 duprintf(
"translate_table: size %u\n", newinfo->size);
818 ret = check_entry_size_and_hooks(iter, newinfo, entry0,
826 if (
strcmp(ip6t_get_target(iter)->u.user.name,
828 ++newinfo->stacksize;
831 if (i != repl->num_entries) {
832 duprintf(
"translate_table: %u not %u entries\n",
833 i, repl->num_entries);
840 if (!(repl->valid_hooks & (1 << i)))
842 if (newinfo->hook_entry[i] == 0xFFFFFFFF) {
843 duprintf(
"Invalid hook entry %u %u\n",
844 i, repl->hook_entry[i]);
847 if (newinfo->underflow[i] == 0xFFFFFFFF) {
848 duprintf(
"Invalid underflow %u %u\n",
849 i, repl->underflow[i]);
854 if (!mark_source_chains(newinfo, repl->valid_hooks, entry0))
860 ret = find_check_entry(iter, net, repl->name, repl->size);
870 cleanup_entry(iter, net);
877 if (newinfo->entries[i] && newinfo->entries[i] != entry0)
878 memcpy(newinfo->entries[i], entry0, newinfo->size);
901 start = read_seqcount_begin(s);
904 }
while (read_seqcount_retry(s, start));
914 unsigned int countersize;
921 countersize =
sizeof(
struct xt_counters) *
private->number;
922 counters =
vzalloc(countersize);
924 if (counters ==
NULL)
935 void __user *userptr)
937 unsigned int off,
num;
942 const void *loc_cpu_entry;
944 counters = alloc_counters(table);
945 if (IS_ERR(counters))
946 return PTR_ERR(counters);
953 if (
copy_to_user(userptr, loc_cpu_entry, total_size) != 0) {
965 e = (
struct ip6t_entry *)(loc_cpu_entry + off);
969 sizeof(counters[num])) != 0) {
990 t = ip6t_get_target_c(e);
1006 #ifdef CONFIG_COMPAT
1007 static void compat_standard_from_user(
void *
dst,
const void *
src)
1012 v += xt_compat_calc_jump(AF_INET6, v);
1013 memcpy(dst, &v,
sizeof(v));
1016 static int compat_standard_to_user(
void __user *dst,
const void *src)
1021 cv -= xt_compat_calc_jump(AF_INET6, cv);
1025 static int compat_calc_entry(
const struct ip6t_entry *e,
1031 unsigned int entry_offset;
1035 entry_offset = (
void *)e - base;
1037 off += xt_compat_match_offset(ematch->u.kernel.match);
1038 t = ip6t_get_target_c(e);
1039 off += xt_compat_target_offset(t->u.kernel.target);
1040 newinfo->size -= off;
1041 ret = xt_compat_add_offset(AF_INET6, entry_offset, off);
1045 for (i = 0; i < NF_INET_NUMHOOKS; i++) {
1056 static int compat_table_info(
const struct xt_table_info *info,
1060 void *loc_cpu_entry;
1063 if (!newinfo || !info)
1070 xt_compat_init_offsets(AF_INET6, info->
number);
1072 ret = compat_calc_entry(iter, info, loc_cpu_entry, newinfo);
1080 static int get_info(
struct net *net,
void __user *
user,
1081 const int *len,
int compat)
1088 duprintf(
"length %u != %zu\n", *len,
1097 #ifdef CONFIG_COMPAT
1099 xt_compat_lock(AF_INET6);
1102 "ip6table_%s", name);
1103 if (t && !IS_ERR(t)) {
1106 #ifdef CONFIG_COMPAT
1110 ret = compat_table_info(
private, &
tmp);
1111 xt_compat_flush_offsets(AF_INET6);
1115 memset(&info, 0,
sizeof(info));
1121 info.num_entries =
private->
number;
1122 info.
size =
private->size;
1133 ret = t ? PTR_ERR(t) : -
ENOENT;
1134 #ifdef CONFIG_COMPAT
1136 xt_compat_unlock(AF_INET6);
1149 if (*len <
sizeof(
get)) {
1150 duprintf(
"get_entries: %u < %zu\n", *len,
sizeof(
get));
1156 duprintf(
"get_entries: %u != %zu\n",
1157 *len,
sizeof(
get) +
get.size);
1162 if (t && !IS_ERR(t)) {
1164 duprintf(
"t->private->number = %u\n", private->number);
1165 if (
get.size == private->size)
1166 ret = copy_entries_to_user(private->size,
1167 t, uptr->entrytable);
1169 duprintf(
"get_entries: I've got %u not %u!\n",
1170 private->size,
get.size);
1176 ret = t ? PTR_ERR(t) : -
ENOENT;
1182 __do_replace(
struct net *net,
const char *name,
unsigned int valid_hooks,
1184 void __user *counters_ptr)
1190 const void *loc_cpu_old_entry;
1201 "ip6table_%s", name);
1202 if (!t || IS_ERR(t)) {
1203 ret = t ? PTR_ERR(t) : -
ENOENT;
1204 goto free_newinfo_counters_untrans;
1209 duprintf(
"Valid hook crap: %08X vs %08X\n",
1220 duprintf(
"do_replace: oldnum=%u, initnum=%u, newnum=%u\n",
1235 cleanup_entry(iter, net);
1248 free_newinfo_counters_untrans:
1255 do_replace(
struct net *net,
const void __user *user,
unsigned int len)
1260 void *loc_cpu_entry;
1283 ret = translate_table(net, newinfo, loc_cpu_entry, &
tmp);
1287 duprintf(
"ip_tables: Translated table\n");
1289 ret = __do_replace(net,
tmp.
name,
tmp.valid_hooks, newinfo,
1290 tmp.num_counters,
tmp.counters);
1292 goto free_newinfo_untrans;
1295 free_newinfo_untrans:
1297 cleanup_entry(iter, net);
1304 do_add_counters(
struct net *net,
const void __user *user,
unsigned int len,
1307 unsigned int i, curcpu;
1310 unsigned int num_counters;
1317 const void *loc_cpu_entry;
1319 unsigned int addend;
1320 #ifdef CONFIG_COMPAT
1321 struct compat_xt_counters_info compat_tmp;
1325 size =
sizeof(
struct compat_xt_counters_info);
1336 #ifdef CONFIG_COMPAT
1338 num_counters = compat_tmp.num_counters;
1339 name = compat_tmp.name;
1343 num_counters =
tmp.num_counters;
1347 if (len != size + num_counters *
sizeof(
struct xt_counters))
1360 if (!t || IS_ERR(t)) {
1361 ret = t ? PTR_ERR(t) : -
ENOENT;
1368 if (private->number != num_counters) {
1370 goto unlock_up_free;
1376 addend = xt_write_recseq_begin();
1377 loc_cpu_entry =
private->entries[curcpu];
1382 xt_write_recseq_end(addend);
1394 #ifdef CONFIG_COMPAT
1395 struct compat_ip6t_replace {
1404 struct compat_ip6t_entry
entries[0];
1408 compat_copy_entry_to_user(
struct ip6t_entry *e,
void __user **dstptr,
1413 struct compat_ip6t_entry
__user *
ce;
1420 ce = (
struct compat_ip6t_entry
__user *)*dstptr;
1423 sizeof(counters[i])) != 0)
1426 *dstptr +=
sizeof(
struct compat_ip6t_entry);
1430 ret = xt_compat_match_to_user(ematch, dstptr, size);
1435 t = ip6t_get_target(e);
1436 ret = xt_compat_target_to_user(t, dstptr, size);
1440 if (
put_user(target_offset, &ce->target_offset) != 0 ||
1441 put_user(next_offset, &ce->next_offset) != 0)
1450 unsigned int hookmask,
1456 m->
u.
user.revision);
1457 if (IS_ERR(match)) {
1458 duprintf(
"compat_check_calc_match: `%s' not found\n",
1460 return PTR_ERR(match);
1463 *size += xt_compat_match_offset(match);
1467 static void compat_release_entry(
struct compat_ip6t_entry *e)
1474 module_put(ematch->u.
kernel.match->me);
1475 t = compat_ip6t_get_target(e);
1476 module_put(t->u.
kernel.target->me);
1480 check_compat_entry_size_and_hooks(
struct compat_ip6t_entry *e,
1483 const unsigned char *base,
1484 const unsigned char *limit,
1485 const unsigned int *hook_entries,
1486 const unsigned int *underflows,
1492 unsigned int entry_offset;
1496 duprintf(
"check_compat_entry_size_and_hooks %p\n", e);
1497 if ((
unsigned long)e % __alignof__(
struct compat_ip6t_entry) != 0 ||
1498 (
unsigned char *)e +
sizeof(
struct compat_ip6t_entry) >= limit) {
1499 duprintf(
"Bad offset %p, limit = %p\n", e, limit);
1503 if (e->next_offset <
sizeof(
struct compat_ip6t_entry) +
1504 sizeof(
struct compat_xt_entry_target)) {
1505 duprintf(
"checking: element %p size %u\n",
1511 ret = check_entry((
struct ip6t_entry *)e, name);
1516 entry_offset = (
void *)e - (
void *)base;
1519 ret = compat_find_calc_match(ematch, name,
1520 &e->ipv6, e->comefrom, &off);
1522 goto release_matches;
1526 t = compat_ip6t_get_target(e);
1528 t->
u.
user.revision);
1529 if (IS_ERR(target)) {
1530 duprintf(
"check_compat_entry_size_and_hooks: `%s' not found\n",
1532 ret = PTR_ERR(target);
1533 goto release_matches;
1537 off += xt_compat_target_offset(target);
1539 ret = xt_compat_add_offset(AF_INET6, entry_offset, off);
1545 if ((
unsigned char *)e - base == hook_entries[h])
1546 newinfo->hook_entry[
h] = hook_entries[
h];
1547 if ((
unsigned char *)e - base == underflows[h])
1548 newinfo->underflow[
h] = underflows[
h];
1552 memset(&e->counters, 0,
sizeof(e->counters));
1557 module_put(t->
u.
kernel.target->me);
1562 module_put(ematch->
u.
kernel.match->me);
1568 compat_copy_entry_from_user(
struct compat_ip6t_entry *e,
void **dstptr,
1569 unsigned int *size,
const char *name,
1574 unsigned int origsize;
1588 ret = xt_compat_match_from_user(ematch, dstptr, size);
1593 t = compat_ip6t_get_target(e);
1594 xt_compat_target_from_user(t, dstptr, size);
1598 if ((
unsigned char *)de - base < newinfo->
hook_entry[
h])
1600 if ((
unsigned char *)de - base < newinfo->
underflow[
h])
1601 newinfo->
underflow[h] -= origsize - *size;
1606 static int compat_check_entry(
struct ip6t_entry *e,
struct net *net,
1617 mtpar.entryinfo = &e->
ipv6;
1623 goto cleanup_matches;
1627 ret = check_target(e, net, name);
1629 goto cleanup_matches;
1636 cleanup_match(ematch, net);
1642 translate_compat_table(
struct net *net,
1644 unsigned int valid_hooks,
1647 unsigned int total_size,
1648 unsigned int number,
1649 unsigned int *hook_entries,
1650 unsigned int *underflows)
1654 void *
pos, *entry0, *entry1;
1655 struct compat_ip6t_entry *iter0;
1671 duprintf(
"translate_compat_table: size %u\n", info->
size);
1673 xt_compat_lock(AF_INET6);
1674 xt_compat_init_offsets(AF_INET6, number);
1677 ret = check_compat_entry_size_and_hooks(iter0, info, &size,
1679 entry0 + total_size,
1690 duprintf(
"translate_compat_table: %u not %u entries\n",
1698 if (!(valid_hooks & (1 << i)))
1701 duprintf(
"Invalid hook entry %u %u\n",
1702 i, hook_entries[i]);
1706 duprintf(
"Invalid underflow %u %u\n",
1717 newinfo->
number = number;
1726 ret = compat_copy_entry_from_user(iter0, &pos, &size,
1727 name, newinfo, entry1);
1731 xt_compat_flush_offsets(AF_INET6);
1732 xt_compat_unlock(AF_INET6);
1737 if (!mark_source_chains(newinfo, valid_hooks, entry1))
1742 ret = compat_check_entry(iter1, net, name);
1746 if (
strcmp(ip6t_get_target(iter1)->u.user.name,
1763 compat_release_entry(iter0);
1768 cleanup_entry(iter1, net);
1790 compat_release_entry(iter0);
1794 xt_compat_flush_offsets(AF_INET6);
1795 xt_compat_unlock(AF_INET6);
1800 compat_do_replace(
struct net *net,
void __user *user,
unsigned int len)
1803 struct compat_ip6t_replace
tmp;
1805 void *loc_cpu_entry;
1830 ret = translate_compat_table(net,
tmp.
name,
tmp.valid_hooks,
1831 &newinfo, &loc_cpu_entry,
tmp.size,
1832 tmp.num_entries,
tmp.hook_entry,
1837 duprintf(
"compat_do_replace: Translated table\n");
1839 ret = __do_replace(net,
tmp.
name,
tmp.valid_hooks, newinfo,
1840 tmp.num_counters, compat_ptr(
tmp.counters));
1842 goto free_newinfo_untrans;
1845 free_newinfo_untrans:
1847 cleanup_entry(iter, net);
1864 ret = compat_do_replace(sock_net(sk), user, len);
1868 ret = do_add_counters(sock_net(sk), user, len, 1);
1872 duprintf(
"do_ip6t_set_ctl: unknown request %i\n", cmd);
1879 struct compat_ip6t_get_entries {
1882 struct compat_ip6t_entry entrytable[0];
1886 compat_copy_entries_to_user(
unsigned int total_size,
struct xt_table *table,
1887 void __user *userptr)
1894 const void *loc_cpu_entry;
1898 counters = alloc_counters(table);
1899 if (IS_ERR(counters))
1900 return PTR_ERR(counters);
1910 ret = compat_copy_entry_to_user(iter, &pos,
1911 &size, counters, i++);
1921 compat_get_entries(
struct net *net,
struct compat_ip6t_get_entries __user *uptr,
1925 struct compat_ip6t_get_entries
get;
1928 if (*len <
sizeof(
get)) {
1929 duprintf(
"compat_get_entries: %u < %zu\n", *len,
sizeof(
get));
1936 if (*len !=
sizeof(
struct compat_ip6t_get_entries) +
get.size) {
1937 duprintf(
"compat_get_entries: %u != %zu\n",
1938 *len,
sizeof(
get) +
get.size);
1942 xt_compat_lock(AF_INET6);
1944 if (t && !IS_ERR(t)) {
1947 duprintf(
"t->private->number = %u\n", private->number);
1948 ret = compat_table_info(
private, &info);
1949 if (!ret &&
get.size == info.
size) {
1950 ret = compat_copy_entries_to_user(private->size,
1951 t, uptr->entrytable);
1953 duprintf(
"compat_get_entries: I've got %u not %u!\n",
1954 private->size,
get.size);
1957 xt_compat_flush_offsets(AF_INET6);
1961 ret = t ? PTR_ERR(t) : -
ENOENT;
1963 xt_compat_unlock(AF_INET6);
1967 static int do_ip6t_get_ctl(
struct sock *,
int,
void __user *,
int *);
1970 compat_do_ip6t_get_ctl(
struct sock *sk,
int cmd,
void __user *user,
int *len)
1979 ret = get_info(sock_net(sk), user, len, 1);
1982 ret = compat_get_entries(sock_net(sk), user, len);
1985 ret = do_ip6t_get_ctl(sk, cmd, user, len);
1992 do_ip6t_set_ctl(
struct sock *sk,
int cmd,
void __user *user,
unsigned int len)
2001 ret = do_replace(sock_net(sk), user, len);
2005 ret = do_add_counters(sock_net(sk), user, len, 0);
2009 duprintf(
"do_ip6t_set_ctl: unknown request %i\n", cmd);
2017 do_ip6t_get_ctl(
struct sock *sk,
int cmd,
void __user *user,
int *len)
2026 ret = get_info(sock_net(sk), user, len, 0);
2030 ret = get_entries(sock_net(sk), user, len);
2038 if (*len !=
sizeof(
rev)) {
2046 rev.name[
sizeof(
rev.name)-1] = 0;
2056 "ip6t_%s",
rev.name);
2061 duprintf(
"do_ip6t_get_ctl: unknown request %i\n", cmd);
2075 void *loc_cpu_entry;
2088 ret = translate_table(net, newinfo, loc_cpu_entry, repl);
2093 if (IS_ERR(new_table)) {
2094 ret = PTR_ERR(new_table);
2102 return ERR_PTR(ret);
2108 void *loc_cpu_entry;
2109 struct module *table_owner = table->
me;
2117 cleanup_entry(iter, net);
2118 if (private->number > private->initial_entries)
2119 module_put(table_owner);
2129 return (type == test_type && code >= min_code && code <= max_code)
2144 ic = skb_header_pointer(skb, par->
thoff,
sizeof(_icmph), &_icmph);
2149 duprintf(
"Dropping evil ICMP tinygram.\n");
2154 return icmp6_type_code_match(icmpinfo->
type,
2174 .targetsize =
sizeof(
int),
2176 #ifdef CONFIG_COMPAT
2178 .compat_from_user = compat_standard_from_user,
2179 .compat_to_user = compat_standard_to_user,
2190 static struct nf_sockopt_ops ip6t_sockopts = {
2194 .set = do_ip6t_set_ctl,
2195 #ifdef CONFIG_COMPAT
2196 .compat_set = compat_do_ip6t_set_ctl,
2200 .get = do_ip6t_get_ctl,
2201 #ifdef CONFIG_COMPAT
2202 .compat_get = compat_do_ip6t_get_ctl,
2207 static struct xt_match ip6t_builtin_mt[] __read_mostly = {
2210 .match = icmp6_match,
2212 .checkentry = icmp6_checkentry,
2218 static int __net_init ip6_tables_net_init(
struct net *net)
2223 static void __net_exit ip6_tables_net_exit(
struct net *net)
2229 .init = ip6_tables_net_init,
2230 .exit = ip6_tables_net_exit,
2233 static int __init ip6_tables_init(
void)
2254 pr_info(
"(C) 2000-2006 Netfilter Core Team\n");
2267 static void __exit ip6_tables_fini(
void)
2301 int target,
unsigned short *fragoff,
int *
flags)
2303 unsigned int start = skb_network_offset(skb) +
sizeof(
struct ipv6hdr);
2313 ip6 = skb_header_pointer(skb, *offset,
sizeof(_ip6), &_ip6);
2314 if (!ip6 || (ip6->version != 6)) {
2318 start = *offset +
sizeof(
struct ipv6hdr);
2323 while (nexthdr != target) {
2333 hp = skb_header_pointer(skb, start,
sizeof(_hdr), &_hdr);
2337 unsigned short _frag_off;
2342 fp = skb_header_pointer(skb,
2350 _frag_off =
ntohs(*fp) & ~0x7;
2356 *fragoff = _frag_off;
2365 hdrlen = (hp->
hdrlen + 2) << 2;