aboutsummaryrefslogtreecommitdiffstats
path: root/net/tipc
diff options
context:
space:
mode:
authorRichard Alpe <richard.alpe@ericsson.com>2014-11-20 04:29:11 -0500
committerDavid S. Miller <davem@davemloft.net>2014-11-21 15:01:30 -0500
commit1a1a143daf84db95dd7212086042004a3abb7bc2 (patch)
treeac69d87fa4ab8434bf69f0121a51d83a48cf728d /net/tipc
parent34b78a127c4fd57cf3d5c64031693d10a8e0fae1 (diff)
tipc: add publication dump to new netlink api
Add TIPC_NL_PUBL_GET command to the new tipc netlink API. This command supports dumping of all publications for a specific socket. Netlink logical layout of request message: -> socket -> reference Netlink logical layout of response message: -> publication -> type -> lower -> upper Signed-off-by: Richard Alpe <richard.alpe@ericsson.com> Reviewed-by: Erik Hugne <erik.hugne@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/netlink.c17
-rw-r--r--net/tipc/netlink.h1
-rw-r--r--net/tipc/socket.c135
-rw-r--r--net/tipc/socket.h1
4 files changed, 154 insertions, 0 deletions
diff --git a/net/tipc/netlink.c b/net/tipc/netlink.c
index 951fabeec8b7..9bc64aaff466 100644
--- a/net/tipc/netlink.c
+++ b/net/tipc/netlink.c
@@ -74,6 +74,7 @@ static const struct nla_policy tipc_nl_policy[TIPC_NLA_MAX + 1] = {
74 [TIPC_NLA_UNSPEC] = { .type = NLA_UNSPEC, }, 74 [TIPC_NLA_UNSPEC] = { .type = NLA_UNSPEC, },
75 [TIPC_NLA_BEARER] = { .type = NLA_NESTED, }, 75 [TIPC_NLA_BEARER] = { .type = NLA_NESTED, },
76 [TIPC_NLA_SOCK] = { .type = NLA_NESTED, }, 76 [TIPC_NLA_SOCK] = { .type = NLA_NESTED, },
77 [TIPC_NLA_PUBL] = { .type = NLA_NESTED, }
77}; 78};
78 79
79/* Legacy ASCII API */ 80/* Legacy ASCII API */
@@ -130,9 +131,25 @@ static const struct genl_ops tipc_genl_v2_ops[] = {
130 .cmd = TIPC_NL_SOCK_GET, 131 .cmd = TIPC_NL_SOCK_GET,
131 .dumpit = tipc_nl_sk_dump, 132 .dumpit = tipc_nl_sk_dump,
132 .policy = tipc_nl_policy, 133 .policy = tipc_nl_policy,
134 },
135 {
136 .cmd = TIPC_NL_PUBL_GET,
137 .dumpit = tipc_nl_publ_dump,
138 .policy = tipc_nl_policy,
133 } 139 }
134}; 140};
135 141
142int tipc_nlmsg_parse(const struct nlmsghdr *nlh, struct nlattr ***attr)
143{
144 u32 maxattr = tipc_genl_v2_family.maxattr;
145
146 *attr = tipc_genl_v2_family.attrbuf;
147 if (!*attr)
148 return -EOPNOTSUPP;
149
150 return nlmsg_parse(nlh, GENL_HDRLEN, *attr, maxattr, tipc_nl_policy);
151}
152
136int tipc_netlink_start(void) 153int tipc_netlink_start(void)
137{ 154{
138 int res; 155 int res;
diff --git a/net/tipc/netlink.h b/net/tipc/netlink.h
index e34a3fca7d3d..1425c6869de0 100644
--- a/net/tipc/netlink.h
+++ b/net/tipc/netlink.h
@@ -37,6 +37,7 @@
37#define _TIPC_NETLINK_H 37#define _TIPC_NETLINK_H
38 38
39extern struct genl_family tipc_genl_v2_family; 39extern struct genl_family tipc_genl_v2_family;
40int tipc_nlmsg_parse(const struct nlmsghdr *nlh, struct nlattr ***buf);
40 41
41struct tipc_nl_msg { 42struct tipc_nl_msg {
42 struct sk_buff *skb; 43 struct sk_buff *skb;
diff --git a/net/tipc/socket.c b/net/tipc/socket.c
index 9e95c1ea5564..e91809182c28 100644
--- a/net/tipc/socket.c
+++ b/net/tipc/socket.c
@@ -121,6 +121,14 @@ static const struct proto_ops msg_ops;
121static struct proto tipc_proto; 121static struct proto tipc_proto;
122static struct proto tipc_proto_kern; 122static struct proto tipc_proto_kern;
123 123
124static const struct nla_policy tipc_nl_sock_policy[TIPC_NLA_SOCK_MAX + 1] = {
125 [TIPC_NLA_SOCK_UNSPEC] = { .type = NLA_UNSPEC },
126 [TIPC_NLA_SOCK_ADDR] = { .type = NLA_U32 },
127 [TIPC_NLA_SOCK_REF] = { .type = NLA_U32 },
128 [TIPC_NLA_SOCK_CON] = { .type = NLA_NESTED },
129 [TIPC_NLA_SOCK_HAS_PUBL] = { .type = NLA_FLAG }
130};
131
124/* 132/*
125 * Revised TIPC socket locking policy: 133 * Revised TIPC socket locking policy:
126 * 134 *
@@ -2902,3 +2910,130 @@ int tipc_nl_sk_dump(struct sk_buff *skb, struct netlink_callback *cb)
2902 2910
2903 return skb->len; 2911 return skb->len;
2904} 2912}
2913
2914/* Caller should hold socket lock for the passed tipc socket. */
2915int __tipc_nl_add_sk_publ(struct sk_buff *skb, struct netlink_callback *cb,
2916 struct publication *publ)
2917{
2918 void *hdr;
2919 struct nlattr *attrs;
2920
2921 hdr = genlmsg_put(skb, NETLINK_CB(cb->skb).portid, cb->nlh->nlmsg_seq,
2922 &tipc_genl_v2_family, NLM_F_MULTI, TIPC_NL_PUBL_GET);
2923 if (!hdr)
2924 goto msg_cancel;
2925
2926 attrs = nla_nest_start(skb, TIPC_NLA_PUBL);
2927 if (!attrs)
2928 goto genlmsg_cancel;
2929
2930 if (nla_put_u32(skb, TIPC_NLA_PUBL_KEY, publ->key))
2931 goto attr_msg_cancel;
2932 if (nla_put_u32(skb, TIPC_NLA_PUBL_TYPE, publ->type))
2933 goto attr_msg_cancel;
2934 if (nla_put_u32(skb, TIPC_NLA_PUBL_LOWER, publ->lower))
2935 goto attr_msg_cancel;
2936 if (nla_put_u32(skb, TIPC_NLA_PUBL_UPPER, publ->upper))
2937 goto attr_msg_cancel;
2938
2939 nla_nest_end(skb, attrs);
2940 genlmsg_end(skb, hdr);
2941
2942 return 0;
2943
2944attr_msg_cancel:
2945 nla_nest_cancel(skb, attrs);
2946genlmsg_cancel:
2947 genlmsg_cancel(skb, hdr);
2948msg_cancel:
2949 return -EMSGSIZE;
2950}
2951
2952/* Caller should hold socket lock for the passed tipc socket. */
2953int __tipc_nl_list_sk_publ(struct sk_buff *skb, struct netlink_callback *cb,
2954 struct tipc_sock *tsk, u32 *last_publ)
2955{
2956 int err;
2957 struct publication *p;
2958
2959 if (*last_publ) {
2960 list_for_each_entry(p, &tsk->publications, pport_list) {
2961 if (p->key == *last_publ)
2962 break;
2963 }
2964 if (p->key != *last_publ) {
2965 /* We never set seq or call nl_dump_check_consistent()
2966 * this means that setting prev_seq here will cause the
2967 * consistence check to fail in the netlink callback
2968 * handler. Resulting in the last NLMSG_DONE message
2969 * having the NLM_F_DUMP_INTR flag set.
2970 */
2971 cb->prev_seq = 1;
2972 *last_publ = 0;
2973 return -EPIPE;
2974 }
2975 } else {
2976 p = list_first_entry(&tsk->publications, struct publication,
2977 pport_list);
2978 }
2979
2980 list_for_each_entry_from(p, &tsk->publications, pport_list) {
2981 err = __tipc_nl_add_sk_publ(skb, cb, p);
2982 if (err) {
2983 *last_publ = p->key;
2984 return err;
2985 }
2986 }
2987 *last_publ = 0;
2988
2989 return 0;
2990}
2991
2992int tipc_nl_publ_dump(struct sk_buff *skb, struct netlink_callback *cb)
2993{
2994 int err;
2995 u32 tsk_ref = cb->args[0];
2996 u32 last_publ = cb->args[1];
2997 u32 done = cb->args[2];
2998 struct tipc_sock *tsk;
2999
3000 if (!tsk_ref) {
3001 struct nlattr **attrs;
3002 struct nlattr *sock[TIPC_NLA_SOCK_MAX + 1];
3003
3004 err = tipc_nlmsg_parse(cb->nlh, &attrs);
3005 if (err)
3006 return err;
3007
3008 err = nla_parse_nested(sock, TIPC_NLA_SOCK_MAX,
3009 attrs[TIPC_NLA_SOCK],
3010 tipc_nl_sock_policy);
3011 if (err)
3012 return err;
3013
3014 if (!sock[TIPC_NLA_SOCK_REF])
3015 return -EINVAL;
3016
3017 tsk_ref = nla_get_u32(sock[TIPC_NLA_SOCK_REF]);
3018 }
3019
3020 if (done)
3021 return 0;
3022
3023 tsk = tipc_sk_get(tsk_ref);
3024 if (!tsk)
3025 return -EINVAL;
3026
3027 lock_sock(&tsk->sk);
3028 err = __tipc_nl_list_sk_publ(skb, cb, tsk, &last_publ);
3029 if (!err)
3030 done = 1;
3031 release_sock(&tsk->sk);
3032 tipc_sk_put(tsk);
3033
3034 cb->args[0] = tsk_ref;
3035 cb->args[1] = last_publ;
3036 cb->args[2] = done;
3037
3038 return skb->len;
3039}
diff --git a/net/tipc/socket.h b/net/tipc/socket.h
index 16dfd62983a8..d34089387006 100644
--- a/net/tipc/socket.h
+++ b/net/tipc/socket.h
@@ -49,5 +49,6 @@ void tipc_sk_reinit(void);
49int tipc_sk_ref_table_init(u32 requested_size, u32 start); 49int tipc_sk_ref_table_init(u32 requested_size, u32 start);
50void tipc_sk_ref_table_stop(void); 50void tipc_sk_ref_table_stop(void);
51int tipc_nl_sk_dump(struct sk_buff *skb, struct netlink_callback *cb); 51int tipc_nl_sk_dump(struct sk_buff *skb, struct netlink_callback *cb);
52int tipc_nl_publ_dump(struct sk_buff *skb, struct netlink_callback *cb);
52 53
53#endif 54#endif