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