aboutsummaryrefslogtreecommitdiffstats
path: root/net/tipc
diff options
context:
space:
mode:
authorRichard Alpe <richard.alpe@ericsson.com>2016-08-26 04:52:56 -0400
committerDavid S. Miller <davem@davemloft.net>2016-08-27 00:38:41 -0400
commit832629ca5c313e122b22b8e73a6d80f111b1a1ae (patch)
treed493c51cbc2bdf880e452f4a21430fbc47ee128e /net/tipc
parentfdb3accc2c15fabc2b687b2819da9167027c61b6 (diff)
tipc: add UDP remoteip dump to netlink API
When using replicast a UDP bearer can have an arbitrary amount of remote ip addresses associated with it. This means we cannot simply add all remote ip addresses to an existing bearer data message as it might fill the message, leaving us with a truncated message that we can't safely resume. To handle this we introduce the new netlink command TIPC_NL_UDP_GET_REMOTEIP. This command is intended to be called when the bearer data message has the TIPC_NLA_UDP_MULTI_REMOTEIP flag set, indicating there are more than one remote ip (replicast). Signed-off-by: Richard Alpe <richard.alpe@ericsson.com> Reviewed-by: Jon Maloy <jon.maloy@ericsson.com> Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'net/tipc')
-rw-r--r--net/tipc/netlink.c10
-rw-r--r--net/tipc/udp_media.c90
-rw-r--r--net/tipc/udp_media.h1
3 files changed, 100 insertions, 1 deletions
diff --git a/net/tipc/netlink.c b/net/tipc/netlink.c
index 3122f21ca979..3200059d14b2 100644
--- a/net/tipc/netlink.c
+++ b/net/tipc/netlink.c
@@ -41,6 +41,7 @@
41#include "link.h" 41#include "link.h"
42#include "node.h" 42#include "node.h"
43#include "net.h" 43#include "net.h"
44#include "udp_media.h"
44#include <net/genetlink.h> 45#include <net/genetlink.h>
45 46
46static const struct nla_policy tipc_nl_policy[TIPC_NLA_MAX + 1] = { 47static const struct nla_policy tipc_nl_policy[TIPC_NLA_MAX + 1] = {
@@ -247,7 +248,14 @@ static const struct genl_ops tipc_genl_v2_ops[] = {
247 .cmd = TIPC_NL_PEER_REMOVE, 248 .cmd = TIPC_NL_PEER_REMOVE,
248 .doit = tipc_nl_peer_rm, 249 .doit = tipc_nl_peer_rm,
249 .policy = tipc_nl_policy, 250 .policy = tipc_nl_policy,
250 } 251 },
252#ifdef CONFIG_TIPC_MEDIA_UDP
253 {
254 .cmd = TIPC_NL_UDP_GET_REMOTEIP,
255 .dumpit = tipc_udp_nl_dump_remoteip,
256 .policy = tipc_nl_policy,
257 },
258#endif
251}; 259};
252 260
253int tipc_nlmsg_parse(const struct nlmsghdr *nlh, struct nlattr ***attr) 261int tipc_nlmsg_parse(const struct nlmsghdr *nlh, struct nlattr ***attr)
diff --git a/net/tipc/udp_media.c b/net/tipc/udp_media.c
index a6cdd9895653..245e9a2eac41 100644
--- a/net/tipc/udp_media.c
+++ b/net/tipc/udp_media.c
@@ -428,6 +428,96 @@ static int __tipc_nl_add_udp_addr(struct sk_buff *skb,
428 return 0; 428 return 0;
429} 429}
430 430
431int tipc_udp_nl_dump_remoteip(struct sk_buff *skb, struct netlink_callback *cb)
432{
433 u32 bid = cb->args[0];
434 u32 skip_cnt = cb->args[1];
435 u32 portid = NETLINK_CB(cb->skb).portid;
436 struct udp_replicast *rcast, *tmp;
437 struct tipc_bearer *b;
438 struct udp_bearer *ub;
439 void *hdr;
440 int err;
441 int i;
442
443 if (!bid && !skip_cnt) {
444 struct net *net = sock_net(skb->sk);
445 struct nlattr *battrs[TIPC_NLA_BEARER_MAX + 1];
446 struct nlattr **attrs;
447 char *bname;
448
449 err = tipc_nlmsg_parse(cb->nlh, &attrs);
450 if (err)
451 return err;
452
453 if (!attrs[TIPC_NLA_BEARER])
454 return -EINVAL;
455
456 err = nla_parse_nested(battrs, TIPC_NLA_BEARER_MAX,
457 attrs[TIPC_NLA_BEARER],
458 tipc_nl_bearer_policy);
459 if (err)
460 return err;
461
462 if (!battrs[TIPC_NLA_BEARER_NAME])
463 return -EINVAL;
464
465 bname = nla_data(battrs[TIPC_NLA_BEARER_NAME]);
466
467 rtnl_lock();
468 b = tipc_bearer_find(net, bname);
469 if (!b) {
470 rtnl_unlock();
471 return -EINVAL;
472 }
473 bid = b->identity;
474 } else {
475 struct net *net = sock_net(skb->sk);
476 struct tipc_net *tn = net_generic(net, tipc_net_id);
477
478 rtnl_lock();
479 b = rtnl_dereference(tn->bearer_list[bid]);
480 if (!b) {
481 rtnl_unlock();
482 return -EINVAL;
483 }
484 }
485
486 ub = rcu_dereference_rtnl(b->media_ptr);
487 if (!ub) {
488 rtnl_unlock();
489 return -EINVAL;
490 }
491
492 i = 0;
493 list_for_each_entry_safe(rcast, tmp, &ub->rcast.list, list) {
494 if (i < skip_cnt)
495 goto count;
496
497 hdr = genlmsg_put(skb, portid, cb->nlh->nlmsg_seq,
498 &tipc_genl_family, NLM_F_MULTI,
499 TIPC_NL_BEARER_GET);
500 if (!hdr)
501 goto done;
502
503 err = __tipc_nl_add_udp_addr(skb, &rcast->addr,
504 TIPC_NLA_UDP_REMOTE);
505 if (err) {
506 genlmsg_cancel(skb, hdr);
507 goto done;
508 }
509 genlmsg_end(skb, hdr);
510count:
511 i++;
512 }
513done:
514 rtnl_unlock();
515 cb->args[0] = bid;
516 cb->args[1] = i;
517
518 return skb->len;
519}
520
431int tipc_udp_nl_add_bearer_data(struct tipc_nl_msg *msg, struct tipc_bearer *b) 521int tipc_udp_nl_add_bearer_data(struct tipc_nl_msg *msg, struct tipc_bearer *b)
432{ 522{
433 struct udp_media_addr *src = (struct udp_media_addr *)&b->addr.value; 523 struct udp_media_addr *src = (struct udp_media_addr *)&b->addr.value;
diff --git a/net/tipc/udp_media.h b/net/tipc/udp_media.h
index c06326a134db..281bbae87726 100644
--- a/net/tipc/udp_media.h
+++ b/net/tipc/udp_media.h
@@ -40,6 +40,7 @@
40 40
41int tipc_udp_nl_bearer_add(struct tipc_bearer *b, struct nlattr *attr); 41int tipc_udp_nl_bearer_add(struct tipc_bearer *b, struct nlattr *attr);
42int tipc_udp_nl_add_bearer_data(struct tipc_nl_msg *msg, struct tipc_bearer *b); 42int tipc_udp_nl_add_bearer_data(struct tipc_nl_msg *msg, struct tipc_bearer *b);
43int tipc_udp_nl_dump_remoteip(struct sk_buff *skb, struct netlink_callback *cb);
43 44
44#endif 45#endif
45#endif 46#endif