mirror of
https://github.com/BobTheBlinker/android_kernel_motorola_sm6375.git
synced 2026-10-30 19:51:31 -04:00
Merge branch 'master' of git://git.kernel.org/pub/scm/linux/kernel/git/kaber/nf-next-2.6
This commit is contained in:
commit
9941fb6276
78 changed files with 4226 additions and 1929 deletions
|
|
@ -343,7 +343,8 @@ int inet6_bind(struct socket *sock, struct sockaddr *uaddr, int addr_len)
|
|||
*/
|
||||
v4addr = LOOPBACK4_IPV6;
|
||||
if (!(addr_type & IPV6_ADDR_MULTICAST)) {
|
||||
if (!ipv6_chk_addr(net, &addr->sin6_addr,
|
||||
if (!inet->transparent &&
|
||||
!ipv6_chk_addr(net, &addr->sin6_addr,
|
||||
dev, 0)) {
|
||||
err = -EADDRNOTAVAIL;
|
||||
goto out_unlock;
|
||||
|
|
|
|||
|
|
@ -577,6 +577,25 @@ int datagram_recv_ctl(struct sock *sk, struct msghdr *msg, struct sk_buff *skb)
|
|||
u8 *ptr = nh + opt->dst1;
|
||||
put_cmsg(msg, SOL_IPV6, IPV6_2292DSTOPTS, (ptr[1]+1)<<3, ptr);
|
||||
}
|
||||
if (np->rxopt.bits.rxorigdstaddr) {
|
||||
struct sockaddr_in6 sin6;
|
||||
u16 *ports = (u16 *) skb_transport_header(skb);
|
||||
|
||||
if (skb_transport_offset(skb) + 4 <= skb->len) {
|
||||
/* All current transport protocols have the port numbers in the
|
||||
* first four bytes of the transport header and this function is
|
||||
* written with this assumption in mind.
|
||||
*/
|
||||
|
||||
sin6.sin6_family = AF_INET6;
|
||||
ipv6_addr_copy(&sin6.sin6_addr, &ipv6_hdr(skb)->daddr);
|
||||
sin6.sin6_port = ports[1];
|
||||
sin6.sin6_flowinfo = 0;
|
||||
sin6.sin6_scope_id = 0;
|
||||
|
||||
put_cmsg(msg, SOL_IPV6, IPV6_ORIGDSTADDR, sizeof(sin6), &sin6);
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -342,6 +342,21 @@ static int do_ipv6_setsockopt(struct sock *sk, int level, int optname,
|
|||
retv = 0;
|
||||
break;
|
||||
|
||||
case IPV6_TRANSPARENT:
|
||||
if (optlen < sizeof(int))
|
||||
goto e_inval;
|
||||
/* we don't have a separate transparent bit for IPV6 we use the one in the IPv4 socket */
|
||||
inet_sk(sk)->transparent = valbool;
|
||||
retv = 0;
|
||||
break;
|
||||
|
||||
case IPV6_RECVORIGDSTADDR:
|
||||
if (optlen < sizeof(int))
|
||||
goto e_inval;
|
||||
np->rxopt.bits.rxorigdstaddr = valbool;
|
||||
retv = 0;
|
||||
break;
|
||||
|
||||
case IPV6_HOPOPTS:
|
||||
case IPV6_RTHDRDSTOPTS:
|
||||
case IPV6_RTHDR:
|
||||
|
|
@ -1104,6 +1119,14 @@ static int do_ipv6_getsockopt(struct sock *sk, int level, int optname,
|
|||
break;
|
||||
}
|
||||
|
||||
case IPV6_TRANSPARENT:
|
||||
val = inet_sk(sk)->transparent;
|
||||
break;
|
||||
|
||||
case IPV6_RECVORIGDSTADDR:
|
||||
val = np->rxopt.bits.rxorigdstaddr;
|
||||
break;
|
||||
|
||||
case IPV6_UNICAST_HOPS:
|
||||
case IPV6_MULTICAST_HOPS:
|
||||
{
|
||||
|
|
|
|||
|
|
@ -132,10 +132,10 @@ config IP6_NF_MATCH_RT
|
|||
# The targets
|
||||
config IP6_NF_TARGET_HL
|
||||
tristate '"HL" hoplimit target support'
|
||||
depends on NETFILTER_ADVANCED
|
||||
depends on NETFILTER_ADVANCED && IP6_NF_MANGLE
|
||||
select NETFILTER_XT_TARGET_HL
|
||||
---help---
|
||||
This is a backwards-compat option for the user's convenience
|
||||
This is a backwards-compatible option for the user's convenience
|
||||
(e.g. when running oldconfig). It selects
|
||||
CONFIG_NETFILTER_XT_TARGET_HL.
|
||||
|
||||
|
|
|
|||
|
|
@ -11,10 +11,11 @@ obj-$(CONFIG_IP6_NF_RAW) += ip6table_raw.o
|
|||
obj-$(CONFIG_IP6_NF_SECURITY) += ip6table_security.o
|
||||
|
||||
# objects for l3 independent conntrack
|
||||
nf_conntrack_ipv6-objs := nf_conntrack_l3proto_ipv6.o nf_conntrack_proto_icmpv6.o nf_conntrack_reasm.o
|
||||
nf_conntrack_ipv6-objs := nf_conntrack_l3proto_ipv6.o nf_conntrack_proto_icmpv6.o
|
||||
nf_defrag_ipv6-objs := nf_defrag_ipv6_hooks.o nf_conntrack_reasm.o
|
||||
|
||||
# l3 independent conntrack
|
||||
obj-$(CONFIG_NF_CONNTRACK_IPV6) += nf_conntrack_ipv6.o
|
||||
obj-$(CONFIG_NF_CONNTRACK_IPV6) += nf_conntrack_ipv6.o nf_defrag_ipv6.o
|
||||
|
||||
# matches
|
||||
obj-$(CONFIG_IP6_NF_MATCH_AH) += ip6t_ah.o
|
||||
|
|
|
|||
|
|
@ -215,7 +215,7 @@ static inline bool unconditional(const struct ip6t_ip6 *ipv6)
|
|||
return memcmp(ipv6, &uncond, sizeof(uncond)) == 0;
|
||||
}
|
||||
|
||||
static inline const struct ip6t_entry_target *
|
||||
static inline const struct xt_entry_target *
|
||||
ip6t_get_target_c(const struct ip6t_entry *e)
|
||||
{
|
||||
return ip6t_get_target((struct ip6t_entry *)e);
|
||||
|
|
@ -260,9 +260,9 @@ get_chainname_rulenum(const struct ip6t_entry *s, const struct ip6t_entry *e,
|
|||
const char *hookname, const char **chainname,
|
||||
const char **comment, unsigned int *rulenum)
|
||||
{
|
||||
const struct ip6t_standard_target *t = (void *)ip6t_get_target_c(s);
|
||||
const struct xt_standard_target *t = (void *)ip6t_get_target_c(s);
|
||||
|
||||
if (strcmp(t->target.u.kernel.target->name, IP6T_ERROR_TARGET) == 0) {
|
||||
if (strcmp(t->target.u.kernel.target->name, XT_ERROR_TARGET) == 0) {
|
||||
/* Head of user chain: ERROR target with chainname */
|
||||
*chainname = t->target.data;
|
||||
(*rulenum) = 0;
|
||||
|
|
@ -271,7 +271,7 @@ get_chainname_rulenum(const struct ip6t_entry *s, const struct ip6t_entry *e,
|
|||
|
||||
if (s->target_offset == sizeof(struct ip6t_entry) &&
|
||||
strcmp(t->target.u.kernel.target->name,
|
||||
IP6T_STANDARD_TARGET) == 0 &&
|
||||
XT_STANDARD_TARGET) == 0 &&
|
||||
t->verdict < 0 &&
|
||||
unconditional(&s->ipv6)) {
|
||||
/* Tail of chains: STANDARD target (return/policy) */
|
||||
|
|
@ -369,7 +369,7 @@ ip6t_do_table(struct sk_buff *skb,
|
|||
e = get_entry(table_base, private->hook_entry[hook]);
|
||||
|
||||
do {
|
||||
const struct ip6t_entry_target *t;
|
||||
const struct xt_entry_target *t;
|
||||
const struct xt_entry_match *ematch;
|
||||
|
||||
IP_NF_ASSERT(e);
|
||||
|
|
@ -403,10 +403,10 @@ ip6t_do_table(struct sk_buff *skb,
|
|||
if (!t->u.kernel.target->target) {
|
||||
int v;
|
||||
|
||||
v = ((struct ip6t_standard_target *)t)->verdict;
|
||||
v = ((struct xt_standard_target *)t)->verdict;
|
||||
if (v < 0) {
|
||||
/* Pop from stack? */
|
||||
if (v != IP6T_RETURN) {
|
||||
if (v != XT_RETURN) {
|
||||
verdict = (unsigned)(-v) - 1;
|
||||
break;
|
||||
}
|
||||
|
|
@ -434,7 +434,7 @@ ip6t_do_table(struct sk_buff *skb,
|
|||
acpar.targinfo = t->data;
|
||||
|
||||
verdict = t->u.kernel.target->target(skb, &acpar);
|
||||
if (verdict == IP6T_CONTINUE)
|
||||
if (verdict == XT_CONTINUE)
|
||||
e = ip6t_next_entry(e);
|
||||
else
|
||||
/* Verdict */
|
||||
|
|
@ -474,7 +474,7 @@ mark_source_chains(const struct xt_table_info *newinfo,
|
|||
e->counters.pcnt = pos;
|
||||
|
||||
for (;;) {
|
||||
const struct ip6t_standard_target *t
|
||||
const struct xt_standard_target *t
|
||||
= (void *)ip6t_get_target_c(e);
|
||||
int visited = e->comefrom & (1 << hook);
|
||||
|
||||
|
|
@ -488,13 +488,13 @@ mark_source_chains(const struct xt_table_info *newinfo,
|
|||
/* Unconditional return/END. */
|
||||
if ((e->target_offset == sizeof(struct ip6t_entry) &&
|
||||
(strcmp(t->target.u.user.name,
|
||||
IP6T_STANDARD_TARGET) == 0) &&
|
||||
XT_STANDARD_TARGET) == 0) &&
|
||||
t->verdict < 0 &&
|
||||
unconditional(&e->ipv6)) || visited) {
|
||||
unsigned int oldpos, size;
|
||||
|
||||
if ((strcmp(t->target.u.user.name,
|
||||
IP6T_STANDARD_TARGET) == 0) &&
|
||||
XT_STANDARD_TARGET) == 0) &&
|
||||
t->verdict < -NF_MAX_VERDICT - 1) {
|
||||
duprintf("mark_source_chains: bad "
|
||||
"negative verdict (%i)\n",
|
||||
|
|
@ -537,7 +537,7 @@ mark_source_chains(const struct xt_table_info *newinfo,
|
|||
int newpos = t->verdict;
|
||||
|
||||
if (strcmp(t->target.u.user.name,
|
||||
IP6T_STANDARD_TARGET) == 0 &&
|
||||
XT_STANDARD_TARGET) == 0 &&
|
||||
newpos >= 0) {
|
||||
if (newpos > newinfo->size -
|
||||
sizeof(struct ip6t_entry)) {
|
||||
|
|
@ -565,7 +565,7 @@ mark_source_chains(const struct xt_table_info *newinfo,
|
|||
return 1;
|
||||
}
|
||||
|
||||
static void cleanup_match(struct ip6t_entry_match *m, struct net *net)
|
||||
static void cleanup_match(struct xt_entry_match *m, struct net *net)
|
||||
{
|
||||
struct xt_mtdtor_param par;
|
||||
|
||||
|
|
@ -581,14 +581,14 @@ static void cleanup_match(struct ip6t_entry_match *m, struct net *net)
|
|||
static int
|
||||
check_entry(const struct ip6t_entry *e, const char *name)
|
||||
{
|
||||
const struct ip6t_entry_target *t;
|
||||
const struct xt_entry_target *t;
|
||||
|
||||
if (!ip6_checkentry(&e->ipv6)) {
|
||||
duprintf("ip_tables: ip check failed %p %s.\n", e, name);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
if (e->target_offset + sizeof(struct ip6t_entry_target) >
|
||||
if (e->target_offset + sizeof(struct xt_entry_target) >
|
||||
e->next_offset)
|
||||
return -EINVAL;
|
||||
|
||||
|
|
@ -599,7 +599,7 @@ check_entry(const struct ip6t_entry *e, const char *name)
|
|||
return 0;
|
||||
}
|
||||
|
||||
static int check_match(struct ip6t_entry_match *m, struct xt_mtchk_param *par)
|
||||
static int check_match(struct xt_entry_match *m, struct xt_mtchk_param *par)
|
||||
{
|
||||
const struct ip6t_ip6 *ipv6 = par->entryinfo;
|
||||
int ret;
|
||||
|
|
@ -618,7 +618,7 @@ static int check_match(struct ip6t_entry_match *m, struct xt_mtchk_param *par)
|
|||
}
|
||||
|
||||
static int
|
||||
find_check_match(struct ip6t_entry_match *m, struct xt_mtchk_param *par)
|
||||
find_check_match(struct xt_entry_match *m, struct xt_mtchk_param *par)
|
||||
{
|
||||
struct xt_match *match;
|
||||
int ret;
|
||||
|
|
@ -643,7 +643,7 @@ err:
|
|||
|
||||
static int check_target(struct ip6t_entry *e, struct net *net, const char *name)
|
||||
{
|
||||
struct ip6t_entry_target *t = ip6t_get_target(e);
|
||||
struct xt_entry_target *t = ip6t_get_target(e);
|
||||
struct xt_tgchk_param par = {
|
||||
.net = net,
|
||||
.table = name,
|
||||
|
|
@ -670,7 +670,7 @@ static int
|
|||
find_check_entry(struct ip6t_entry *e, struct net *net, const char *name,
|
||||
unsigned int size)
|
||||
{
|
||||
struct ip6t_entry_target *t;
|
||||
struct xt_entry_target *t;
|
||||
struct xt_target *target;
|
||||
int ret;
|
||||
unsigned int j;
|
||||
|
|
@ -721,7 +721,7 @@ find_check_entry(struct ip6t_entry *e, struct net *net, const char *name,
|
|||
|
||||
static bool check_underflow(const struct ip6t_entry *e)
|
||||
{
|
||||
const struct ip6t_entry_target *t;
|
||||
const struct xt_entry_target *t;
|
||||
unsigned int verdict;
|
||||
|
||||
if (!unconditional(&e->ipv6))
|
||||
|
|
@ -729,7 +729,7 @@ static bool check_underflow(const struct ip6t_entry *e)
|
|||
t = ip6t_get_target_c(e);
|
||||
if (strcmp(t->u.user.name, XT_STANDARD_TARGET) != 0)
|
||||
return false;
|
||||
verdict = ((struct ip6t_standard_target *)t)->verdict;
|
||||
verdict = ((struct xt_standard_target *)t)->verdict;
|
||||
verdict = -verdict - 1;
|
||||
return verdict == NF_DROP || verdict == NF_ACCEPT;
|
||||
}
|
||||
|
|
@ -752,7 +752,7 @@ check_entry_size_and_hooks(struct ip6t_entry *e,
|
|||
}
|
||||
|
||||
if (e->next_offset
|
||||
< sizeof(struct ip6t_entry) + sizeof(struct ip6t_entry_target)) {
|
||||
< sizeof(struct ip6t_entry) + sizeof(struct xt_entry_target)) {
|
||||
duprintf("checking: element %p size %u\n",
|
||||
e, e->next_offset);
|
||||
return -EINVAL;
|
||||
|
|
@ -784,7 +784,7 @@ check_entry_size_and_hooks(struct ip6t_entry *e,
|
|||
static void cleanup_entry(struct ip6t_entry *e, struct net *net)
|
||||
{
|
||||
struct xt_tgdtor_param par;
|
||||
struct ip6t_entry_target *t;
|
||||
struct xt_entry_target *t;
|
||||
struct xt_entry_match *ematch;
|
||||
|
||||
/* Cleanup all matches */
|
||||
|
|
@ -985,8 +985,8 @@ copy_entries_to_user(unsigned int total_size,
|
|||
/* ... then go back and fix counters and names */
|
||||
for (off = 0, num = 0; off < total_size; off += e->next_offset, num++){
|
||||
unsigned int i;
|
||||
const struct ip6t_entry_match *m;
|
||||
const struct ip6t_entry_target *t;
|
||||
const struct xt_entry_match *m;
|
||||
const struct xt_entry_target *t;
|
||||
|
||||
e = (struct ip6t_entry *)(loc_cpu_entry + off);
|
||||
if (copy_to_user(userptr + off
|
||||
|
|
@ -1003,7 +1003,7 @@ copy_entries_to_user(unsigned int total_size,
|
|||
m = (void *)e + i;
|
||||
|
||||
if (copy_to_user(userptr + off + i
|
||||
+ offsetof(struct ip6t_entry_match,
|
||||
+ offsetof(struct xt_entry_match,
|
||||
u.user.name),
|
||||
m->u.kernel.match->name,
|
||||
strlen(m->u.kernel.match->name)+1)
|
||||
|
|
@ -1015,7 +1015,7 @@ copy_entries_to_user(unsigned int total_size,
|
|||
|
||||
t = ip6t_get_target_c(e);
|
||||
if (copy_to_user(userptr + off + e->target_offset
|
||||
+ offsetof(struct ip6t_entry_target,
|
||||
+ offsetof(struct xt_entry_target,
|
||||
u.user.name),
|
||||
t->u.kernel.target->name,
|
||||
strlen(t->u.kernel.target->name)+1) != 0) {
|
||||
|
|
@ -1053,7 +1053,7 @@ static int compat_calc_entry(const struct ip6t_entry *e,
|
|||
const void *base, struct xt_table_info *newinfo)
|
||||
{
|
||||
const struct xt_entry_match *ematch;
|
||||
const struct ip6t_entry_target *t;
|
||||
const struct xt_entry_target *t;
|
||||
unsigned int entry_offset;
|
||||
int off, i, ret;
|
||||
|
||||
|
|
@ -1105,7 +1105,7 @@ static int compat_table_info(const struct xt_table_info *info,
|
|||
static int get_info(struct net *net, void __user *user,
|
||||
const int *len, int compat)
|
||||
{
|
||||
char name[IP6T_TABLE_MAXNAMELEN];
|
||||
char name[XT_TABLE_MAXNAMELEN];
|
||||
struct xt_table *t;
|
||||
int ret;
|
||||
|
||||
|
|
@ -1118,7 +1118,7 @@ static int get_info(struct net *net, void __user *user,
|
|||
if (copy_from_user(name, user, sizeof(name)) != 0)
|
||||
return -EFAULT;
|
||||
|
||||
name[IP6T_TABLE_MAXNAMELEN-1] = '\0';
|
||||
name[XT_TABLE_MAXNAMELEN-1] = '\0';
|
||||
#ifdef CONFIG_COMPAT
|
||||
if (compat)
|
||||
xt_compat_lock(AF_INET6);
|
||||
|
|
@ -1415,14 +1415,14 @@ do_add_counters(struct net *net, const void __user *user, unsigned int len,
|
|||
|
||||
#ifdef CONFIG_COMPAT
|
||||
struct compat_ip6t_replace {
|
||||
char name[IP6T_TABLE_MAXNAMELEN];
|
||||
char name[XT_TABLE_MAXNAMELEN];
|
||||
u32 valid_hooks;
|
||||
u32 num_entries;
|
||||
u32 size;
|
||||
u32 hook_entry[NF_INET_NUMHOOKS];
|
||||
u32 underflow[NF_INET_NUMHOOKS];
|
||||
u32 num_counters;
|
||||
compat_uptr_t counters; /* struct ip6t_counters * */
|
||||
compat_uptr_t counters; /* struct xt_counters * */
|
||||
struct compat_ip6t_entry entries[0];
|
||||
};
|
||||
|
||||
|
|
@ -1431,7 +1431,7 @@ compat_copy_entry_to_user(struct ip6t_entry *e, void __user **dstptr,
|
|||
unsigned int *size, struct xt_counters *counters,
|
||||
unsigned int i)
|
||||
{
|
||||
struct ip6t_entry_target *t;
|
||||
struct xt_entry_target *t;
|
||||
struct compat_ip6t_entry __user *ce;
|
||||
u_int16_t target_offset, next_offset;
|
||||
compat_uint_t origsize;
|
||||
|
|
@ -1466,7 +1466,7 @@ compat_copy_entry_to_user(struct ip6t_entry *e, void __user **dstptr,
|
|||
}
|
||||
|
||||
static int
|
||||
compat_find_calc_match(struct ip6t_entry_match *m,
|
||||
compat_find_calc_match(struct xt_entry_match *m,
|
||||
const char *name,
|
||||
const struct ip6t_ip6 *ipv6,
|
||||
unsigned int hookmask,
|
||||
|
|
@ -1488,7 +1488,7 @@ compat_find_calc_match(struct ip6t_entry_match *m,
|
|||
|
||||
static void compat_release_entry(struct compat_ip6t_entry *e)
|
||||
{
|
||||
struct ip6t_entry_target *t;
|
||||
struct xt_entry_target *t;
|
||||
struct xt_entry_match *ematch;
|
||||
|
||||
/* Cleanup all matches */
|
||||
|
|
@ -1509,7 +1509,7 @@ check_compat_entry_size_and_hooks(struct compat_ip6t_entry *e,
|
|||
const char *name)
|
||||
{
|
||||
struct xt_entry_match *ematch;
|
||||
struct ip6t_entry_target *t;
|
||||
struct xt_entry_target *t;
|
||||
struct xt_target *target;
|
||||
unsigned int entry_offset;
|
||||
unsigned int j;
|
||||
|
|
@ -1591,7 +1591,7 @@ compat_copy_entry_from_user(struct compat_ip6t_entry *e, void **dstptr,
|
|||
unsigned int *size, const char *name,
|
||||
struct xt_table_info *newinfo, unsigned char *base)
|
||||
{
|
||||
struct ip6t_entry_target *t;
|
||||
struct xt_entry_target *t;
|
||||
struct xt_target *target;
|
||||
struct ip6t_entry *de;
|
||||
unsigned int origsize;
|
||||
|
|
@ -1899,7 +1899,7 @@ compat_do_ip6t_set_ctl(struct sock *sk, int cmd, void __user *user,
|
|||
}
|
||||
|
||||
struct compat_ip6t_get_entries {
|
||||
char name[IP6T_TABLE_MAXNAMELEN];
|
||||
char name[XT_TABLE_MAXNAMELEN];
|
||||
compat_uint_t size;
|
||||
struct compat_ip6t_entry entrytable[0];
|
||||
};
|
||||
|
|
@ -2054,7 +2054,7 @@ do_ip6t_get_ctl(struct sock *sk, int cmd, void __user *user, int *len)
|
|||
|
||||
case IP6T_SO_GET_REVISION_MATCH:
|
||||
case IP6T_SO_GET_REVISION_TARGET: {
|
||||
struct ip6t_get_revision rev;
|
||||
struct xt_get_revision rev;
|
||||
int target;
|
||||
|
||||
if (*len != sizeof(rev)) {
|
||||
|
|
@ -2191,7 +2191,7 @@ static int icmp6_checkentry(const struct xt_mtchk_param *par)
|
|||
/* The built-in targets: standard (NULL) and error. */
|
||||
static struct xt_target ip6t_builtin_tg[] __read_mostly = {
|
||||
{
|
||||
.name = IP6T_STANDARD_TARGET,
|
||||
.name = XT_STANDARD_TARGET,
|
||||
.targetsize = sizeof(int),
|
||||
.family = NFPROTO_IPV6,
|
||||
#ifdef CONFIG_COMPAT
|
||||
|
|
@ -2201,9 +2201,9 @@ static struct xt_target ip6t_builtin_tg[] __read_mostly = {
|
|||
#endif
|
||||
},
|
||||
{
|
||||
.name = IP6T_ERROR_TARGET,
|
||||
.name = XT_ERROR_TARGET,
|
||||
.target = ip6t_error,
|
||||
.targetsize = IP6T_FUNCTION_MAXNAMELEN,
|
||||
.targetsize = XT_FUNCTION_MAXNAMELEN,
|
||||
.family = NFPROTO_IPV6,
|
||||
},
|
||||
};
|
||||
|
|
|
|||
|
|
@ -23,6 +23,7 @@
|
|||
#include <linux/netfilter/x_tables.h>
|
||||
#include <linux/netfilter_ipv6/ip6_tables.h>
|
||||
#include <net/netfilter/nf_log.h>
|
||||
#include <net/netfilter/xt_log.h>
|
||||
|
||||
MODULE_AUTHOR("Jan Rekorajski <[email protected]>");
|
||||
MODULE_DESCRIPTION("Xtables: IPv6 packet logging to syslog");
|
||||
|
|
@ -32,11 +33,9 @@ struct in_device;
|
|||
#include <net/route.h>
|
||||
#include <linux/netfilter_ipv6/ip6t_LOG.h>
|
||||
|
||||
/* Use lock to serialize, so printks don't overlap */
|
||||
static DEFINE_SPINLOCK(log_lock);
|
||||
|
||||
/* One level of recursion won't kill us */
|
||||
static void dump_packet(const struct nf_loginfo *info,
|
||||
static void dump_packet(struct sbuff *m,
|
||||
const struct nf_loginfo *info,
|
||||
const struct sk_buff *skb, unsigned int ip6hoff,
|
||||
int recurse)
|
||||
{
|
||||
|
|
@ -55,15 +54,15 @@ static void dump_packet(const struct nf_loginfo *info,
|
|||
|
||||
ih = skb_header_pointer(skb, ip6hoff, sizeof(_ip6h), &_ip6h);
|
||||
if (ih == NULL) {
|
||||
printk("TRUNCATED");
|
||||
sb_add(m, "TRUNCATED");
|
||||
return;
|
||||
}
|
||||
|
||||
/* Max length: 88 "SRC=0000.0000.0000.0000.0000.0000.0000.0000 DST=0000.0000.0000.0000.0000.0000.0000.0000 " */
|
||||
printk("SRC=%pI6 DST=%pI6 ", &ih->saddr, &ih->daddr);
|
||||
sb_add(m, "SRC=%pI6 DST=%pI6 ", &ih->saddr, &ih->daddr);
|
||||
|
||||
/* Max length: 44 "LEN=65535 TC=255 HOPLIMIT=255 FLOWLBL=FFFFF " */
|
||||
printk("LEN=%Zu TC=%u HOPLIMIT=%u FLOWLBL=%u ",
|
||||
sb_add(m, "LEN=%Zu TC=%u HOPLIMIT=%u FLOWLBL=%u ",
|
||||
ntohs(ih->payload_len) + sizeof(struct ipv6hdr),
|
||||
(ntohl(*(__be32 *)ih) & 0x0ff00000) >> 20,
|
||||
ih->hop_limit,
|
||||
|
|
@ -78,35 +77,35 @@ static void dump_packet(const struct nf_loginfo *info,
|
|||
|
||||
hp = skb_header_pointer(skb, ptr, sizeof(_hdr), &_hdr);
|
||||
if (hp == NULL) {
|
||||
printk("TRUNCATED");
|
||||
sb_add(m, "TRUNCATED");
|
||||
return;
|
||||
}
|
||||
|
||||
/* Max length: 48 "OPT (...) " */
|
||||
if (logflags & IP6T_LOG_IPOPT)
|
||||
printk("OPT ( ");
|
||||
sb_add(m, "OPT ( ");
|
||||
|
||||
switch (currenthdr) {
|
||||
case IPPROTO_FRAGMENT: {
|
||||
struct frag_hdr _fhdr;
|
||||
const struct frag_hdr *fh;
|
||||
|
||||
printk("FRAG:");
|
||||
sb_add(m, "FRAG:");
|
||||
fh = skb_header_pointer(skb, ptr, sizeof(_fhdr),
|
||||
&_fhdr);
|
||||
if (fh == NULL) {
|
||||
printk("TRUNCATED ");
|
||||
sb_add(m, "TRUNCATED ");
|
||||
return;
|
||||
}
|
||||
|
||||
/* Max length: 6 "65535 " */
|
||||
printk("%u ", ntohs(fh->frag_off) & 0xFFF8);
|
||||
sb_add(m, "%u ", ntohs(fh->frag_off) & 0xFFF8);
|
||||
|
||||
/* Max length: 11 "INCOMPLETE " */
|
||||
if (fh->frag_off & htons(0x0001))
|
||||
printk("INCOMPLETE ");
|
||||
sb_add(m, "INCOMPLETE ");
|
||||
|
||||
printk("ID:%08x ", ntohl(fh->identification));
|
||||
sb_add(m, "ID:%08x ", ntohl(fh->identification));
|
||||
|
||||
if (ntohs(fh->frag_off) & 0xFFF8)
|
||||
fragment = 1;
|
||||
|
|
@ -120,7 +119,7 @@ static void dump_packet(const struct nf_loginfo *info,
|
|||
case IPPROTO_HOPOPTS:
|
||||
if (fragment) {
|
||||
if (logflags & IP6T_LOG_IPOPT)
|
||||
printk(")");
|
||||
sb_add(m, ")");
|
||||
return;
|
||||
}
|
||||
hdrlen = ipv6_optlen(hp);
|
||||
|
|
@ -132,10 +131,10 @@ static void dump_packet(const struct nf_loginfo *info,
|
|||
const struct ip_auth_hdr *ah;
|
||||
|
||||
/* Max length: 3 "AH " */
|
||||
printk("AH ");
|
||||
sb_add(m, "AH ");
|
||||
|
||||
if (fragment) {
|
||||
printk(")");
|
||||
sb_add(m, ")");
|
||||
return;
|
||||
}
|
||||
|
||||
|
|
@ -146,13 +145,13 @@ static void dump_packet(const struct nf_loginfo *info,
|
|||
* Max length: 26 "INCOMPLETE [65535
|
||||
* bytes] )"
|
||||
*/
|
||||
printk("INCOMPLETE [%u bytes] )",
|
||||
sb_add(m, "INCOMPLETE [%u bytes] )",
|
||||
skb->len - ptr);
|
||||
return;
|
||||
}
|
||||
|
||||
/* Length: 15 "SPI=0xF1234567 */
|
||||
printk("SPI=0x%x ", ntohl(ah->spi));
|
||||
sb_add(m, "SPI=0x%x ", ntohl(ah->spi));
|
||||
|
||||
}
|
||||
|
||||
|
|
@ -164,10 +163,10 @@ static void dump_packet(const struct nf_loginfo *info,
|
|||
const struct ip_esp_hdr *eh;
|
||||
|
||||
/* Max length: 4 "ESP " */
|
||||
printk("ESP ");
|
||||
sb_add(m, "ESP ");
|
||||
|
||||
if (fragment) {
|
||||
printk(")");
|
||||
sb_add(m, ")");
|
||||
return;
|
||||
}
|
||||
|
||||
|
|
@ -177,23 +176,23 @@ static void dump_packet(const struct nf_loginfo *info,
|
|||
eh = skb_header_pointer(skb, ptr, sizeof(_esph),
|
||||
&_esph);
|
||||
if (eh == NULL) {
|
||||
printk("INCOMPLETE [%u bytes] )",
|
||||
sb_add(m, "INCOMPLETE [%u bytes] )",
|
||||
skb->len - ptr);
|
||||
return;
|
||||
}
|
||||
|
||||
/* Length: 16 "SPI=0xF1234567 )" */
|
||||
printk("SPI=0x%x )", ntohl(eh->spi) );
|
||||
sb_add(m, "SPI=0x%x )", ntohl(eh->spi) );
|
||||
|
||||
}
|
||||
return;
|
||||
default:
|
||||
/* Max length: 20 "Unknown Ext Hdr 255" */
|
||||
printk("Unknown Ext Hdr %u", currenthdr);
|
||||
sb_add(m, "Unknown Ext Hdr %u", currenthdr);
|
||||
return;
|
||||
}
|
||||
if (logflags & IP6T_LOG_IPOPT)
|
||||
printk(") ");
|
||||
sb_add(m, ") ");
|
||||
|
||||
currenthdr = hp->nexthdr;
|
||||
ptr += hdrlen;
|
||||
|
|
@ -205,7 +204,7 @@ static void dump_packet(const struct nf_loginfo *info,
|
|||
const struct tcphdr *th;
|
||||
|
||||
/* Max length: 10 "PROTO=TCP " */
|
||||
printk("PROTO=TCP ");
|
||||
sb_add(m, "PROTO=TCP ");
|
||||
|
||||
if (fragment)
|
||||
break;
|
||||
|
|
@ -213,40 +212,40 @@ static void dump_packet(const struct nf_loginfo *info,
|
|||
/* Max length: 25 "INCOMPLETE [65535 bytes] " */
|
||||
th = skb_header_pointer(skb, ptr, sizeof(_tcph), &_tcph);
|
||||
if (th == NULL) {
|
||||
printk("INCOMPLETE [%u bytes] ", skb->len - ptr);
|
||||
sb_add(m, "INCOMPLETE [%u bytes] ", skb->len - ptr);
|
||||
return;
|
||||
}
|
||||
|
||||
/* Max length: 20 "SPT=65535 DPT=65535 " */
|
||||
printk("SPT=%u DPT=%u ",
|
||||
sb_add(m, "SPT=%u DPT=%u ",
|
||||
ntohs(th->source), ntohs(th->dest));
|
||||
/* Max length: 30 "SEQ=4294967295 ACK=4294967295 " */
|
||||
if (logflags & IP6T_LOG_TCPSEQ)
|
||||
printk("SEQ=%u ACK=%u ",
|
||||
sb_add(m, "SEQ=%u ACK=%u ",
|
||||
ntohl(th->seq), ntohl(th->ack_seq));
|
||||
/* Max length: 13 "WINDOW=65535 " */
|
||||
printk("WINDOW=%u ", ntohs(th->window));
|
||||
sb_add(m, "WINDOW=%u ", ntohs(th->window));
|
||||
/* Max length: 9 "RES=0x3C " */
|
||||
printk("RES=0x%02x ", (u_int8_t)(ntohl(tcp_flag_word(th) & TCP_RESERVED_BITS) >> 22));
|
||||
sb_add(m, "RES=0x%02x ", (u_int8_t)(ntohl(tcp_flag_word(th) & TCP_RESERVED_BITS) >> 22));
|
||||
/* Max length: 32 "CWR ECE URG ACK PSH RST SYN FIN " */
|
||||
if (th->cwr)
|
||||
printk("CWR ");
|
||||
sb_add(m, "CWR ");
|
||||
if (th->ece)
|
||||
printk("ECE ");
|
||||
sb_add(m, "ECE ");
|
||||
if (th->urg)
|
||||
printk("URG ");
|
||||
sb_add(m, "URG ");
|
||||
if (th->ack)
|
||||
printk("ACK ");
|
||||
sb_add(m, "ACK ");
|
||||
if (th->psh)
|
||||
printk("PSH ");
|
||||
sb_add(m, "PSH ");
|
||||
if (th->rst)
|
||||
printk("RST ");
|
||||
sb_add(m, "RST ");
|
||||
if (th->syn)
|
||||
printk("SYN ");
|
||||
sb_add(m, "SYN ");
|
||||
if (th->fin)
|
||||
printk("FIN ");
|
||||
sb_add(m, "FIN ");
|
||||
/* Max length: 11 "URGP=65535 " */
|
||||
printk("URGP=%u ", ntohs(th->urg_ptr));
|
||||
sb_add(m, "URGP=%u ", ntohs(th->urg_ptr));
|
||||
|
||||
if ((logflags & IP6T_LOG_TCPOPT) &&
|
||||
th->doff * 4 > sizeof(struct tcphdr)) {
|
||||
|
|
@ -260,15 +259,15 @@ static void dump_packet(const struct nf_loginfo *info,
|
|||
ptr + sizeof(struct tcphdr),
|
||||
optsize, _opt);
|
||||
if (op == NULL) {
|
||||
printk("OPT (TRUNCATED)");
|
||||
sb_add(m, "OPT (TRUNCATED)");
|
||||
return;
|
||||
}
|
||||
|
||||
/* Max length: 127 "OPT (" 15*4*2chars ") " */
|
||||
printk("OPT (");
|
||||
sb_add(m, "OPT (");
|
||||
for (i =0; i < optsize; i++)
|
||||
printk("%02X", op[i]);
|
||||
printk(") ");
|
||||
sb_add(m, "%02X", op[i]);
|
||||
sb_add(m, ") ");
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
|
@ -279,9 +278,9 @@ static void dump_packet(const struct nf_loginfo *info,
|
|||
|
||||
if (currenthdr == IPPROTO_UDP)
|
||||
/* Max length: 10 "PROTO=UDP " */
|
||||
printk("PROTO=UDP " );
|
||||
sb_add(m, "PROTO=UDP " );
|
||||
else /* Max length: 14 "PROTO=UDPLITE " */
|
||||
printk("PROTO=UDPLITE ");
|
||||
sb_add(m, "PROTO=UDPLITE ");
|
||||
|
||||
if (fragment)
|
||||
break;
|
||||
|
|
@ -289,12 +288,12 @@ static void dump_packet(const struct nf_loginfo *info,
|
|||
/* Max length: 25 "INCOMPLETE [65535 bytes] " */
|
||||
uh = skb_header_pointer(skb, ptr, sizeof(_udph), &_udph);
|
||||
if (uh == NULL) {
|
||||
printk("INCOMPLETE [%u bytes] ", skb->len - ptr);
|
||||
sb_add(m, "INCOMPLETE [%u bytes] ", skb->len - ptr);
|
||||
return;
|
||||
}
|
||||
|
||||
/* Max length: 20 "SPT=65535 DPT=65535 " */
|
||||
printk("SPT=%u DPT=%u LEN=%u ",
|
||||
sb_add(m, "SPT=%u DPT=%u LEN=%u ",
|
||||
ntohs(uh->source), ntohs(uh->dest),
|
||||
ntohs(uh->len));
|
||||
break;
|
||||
|
|
@ -304,7 +303,7 @@ static void dump_packet(const struct nf_loginfo *info,
|
|||
const struct icmp6hdr *ic;
|
||||
|
||||
/* Max length: 13 "PROTO=ICMPv6 " */
|
||||
printk("PROTO=ICMPv6 ");
|
||||
sb_add(m, "PROTO=ICMPv6 ");
|
||||
|
||||
if (fragment)
|
||||
break;
|
||||
|
|
@ -312,18 +311,18 @@ static void dump_packet(const struct nf_loginfo *info,
|
|||
/* Max length: 25 "INCOMPLETE [65535 bytes] " */
|
||||
ic = skb_header_pointer(skb, ptr, sizeof(_icmp6h), &_icmp6h);
|
||||
if (ic == NULL) {
|
||||
printk("INCOMPLETE [%u bytes] ", skb->len - ptr);
|
||||
sb_add(m, "INCOMPLETE [%u bytes] ", skb->len - ptr);
|
||||
return;
|
||||
}
|
||||
|
||||
/* Max length: 18 "TYPE=255 CODE=255 " */
|
||||
printk("TYPE=%u CODE=%u ", ic->icmp6_type, ic->icmp6_code);
|
||||
sb_add(m, "TYPE=%u CODE=%u ", ic->icmp6_type, ic->icmp6_code);
|
||||
|
||||
switch (ic->icmp6_type) {
|
||||
case ICMPV6_ECHO_REQUEST:
|
||||
case ICMPV6_ECHO_REPLY:
|
||||
/* Max length: 19 "ID=65535 SEQ=65535 " */
|
||||
printk("ID=%u SEQ=%u ",
|
||||
sb_add(m, "ID=%u SEQ=%u ",
|
||||
ntohs(ic->icmp6_identifier),
|
||||
ntohs(ic->icmp6_sequence));
|
||||
break;
|
||||
|
|
@ -334,35 +333,35 @@ static void dump_packet(const struct nf_loginfo *info,
|
|||
|
||||
case ICMPV6_PARAMPROB:
|
||||
/* Max length: 17 "POINTER=ffffffff " */
|
||||
printk("POINTER=%08x ", ntohl(ic->icmp6_pointer));
|
||||
sb_add(m, "POINTER=%08x ", ntohl(ic->icmp6_pointer));
|
||||
/* Fall through */
|
||||
case ICMPV6_DEST_UNREACH:
|
||||
case ICMPV6_PKT_TOOBIG:
|
||||
case ICMPV6_TIME_EXCEED:
|
||||
/* Max length: 3+maxlen */
|
||||
if (recurse) {
|
||||
printk("[");
|
||||
dump_packet(info, skb, ptr + sizeof(_icmp6h),
|
||||
0);
|
||||
printk("] ");
|
||||
sb_add(m, "[");
|
||||
dump_packet(m, info, skb,
|
||||
ptr + sizeof(_icmp6h), 0);
|
||||
sb_add(m, "] ");
|
||||
}
|
||||
|
||||
/* Max length: 10 "MTU=65535 " */
|
||||
if (ic->icmp6_type == ICMPV6_PKT_TOOBIG)
|
||||
printk("MTU=%u ", ntohl(ic->icmp6_mtu));
|
||||
sb_add(m, "MTU=%u ", ntohl(ic->icmp6_mtu));
|
||||
}
|
||||
break;
|
||||
}
|
||||
/* Max length: 10 "PROTO=255 " */
|
||||
default:
|
||||
printk("PROTO=%u ", currenthdr);
|
||||
sb_add(m, "PROTO=%u ", currenthdr);
|
||||
}
|
||||
|
||||
/* Max length: 15 "UID=4294967295 " */
|
||||
if ((logflags & IP6T_LOG_UID) && recurse && skb->sk) {
|
||||
read_lock_bh(&skb->sk->sk_callback_lock);
|
||||
if (skb->sk->sk_socket && skb->sk->sk_socket->file)
|
||||
printk("UID=%u GID=%u ",
|
||||
sb_add(m, "UID=%u GID=%u ",
|
||||
skb->sk->sk_socket->file->f_cred->fsuid,
|
||||
skb->sk->sk_socket->file->f_cred->fsgid);
|
||||
read_unlock_bh(&skb->sk->sk_callback_lock);
|
||||
|
|
@ -370,10 +369,11 @@ static void dump_packet(const struct nf_loginfo *info,
|
|||
|
||||
/* Max length: 16 "MARK=0xFFFFFFFF " */
|
||||
if (!recurse && skb->mark)
|
||||
printk("MARK=0x%x ", skb->mark);
|
||||
sb_add(m, "MARK=0x%x ", skb->mark);
|
||||
}
|
||||
|
||||
static void dump_mac_header(const struct nf_loginfo *info,
|
||||
static void dump_mac_header(struct sbuff *m,
|
||||
const struct nf_loginfo *info,
|
||||
const struct sk_buff *skb)
|
||||
{
|
||||
struct net_device *dev = skb->dev;
|
||||
|
|
@ -387,7 +387,7 @@ static void dump_mac_header(const struct nf_loginfo *info,
|
|||
|
||||
switch (dev->type) {
|
||||
case ARPHRD_ETHER:
|
||||
printk("MACSRC=%pM MACDST=%pM MACPROTO=%04x ",
|
||||
sb_add(m, "MACSRC=%pM MACDST=%pM MACPROTO=%04x ",
|
||||
eth_hdr(skb)->h_source, eth_hdr(skb)->h_dest,
|
||||
ntohs(eth_hdr(skb)->h_proto));
|
||||
return;
|
||||
|
|
@ -396,7 +396,7 @@ static void dump_mac_header(const struct nf_loginfo *info,
|
|||
}
|
||||
|
||||
fallback:
|
||||
printk("MAC=");
|
||||
sb_add(m, "MAC=");
|
||||
if (dev->hard_header_len &&
|
||||
skb->mac_header != skb->network_header) {
|
||||
const unsigned char *p = skb_mac_header(skb);
|
||||
|
|
@ -408,19 +408,19 @@ fallback:
|
|||
p = NULL;
|
||||
|
||||
if (p != NULL) {
|
||||
printk("%02x", *p++);
|
||||
sb_add(m, "%02x", *p++);
|
||||
for (i = 1; i < len; i++)
|
||||
printk(":%02x", p[i]);
|
||||
sb_add(m, ":%02x", p[i]);
|
||||
}
|
||||
printk(" ");
|
||||
sb_add(m, " ");
|
||||
|
||||
if (dev->type == ARPHRD_SIT) {
|
||||
const struct iphdr *iph =
|
||||
(struct iphdr *)skb_mac_header(skb);
|
||||
printk("TUNNEL=%pI4->%pI4 ", &iph->saddr, &iph->daddr);
|
||||
sb_add(m, "TUNNEL=%pI4->%pI4 ", &iph->saddr, &iph->daddr);
|
||||
}
|
||||
} else
|
||||
printk(" ");
|
||||
sb_add(m, " ");
|
||||
}
|
||||
|
||||
static struct nf_loginfo default_loginfo = {
|
||||
|
|
@ -442,22 +442,23 @@ ip6t_log_packet(u_int8_t pf,
|
|||
const struct nf_loginfo *loginfo,
|
||||
const char *prefix)
|
||||
{
|
||||
struct sbuff *m = sb_open();
|
||||
|
||||
if (!loginfo)
|
||||
loginfo = &default_loginfo;
|
||||
|
||||
spin_lock_bh(&log_lock);
|
||||
printk("<%d>%sIN=%s OUT=%s ", loginfo->u.log.level,
|
||||
prefix,
|
||||
in ? in->name : "",
|
||||
out ? out->name : "");
|
||||
sb_add(m, "<%d>%sIN=%s OUT=%s ", loginfo->u.log.level,
|
||||
prefix,
|
||||
in ? in->name : "",
|
||||
out ? out->name : "");
|
||||
|
||||
/* MAC logging for input path only. */
|
||||
if (in && !out)
|
||||
dump_mac_header(loginfo, skb);
|
||||
dump_mac_header(m, loginfo, skb);
|
||||
|
||||
dump_packet(loginfo, skb, skb_network_offset(skb), 1);
|
||||
printk("\n");
|
||||
spin_unlock_bh(&log_lock);
|
||||
dump_packet(m, loginfo, skb, skb_network_offset(skb), 1);
|
||||
|
||||
sb_close(m);
|
||||
}
|
||||
|
||||
static unsigned int
|
||||
|
|
|
|||
|
|
@ -16,7 +16,6 @@
|
|||
#include <linux/module.h>
|
||||
#include <linux/skbuff.h>
|
||||
#include <linux/icmp.h>
|
||||
#include <linux/sysctl.h>
|
||||
#include <net/ipv6.h>
|
||||
#include <net/inet_frag.h>
|
||||
|
||||
|
|
@ -29,6 +28,7 @@
|
|||
#include <net/netfilter/nf_conntrack_core.h>
|
||||
#include <net/netfilter/nf_conntrack_zones.h>
|
||||
#include <net/netfilter/ipv6/nf_conntrack_ipv6.h>
|
||||
#include <net/netfilter/ipv6/nf_defrag_ipv6.h>
|
||||
#include <net/netfilter/nf_log.h>
|
||||
|
||||
static bool ipv6_pkt_to_tuple(const struct sk_buff *skb, unsigned int nhoff,
|
||||
|
|
@ -189,53 +189,6 @@ out:
|
|||
return nf_conntrack_confirm(skb);
|
||||
}
|
||||
|
||||
static enum ip6_defrag_users nf_ct6_defrag_user(unsigned int hooknum,
|
||||
struct sk_buff *skb)
|
||||
{
|
||||
u16 zone = NF_CT_DEFAULT_ZONE;
|
||||
|
||||
if (skb->nfct)
|
||||
zone = nf_ct_zone((struct nf_conn *)skb->nfct);
|
||||
|
||||
#ifdef CONFIG_BRIDGE_NETFILTER
|
||||
if (skb->nf_bridge &&
|
||||
skb->nf_bridge->mask & BRNF_NF_BRIDGE_PREROUTING)
|
||||
return IP6_DEFRAG_CONNTRACK_BRIDGE_IN + zone;
|
||||
#endif
|
||||
if (hooknum == NF_INET_PRE_ROUTING)
|
||||
return IP6_DEFRAG_CONNTRACK_IN + zone;
|
||||
else
|
||||
return IP6_DEFRAG_CONNTRACK_OUT + zone;
|
||||
|
||||
}
|
||||
|
||||
static unsigned int ipv6_defrag(unsigned int hooknum,
|
||||
struct sk_buff *skb,
|
||||
const struct net_device *in,
|
||||
const struct net_device *out,
|
||||
int (*okfn)(struct sk_buff *))
|
||||
{
|
||||
struct sk_buff *reasm;
|
||||
|
||||
/* Previously seen (loopback)? */
|
||||
if (skb->nfct && !nf_ct_is_template((struct nf_conn *)skb->nfct))
|
||||
return NF_ACCEPT;
|
||||
|
||||
reasm = nf_ct_frag6_gather(skb, nf_ct6_defrag_user(hooknum, skb));
|
||||
/* queued */
|
||||
if (reasm == NULL)
|
||||
return NF_STOLEN;
|
||||
|
||||
/* error occured or not fragmented */
|
||||
if (reasm == skb)
|
||||
return NF_ACCEPT;
|
||||
|
||||
nf_ct_frag6_output(hooknum, reasm, (struct net_device *)in,
|
||||
(struct net_device *)out, okfn);
|
||||
|
||||
return NF_STOLEN;
|
||||
}
|
||||
|
||||
static unsigned int __ipv6_conntrack_in(struct net *net,
|
||||
unsigned int hooknum,
|
||||
struct sk_buff *skb,
|
||||
|
|
@ -287,13 +240,6 @@ static unsigned int ipv6_conntrack_local(unsigned int hooknum,
|
|||
}
|
||||
|
||||
static struct nf_hook_ops ipv6_conntrack_ops[] __read_mostly = {
|
||||
{
|
||||
.hook = ipv6_defrag,
|
||||
.owner = THIS_MODULE,
|
||||
.pf = NFPROTO_IPV6,
|
||||
.hooknum = NF_INET_PRE_ROUTING,
|
||||
.priority = NF_IP6_PRI_CONNTRACK_DEFRAG,
|
||||
},
|
||||
{
|
||||
.hook = ipv6_conntrack_in,
|
||||
.owner = THIS_MODULE,
|
||||
|
|
@ -308,13 +254,6 @@ static struct nf_hook_ops ipv6_conntrack_ops[] __read_mostly = {
|
|||
.hooknum = NF_INET_LOCAL_OUT,
|
||||
.priority = NF_IP6_PRI_CONNTRACK,
|
||||
},
|
||||
{
|
||||
.hook = ipv6_defrag,
|
||||
.owner = THIS_MODULE,
|
||||
.pf = NFPROTO_IPV6,
|
||||
.hooknum = NF_INET_LOCAL_OUT,
|
||||
.priority = NF_IP6_PRI_CONNTRACK_DEFRAG,
|
||||
},
|
||||
{
|
||||
.hook = ipv6_confirm,
|
||||
.owner = THIS_MODULE,
|
||||
|
|
@ -386,10 +325,6 @@ struct nf_conntrack_l3proto nf_conntrack_l3proto_ipv6 __read_mostly = {
|
|||
.nlattr_tuple_size = ipv6_nlattr_tuple_size,
|
||||
.nlattr_to_tuple = ipv6_nlattr_to_tuple,
|
||||
.nla_policy = ipv6_nla_policy,
|
||||
#endif
|
||||
#ifdef CONFIG_SYSCTL
|
||||
.ctl_table_path = nf_net_netfilter_sysctl_path,
|
||||
.ctl_table = nf_ct_ipv6_sysctl_table,
|
||||
#endif
|
||||
.me = THIS_MODULE,
|
||||
};
|
||||
|
|
@ -403,16 +338,12 @@ static int __init nf_conntrack_l3proto_ipv6_init(void)
|
|||
int ret = 0;
|
||||
|
||||
need_conntrack();
|
||||
nf_defrag_ipv6_enable();
|
||||
|
||||
ret = nf_ct_frag6_init();
|
||||
if (ret < 0) {
|
||||
pr_err("nf_conntrack_ipv6: can't initialize frag6.\n");
|
||||
return ret;
|
||||
}
|
||||
ret = nf_conntrack_l4proto_register(&nf_conntrack_l4proto_tcp6);
|
||||
if (ret < 0) {
|
||||
pr_err("nf_conntrack_ipv6: can't register tcp.\n");
|
||||
goto cleanup_frag6;
|
||||
return ret;
|
||||
}
|
||||
|
||||
ret = nf_conntrack_l4proto_register(&nf_conntrack_l4proto_udp6);
|
||||
|
|
@ -450,8 +381,6 @@ static int __init nf_conntrack_l3proto_ipv6_init(void)
|
|||
nf_conntrack_l4proto_unregister(&nf_conntrack_l4proto_udp6);
|
||||
cleanup_tcp:
|
||||
nf_conntrack_l4proto_unregister(&nf_conntrack_l4proto_tcp6);
|
||||
cleanup_frag6:
|
||||
nf_ct_frag6_cleanup();
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
|
@ -463,7 +392,6 @@ static void __exit nf_conntrack_l3proto_ipv6_fini(void)
|
|||
nf_conntrack_l4proto_unregister(&nf_conntrack_l4proto_icmpv6);
|
||||
nf_conntrack_l4proto_unregister(&nf_conntrack_l4proto_udp6);
|
||||
nf_conntrack_l4proto_unregister(&nf_conntrack_l4proto_tcp6);
|
||||
nf_ct_frag6_cleanup();
|
||||
}
|
||||
|
||||
module_init(nf_conntrack_l3proto_ipv6_init);
|
||||
|
|
|
|||
|
|
@ -73,7 +73,7 @@ static struct inet_frags nf_frags;
|
|||
static struct netns_frags nf_init_frags;
|
||||
|
||||
#ifdef CONFIG_SYSCTL
|
||||
struct ctl_table nf_ct_ipv6_sysctl_table[] = {
|
||||
struct ctl_table nf_ct_frag6_sysctl_table[] = {
|
||||
{
|
||||
.procname = "nf_conntrack_frag6_timeout",
|
||||
.data = &nf_init_frags.timeout,
|
||||
|
|
@ -97,6 +97,8 @@ struct ctl_table nf_ct_ipv6_sysctl_table[] = {
|
|||
},
|
||||
{ }
|
||||
};
|
||||
|
||||
static struct ctl_table_header *nf_ct_frag6_sysctl_header;
|
||||
#endif
|
||||
|
||||
static unsigned int nf_hashfn(struct inet_frag_queue *q)
|
||||
|
|
@ -623,11 +625,21 @@ int nf_ct_frag6_init(void)
|
|||
inet_frags_init_net(&nf_init_frags);
|
||||
inet_frags_init(&nf_frags);
|
||||
|
||||
nf_ct_frag6_sysctl_header = register_sysctl_paths(nf_net_netfilter_sysctl_path,
|
||||
nf_ct_frag6_sysctl_table);
|
||||
if (!nf_ct_frag6_sysctl_header) {
|
||||
inet_frags_fini(&nf_frags);
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void nf_ct_frag6_cleanup(void)
|
||||
{
|
||||
unregister_sysctl_table(nf_ct_frag6_sysctl_header);
|
||||
nf_ct_frag6_sysctl_header = NULL;
|
||||
|
||||
inet_frags_fini(&nf_frags);
|
||||
|
||||
nf_init_frags.low_thresh = 0;
|
||||
|
|
|
|||
131
net/ipv6/netfilter/nf_defrag_ipv6_hooks.c
Normal file
131
net/ipv6/netfilter/nf_defrag_ipv6_hooks.c
Normal file
|
|
@ -0,0 +1,131 @@
|
|||
/* (C) 1999-2001 Paul `Rusty' Russell
|
||||
* (C) 2002-2004 Netfilter Core Team <coreteam@netfilter.org>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License version 2 as
|
||||
* published by the Free Software Foundation.
|
||||
*/
|
||||
|
||||
#include <linux/types.h>
|
||||
#include <linux/ipv6.h>
|
||||
#include <linux/in6.h>
|
||||
#include <linux/netfilter.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/skbuff.h>
|
||||
#include <linux/icmp.h>
|
||||
#include <linux/sysctl.h>
|
||||
#include <net/ipv6.h>
|
||||
#include <net/inet_frag.h>
|
||||
|
||||
#include <linux/netfilter_ipv6.h>
|
||||
#include <linux/netfilter_bridge.h>
|
||||
#include <net/netfilter/nf_conntrack.h>
|
||||
#include <net/netfilter/nf_conntrack_helper.h>
|
||||
#include <net/netfilter/nf_conntrack_l4proto.h>
|
||||
#include <net/netfilter/nf_conntrack_l3proto.h>
|
||||
#include <net/netfilter/nf_conntrack_core.h>
|
||||
#include <net/netfilter/nf_conntrack_zones.h>
|
||||
#include <net/netfilter/ipv6/nf_conntrack_ipv6.h>
|
||||
#include <net/netfilter/ipv6/nf_defrag_ipv6.h>
|
||||
|
||||
static enum ip6_defrag_users nf_ct6_defrag_user(unsigned int hooknum,
|
||||
struct sk_buff *skb)
|
||||
{
|
||||
u16 zone = NF_CT_DEFAULT_ZONE;
|
||||
|
||||
if (skb->nfct)
|
||||
zone = nf_ct_zone((struct nf_conn *)skb->nfct);
|
||||
|
||||
#ifdef CONFIG_BRIDGE_NETFILTER
|
||||
if (skb->nf_bridge &&
|
||||
skb->nf_bridge->mask & BRNF_NF_BRIDGE_PREROUTING)
|
||||
return IP6_DEFRAG_CONNTRACK_BRIDGE_IN + zone;
|
||||
#endif
|
||||
if (hooknum == NF_INET_PRE_ROUTING)
|
||||
return IP6_DEFRAG_CONNTRACK_IN + zone;
|
||||
else
|
||||
return IP6_DEFRAG_CONNTRACK_OUT + zone;
|
||||
|
||||
}
|
||||
|
||||
static unsigned int ipv6_defrag(unsigned int hooknum,
|
||||
struct sk_buff *skb,
|
||||
const struct net_device *in,
|
||||
const struct net_device *out,
|
||||
int (*okfn)(struct sk_buff *))
|
||||
{
|
||||
struct sk_buff *reasm;
|
||||
|
||||
/* Previously seen (loopback)? */
|
||||
if (skb->nfct && !nf_ct_is_template((struct nf_conn *)skb->nfct))
|
||||
return NF_ACCEPT;
|
||||
|
||||
reasm = nf_ct_frag6_gather(skb, nf_ct6_defrag_user(hooknum, skb));
|
||||
/* queued */
|
||||
if (reasm == NULL)
|
||||
return NF_STOLEN;
|
||||
|
||||
/* error occured or not fragmented */
|
||||
if (reasm == skb)
|
||||
return NF_ACCEPT;
|
||||
|
||||
nf_ct_frag6_output(hooknum, reasm, (struct net_device *)in,
|
||||
(struct net_device *)out, okfn);
|
||||
|
||||
return NF_STOLEN;
|
||||
}
|
||||
|
||||
static struct nf_hook_ops ipv6_defrag_ops[] = {
|
||||
{
|
||||
.hook = ipv6_defrag,
|
||||
.owner = THIS_MODULE,
|
||||
.pf = NFPROTO_IPV6,
|
||||
.hooknum = NF_INET_PRE_ROUTING,
|
||||
.priority = NF_IP6_PRI_CONNTRACK_DEFRAG,
|
||||
},
|
||||
{
|
||||
.hook = ipv6_defrag,
|
||||
.owner = THIS_MODULE,
|
||||
.pf = NFPROTO_IPV6,
|
||||
.hooknum = NF_INET_LOCAL_OUT,
|
||||
.priority = NF_IP6_PRI_CONNTRACK_DEFRAG,
|
||||
},
|
||||
};
|
||||
|
||||
static int __init nf_defrag_init(void)
|
||||
{
|
||||
int ret = 0;
|
||||
|
||||
ret = nf_ct_frag6_init();
|
||||
if (ret < 0) {
|
||||
pr_err("nf_defrag_ipv6: can't initialize frag6.\n");
|
||||
return ret;
|
||||
}
|
||||
ret = nf_register_hooks(ipv6_defrag_ops, ARRAY_SIZE(ipv6_defrag_ops));
|
||||
if (ret < 0) {
|
||||
pr_err("nf_defrag_ipv6: can't register hooks\n");
|
||||
goto cleanup_frag6;
|
||||
}
|
||||
return ret;
|
||||
|
||||
cleanup_frag6:
|
||||
nf_ct_frag6_cleanup();
|
||||
return ret;
|
||||
|
||||
}
|
||||
|
||||
static void __exit nf_defrag_fini(void)
|
||||
{
|
||||
nf_unregister_hooks(ipv6_defrag_ops, ARRAY_SIZE(ipv6_defrag_ops));
|
||||
nf_ct_frag6_cleanup();
|
||||
}
|
||||
|
||||
void nf_defrag_ipv6_enable(void)
|
||||
{
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(nf_defrag_ipv6_enable);
|
||||
|
||||
module_init(nf_defrag_init);
|
||||
module_exit(nf_defrag_fini);
|
||||
|
||||
MODULE_LICENSE("GPL");
|
||||
|
|
@ -1409,7 +1409,7 @@ static struct sock * tcp_v6_syn_recv_sock(struct sock *sk, struct sk_buff *skb,
|
|||
|
||||
newsk = tcp_create_openreq_child(sk, req, skb);
|
||||
if (newsk == NULL)
|
||||
goto out;
|
||||
goto out_nonewsk;
|
||||
|
||||
/*
|
||||
* No need to charge this sock to the relevant IPv6 refcnt debug socks
|
||||
|
|
@ -1497,18 +1497,22 @@ static struct sock * tcp_v6_syn_recv_sock(struct sock *sk, struct sk_buff *skb,
|
|||
}
|
||||
#endif
|
||||
|
||||
if (__inet_inherit_port(sk, newsk) < 0) {
|
||||
sock_put(newsk);
|
||||
goto out;
|
||||
}
|
||||
__inet6_hash(newsk, NULL);
|
||||
__inet_inherit_port(sk, newsk);
|
||||
|
||||
return newsk;
|
||||
|
||||
out_overflow:
|
||||
NET_INC_STATS_BH(sock_net(sk), LINUX_MIB_LISTENOVERFLOWS);
|
||||
out:
|
||||
NET_INC_STATS_BH(sock_net(sk), LINUX_MIB_LISTENDROPS);
|
||||
out_nonewsk:
|
||||
if (opt && opt != np->opt)
|
||||
sock_kfree_s(sk, opt, opt->tot_len);
|
||||
dst_release(dst);
|
||||
out:
|
||||
NET_INC_STATS_BH(sock_net(sk), LINUX_MIB_LISTENDROPS);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -122,8 +122,8 @@ static void udp_v6_rehash(struct sock *sk)
|
|||
|
||||
static inline int compute_score(struct sock *sk, struct net *net,
|
||||
unsigned short hnum,
|
||||
struct in6_addr *saddr, __be16 sport,
|
||||
struct in6_addr *daddr, __be16 dport,
|
||||
const struct in6_addr *saddr, __be16 sport,
|
||||
const struct in6_addr *daddr, __be16 dport,
|
||||
int dif)
|
||||
{
|
||||
int score = -1;
|
||||
|
|
@ -239,8 +239,8 @@ exact_match:
|
|||
}
|
||||
|
||||
static struct sock *__udp6_lib_lookup(struct net *net,
|
||||
struct in6_addr *saddr, __be16 sport,
|
||||
struct in6_addr *daddr, __be16 dport,
|
||||
const struct in6_addr *saddr, __be16 sport,
|
||||
const struct in6_addr *daddr, __be16 dport,
|
||||
int dif, struct udp_table *udptable)
|
||||
{
|
||||
struct sock *sk, *result;
|
||||
|
|
@ -320,6 +320,14 @@ static struct sock *__udp6_lib_lookup_skb(struct sk_buff *skb,
|
|||
udptable);
|
||||
}
|
||||
|
||||
struct sock *udp6_lib_lookup(struct net *net, const struct in6_addr *saddr, __be16 sport,
|
||||
const struct in6_addr *daddr, __be16 dport, int dif)
|
||||
{
|
||||
return __udp6_lib_lookup(net, saddr, sport, daddr, dport, dif, &udp_table);
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(udp6_lib_lookup);
|
||||
|
||||
|
||||
/*
|
||||
* This should be easy, if there is something there we
|
||||
* return it, otherwise we block.
|
||||
|
|
|
|||
Loading…
Reference in a new issue