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 	sk = socket(AF_TIPC, SOCK_RDM, 0);
    113 	if (sk < 0) {
    114 		fprintf(stderr, "opening TIPC socket: %s\n", strerror(errno));
    115 		return -1;
    116 	}
    117 
    118 	if (getsockname(sk, (struct sockaddr *)&addr, &sz) < 0) {
    119 		fprintf(stderr, "getting TIPC socket address: %s\n",
    120 			strerror(errno));
    121 		close(sk);
    122 		return -1;
    123 	}
    124 	close(sk);
    125 
    126 	printf("<%u.%u.%u>\n",
    127 		tipc_zone(addr.addr.id.node),
    128 		tipc_cluster(addr.addr.id.node),
    129 		tipc_node(addr.addr.id.node));
    130 
    131 	return 0;
    132 }
    133 
    134 static int netid_get_cb(const struct nlmsghdr *nlh, void *data)
    135 {
    136 	struct genlmsghdr *genl = mnl_nlmsg_get_payload(nlh);
    137 	struct nlattr *info[TIPC_NLA_MAX + 1] = {};
    138 	struct nlattr *attrs[TIPC_NLA_NET_MAX + 1] = {};
    139 
    140 	mnl_attr_parse(nlh, sizeof(*genl), parse_attrs, info);
    141 	if (!info[TIPC_NLA_NET])
    142 		return MNL_CB_ERROR;
    143 
    144 	mnl_attr_parse_nested(info[TIPC_NLA_NET], parse_attrs, attrs);
    145 	if (!attrs[TIPC_NLA_NET_ID])
    146 		return MNL_CB_ERROR;
    147 
    148 	printf("%u\n", mnl_attr_get_u32(attrs[TIPC_NLA_NET_ID]));
    149 
    150 	return MNL_CB_OK;
    151 }
    152 
    153 static int cmd_node_get_netid(struct nlmsghdr *nlh, const struct cmd *cmd,
    154 			      struct cmdl *cmdl, void *data)
    155 {
    156 	char buf[MNL_SOCKET_BUFFER_SIZE];
    157 
    158 	if (help_flag) {
    159 		(cmd->help)(cmdl);
    160 		return -EINVAL;
    161 	}
    162 
    163 	if (!(nlh = msg_init(buf, TIPC_NL_NET_GET))) {
    164 		fprintf(stderr, "error, message initialisation failed\n");
    165 		return -1;
    166 	}
    167 
    168 	return msg_dumpit(nlh, netid_get_cb, NULL);
    169 }
    170 
    171 static int cmd_node_set_netid(struct nlmsghdr *nlh, const struct cmd *cmd,
    172 			      struct cmdl *cmdl, void *data)
    173 {
    174 	int netid;
    175 	char buf[MNL_SOCKET_BUFFER_SIZE];
    176 	struct nlattr *nest;
    177 
    178 	if (help_flag) {
    179 		(cmd->help)(cmdl);
    180 		return -EINVAL;
    181 	}
    182 
    183 	if (!(nlh = msg_init(buf, TIPC_NL_NET_SET))) {
    184 		fprintf(stderr, "error, message initialisation failed\n");
    185 		return -1;
    186 	}
    187 
    188 	if (cmdl->argc != cmdl->optind + 1) {
    189 		fprintf(stderr, "Usage: %s node set netid NETID\n",
    190 			cmdl->argv[0]);
    191 		return -EINVAL;
    192 	}
    193 	netid = atoi(shift_cmdl(cmdl));
    194 
    195 	nest = mnl_attr_nest_start(nlh, TIPC_NLA_NET);
    196 	mnl_attr_put_u32(nlh, TIPC_NLA_NET_ID, netid);
    197 	mnl_attr_nest_end(nlh, nest);
    198 
    199 	return msg_doit(nlh, NULL, NULL);
    200 }
    201 
    202 static void cmd_node_set_help(struct cmdl *cmdl)
    203 {
    204 	fprintf(stderr,
    205 		"Usage: %s node set PROPERTY\n\n"
    206 		"PROPERTIES\n"
    207 		" address ADDRESS       - Set local address\n"
    208 		" netid NETID           - Set local netid\n",
    209 		cmdl->argv[0]);
    210 }
    211 
    212 static int cmd_node_set(struct nlmsghdr *nlh, const struct cmd *cmd,
    213 			struct cmdl *cmdl, void *data)
    214 {
    215 	const struct cmd cmds[] = {
    216 		{ "address",	cmd_node_set_addr,	NULL },
    217 		{ "netid",	cmd_node_set_netid,	NULL },
    218 		{ NULL }
    219 	};
    220 
    221 	return run_cmd(nlh, cmd, cmds, cmdl, NULL);
    222 }
    223 
    224 static void cmd_node_get_help(struct cmdl *cmdl)
    225 {
    226 	fprintf(stderr,
    227 		"Usage: %s node get PROPERTY\n\n"
    228 		"PROPERTIES\n"
    229 		" address               - Get local address\n"
    230 		" netid                 - Get local netid\n",
    231 		cmdl->argv[0]);
    232 }
    233 
    234 static int cmd_node_get(struct nlmsghdr *nlh, const struct cmd *cmd,
    235 			struct cmdl *cmdl, void *data)
    236 {
    237 	const struct cmd cmds[] = {
    238 		{ "address",	cmd_node_get_addr,	NULL },
    239 		{ "netid",	cmd_node_get_netid,	NULL },
    240 		{ NULL }
    241 	};
    242 
    243 	return run_cmd(nlh, cmd, cmds, cmdl, NULL);
    244 }
    245 
    246 void cmd_node_help(struct cmdl *cmdl)
    247 {
    248 	fprintf(stderr,
    249 		"Usage: %s node COMMAND [ARGS] ...\n\n"
    250 		"COMMANDS\n"
    251 		" list                  - List remote nodes\n"
    252 		" get                   - Get local node parameters\n"
    253 		" set                   - Set local node parameters\n",
    254 		cmdl->argv[0]);
    255 }
    256 
    257 int cmd_node(struct nlmsghdr *nlh, const struct cmd *cmd, struct cmdl *cmdl,
    258 	     void *data)
    259 {
    260 	const struct cmd cmds[] = {
    261 		{ "list",	cmd_node_list,	NULL },
    262 		{ "get",	cmd_node_get,	cmd_node_get_help },
    263 		{ "set",	cmd_node_set,	cmd_node_set_help },
    264 		{ NULL }
    265 	};
    266 
    267 	return run_cmd(nlh, cmd, cmds, cmdl, NULL);
    268 }
    269