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