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