Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 545b2901 authored by David S. Miller's avatar David S. Miller
Browse files

Merge branch 'master' of git://1984.lsi.us.es/nf-next



Conflicts:
	net/ipv6/netfilter/nf_conntrack_l3proto_ipv6.c

Minor conflict due to some IS_ENABLED conversions done
in net-next.

Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parents 130cd273 d3976a53
Loading
Loading
Loading
Loading
+1 −0
Original line number Diff line number Diff line
@@ -240,6 +240,7 @@ struct in6_flowlabel_req {
 *
 * IP6T_SO_GET_REVISION_MATCH	68
 * IP6T_SO_GET_REVISION_TARGET	69
 * IP6T_SO_ORIGINAL_DST		80
 */

/* RFC5014: Source address selection */
+3 −0
Original line number Diff line number Diff line
@@ -178,6 +178,9 @@ struct ip6t_error {
#define IP6T_SO_GET_REVISION_TARGET	(IP6T_BASE_CTL + 5)
#define IP6T_SO_GET_MAX			IP6T_SO_GET_REVISION_TARGET

/* obtain original address if REDIRECT'd connection */
#define IP6T_SO_ORIGINAL_DST            80

/* ICMP matching stuff */
struct ip6t_icmp {
	__u8 type;				/* type to match */
+1 −3
Original line number Diff line number Diff line
@@ -276,9 +276,7 @@ static int __net_init iptable_nat_net_init(struct net *net)
		return -ENOMEM;
	net->ipv4.nat_table = ipt_register_table(net, &nf_nat_ipv4_table, repl);
	kfree(repl);
	if (IS_ERR(net->ipv4.nat_table))
		return PTR_ERR(net->ipv4.nat_table);
	return 0;
	return PTR_RET(net->ipv4.nat_table);
}

static void __net_exit iptable_nat_net_exit(struct net *net)
+1 −3
Original line number Diff line number Diff line
@@ -277,9 +277,7 @@ static int __net_init ip6table_nat_net_init(struct net *net)
		return -ENOMEM;
	net->ipv6.ip6table_nat = ip6t_register_table(net, &nf_nat_ipv6_table, repl);
	kfree(repl);
	if (IS_ERR(net->ipv6.ip6table_nat))
		return PTR_ERR(net->ipv6.ip6table_nat);
	return 0;
	return PTR_RET(net->ipv6.ip6table_nat);
}

static void __net_exit ip6table_nat_net_exit(struct net *net)
+66 −0
Original line number Diff line number Diff line
@@ -21,6 +21,7 @@

#include <linux/netfilter_bridge.h>
#include <linux/netfilter_ipv6.h>
#include <linux/netfilter_ipv6/ip6_tables.h>
#include <net/netfilter/nf_conntrack.h>
#include <net/netfilter/nf_conntrack_helper.h>
#include <net/netfilter/nf_conntrack_l4proto.h>
@@ -295,6 +296,55 @@ static struct nf_hook_ops ipv6_conntrack_ops[] __read_mostly = {
	},
};

static int
ipv6_getorigdst(struct sock *sk, int optval, void __user *user, int *len)
{
	const struct inet_sock *inet = inet_sk(sk);
	const struct ipv6_pinfo *inet6 = inet6_sk(sk);
	const struct nf_conntrack_tuple_hash *h;
	struct sockaddr_in6 sin6;
	struct nf_conntrack_tuple tuple = { .src.l3num = NFPROTO_IPV6 };
	struct nf_conn *ct;

	tuple.src.u3.in6 = inet6->rcv_saddr;
	tuple.src.u.tcp.port = inet->inet_sport;
	tuple.dst.u3.in6 = inet6->daddr;
	tuple.dst.u.tcp.port = inet->inet_dport;
	tuple.dst.protonum = sk->sk_protocol;

	if (sk->sk_protocol != IPPROTO_TCP && sk->sk_protocol != IPPROTO_SCTP)
		return -ENOPROTOOPT;

	if (*len < 0 || (unsigned int) *len < sizeof(sin6))
		return -EINVAL;

	h = nf_conntrack_find_get(sock_net(sk), NF_CT_DEFAULT_ZONE, &tuple);
	if (!h) {
		pr_debug("IP6T_SO_ORIGINAL_DST: Can't find %pI6c/%u-%pI6c/%u.\n",
			 &tuple.src.u3.ip6, ntohs(tuple.src.u.tcp.port),
			 &tuple.dst.u3.ip6, ntohs(tuple.dst.u.tcp.port));
		return -ENOENT;
	}

	ct = nf_ct_tuplehash_to_ctrack(h);

	sin6.sin6_family = AF_INET6;
	sin6.sin6_port = ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple.dst.u.tcp.port;
	sin6.sin6_flowinfo = inet6->flow_label & IPV6_FLOWINFO_MASK;
	memcpy(&sin6.sin6_addr,
		&ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple.dst.u3.in6,
					sizeof(sin6.sin6_addr));

	nf_ct_put(ct);

	if (ipv6_addr_type(&sin6.sin6_addr) & IPV6_ADDR_LINKLOCAL)
		sin6.sin6_scope_id = sk->sk_bound_dev_if;
	else
		sin6.sin6_scope_id = 0;

	return copy_to_user(user, &sin6, sizeof(sin6)) ? -EFAULT : 0;
}

#if IS_ENABLED(CONFIG_NF_CT_NETLINK)

#include <linux/netfilter/nfnetlink.h>
@@ -359,6 +409,14 @@ MODULE_ALIAS("nf_conntrack-" __stringify(AF_INET6));
MODULE_LICENSE("GPL");
MODULE_AUTHOR("Yasuyuki KOZAKAI @USAGI <yasuyuki.kozakai@toshiba.co.jp>");

static struct nf_sockopt_ops so_getorigdst6 = {
	.pf		= NFPROTO_IPV6,
	.get_optmin	= IP6T_SO_ORIGINAL_DST,
	.get_optmax	= IP6T_SO_ORIGINAL_DST + 1,
	.get		= ipv6_getorigdst,
	.owner		= THIS_MODULE,
};

static int ipv6_net_init(struct net *net)
{
	int ret = 0;
@@ -425,6 +483,12 @@ static int __init nf_conntrack_l3proto_ipv6_init(void)
	need_conntrack();
	nf_defrag_ipv6_enable();

	ret = nf_register_sockopt(&so_getorigdst6);
	if (ret < 0) {
		pr_err("Unable to register netfilter socket option\n");
		return ret;
	}

	ret = register_pernet_subsys(&ipv6_net_ops);
	if (ret < 0)
		goto cleanup_pernet;
@@ -440,6 +504,7 @@ static int __init nf_conntrack_l3proto_ipv6_init(void)
 cleanup_ipv6:
	unregister_pernet_subsys(&ipv6_net_ops);
 cleanup_pernet:
	nf_unregister_sockopt(&so_getorigdst6);
	return ret;
}

@@ -448,6 +513,7 @@ static void __exit nf_conntrack_l3proto_ipv6_fini(void)
	synchronize_net();
	nf_unregister_hooks(ipv6_conntrack_ops, ARRAY_SIZE(ipv6_conntrack_ops));
	unregister_pernet_subsys(&ipv6_net_ops);
	nf_unregister_sockopt(&so_getorigdst6);
}

module_init(nf_conntrack_l3proto_ipv6_init);
Loading