]> git.proxmox.com Git - mirror_iproute2.git/blame - tipc/node.c
tipc: add new commands to set TIPC AEAD key
[mirror_iproute2.git] / tipc / node.c
CommitLineData
f043759d
RA
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
27static int node_list_cb(const struct nlmsghdr *nlh, void *data)
28{
f043759d
RA
29 struct nlattr *info[TIPC_NLA_MAX + 1] = {};
30 struct nlattr *attrs[TIPC_NLA_NODE_MAX + 1] = {};
5947046d
JM
31 char str[33] = {};
32 uint32_t addr;
f043759d 33
8d05f33a 34 mnl_attr_parse(nlh, sizeof(struct genlmsghdr), parse_attrs, info);
f043759d
RA
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]);
5947046d
JM
43 hash2nodestr(addr, str);
44 printf("%-32s %08x ", str, addr);
f043759d
RA
45 if (attrs[TIPC_NLA_NODE_UP])
46 printf("up\n");
47 else
48 printf("down\n");
f043759d
RA
49 return MNL_CB_OK;
50}
51
52static 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 }
5947046d 66 printf("Node Identity Hash State\n");
f043759d
RA
67 return msg_dumpit(nlh, node_list_cb, NULL);
68}
69
70static 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
101static 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
436270a4
PS
108 sk = socket(AF_TIPC, SOCK_RDM, 0);
109 if (sk < 0) {
f043759d
RA
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
5947046d 122 printf("%08x\n", addr.addr.id.node);
f043759d
RA
123 return 0;
124}
125
725ebfbf
JM
126static 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
24bee3bf
TL
160static void cmd_node_set_key_help(struct cmdl *cmdl)
161{
162 fprintf(stderr,
163 "Usage: %s node set key KEY [algname ALGNAME] [nodeid NODEID]\n\n"
164 "PROPERTIES\n"
165 " KEY - Symmetric KEY & SALT as a normal or hex string\n"
166 " that consists of two parts:\n"
167 " [KEY: 16, 24 or 32 octets][SALT: 4 octets]\n\n"
168 " algname ALGNAME - Default: \"gcm(aes)\"\n\n"
169 " nodeid NODEID - Own or peer node identity to which the key will\n"
170 " be attached. If not present, the key is a cluster\n"
171 " key!\n\n"
172 "EXAMPLES\n"
173 " %s node set key this_is_a_key16_salt algname \"gcm(aes)\" nodeid node1\n"
174 " %s node set key 0x746869735F69735F615F6B657931365F73616C74 nodeid node2\n\n",
175 cmdl->argv[0], cmdl->argv[0], cmdl->argv[0]);
176}
177
178static int cmd_node_set_key(struct nlmsghdr *nlh, const struct cmd *cmd,
179 struct cmdl *cmdl, void *data)
180{
181 struct {
182 struct tipc_aead_key key;
183 char mem[TIPC_AEAD_KEYLEN_MAX + 1];
184 } input = {};
185 struct opt opts[] = {
186 { "algname", OPT_KEYVAL, NULL },
187 { "nodeid", OPT_KEYVAL, NULL },
188 { NULL }
189 };
190 struct nlattr *nest;
191 struct opt *opt_algname, *opt_nodeid;
192 char buf[MNL_SOCKET_BUFFER_SIZE];
193 uint8_t id[TIPC_NODEID_LEN] = {0,};
194 int keysize;
195 char *str;
196
197 if (help_flag) {
198 (cmd->help)(cmdl);
199 return -EINVAL;
200 }
201
202 if (cmdl->optind >= cmdl->argc) {
203 fprintf(stderr, "error, missing key\n");
204 return -EINVAL;
205 }
206
207 /* Get user key */
208 str = shift_cmdl(cmdl);
209 if (str2key(str, &input.key)) {
210 fprintf(stderr, "error, invalid key input\n");
211 return -EINVAL;
212 }
213
214 if (parse_opts(opts, cmdl) < 0)
215 return -EINVAL;
216
217 /* Get algorithm name, default: "gcm(aes)" */
218 opt_algname = get_opt(opts, "algname");
219 if (!opt_algname)
220 strcpy(input.key.alg_name, "gcm(aes)");
221 else
222 strcpy(input.key.alg_name, opt_algname->val);
223
224 /* Get node identity */
225 opt_nodeid = get_opt(opts, "nodeid");
226 if (opt_nodeid && str2nodeid(opt_nodeid->val, id)) {
227 fprintf(stderr, "error, invalid node identity\n");
228 return -EINVAL;
229 }
230
231 /* Init & do the command */
232 nlh = msg_init(buf, TIPC_NL_KEY_SET);
233 if (!nlh) {
234 fprintf(stderr, "error, message initialisation failed\n");
235 return -1;
236 }
237 nest = mnl_attr_nest_start(nlh, TIPC_NLA_NODE);
238 keysize = tipc_aead_key_size(&input.key);
239 mnl_attr_put(nlh, TIPC_NLA_NODE_KEY, keysize, &input.key);
240 if (opt_nodeid)
241 mnl_attr_put(nlh, TIPC_NLA_NODE_ID, TIPC_NODEID_LEN, id);
242 mnl_attr_nest_end(nlh, nest);
243 return msg_doit(nlh, NULL, NULL);
244}
245
246static int cmd_node_flush_key(struct nlmsghdr *nlh, const struct cmd *cmd,
247 struct cmdl *cmdl, void *data)
248{
249 char buf[MNL_SOCKET_BUFFER_SIZE];
250
251 if (help_flag) {
252 (cmd->help)(cmdl);
253 return -EINVAL;
254 }
255
256 /* Init & do the command */
257 nlh = msg_init(buf, TIPC_NL_KEY_FLUSH);
258 if (!nlh) {
259 fprintf(stderr, "error, message initialisation failed\n");
260 return -1;
261 }
262 return msg_doit(nlh, NULL, NULL);
263}
264
725ebfbf
JM
265static int nodeid_get_cb(const struct nlmsghdr *nlh, void *data)
266{
725ebfbf
JM
267 struct nlattr *info[TIPC_NLA_MAX + 1] = {};
268 struct nlattr *attrs[TIPC_NLA_NET_MAX + 1] = {};
269 char str[33] = {0,};
270 uint8_t id[16] = {0,};
271 uint64_t *w0 = (uint64_t *) &id[0];
272 uint64_t *w1 = (uint64_t *) &id[8];
725ebfbf 273
8d05f33a 274 mnl_attr_parse(nlh, sizeof(struct genlmsghdr), parse_attrs, info);
725ebfbf
JM
275 if (!info[TIPC_NLA_NET])
276 return MNL_CB_ERROR;
277
278 mnl_attr_parse_nested(info[TIPC_NLA_NET], parse_attrs, attrs);
279 if (!attrs[TIPC_NLA_NET_ID])
280 return MNL_CB_ERROR;
281
282 *w0 = mnl_attr_get_u64(attrs[TIPC_NLA_NET_NODEID]);
283 *w1 = mnl_attr_get_u64(attrs[TIPC_NLA_NET_NODEID_W1]);
284 nodeid2str(id, str);
5947046d
JM
285 printf("Node Identity Hash\n");
286 printf("%-33s", str);
725ebfbf
JM
287 cmd_node_get_addr(NULL, NULL, NULL, NULL);
288 return MNL_CB_OK;
289}
290
291static int cmd_node_get_nodeid(struct nlmsghdr *nlh, const struct cmd *cmd,
292 struct cmdl *cmdl, void *data)
293{
294 char buf[MNL_SOCKET_BUFFER_SIZE];
295
296 if (help_flag) {
297 (cmd->help)(cmdl);
298 return -EINVAL;
299 }
300
301 nlh = msg_init(buf, TIPC_NL_NET_GET);
302 if (!nlh) {
303 fprintf(stderr, "error, message initialisation failed\n");
304 return -1;
305 }
306
307 return msg_dumpit(nlh, nodeid_get_cb, NULL);
308}
309
310
f043759d
RA
311static int netid_get_cb(const struct nlmsghdr *nlh, void *data)
312{
f043759d
RA
313 struct nlattr *info[TIPC_NLA_MAX + 1] = {};
314 struct nlattr *attrs[TIPC_NLA_NET_MAX + 1] = {};
315
8d05f33a 316 mnl_attr_parse(nlh, sizeof(struct genlmsghdr), parse_attrs, info);
f043759d
RA
317 if (!info[TIPC_NLA_NET])
318 return MNL_CB_ERROR;
319
320 mnl_attr_parse_nested(info[TIPC_NLA_NET], parse_attrs, attrs);
321 if (!attrs[TIPC_NLA_NET_ID])
322 return MNL_CB_ERROR;
323
324 printf("%u\n", mnl_attr_get_u32(attrs[TIPC_NLA_NET_ID]));
325
326 return MNL_CB_OK;
327}
328
329static int cmd_node_get_netid(struct nlmsghdr *nlh, const struct cmd *cmd,
330 struct cmdl *cmdl, void *data)
331{
332 char buf[MNL_SOCKET_BUFFER_SIZE];
333
334 if (help_flag) {
335 (cmd->help)(cmdl);
336 return -EINVAL;
337 }
338
339 if (!(nlh = msg_init(buf, TIPC_NL_NET_GET))) {
340 fprintf(stderr, "error, message initialisation failed\n");
341 return -1;
342 }
343
344 return msg_dumpit(nlh, netid_get_cb, NULL);
345}
346
347static int cmd_node_set_netid(struct nlmsghdr *nlh, const struct cmd *cmd,
348 struct cmdl *cmdl, void *data)
349{
350 int netid;
351 char buf[MNL_SOCKET_BUFFER_SIZE];
352 struct nlattr *nest;
353
354 if (help_flag) {
355 (cmd->help)(cmdl);
356 return -EINVAL;
357 }
358
359 if (!(nlh = msg_init(buf, TIPC_NL_NET_SET))) {
360 fprintf(stderr, "error, message initialisation failed\n");
361 return -1;
362 }
363
364 if (cmdl->argc != cmdl->optind + 1) {
365 fprintf(stderr, "Usage: %s node set netid NETID\n",
366 cmdl->argv[0]);
367 return -EINVAL;
368 }
369 netid = atoi(shift_cmdl(cmdl));
370
371 nest = mnl_attr_nest_start(nlh, TIPC_NLA_NET);
372 mnl_attr_put_u32(nlh, TIPC_NLA_NET_ID, netid);
373 mnl_attr_nest_end(nlh, nest);
374
375 return msg_doit(nlh, NULL, NULL);
376}
377
24bee3bf
TL
378static void cmd_node_flush_help(struct cmdl *cmdl)
379{
380 fprintf(stderr,
381 "Usage: %s node flush PROPERTY\n\n"
382 "PROPERTIES\n"
383 " key - Flush all symmetric-keys\n",
384 cmdl->argv[0]);
385}
386
387static int cmd_node_flush(struct nlmsghdr *nlh, const struct cmd *cmd,
388 struct cmdl *cmdl, void *data)
389{
390 const struct cmd cmds[] = {
391 { "key", cmd_node_flush_key, NULL },
392 { NULL }
393 };
394
395 return run_cmd(nlh, cmd, cmds, cmdl, NULL);
396}
397
f043759d
RA
398static void cmd_node_set_help(struct cmdl *cmdl)
399{
400 fprintf(stderr,
401 "Usage: %s node set PROPERTY\n\n"
402 "PROPERTIES\n"
725ebfbf 403 " identity NODEID - Set node identity\n"
24bee3bf
TL
404 " clusterid CLUSTERID - Set local cluster id\n"
405 " key PROPERTY - Set symmetric-key\n",
f043759d
RA
406 cmdl->argv[0]);
407}
408
409static int cmd_node_set(struct nlmsghdr *nlh, const struct cmd *cmd,
410 struct cmdl *cmdl, void *data)
411{
412 const struct cmd cmds[] = {
725ebfbf
JM
413 { "address", cmd_node_set_addr, NULL },
414 { "identity", cmd_node_set_nodeid, NULL },
f043759d 415 { "netid", cmd_node_set_netid, NULL },
725ebfbf 416 { "clusterid", cmd_node_set_netid, NULL },
24bee3bf 417 { "key", cmd_node_set_key, cmd_node_set_key_help },
f043759d
RA
418 { NULL }
419 };
420
421 return run_cmd(nlh, cmd, cmds, cmdl, NULL);
422}
423
424static void cmd_node_get_help(struct cmdl *cmdl)
425{
426 fprintf(stderr,
427 "Usage: %s node get PROPERTY\n\n"
428 "PROPERTIES\n"
725ebfbf
JM
429 " identity - Get node identity\n"
430 " clusterid - Get local clusterid\n",
f043759d
RA
431 cmdl->argv[0]);
432}
433
434static int cmd_node_get(struct nlmsghdr *nlh, const struct cmd *cmd,
435 struct cmdl *cmdl, void *data)
436{
437 const struct cmd cmds[] = {
438 { "address", cmd_node_get_addr, NULL },
725ebfbf 439 { "identity", cmd_node_get_nodeid, NULL },
f043759d 440 { "netid", cmd_node_get_netid, NULL },
725ebfbf 441 { "clusterid", cmd_node_get_netid, NULL },
f043759d
RA
442 { NULL }
443 };
444
445 return run_cmd(nlh, cmd, cmds, cmdl, NULL);
446}
447
448void cmd_node_help(struct cmdl *cmdl)
449{
450 fprintf(stderr,
02573698 451 "Usage: %s node COMMAND [ARGS] ...\n\n"
f043759d
RA
452 "COMMANDS\n"
453 " list - List remote nodes\n"
454 " get - Get local node parameters\n"
24bee3bf
TL
455 " set - Set local node parameters\n"
456 " flush - Flush local node parameters\n",
f043759d
RA
457 cmdl->argv[0]);
458}
459
460int cmd_node(struct nlmsghdr *nlh, const struct cmd *cmd, struct cmdl *cmdl,
461 void *data)
462{
463 const struct cmd cmds[] = {
464 { "list", cmd_node_list, NULL },
465 { "get", cmd_node_get, cmd_node_get_help },
466 { "set", cmd_node_set, cmd_node_set_help },
24bee3bf 467 { "flush", cmd_node_flush, cmd_node_flush_help},
f043759d
RA
468 { NULL }
469 };
470
471 return run_cmd(nlh, cmd, cmds, cmdl, NULL);
472}