Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

tipc: add the ability to get UDP options via netlink

Add UDP bearer options to netlink bearer get message. This is used by
the tipc user space tool to display UDP options.

The UDP bearer information is passed using either a sockaddr_in or
sockaddr_in6 structs. This means the user space receiver should
intermediately store the retrieved data in a large enough struct
(sockaddr_strage) before casting to the proper IP version type.

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>

authored by

Richard Alpe and committed by
David S. Miller
fdb3accc c9b64d49

+72
+2
include/uapi/linux/tipc_netlink.h
··· 61 61 TIPC_NL_MON_PEER_GET, 62 62 TIPC_NL_PEER_REMOVE, 63 63 TIPC_NL_BEARER_ADD, 64 + TIPC_NL_UDP_GET_REMOTEIP, 64 65 65 66 __TIPC_NL_CMD_MAX, 66 67 TIPC_NL_CMD_MAX = __TIPC_NL_CMD_MAX - 1 ··· 101 100 TIPC_NLA_UDP_UNSPEC, 102 101 TIPC_NLA_UDP_LOCAL, /* sockaddr_storage */ 103 102 TIPC_NLA_UDP_REMOTE, /* sockaddr_storage */ 103 + TIPC_NLA_UDP_MULTI_REMOTEIP, /* flag */ 104 104 105 105 __TIPC_NLA_UDP_MAX, 106 106 TIPC_NLA_UDP_MAX = __TIPC_NLA_UDP_MAX - 1
+8
net/tipc/bearer.c
··· 712 712 goto prop_msg_full; 713 713 714 714 nla_nest_end(msg->skb, prop); 715 + 716 + #ifdef CONFIG_TIPC_MEDIA_UDP 717 + if (bearer->media->type_id == TIPC_MEDIA_TYPE_UDP) { 718 + if (tipc_udp_nl_add_bearer_data(msg, bearer)) 719 + goto attr_msg_full; 720 + } 721 + #endif 722 + 715 723 nla_nest_end(msg->skb, attrs); 716 724 genlmsg_end(msg->skb, hdr); 717 725
+61
net/tipc/udp_media.c
··· 401 401 return err; 402 402 } 403 403 404 + static int __tipc_nl_add_udp_addr(struct sk_buff *skb, 405 + struct udp_media_addr *addr, int nla_t) 406 + { 407 + if (ntohs(addr->proto) == ETH_P_IP) { 408 + struct sockaddr_in ip4; 409 + 410 + ip4.sin_family = AF_INET; 411 + ip4.sin_port = addr->port; 412 + ip4.sin_addr.s_addr = addr->ipv4.s_addr; 413 + if (nla_put(skb, nla_t, sizeof(ip4), &ip4)) 414 + return -EMSGSIZE; 415 + 416 + #if IS_ENABLED(CONFIG_IPV6) 417 + } else if (ntohs(addr->proto) == ETH_P_IPV6) { 418 + struct sockaddr_in6 ip6; 419 + 420 + ip6.sin6_family = AF_INET6; 421 + ip6.sin6_port = addr->port; 422 + memcpy(&ip6.sin6_addr, &addr->ipv6, sizeof(struct in6_addr)); 423 + if (nla_put(skb, nla_t, sizeof(ip6), &ip6)) 424 + return -EMSGSIZE; 425 + #endif 426 + } 427 + 428 + return 0; 429 + } 430 + 431 + int tipc_udp_nl_add_bearer_data(struct tipc_nl_msg *msg, struct tipc_bearer *b) 432 + { 433 + struct udp_media_addr *src = (struct udp_media_addr *)&b->addr.value; 434 + struct udp_media_addr *dst; 435 + struct udp_bearer *ub; 436 + struct nlattr *nest; 437 + 438 + ub = rcu_dereference_rtnl(b->media_ptr); 439 + if (!ub) 440 + return -ENODEV; 441 + 442 + nest = nla_nest_start(msg->skb, TIPC_NLA_BEARER_UDP_OPTS); 443 + if (!nest) 444 + goto msg_full; 445 + 446 + if (__tipc_nl_add_udp_addr(msg->skb, src, TIPC_NLA_UDP_LOCAL)) 447 + goto msg_full; 448 + 449 + dst = (struct udp_media_addr *)&b->bcast_addr.value; 450 + if (__tipc_nl_add_udp_addr(msg->skb, dst, TIPC_NLA_UDP_REMOTE)) 451 + goto msg_full; 452 + 453 + if (!list_empty(&ub->rcast.list)) { 454 + if (nla_put_flag(msg->skb, TIPC_NLA_UDP_MULTI_REMOTEIP)) 455 + goto msg_full; 456 + } 457 + 458 + nla_nest_end(msg->skb, nest); 459 + return 0; 460 + msg_full: 461 + nla_nest_cancel(msg->skb, nest); 462 + return -EMSGSIZE; 463 + } 464 + 404 465 /** 405 466 * tipc_parse_udp_addr - build udp media address from netlink data 406 467 * @nlattr: netlink attribute containing sockaddr storage aligned address
+1
net/tipc/udp_media.h
··· 39 39 #define _TIPC_UDP_MEDIA_H 40 40 41 41 int tipc_udp_nl_bearer_add(struct tipc_bearer *b, struct nlattr *attr); 42 + int tipc_udp_nl_add_bearer_data(struct tipc_nl_msg *msg, struct tipc_bearer *b); 42 43 43 44 #endif 44 45 #endif