diff options
author | Chris Elston <celston@katalix.com> | 2012-04-29 17:48:52 -0400 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2012-05-01 09:30:55 -0400 |
commit | f9bac8df908d7c0a36960265c92f3445623b19d1 (patch) | |
tree | 58bc4af4f65eed62a01027d2358b713b1a060e37 /net/l2tp/l2tp_netlink.c | |
parent | 2121c3f571f08bd723f449f2477f1582709f5a2a (diff) |
l2tp: netlink api for l2tpv3 ipv6 unmanaged tunnels
This patch adds support for unmanaged L2TPv3 tunnels over IPv6 using
the netlink API. We already support unmanaged L2TPv3 tunnels over
IPv4. A patch to iproute2 to make use of this feature will be
submitted separately.
Signed-off-by: Chris Elston <celston@katalix.com>
Signed-off-by: James Chapman <jchapman@katalix.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'net/l2tp/l2tp_netlink.c')
-rw-r--r-- | net/l2tp/l2tp_netlink.c | 48 |
1 files changed, 44 insertions, 4 deletions
diff --git a/net/l2tp/l2tp_netlink.c b/net/l2tp/l2tp_netlink.c index 1dbb9772fc45..24edad0fd9ba 100644 --- a/net/l2tp/l2tp_netlink.c +++ b/net/l2tp/l2tp_netlink.c | |||
@@ -133,10 +133,25 @@ static int l2tp_nl_cmd_tunnel_create(struct sk_buff *skb, struct genl_info *info | |||
133 | if (info->attrs[L2TP_ATTR_FD]) { | 133 | if (info->attrs[L2TP_ATTR_FD]) { |
134 | fd = nla_get_u32(info->attrs[L2TP_ATTR_FD]); | 134 | fd = nla_get_u32(info->attrs[L2TP_ATTR_FD]); |
135 | } else { | 135 | } else { |
136 | if (info->attrs[L2TP_ATTR_IP_SADDR]) | 136 | #if IS_ENABLED(CONFIG_IPV6) |
137 | cfg.local_ip.s_addr = nla_get_be32(info->attrs[L2TP_ATTR_IP_SADDR]); | 137 | if (info->attrs[L2TP_ATTR_IP6_SADDR] && |
138 | if (info->attrs[L2TP_ATTR_IP_DADDR]) | 138 | info->attrs[L2TP_ATTR_IP6_DADDR]) { |
139 | cfg.peer_ip.s_addr = nla_get_be32(info->attrs[L2TP_ATTR_IP_DADDR]); | 139 | cfg.local_ip6 = nla_data( |
140 | info->attrs[L2TP_ATTR_IP6_SADDR]); | ||
141 | cfg.peer_ip6 = nla_data( | ||
142 | info->attrs[L2TP_ATTR_IP6_DADDR]); | ||
143 | } else | ||
144 | #endif | ||
145 | if (info->attrs[L2TP_ATTR_IP_SADDR] && | ||
146 | info->attrs[L2TP_ATTR_IP_DADDR]) { | ||
147 | cfg.local_ip.s_addr = nla_get_be32( | ||
148 | info->attrs[L2TP_ATTR_IP_SADDR]); | ||
149 | cfg.peer_ip.s_addr = nla_get_be32( | ||
150 | info->attrs[L2TP_ATTR_IP_DADDR]); | ||
151 | } else { | ||
152 | ret = -EINVAL; | ||
153 | goto out; | ||
154 | } | ||
140 | if (info->attrs[L2TP_ATTR_UDP_SPORT]) | 155 | if (info->attrs[L2TP_ATTR_UDP_SPORT]) |
141 | cfg.local_udp_port = nla_get_u16(info->attrs[L2TP_ATTR_UDP_SPORT]); | 156 | cfg.local_udp_port = nla_get_u16(info->attrs[L2TP_ATTR_UDP_SPORT]); |
142 | if (info->attrs[L2TP_ATTR_UDP_DPORT]) | 157 | if (info->attrs[L2TP_ATTR_UDP_DPORT]) |
@@ -225,6 +240,9 @@ static int l2tp_nl_tunnel_send(struct sk_buff *skb, u32 pid, u32 seq, int flags, | |||
225 | struct nlattr *nest; | 240 | struct nlattr *nest; |
226 | struct sock *sk = NULL; | 241 | struct sock *sk = NULL; |
227 | struct inet_sock *inet; | 242 | struct inet_sock *inet; |
243 | #if IS_ENABLED(CONFIG_IPV6) | ||
244 | struct ipv6_pinfo *np = NULL; | ||
245 | #endif | ||
228 | struct l2tp_stats stats; | 246 | struct l2tp_stats stats; |
229 | unsigned int start; | 247 | unsigned int start; |
230 | 248 | ||
@@ -273,6 +291,11 @@ static int l2tp_nl_tunnel_send(struct sk_buff *skb, u32 pid, u32 seq, int flags, | |||
273 | if (!sk) | 291 | if (!sk) |
274 | goto out; | 292 | goto out; |
275 | 293 | ||
294 | #if IS_ENABLED(CONFIG_IPV6) | ||
295 | if (sk->sk_family == AF_INET6) | ||
296 | np = inet6_sk(sk); | ||
297 | #endif | ||
298 | |||
276 | inet = inet_sk(sk); | 299 | inet = inet_sk(sk); |
277 | 300 | ||
278 | switch (tunnel->encap) { | 301 | switch (tunnel->encap) { |
@@ -284,6 +307,15 @@ static int l2tp_nl_tunnel_send(struct sk_buff *skb, u32 pid, u32 seq, int flags, | |||
284 | goto nla_put_failure; | 307 | goto nla_put_failure; |
285 | /* NOBREAK */ | 308 | /* NOBREAK */ |
286 | case L2TP_ENCAPTYPE_IP: | 309 | case L2TP_ENCAPTYPE_IP: |
310 | #if IS_ENABLED(CONFIG_IPV6) | ||
311 | if (np) { | ||
312 | if (nla_put(skb, L2TP_ATTR_IP6_SADDR, sizeof(np->saddr), | ||
313 | &np->saddr) || | ||
314 | nla_put(skb, L2TP_ATTR_IP6_DADDR, sizeof(np->daddr), | ||
315 | &np->daddr)) | ||
316 | goto nla_put_failure; | ||
317 | } else | ||
318 | #endif | ||
287 | if (nla_put_be32(skb, L2TP_ATTR_IP_SADDR, inet->inet_saddr) || | 319 | if (nla_put_be32(skb, L2TP_ATTR_IP_SADDR, inet->inet_saddr) || |
288 | nla_put_be32(skb, L2TP_ATTR_IP_DADDR, inet->inet_daddr)) | 320 | nla_put_be32(skb, L2TP_ATTR_IP_DADDR, inet->inet_daddr)) |
289 | goto nla_put_failure; | 321 | goto nla_put_failure; |
@@ -752,6 +784,14 @@ static struct nla_policy l2tp_nl_policy[L2TP_ATTR_MAX + 1] = { | |||
752 | [L2TP_ATTR_MTU] = { .type = NLA_U16, }, | 784 | [L2TP_ATTR_MTU] = { .type = NLA_U16, }, |
753 | [L2TP_ATTR_MRU] = { .type = NLA_U16, }, | 785 | [L2TP_ATTR_MRU] = { .type = NLA_U16, }, |
754 | [L2TP_ATTR_STATS] = { .type = NLA_NESTED, }, | 786 | [L2TP_ATTR_STATS] = { .type = NLA_NESTED, }, |
787 | [L2TP_ATTR_IP6_SADDR] = { | ||
788 | .type = NLA_BINARY, | ||
789 | .len = sizeof(struct in6_addr), | ||
790 | }, | ||
791 | [L2TP_ATTR_IP6_DADDR] = { | ||
792 | .type = NLA_BINARY, | ||
793 | .len = sizeof(struct in6_addr), | ||
794 | }, | ||
755 | [L2TP_ATTR_IFNAME] = { | 795 | [L2TP_ATTR_IFNAME] = { |
756 | .type = NLA_NUL_STRING, | 796 | .type = NLA_NUL_STRING, |
757 | .len = IFNAMSIZ - 1, | 797 | .len = IFNAMSIZ - 1, |