aboutsummaryrefslogtreecommitdiffstats
path: root/net/tipc
diff options
context:
space:
mode:
authorRichard Alpe <richard.alpe@ericsson.com>2016-08-26 04:52:50 -0400
committerDavid S. Miller <davem@davemloft.net>2016-08-27 00:38:40 -0400
commitba5aa84a2d2243d56328e51497a6106dcdf67eef (patch)
treefbc7f88041286bb45b8f6d82955cf5776299e8ce /net/tipc
parentf01d5988639bc7f8c525d16d5d84562755d3c0ca (diff)
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: Richard Alpe <richard.alpe@ericsson.com> Reviewed-by: Jon Maloy <jon.maloy@ericsson.com> Acked-by: Ying Xue <ying.xue@windriver.com> Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'net/tipc')
-rw-r--r--net/tipc/udp_media.c112
1 files changed, 55 insertions, 57 deletions
diff --git a/net/tipc/udp_media.c b/net/tipc/udp_media.c
index 33bdf5449a5e..adb3c2117a1c 100644
--- a/net/tipc/udp_media.c
+++ b/net/tipc/udp_media.c
@@ -258,68 +258,47 @@ static int enable_mcast(struct udp_bearer *ub, struct udp_media_addr *remote)
258} 258}
259 259
260/** 260/**
261 * parse_options - build local/remote addresses from configuration 261 * tipc_parse_udp_addr - build udp media address from netlink data
262 * @attrs: netlink config data 262 * @nlattr: netlink attribute containing sockaddr storage aligned address
263 * @ub: UDP bearer instance 263 * @addr: tipc media address to fill with address, port and protocol type
264 * @local: local bearer IP address/port 264 * @scope_id: IPv6 scope id pointer, not NULL indicates it's required
265 * @remote: peer or multicast IP/port
266 */ 265 */
267static int parse_options(struct nlattr *attrs[], struct udp_bearer *ub, 266
268 struct udp_media_addr *local, 267static int tipc_parse_udp_addr(struct nlattr *nla, struct udp_media_addr *addr,
269 struct udp_media_addr *remote) 268 u32 *scope_id)
270{ 269{
271 struct nlattr *opts[TIPC_NLA_UDP_MAX + 1]; 270 struct sockaddr_storage sa;
272 struct sockaddr_storage sa_local, sa_remote;
273 271
274 if (!attrs[TIPC_NLA_BEARER_UDP_OPTS]) 272 nla_memcpy(&sa, nla, sizeof(sa));
275 goto err; 273 if (sa.ss_family == AF_INET) {
276 if (nla_parse_nested(opts, TIPC_NLA_UDP_MAX, 274 struct sockaddr_in *ip4 = (struct sockaddr_in *)&sa;
277 attrs[TIPC_NLA_BEARER_UDP_OPTS], 275
278 tipc_nl_udp_policy)) 276 addr->proto = htons(ETH_P_IP);
279 goto err; 277 addr->port = ip4->sin_port;
280 if (opts[TIPC_NLA_UDP_LOCAL] && opts[TIPC_NLA_UDP_REMOTE]) { 278 addr->ipv4.s_addr = ip4->sin_addr.s_addr;
281 nla_memcpy(&sa_local, opts[TIPC_NLA_UDP_LOCAL],
282 sizeof(sa_local));
283 nla_memcpy(&sa_remote, opts[TIPC_NLA_UDP_REMOTE],
284 sizeof(sa_remote));
285 } else {
286err:
287 pr_err("Invalid UDP bearer configuration");
288 return -EINVAL;
289 }
290 if ((sa_local.ss_family & sa_remote.ss_family) == AF_INET) {
291 struct sockaddr_in *ip4;
292
293 ip4 = (struct sockaddr_in *)&sa_local;
294 local->proto = htons(ETH_P_IP);
295 local->port = ip4->sin_port;
296 local->ipv4.s_addr = ip4->sin_addr.s_addr;
297
298 ip4 = (struct sockaddr_in *)&sa_remote;
299 remote->proto = htons(ETH_P_IP);
300 remote->port = ip4->sin_port;
301 remote->ipv4.s_addr = ip4->sin_addr.s_addr;
302 return 0; 279 return 0;
303 280
304#if IS_ENABLED(CONFIG_IPV6) 281#if IS_ENABLED(CONFIG_IPV6)
305 } else if ((sa_local.ss_family & sa_remote.ss_family) == AF_INET6) { 282 } else if (sa.ss_family == AF_INET6) {
306 int atype; 283 struct sockaddr_in6 *ip6 = (struct sockaddr_in6 *)&sa;
307 struct sockaddr_in6 *ip6; 284
308 285 addr->proto = htons(ETH_P_IPV6);
309 ip6 = (struct sockaddr_in6 *)&sa_local; 286 addr->port = ip6->sin6_port;
310 atype = ipv6_addr_type(&ip6->sin6_addr); 287 memcpy(&addr->ipv6, &ip6->sin6_addr, sizeof(struct in6_addr));
311 if (__ipv6_addr_needs_scope_id(atype) && !ip6->sin6_scope_id) 288
312 return -EINVAL; 289 /* Scope ID is only interesting for local addresses */
313 290 if (scope_id) {
314 local->proto = htons(ETH_P_IPV6); 291 int atype;
315 local->port = ip6->sin6_port; 292
316 memcpy(&local->ipv6, &ip6->sin6_addr, sizeof(struct in6_addr)); 293 atype = ipv6_addr_type(&ip6->sin6_addr);
317 ub->ifindex = ip6->sin6_scope_id; 294 if (__ipv6_addr_needs_scope_id(atype) &&
318 295 !ip6->sin6_scope_id) {
319 ip6 = (struct sockaddr_in6 *)&sa_remote; 296 return -EINVAL;
320 remote->proto = htons(ETH_P_IPV6); 297 }
321 remote->port = ip6->sin6_port; 298
322 memcpy(&remote->ipv6, &ip6->sin6_addr, sizeof(struct in6_addr)); 299 *scope_id = ip6->sin6_scope_id ? : 0;
300 }
301
323 return 0; 302 return 0;
324#endif 303#endif
325 } 304 }
@@ -344,14 +323,33 @@ static int tipc_udp_enable(struct net *net, struct tipc_bearer *b,
344 struct udp_media_addr local = {0}; 323 struct udp_media_addr local = {0};
345 struct udp_port_cfg udp_conf = {0}; 324 struct udp_port_cfg udp_conf = {0};
346 struct udp_tunnel_sock_cfg tuncfg = {NULL}; 325 struct udp_tunnel_sock_cfg tuncfg = {NULL};
326 struct nlattr *opts[TIPC_NLA_UDP_MAX + 1];
347 327
348 ub = kzalloc(sizeof(*ub), GFP_ATOMIC); 328 ub = kzalloc(sizeof(*ub), GFP_ATOMIC);
349 if (!ub) 329 if (!ub)
350 return -ENOMEM; 330 return -ENOMEM;
351 331
332 if (!attrs[TIPC_NLA_BEARER_UDP_OPTS])
333 goto err;
334
335 if (nla_parse_nested(opts, TIPC_NLA_UDP_MAX,
336 attrs[TIPC_NLA_BEARER_UDP_OPTS],
337 tipc_nl_udp_policy))
338 goto err;
339
340 if (!opts[TIPC_NLA_UDP_LOCAL] || !opts[TIPC_NLA_UDP_REMOTE]) {
341 pr_err("Invalid UDP bearer configuration");
342 return -EINVAL;
343 }
344
345 err = tipc_parse_udp_addr(opts[TIPC_NLA_UDP_LOCAL], &local,
346 &ub->ifindex);
347 if (err)
348 goto err;
349
352 remote = (struct udp_media_addr *)&b->bcast_addr.value; 350 remote = (struct udp_media_addr *)&b->bcast_addr.value;
353 memset(remote, 0, sizeof(struct udp_media_addr)); 351 memset(remote, 0, sizeof(struct udp_media_addr));
354 err = parse_options(attrs, ub, &local, remote); 352 err = tipc_parse_udp_addr(opts[TIPC_NLA_UDP_REMOTE], remote, NULL);
355 if (err) 353 if (err)
356 goto err; 354 goto err;
357 355