• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 
node_list_cb(const struct nlmsghdr * nlh,void * data)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 
cmd_node_list(struct nlmsghdr * nlh,const struct cmd * cmd,struct cmdl * cmdl,void * data)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 
cmd_node_set_addr(struct nlmsghdr * nlh,const struct cmd * cmd,struct cmdl * cmdl,void * data)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 
cmd_node_get_addr(struct nlmsghdr * nlh,const struct cmd * cmd,struct cmdl * cmdl,void * data)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 
netid_get_cb(const struct nlmsghdr * nlh,void * data)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 
cmd_node_get_netid(struct nlmsghdr * nlh,const struct cmd * cmd,struct cmdl * cmdl,void * data)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 
cmd_node_set_netid(struct nlmsghdr * nlh,const struct cmd * cmd,struct cmdl * cmdl,void * data)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 
cmd_node_set_help(struct cmdl * cmdl)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 
cmd_node_set(struct nlmsghdr * nlh,const struct cmd * cmd,struct cmdl * cmdl,void * data)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 
cmd_node_get_help(struct cmdl * cmdl)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 
cmd_node_get(struct nlmsghdr * nlh,const struct cmd * cmd,struct cmdl * cmdl,void * data)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 
cmd_node_help(struct cmdl * cmdl)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 
cmd_node(struct nlmsghdr * nlh,const struct cmd * cmd,struct cmdl * cmdl,void * data)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