1 /*
2 * node.c TIPC node functionality.
3 *
4 * This program is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU General Public License
6 * as published by the Free Software Foundation; either version
7 * 2 of the License, or (at your option) any later version.
8 *
9 * Authors: Richard Alpe <richard.alpe@ericsson.com>
10 */
11
12 #include <stdio.h>
13 #include <stdlib.h>
14 #include <string.h>
15 #include <errno.h>
16
17 #include <linux/tipc_netlink.h>
18 #include <linux/tipc.h>
19 #include <linux/genetlink.h>
20 #include <libmnl/libmnl.h>
21
22 #include "cmdl.h"
23 #include "msg.h"
24 #include "misc.h"
25 #include "node.h"
26
node_list_cb(const struct nlmsghdr * nlh,void * data)27 static int node_list_cb(const struct nlmsghdr *nlh, void *data)
28 {
29 uint32_t addr;
30 struct genlmsghdr *genl = mnl_nlmsg_get_payload(nlh);
31 struct nlattr *info[TIPC_NLA_MAX + 1] = {};
32 struct nlattr *attrs[TIPC_NLA_NODE_MAX + 1] = {};
33
34 mnl_attr_parse(nlh, sizeof(*genl), parse_attrs, info);
35 if (!info[TIPC_NLA_NODE])
36 return MNL_CB_ERROR;
37
38 mnl_attr_parse_nested(info[TIPC_NLA_NODE], parse_attrs, attrs);
39 if (!attrs[TIPC_NLA_NODE_ADDR])
40 return MNL_CB_ERROR;
41
42 addr = mnl_attr_get_u32(attrs[TIPC_NLA_NODE_ADDR]);
43 printf("<%u.%u.%u>: ",
44 tipc_zone(addr),
45 tipc_cluster(addr),
46 tipc_node(addr));
47
48 if (attrs[TIPC_NLA_NODE_UP])
49 printf("up\n");
50 else
51 printf("down\n");
52
53 return MNL_CB_OK;
54 }
55
cmd_node_list(struct nlmsghdr * nlh,const struct cmd * cmd,struct cmdl * cmdl,void * data)56 static int cmd_node_list(struct nlmsghdr *nlh, const struct cmd *cmd,
57 struct cmdl *cmdl, void *data)
58 {
59 char buf[MNL_SOCKET_BUFFER_SIZE];
60
61 if (help_flag) {
62 fprintf(stderr, "Usage: %s node list\n", cmdl->argv[0]);
63 return -EINVAL;
64 }
65
66 if (!(nlh = msg_init(buf, TIPC_NL_NODE_GET))) {
67 fprintf(stderr, "error, message initialisation failed\n");
68 return -1;
69 }
70
71 return msg_dumpit(nlh, node_list_cb, NULL);
72 }
73
cmd_node_set_addr(struct nlmsghdr * nlh,const struct cmd * cmd,struct cmdl * cmdl,void * data)74 static int cmd_node_set_addr(struct nlmsghdr *nlh, const struct cmd *cmd,
75 struct cmdl *cmdl, void *data)
76 {
77 char *str;
78 uint32_t addr;
79 struct nlattr *nest;
80 char buf[MNL_SOCKET_BUFFER_SIZE];
81
82 if (cmdl->argc != cmdl->optind + 1) {
83 fprintf(stderr, "Usage: %s node set address ADDRESS\n",
84 cmdl->argv[0]);
85 return -EINVAL;
86 }
87
88 str = shift_cmdl(cmdl);
89 addr = str2addr(str);
90 if (!addr)
91 return -1;
92
93 if (!(nlh = msg_init(buf, TIPC_NL_NET_SET))) {
94 fprintf(stderr, "error, message initialisation failed\n");
95 return -1;
96 }
97
98 nest = mnl_attr_nest_start(nlh, TIPC_NLA_NET);
99 mnl_attr_put_u32(nlh, TIPC_NLA_NET_ADDR, addr);
100 mnl_attr_nest_end(nlh, nest);
101
102 return msg_doit(nlh, NULL, NULL);
103 }
104
cmd_node_get_addr(struct nlmsghdr * nlh,const struct cmd * cmd,struct cmdl * cmdl,void * data)105 static int cmd_node_get_addr(struct nlmsghdr *nlh, const struct cmd *cmd,
106 struct cmdl *cmdl, void *data)
107 {
108 int sk;
109 socklen_t sz = sizeof(struct sockaddr_tipc);
110 struct sockaddr_tipc addr;
111
112 if (!(sk = socket(AF_TIPC, SOCK_RDM, 0))) {
113 fprintf(stderr, "opening TIPC socket: %s\n", strerror(errno));
114 return -1;
115 }
116
117 if (getsockname(sk, (struct sockaddr *)&addr, &sz) < 0) {
118 fprintf(stderr, "getting TIPC socket address: %s\n",
119 strerror(errno));
120 close(sk);
121 return -1;
122 }
123 close(sk);
124
125 printf("<%u.%u.%u>\n",
126 tipc_zone(addr.addr.id.node),
127 tipc_cluster(addr.addr.id.node),
128 tipc_node(addr.addr.id.node));
129
130 return 0;
131 }
132
netid_get_cb(const struct nlmsghdr * nlh,void * data)133 static int netid_get_cb(const struct nlmsghdr *nlh, void *data)
134 {
135 struct genlmsghdr *genl = mnl_nlmsg_get_payload(nlh);
136 struct nlattr *info[TIPC_NLA_MAX + 1] = {};
137 struct nlattr *attrs[TIPC_NLA_NET_MAX + 1] = {};
138
139 mnl_attr_parse(nlh, sizeof(*genl), parse_attrs, info);
140 if (!info[TIPC_NLA_NET])
141 return MNL_CB_ERROR;
142
143 mnl_attr_parse_nested(info[TIPC_NLA_NET], parse_attrs, attrs);
144 if (!attrs[TIPC_NLA_NET_ID])
145 return MNL_CB_ERROR;
146
147 printf("%u\n", mnl_attr_get_u32(attrs[TIPC_NLA_NET_ID]));
148
149 return MNL_CB_OK;
150 }
151
cmd_node_get_netid(struct nlmsghdr * nlh,const struct cmd * cmd,struct cmdl * cmdl,void * data)152 static int cmd_node_get_netid(struct nlmsghdr *nlh, const struct cmd *cmd,
153 struct cmdl *cmdl, void *data)
154 {
155 char buf[MNL_SOCKET_BUFFER_SIZE];
156
157 if (help_flag) {
158 (cmd->help)(cmdl);
159 return -EINVAL;
160 }
161
162 if (!(nlh = msg_init(buf, TIPC_NL_NET_GET))) {
163 fprintf(stderr, "error, message initialisation failed\n");
164 return -1;
165 }
166
167 return msg_dumpit(nlh, netid_get_cb, NULL);
168 }
169
cmd_node_set_netid(struct nlmsghdr * nlh,const struct cmd * cmd,struct cmdl * cmdl,void * data)170 static int cmd_node_set_netid(struct nlmsghdr *nlh, const struct cmd *cmd,
171 struct cmdl *cmdl, void *data)
172 {
173 int netid;
174 char buf[MNL_SOCKET_BUFFER_SIZE];
175 struct nlattr *nest;
176
177 if (help_flag) {
178 (cmd->help)(cmdl);
179 return -EINVAL;
180 }
181
182 if (!(nlh = msg_init(buf, TIPC_NL_NET_SET))) {
183 fprintf(stderr, "error, message initialisation failed\n");
184 return -1;
185 }
186
187 if (cmdl->argc != cmdl->optind + 1) {
188 fprintf(stderr, "Usage: %s node set netid NETID\n",
189 cmdl->argv[0]);
190 return -EINVAL;
191 }
192 netid = atoi(shift_cmdl(cmdl));
193
194 nest = mnl_attr_nest_start(nlh, TIPC_NLA_NET);
195 mnl_attr_put_u32(nlh, TIPC_NLA_NET_ID, netid);
196 mnl_attr_nest_end(nlh, nest);
197
198 return msg_doit(nlh, NULL, NULL);
199 }
200
cmd_node_set_help(struct cmdl * cmdl)201 static void cmd_node_set_help(struct cmdl *cmdl)
202 {
203 fprintf(stderr,
204 "Usage: %s node set PROPERTY\n\n"
205 "PROPERTIES\n"
206 " address ADDRESS - Set local address\n"
207 " netid NETID - Set local netid\n",
208 cmdl->argv[0]);
209 }
210
cmd_node_set(struct nlmsghdr * nlh,const struct cmd * cmd,struct cmdl * cmdl,void * data)211 static int cmd_node_set(struct nlmsghdr *nlh, const struct cmd *cmd,
212 struct cmdl *cmdl, void *data)
213 {
214 const struct cmd cmds[] = {
215 { "address", cmd_node_set_addr, NULL },
216 { "netid", cmd_node_set_netid, NULL },
217 { NULL }
218 };
219
220 return run_cmd(nlh, cmd, cmds, cmdl, NULL);
221 }
222
cmd_node_get_help(struct cmdl * cmdl)223 static void cmd_node_get_help(struct cmdl *cmdl)
224 {
225 fprintf(stderr,
226 "Usage: %s node get PROPERTY\n\n"
227 "PROPERTIES\n"
228 " address - Get local address\n"
229 " netid - Get local netid\n",
230 cmdl->argv[0]);
231 }
232
cmd_node_get(struct nlmsghdr * nlh,const struct cmd * cmd,struct cmdl * cmdl,void * data)233 static int cmd_node_get(struct nlmsghdr *nlh, const struct cmd *cmd,
234 struct cmdl *cmdl, void *data)
235 {
236 const struct cmd cmds[] = {
237 { "address", cmd_node_get_addr, NULL },
238 { "netid", cmd_node_get_netid, NULL },
239 { NULL }
240 };
241
242 return run_cmd(nlh, cmd, cmds, cmdl, NULL);
243 }
244
cmd_node_help(struct cmdl * cmdl)245 void cmd_node_help(struct cmdl *cmdl)
246 {
247 fprintf(stderr,
248 "Usage: %s node COMMAND [ARGS] ...\n\n"
249 "COMMANDS\n"
250 " list - List remote nodes\n"
251 " get - Get local node parameters\n"
252 " set - Set local node parameters\n",
253 cmdl->argv[0]);
254 }
255
cmd_node(struct nlmsghdr * nlh,const struct cmd * cmd,struct cmdl * cmdl,void * data)256 int cmd_node(struct nlmsghdr *nlh, const struct cmd *cmd, struct cmdl *cmdl,
257 void *data)
258 {
259 const struct cmd cmds[] = {
260 { "list", cmd_node_list, NULL },
261 { "get", cmd_node_get, cmd_node_get_help },
262 { "set", cmd_node_set, cmd_node_set_help },
263 { NULL }
264 };
265
266 return run_cmd(nlh, cmd, cmds, cmdl, NULL);
267 }
268