]> git.proxmox.com Git - mirror_iproute2.git/blob - tipc/node.c
lib: print_color_rate(): Fix formatting small rates in IEC mode
[mirror_iproute2.git] / tipc / node.c
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
27 static int node_list_cb(const struct nlmsghdr *nlh, void *data)
28 {
29 struct nlattr *info[TIPC_NLA_MAX + 1] = {};
30 struct nlattr *attrs[TIPC_NLA_NODE_MAX + 1] = {};
31 char str[33] = {};
32 uint32_t addr;
33
34 mnl_attr_parse(nlh, sizeof(struct genlmsghdr), 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 hash2nodestr(addr, str);
44 printf("%-32s %08x ", str, addr);
45 if (attrs[TIPC_NLA_NODE_UP])
46 printf("up\n");
47 else
48 printf("down\n");
49 return MNL_CB_OK;
50 }
51
52 static int cmd_node_list(struct nlmsghdr *nlh, const struct cmd *cmd,
53 struct cmdl *cmdl, void *data)
54 {
55 char buf[MNL_SOCKET_BUFFER_SIZE];
56
57 if (help_flag) {
58 fprintf(stderr, "Usage: %s node list\n", cmdl->argv[0]);
59 return -EINVAL;
60 }
61
62 if (!(nlh = msg_init(buf, TIPC_NL_NODE_GET))) {
63 fprintf(stderr, "error, message initialisation failed\n");
64 return -1;
65 }
66 printf("Node Identity Hash State\n");
67 return msg_dumpit(nlh, node_list_cb, NULL);
68 }
69
70 static int cmd_node_set_addr(struct nlmsghdr *nlh, const struct cmd *cmd,
71 struct cmdl *cmdl, void *data)
72 {
73 char *str;
74 uint32_t addr;
75 struct nlattr *nest;
76 char buf[MNL_SOCKET_BUFFER_SIZE];
77
78 if (cmdl->argc != cmdl->optind + 1) {
79 fprintf(stderr, "Usage: %s node set address ADDRESS\n",
80 cmdl->argv[0]);
81 return -EINVAL;
82 }
83
84 str = shift_cmdl(cmdl);
85 addr = str2addr(str);
86 if (!addr)
87 return -1;
88
89 if (!(nlh = msg_init(buf, TIPC_NL_NET_SET))) {
90 fprintf(stderr, "error, message initialisation failed\n");
91 return -1;
92 }
93
94 nest = mnl_attr_nest_start(nlh, TIPC_NLA_NET);
95 mnl_attr_put_u32(nlh, TIPC_NLA_NET_ADDR, addr);
96 mnl_attr_nest_end(nlh, nest);
97
98 return msg_doit(nlh, NULL, NULL);
99 }
100
101 static int cmd_node_get_addr(struct nlmsghdr *nlh, const struct cmd *cmd,
102 struct cmdl *cmdl, void *data)
103 {
104 int sk;
105 socklen_t sz = sizeof(struct sockaddr_tipc);
106 struct sockaddr_tipc addr;
107
108 sk = socket(AF_TIPC, SOCK_RDM, 0);
109 if (sk < 0) {
110 fprintf(stderr, "opening TIPC socket: %s\n", strerror(errno));
111 return -1;
112 }
113
114 if (getsockname(sk, (struct sockaddr *)&addr, &sz) < 0) {
115 fprintf(stderr, "getting TIPC socket address: %s\n",
116 strerror(errno));
117 close(sk);
118 return -1;
119 }
120 close(sk);
121
122 printf("%08x\n", addr.addr.id.node);
123 return 0;
124 }
125
126 static int cmd_node_set_nodeid(struct nlmsghdr *nlh, const struct cmd *cmd,
127 struct cmdl *cmdl, void *data)
128 {
129 char buf[MNL_SOCKET_BUFFER_SIZE];
130 uint8_t id[16] = {0,};
131 uint64_t *w0 = (uint64_t *) &id[0];
132 uint64_t *w1 = (uint64_t *) &id[8];
133 struct nlattr *nest;
134 char *str;
135
136 if (cmdl->argc != cmdl->optind + 1) {
137 fprintf(stderr, "Usage: %s node set nodeid NODE_ID\n",
138 cmdl->argv[0]);
139 return -EINVAL;
140 }
141
142 str = shift_cmdl(cmdl);
143 if (str2nodeid(str, id)) {
144 fprintf(stderr, "Invalid node identity\n");
145 return -EINVAL;
146 }
147
148 nlh = msg_init(buf, TIPC_NL_NET_SET);
149 if (!nlh) {
150 fprintf(stderr, "error, message initialisation failed\n");
151 return -1;
152 }
153 nest = mnl_attr_nest_start(nlh, TIPC_NLA_NET);
154 mnl_attr_put_u64(nlh, TIPC_NLA_NET_NODEID, *w0);
155 mnl_attr_put_u64(nlh, TIPC_NLA_NET_NODEID_W1, *w1);
156 mnl_attr_nest_end(nlh, nest);
157 return msg_doit(nlh, NULL, NULL);
158 }
159
160 static void cmd_node_set_key_help(struct cmdl *cmdl)
161 {
162 fprintf(stderr,
163 "Usage: %s node set key KEY [algname ALGNAME] [PROPERTIES]\n"
164 " %s node set key rekeying REKEYING\n\n"
165 "KEY\n"
166 " Symmetric KEY & SALT as a composite ASCII or hex string (0x...) in form:\n"
167 " [KEY: 16, 24 or 32 octets][SALT: 4 octets]\n\n"
168 "ALGNAME\n"
169 " Cipher algorithm [default: \"gcm(aes)\"]\n\n"
170 "PROPERTIES\n"
171 " master - Set KEY as a cluster master key\n"
172 " <empty> - Set KEY as a cluster key\n"
173 " nodeid NODEID - Set KEY as a per-node key for own or peer\n\n"
174 "REKEYING\n"
175 " INTERVAL - Set rekeying interval (in minutes) [0: disable]\n"
176 " now - Trigger one (first) rekeying immediately\n\n"
177 "EXAMPLES\n"
178 " %s node set key this_is_a_master_key master\n"
179 " %s node set key 0x746869735F69735F615F6B657931365F73616C74\n"
180 " %s node set key this_is_a_key16_salt algname \"gcm(aes)\" nodeid 1001002\n"
181 " %s node set key rekeying 600\n\n",
182 cmdl->argv[0], cmdl->argv[0], cmdl->argv[0], cmdl->argv[0],
183 cmdl->argv[0], cmdl->argv[0]);
184 }
185
186 static int cmd_node_set_key(struct nlmsghdr *nlh, const struct cmd *cmd,
187 struct cmdl *cmdl, void *data)
188 {
189 struct {
190 union {
191 struct tipc_aead_key key;
192 char mem[TIPC_AEAD_KEY_SIZE_MAX];
193 };
194 } input = {};
195 struct opt opts[] = {
196 { "algname", OPT_KEYVAL, NULL },
197 { "nodeid", OPT_KEYVAL, NULL },
198 { "master", OPT_KEY, NULL },
199 { "rekeying", OPT_KEYVAL, NULL },
200 { NULL }
201 };
202 struct nlattr *nest;
203 struct opt *opt_algname, *opt_nodeid, *opt_master, *opt_rekeying;
204 char buf[MNL_SOCKET_BUFFER_SIZE];
205 uint8_t id[TIPC_NODEID_LEN] = {0,};
206 uint32_t rekeying = 0;
207 bool has_key = false;
208 int keysize;
209 char *str;
210
211 if (help_flag || cmdl->optind >= cmdl->argc) {
212 (cmd->help)(cmdl);
213 return -EINVAL;
214 }
215
216 /* Check if command starts with opts i.e. "rekeying" opt without key */
217 if (find_opt(opts, cmdl->argv[cmdl->optind]))
218 goto get_ops;
219
220 /* Get user key */
221 has_key = true;
222 str = shift_cmdl(cmdl);
223 if (str2key(str, &input.key)) {
224 fprintf(stderr, "error, invalid key input\n");
225 return -EINVAL;
226 }
227
228 get_ops:
229 if (parse_opts(opts, cmdl) < 0)
230 return -EINVAL;
231
232 /* Get rekeying time */
233 opt_rekeying = get_opt(opts, "rekeying");
234 if (opt_rekeying) {
235 if (!strcmp(opt_rekeying->val, "now"))
236 rekeying = TIPC_REKEYING_NOW;
237 else
238 rekeying = atoi(opt_rekeying->val);
239 }
240
241 /* Get algorithm name, default: "gcm(aes)" */
242 opt_algname = get_opt(opts, "algname");
243 if (!opt_algname)
244 strcpy(input.key.alg_name, "gcm(aes)");
245 else
246 strcpy(input.key.alg_name, opt_algname->val);
247
248 /* Get node identity */
249 opt_nodeid = get_opt(opts, "nodeid");
250 if (opt_nodeid && str2nodeid(opt_nodeid->val, id)) {
251 fprintf(stderr, "error, invalid node identity\n");
252 return -EINVAL;
253 }
254
255 /* Get master key indication */
256 opt_master = get_opt(opts, "master");
257
258 /* Sanity check if wrong option */
259 if (opt_nodeid && opt_master) {
260 fprintf(stderr, "error, per-node key cannot be master\n");
261 return -EINVAL;
262 }
263
264 /* Init & do the command */
265 nlh = msg_init(buf, TIPC_NL_KEY_SET);
266 if (!nlh) {
267 fprintf(stderr, "error, message initialisation failed\n");
268 return -1;
269 }
270
271 nest = mnl_attr_nest_start(nlh, TIPC_NLA_NODE);
272 if (has_key) {
273 keysize = tipc_aead_key_size(&input.key);
274 mnl_attr_put(nlh, TIPC_NLA_NODE_KEY, keysize, &input.key);
275 if (opt_nodeid)
276 mnl_attr_put(nlh, TIPC_NLA_NODE_ID, TIPC_NODEID_LEN, id);
277 if (opt_master)
278 mnl_attr_put(nlh, TIPC_NLA_NODE_KEY_MASTER, 0, NULL);
279 }
280 if (opt_rekeying)
281 mnl_attr_put_u32(nlh, TIPC_NLA_NODE_REKEYING, rekeying);
282
283 mnl_attr_nest_end(nlh, nest);
284 return msg_doit(nlh, NULL, NULL);
285 }
286
287 static int cmd_node_flush_key(struct nlmsghdr *nlh, const struct cmd *cmd,
288 struct cmdl *cmdl, void *data)
289 {
290 char buf[MNL_SOCKET_BUFFER_SIZE];
291
292 if (help_flag) {
293 (cmd->help)(cmdl);
294 return -EINVAL;
295 }
296
297 /* Init & do the command */
298 nlh = msg_init(buf, TIPC_NL_KEY_FLUSH);
299 if (!nlh) {
300 fprintf(stderr, "error, message initialisation failed\n");
301 return -1;
302 }
303 return msg_doit(nlh, NULL, NULL);
304 }
305
306 static int nodeid_get_cb(const struct nlmsghdr *nlh, void *data)
307 {
308 struct nlattr *info[TIPC_NLA_MAX + 1] = {};
309 struct nlattr *attrs[TIPC_NLA_NET_MAX + 1] = {};
310 char str[33] = {0,};
311 uint8_t id[16] = {0,};
312 uint64_t *w0 = (uint64_t *) &id[0];
313 uint64_t *w1 = (uint64_t *) &id[8];
314
315 mnl_attr_parse(nlh, sizeof(struct genlmsghdr), parse_attrs, info);
316 if (!info[TIPC_NLA_NET])
317 return MNL_CB_ERROR;
318
319 mnl_attr_parse_nested(info[TIPC_NLA_NET], parse_attrs, attrs);
320 if (!attrs[TIPC_NLA_NET_ID])
321 return MNL_CB_ERROR;
322
323 *w0 = mnl_attr_get_u64(attrs[TIPC_NLA_NET_NODEID]);
324 *w1 = mnl_attr_get_u64(attrs[TIPC_NLA_NET_NODEID_W1]);
325 nodeid2str(id, str);
326 printf("Node Identity Hash\n");
327 printf("%-33s", str);
328 cmd_node_get_addr(NULL, NULL, NULL, NULL);
329 return MNL_CB_OK;
330 }
331
332 static int cmd_node_get_nodeid(struct nlmsghdr *nlh, const struct cmd *cmd,
333 struct cmdl *cmdl, void *data)
334 {
335 char buf[MNL_SOCKET_BUFFER_SIZE];
336
337 if (help_flag) {
338 (cmd->help)(cmdl);
339 return -EINVAL;
340 }
341
342 nlh = msg_init(buf, TIPC_NL_NET_GET);
343 if (!nlh) {
344 fprintf(stderr, "error, message initialisation failed\n");
345 return -1;
346 }
347
348 return msg_dumpit(nlh, nodeid_get_cb, NULL);
349 }
350
351
352 static int netid_get_cb(const struct nlmsghdr *nlh, void *data)
353 {
354 struct nlattr *info[TIPC_NLA_MAX + 1] = {};
355 struct nlattr *attrs[TIPC_NLA_NET_MAX + 1] = {};
356
357 mnl_attr_parse(nlh, sizeof(struct genlmsghdr), parse_attrs, info);
358 if (!info[TIPC_NLA_NET])
359 return MNL_CB_ERROR;
360
361 mnl_attr_parse_nested(info[TIPC_NLA_NET], parse_attrs, attrs);
362 if (!attrs[TIPC_NLA_NET_ID])
363 return MNL_CB_ERROR;
364
365 printf("%u\n", mnl_attr_get_u32(attrs[TIPC_NLA_NET_ID]));
366
367 return MNL_CB_OK;
368 }
369
370 static int cmd_node_get_netid(struct nlmsghdr *nlh, const struct cmd *cmd,
371 struct cmdl *cmdl, void *data)
372 {
373 char buf[MNL_SOCKET_BUFFER_SIZE];
374
375 if (help_flag) {
376 (cmd->help)(cmdl);
377 return -EINVAL;
378 }
379
380 if (!(nlh = msg_init(buf, TIPC_NL_NET_GET))) {
381 fprintf(stderr, "error, message initialisation failed\n");
382 return -1;
383 }
384
385 return msg_dumpit(nlh, netid_get_cb, NULL);
386 }
387
388 static int cmd_node_set_netid(struct nlmsghdr *nlh, const struct cmd *cmd,
389 struct cmdl *cmdl, void *data)
390 {
391 int netid;
392 char buf[MNL_SOCKET_BUFFER_SIZE];
393 struct nlattr *nest;
394
395 if (help_flag) {
396 (cmd->help)(cmdl);
397 return -EINVAL;
398 }
399
400 if (!(nlh = msg_init(buf, TIPC_NL_NET_SET))) {
401 fprintf(stderr, "error, message initialisation failed\n");
402 return -1;
403 }
404
405 if (cmdl->argc != cmdl->optind + 1) {
406 fprintf(stderr, "Usage: %s node set netid NETID\n",
407 cmdl->argv[0]);
408 return -EINVAL;
409 }
410 netid = atoi(shift_cmdl(cmdl));
411
412 nest = mnl_attr_nest_start(nlh, TIPC_NLA_NET);
413 mnl_attr_put_u32(nlh, TIPC_NLA_NET_ID, netid);
414 mnl_attr_nest_end(nlh, nest);
415
416 return msg_doit(nlh, NULL, NULL);
417 }
418
419 static void cmd_node_flush_help(struct cmdl *cmdl)
420 {
421 fprintf(stderr,
422 "Usage: %s node flush PROPERTY\n\n"
423 "PROPERTIES\n"
424 " key - Flush all symmetric-keys\n",
425 cmdl->argv[0]);
426 }
427
428 static int cmd_node_flush(struct nlmsghdr *nlh, const struct cmd *cmd,
429 struct cmdl *cmdl, void *data)
430 {
431 const struct cmd cmds[] = {
432 { "key", cmd_node_flush_key, NULL },
433 { NULL }
434 };
435
436 return run_cmd(nlh, cmd, cmds, cmdl, NULL);
437 }
438
439 static void cmd_node_set_help(struct cmdl *cmdl)
440 {
441 fprintf(stderr,
442 "Usage: %s node set PROPERTY\n\n"
443 "PROPERTIES\n"
444 " identity NODEID - Set node identity\n"
445 " clusterid CLUSTERID - Set local cluster id\n"
446 " key PROPERTY - Set symmetric-key\n",
447 cmdl->argv[0]);
448 }
449
450 static int cmd_node_set(struct nlmsghdr *nlh, const struct cmd *cmd,
451 struct cmdl *cmdl, void *data)
452 {
453 const struct cmd cmds[] = {
454 { "address", cmd_node_set_addr, NULL },
455 { "identity", cmd_node_set_nodeid, NULL },
456 { "netid", cmd_node_set_netid, NULL },
457 { "clusterid", cmd_node_set_netid, NULL },
458 { "key", cmd_node_set_key, cmd_node_set_key_help },
459 { NULL }
460 };
461
462 return run_cmd(nlh, cmd, cmds, cmdl, NULL);
463 }
464
465 static void cmd_node_get_help(struct cmdl *cmdl)
466 {
467 fprintf(stderr,
468 "Usage: %s node get PROPERTY\n\n"
469 "PROPERTIES\n"
470 " identity - Get node identity\n"
471 " clusterid - Get local clusterid\n",
472 cmdl->argv[0]);
473 }
474
475 static int cmd_node_get(struct nlmsghdr *nlh, const struct cmd *cmd,
476 struct cmdl *cmdl, void *data)
477 {
478 const struct cmd cmds[] = {
479 { "address", cmd_node_get_addr, NULL },
480 { "identity", cmd_node_get_nodeid, NULL },
481 { "netid", cmd_node_get_netid, NULL },
482 { "clusterid", cmd_node_get_netid, NULL },
483 { NULL }
484 };
485
486 return run_cmd(nlh, cmd, cmds, cmdl, NULL);
487 }
488
489 void cmd_node_help(struct cmdl *cmdl)
490 {
491 fprintf(stderr,
492 "Usage: %s node COMMAND [ARGS] ...\n\n"
493 "COMMANDS\n"
494 " list - List remote nodes\n"
495 " get - Get local node parameters\n"
496 " set - Set local node parameters\n"
497 " flush - Flush local node parameters\n",
498 cmdl->argv[0]);
499 }
500
501 int cmd_node(struct nlmsghdr *nlh, const struct cmd *cmd, struct cmdl *cmdl,
502 void *data)
503 {
504 const struct cmd cmds[] = {
505 { "list", cmd_node_list, NULL },
506 { "get", cmd_node_get, cmd_node_get_help },
507 { "set", cmd_node_set, cmd_node_set_help },
508 { "flush", cmd_node_flush, cmd_node_flush_help},
509 { NULL }
510 };
511
512 return run_cmd(nlh, cmd, cmds, cmdl, NULL);
513 }