diff options
author | Richard Alpe <richard.alpe@ericsson.com> | 2014-11-20 04:29:11 -0500 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2014-11-21 15:01:30 -0500 |
commit | 1a1a143daf84db95dd7212086042004a3abb7bc2 (patch) | |
tree | ac69d87fa4ab8434bf69f0121a51d83a48cf728d /net/tipc | |
parent | 34b78a127c4fd57cf3d5c64031693d10a8e0fae1 (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.c | 17 | ||||
-rw-r--r-- | net/tipc/netlink.h | 1 | ||||
-rw-r--r-- | net/tipc/socket.c | 135 | ||||
-rw-r--r-- | net/tipc/socket.h | 1 |
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 | ||
142 | int 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 | |||
136 | int tipc_netlink_start(void) | 153 | int 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 | ||
39 | extern struct genl_family tipc_genl_v2_family; | 39 | extern struct genl_family tipc_genl_v2_family; |
40 | int tipc_nlmsg_parse(const struct nlmsghdr *nlh, struct nlattr ***buf); | ||
40 | 41 | ||
41 | struct tipc_nl_msg { | 42 | struct 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; | |||
121 | static struct proto tipc_proto; | 121 | static struct proto tipc_proto; |
122 | static struct proto tipc_proto_kern; | 122 | static struct proto tipc_proto_kern; |
123 | 123 | ||
124 | static 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. */ | ||
2915 | int __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 | |||
2944 | attr_msg_cancel: | ||
2945 | nla_nest_cancel(skb, attrs); | ||
2946 | genlmsg_cancel: | ||
2947 | genlmsg_cancel(skb, hdr); | ||
2948 | msg_cancel: | ||
2949 | return -EMSGSIZE; | ||
2950 | } | ||
2951 | |||
2952 | /* Caller should hold socket lock for the passed tipc socket. */ | ||
2953 | int __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 | |||
2992 | int 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); | |||
49 | int tipc_sk_ref_table_init(u32 requested_size, u32 start); | 49 | int tipc_sk_ref_table_init(u32 requested_size, u32 start); |
50 | void tipc_sk_ref_table_stop(void); | 50 | void tipc_sk_ref_table_stop(void); |
51 | int tipc_nl_sk_dump(struct sk_buff *skb, struct netlink_callback *cb); | 51 | int tipc_nl_sk_dump(struct sk_buff *skb, struct netlink_callback *cb); |
52 | int tipc_nl_publ_dump(struct sk_buff *skb, struct netlink_callback *cb); | ||
52 | 53 | ||
53 | #endif | 54 | #endif |