Commit ba5aa84a authored by Richard Alpe's avatar Richard Alpe Committed by David S. Miller

tipc: split UDP nl address parsing

Split the UDP netlink parse function so that it only parses one
netlink attribute at the time. This makes the parse function more
generic and allow future UDP API functions to use it for parsing.
Signed-off-by: default avatarRichard Alpe <richard.alpe@ericsson.com>
Reviewed-by: default avatarJon Maloy <jon.maloy@ericsson.com>
Acked-by: default avatarYing Xue <ying.xue@windriver.com>
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parent f01d5988
...@@ -258,68 +258,47 @@ static int enable_mcast(struct udp_bearer *ub, struct udp_media_addr *remote) ...@@ -258,68 +258,47 @@ static int enable_mcast(struct udp_bearer *ub, struct udp_media_addr *remote)
} }
/** /**
* parse_options - build local/remote addresses from configuration * tipc_parse_udp_addr - build udp media address from netlink data
* @attrs: netlink config data * @nlattr: netlink attribute containing sockaddr storage aligned address
* @ub: UDP bearer instance * @addr: tipc media address to fill with address, port and protocol type
* @local: local bearer IP address/port * @scope_id: IPv6 scope id pointer, not NULL indicates it's required
* @remote: peer or multicast IP/port
*/ */
static int parse_options(struct nlattr *attrs[], struct udp_bearer *ub,
struct udp_media_addr *local, static int tipc_parse_udp_addr(struct nlattr *nla, struct udp_media_addr *addr,
struct udp_media_addr *remote) u32 *scope_id)
{ {
struct nlattr *opts[TIPC_NLA_UDP_MAX + 1]; struct sockaddr_storage sa;
struct sockaddr_storage sa_local, sa_remote;
if (!attrs[TIPC_NLA_BEARER_UDP_OPTS]) nla_memcpy(&sa, nla, sizeof(sa));
goto err; if (sa.ss_family == AF_INET) {
if (nla_parse_nested(opts, TIPC_NLA_UDP_MAX, struct sockaddr_in *ip4 = (struct sockaddr_in *)&sa;
attrs[TIPC_NLA_BEARER_UDP_OPTS],
tipc_nl_udp_policy)) addr->proto = htons(ETH_P_IP);
goto err; addr->port = ip4->sin_port;
if (opts[TIPC_NLA_UDP_LOCAL] && opts[TIPC_NLA_UDP_REMOTE]) { addr->ipv4.s_addr = ip4->sin_addr.s_addr;
nla_memcpy(&sa_local, opts[TIPC_NLA_UDP_LOCAL],
sizeof(sa_local));
nla_memcpy(&sa_remote, opts[TIPC_NLA_UDP_REMOTE],
sizeof(sa_remote));
} else {
err:
pr_err("Invalid UDP bearer configuration");
return -EINVAL;
}
if ((sa_local.ss_family & sa_remote.ss_family) == AF_INET) {
struct sockaddr_in *ip4;
ip4 = (struct sockaddr_in *)&sa_local;
local->proto = htons(ETH_P_IP);
local->port = ip4->sin_port;
local->ipv4.s_addr = ip4->sin_addr.s_addr;
ip4 = (struct sockaddr_in *)&sa_remote;
remote->proto = htons(ETH_P_IP);
remote->port = ip4->sin_port;
remote->ipv4.s_addr = ip4->sin_addr.s_addr;
return 0; return 0;
#if IS_ENABLED(CONFIG_IPV6) #if IS_ENABLED(CONFIG_IPV6)
} else if ((sa_local.ss_family & sa_remote.ss_family) == AF_INET6) { } else if (sa.ss_family == AF_INET6) {
int atype; struct sockaddr_in6 *ip6 = (struct sockaddr_in6 *)&sa;
struct sockaddr_in6 *ip6;
addr->proto = htons(ETH_P_IPV6);
ip6 = (struct sockaddr_in6 *)&sa_local; addr->port = ip6->sin6_port;
atype = ipv6_addr_type(&ip6->sin6_addr); memcpy(&addr->ipv6, &ip6->sin6_addr, sizeof(struct in6_addr));
if (__ipv6_addr_needs_scope_id(atype) && !ip6->sin6_scope_id)
return -EINVAL; /* Scope ID is only interesting for local addresses */
if (scope_id) {
local->proto = htons(ETH_P_IPV6); int atype;
local->port = ip6->sin6_port;
memcpy(&local->ipv6, &ip6->sin6_addr, sizeof(struct in6_addr)); atype = ipv6_addr_type(&ip6->sin6_addr);
ub->ifindex = ip6->sin6_scope_id; if (__ipv6_addr_needs_scope_id(atype) &&
!ip6->sin6_scope_id) {
ip6 = (struct sockaddr_in6 *)&sa_remote; return -EINVAL;
remote->proto = htons(ETH_P_IPV6); }
remote->port = ip6->sin6_port;
memcpy(&remote->ipv6, &ip6->sin6_addr, sizeof(struct in6_addr)); *scope_id = ip6->sin6_scope_id ? : 0;
}
return 0; return 0;
#endif #endif
} }
...@@ -344,14 +323,33 @@ static int tipc_udp_enable(struct net *net, struct tipc_bearer *b, ...@@ -344,14 +323,33 @@ static int tipc_udp_enable(struct net *net, struct tipc_bearer *b,
struct udp_media_addr local = {0}; struct udp_media_addr local = {0};
struct udp_port_cfg udp_conf = {0}; struct udp_port_cfg udp_conf = {0};
struct udp_tunnel_sock_cfg tuncfg = {NULL}; struct udp_tunnel_sock_cfg tuncfg = {NULL};
struct nlattr *opts[TIPC_NLA_UDP_MAX + 1];
ub = kzalloc(sizeof(*ub), GFP_ATOMIC); ub = kzalloc(sizeof(*ub), GFP_ATOMIC);
if (!ub) if (!ub)
return -ENOMEM; return -ENOMEM;
if (!attrs[TIPC_NLA_BEARER_UDP_OPTS])
goto err;
if (nla_parse_nested(opts, TIPC_NLA_UDP_MAX,
attrs[TIPC_NLA_BEARER_UDP_OPTS],
tipc_nl_udp_policy))
goto err;
if (!opts[TIPC_NLA_UDP_LOCAL] || !opts[TIPC_NLA_UDP_REMOTE]) {
pr_err("Invalid UDP bearer configuration");
return -EINVAL;
}
err = tipc_parse_udp_addr(opts[TIPC_NLA_UDP_LOCAL], &local,
&ub->ifindex);
if (err)
goto err;
remote = (struct udp_media_addr *)&b->bcast_addr.value; remote = (struct udp_media_addr *)&b->bcast_addr.value;
memset(remote, 0, sizeof(struct udp_media_addr)); memset(remote, 0, sizeof(struct udp_media_addr));
err = parse_options(attrs, ub, &local, remote); err = tipc_parse_udp_addr(opts[TIPC_NLA_UDP_REMOTE], remote, NULL);
if (err) if (err)
goto err; goto err;
......
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