Commit 0787840d authored by Tom Parkin's avatar Tom Parkin Committed by David S. Miller

l2tp: cleanup netlink tunnel create address handling

When creating an L2TP tunnel using the netlink API, userspace must
either pass a socket FD for the tunnel to use (for managed tunnels),
or specify the tunnel source/destination address (for unmanaged
tunnels).

Since source/destination addresses may be AF_INET or AF_INET6, the l2tp
netlink code has conditionally compiled blocks to support IPv6.

Rather than embedding these directly into l2tp_nl_cmd_tunnel_create
(where it makes the code difficult to read and confuses checkpatch to
boot) split the handling of address-related attributes into a separate
function.
Signed-off-by: default avatarTom Parkin <tparkin@katalix.com>
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parent 584ca31f
...@@ -155,12 +155,38 @@ static int l2tp_session_notify(struct genl_family *family, ...@@ -155,12 +155,38 @@ static int l2tp_session_notify(struct genl_family *family,
return ret; return ret;
} }
static int l2tp_nl_cmd_tunnel_create_get_addr(struct nlattr **attrs, struct l2tp_tunnel_cfg *cfg)
{
if (attrs[L2TP_ATTR_UDP_SPORT])
cfg->local_udp_port = nla_get_u16(attrs[L2TP_ATTR_UDP_SPORT]);
if (attrs[L2TP_ATTR_UDP_DPORT])
cfg->peer_udp_port = nla_get_u16(attrs[L2TP_ATTR_UDP_DPORT]);
cfg->use_udp_checksums = nla_get_flag(attrs[L2TP_ATTR_UDP_CSUM]);
/* Must have either AF_INET or AF_INET6 address for source and destination */
#if IS_ENABLED(CONFIG_IPV6)
if (attrs[L2TP_ATTR_IP6_SADDR] && attrs[L2TP_ATTR_IP6_DADDR]) {
cfg->local_ip6 = nla_data(attrs[L2TP_ATTR_IP6_SADDR]);
cfg->peer_ip6 = nla_data(attrs[L2TP_ATTR_IP6_DADDR]);
cfg->udp6_zero_tx_checksums = nla_get_flag(attrs[L2TP_ATTR_UDP_ZERO_CSUM6_TX]);
cfg->udp6_zero_rx_checksums = nla_get_flag(attrs[L2TP_ATTR_UDP_ZERO_CSUM6_RX]);
return 0;
}
#endif
if (attrs[L2TP_ATTR_IP_SADDR] && attrs[L2TP_ATTR_IP_DADDR]) {
cfg->local_ip.s_addr = nla_get_in_addr(attrs[L2TP_ATTR_IP_SADDR]);
cfg->peer_ip.s_addr = nla_get_in_addr(attrs[L2TP_ATTR_IP_DADDR]);
return 0;
}
return -EINVAL;
}
static int l2tp_nl_cmd_tunnel_create(struct sk_buff *skb, struct genl_info *info) static int l2tp_nl_cmd_tunnel_create(struct sk_buff *skb, struct genl_info *info)
{ {
u32 tunnel_id; u32 tunnel_id;
u32 peer_tunnel_id; u32 peer_tunnel_id;
int proto_version; int proto_version;
int fd; int fd = -1;
int ret = 0; int ret = 0;
struct l2tp_tunnel_cfg cfg = { 0, }; struct l2tp_tunnel_cfg cfg = { 0, };
struct l2tp_tunnel *tunnel; struct l2tp_tunnel *tunnel;
...@@ -191,34 +217,17 @@ static int l2tp_nl_cmd_tunnel_create(struct sk_buff *skb, struct genl_info *info ...@@ -191,34 +217,17 @@ static int l2tp_nl_cmd_tunnel_create(struct sk_buff *skb, struct genl_info *info
} }
cfg.encap = nla_get_u16(attrs[L2TP_ATTR_ENCAP_TYPE]); cfg.encap = nla_get_u16(attrs[L2TP_ATTR_ENCAP_TYPE]);
fd = -1; /* Managed tunnels take the tunnel socket from userspace.
* Unmanaged tunnels must call out the source and destination addresses
* for the kernel to create the tunnel socket itself.
*/
if (attrs[L2TP_ATTR_FD]) { if (attrs[L2TP_ATTR_FD]) {
fd = nla_get_u32(attrs[L2TP_ATTR_FD]); fd = nla_get_u32(attrs[L2TP_ATTR_FD]);
} else { } else {
#if IS_ENABLED(CONFIG_IPV6) ret = l2tp_nl_cmd_tunnel_create_get_addr(attrs, &cfg);
if (attrs[L2TP_ATTR_IP6_SADDR] && attrs[L2TP_ATTR_IP6_DADDR]) { if (ret < 0)
cfg.local_ip6 = nla_data(attrs[L2TP_ATTR_IP6_SADDR]);
cfg.peer_ip6 = nla_data(attrs[L2TP_ATTR_IP6_DADDR]);
} else
#endif
if (attrs[L2TP_ATTR_IP_SADDR] && attrs[L2TP_ATTR_IP_DADDR]) {
cfg.local_ip.s_addr = nla_get_in_addr(attrs[L2TP_ATTR_IP_SADDR]);
cfg.peer_ip.s_addr = nla_get_in_addr(attrs[L2TP_ATTR_IP_DADDR]);
} else {
ret = -EINVAL;
goto out; goto out;
} }
if (attrs[L2TP_ATTR_UDP_SPORT])
cfg.local_udp_port = nla_get_u16(attrs[L2TP_ATTR_UDP_SPORT]);
if (attrs[L2TP_ATTR_UDP_DPORT])
cfg.peer_udp_port = nla_get_u16(attrs[L2TP_ATTR_UDP_DPORT]);
cfg.use_udp_checksums = nla_get_flag(attrs[L2TP_ATTR_UDP_CSUM]);
#if IS_ENABLED(CONFIG_IPV6)
cfg.udp6_zero_tx_checksums = nla_get_flag(attrs[L2TP_ATTR_UDP_ZERO_CSUM6_TX]);
cfg.udp6_zero_rx_checksums = nla_get_flag(attrs[L2TP_ATTR_UDP_ZERO_CSUM6_RX]);
#endif
}
if (attrs[L2TP_ATTR_DEBUG]) if (attrs[L2TP_ATTR_DEBUG])
cfg.debug = nla_get_u32(attrs[L2TP_ATTR_DEBUG]); cfg.debug = nla_get_u32(attrs[L2TP_ATTR_DEBUG]);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment