Home | History | Annotate | Download | only in tipc
      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 (at) 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 	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 
     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 
     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 
    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 
    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 
    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 
    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 
    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 
    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 
    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 
    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 
    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 
    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