1 /*
2 * socket.c TIPC socket 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 <errno.h>
14
15 #include <linux/tipc.h>
16 #include <linux/tipc_netlink.h>
17 #include <linux/genetlink.h>
18 #include <libmnl/libmnl.h>
19
20 #include "cmdl.h"
21 #include "msg.h"
22 #include "socket.h"
23
24 #define PORTID_STR_LEN 45 /* Four u32 and five delimiter chars */
25
publ_list_cb(const struct nlmsghdr * nlh,void * data)26 static int publ_list_cb(const struct nlmsghdr *nlh, void *data)
27 {
28 struct genlmsghdr *genl = mnl_nlmsg_get_payload(nlh);
29 struct nlattr *info[TIPC_NLA_MAX + 1] = {};
30 struct nlattr *attrs[TIPC_NLA_SOCK_MAX + 1] = {};
31
32 mnl_attr_parse(nlh, sizeof(*genl), parse_attrs, info);
33 if (!info[TIPC_NLA_PUBL])
34 return MNL_CB_ERROR;
35
36 mnl_attr_parse_nested(info[TIPC_NLA_PUBL], parse_attrs, attrs);
37
38 printf(" bound to {%u,%u,%u}\n",
39 mnl_attr_get_u32(attrs[TIPC_NLA_PUBL_TYPE]),
40 mnl_attr_get_u32(attrs[TIPC_NLA_PUBL_LOWER]),
41 mnl_attr_get_u32(attrs[TIPC_NLA_PUBL_UPPER]));
42
43 return MNL_CB_OK;
44 }
45
publ_list(uint32_t sock)46 static int publ_list(uint32_t sock)
47 {
48 struct nlmsghdr *nlh;
49 char buf[MNL_SOCKET_BUFFER_SIZE];
50 struct nlattr *nest;
51
52 if (!(nlh = msg_init(buf, TIPC_NL_PUBL_GET))) {
53 fprintf(stderr, "error, message initialisation failed\n");
54 return -1;
55 }
56
57 nest = mnl_attr_nest_start(nlh, TIPC_NLA_SOCK);
58 mnl_attr_put_u32(nlh, TIPC_NLA_SOCK_REF, sock);
59 mnl_attr_nest_end(nlh, nest);
60
61 return msg_dumpit(nlh, publ_list_cb, NULL);
62 }
63
sock_list_cb(const struct nlmsghdr * nlh,void * data)64 static int sock_list_cb(const struct nlmsghdr *nlh, void *data)
65 {
66 struct genlmsghdr *genl = mnl_nlmsg_get_payload(nlh);
67 struct nlattr *info[TIPC_NLA_MAX + 1] = {};
68 struct nlattr *attrs[TIPC_NLA_SOCK_MAX + 1] = {};
69
70 mnl_attr_parse(nlh, sizeof(*genl), parse_attrs, info);
71 if (!info[TIPC_NLA_SOCK])
72 return MNL_CB_ERROR;
73
74 mnl_attr_parse_nested(info[TIPC_NLA_SOCK], parse_attrs, attrs);
75 if (!attrs[TIPC_NLA_SOCK_REF])
76 return MNL_CB_ERROR;
77
78 printf("socket %u\n", mnl_attr_get_u32(attrs[TIPC_NLA_SOCK_REF]));
79
80 if (attrs[TIPC_NLA_SOCK_CON]) {
81 uint32_t node;
82 struct nlattr *con[TIPC_NLA_CON_MAX + 1] = {};
83
84 mnl_attr_parse_nested(attrs[TIPC_NLA_SOCK_CON], parse_attrs, con);
85 node = mnl_attr_get_u32(con[TIPC_NLA_CON_NODE]);
86
87 printf(" connected to <%u.%u.%u:%u>", tipc_zone(node),
88 tipc_cluster(node), tipc_node(node),
89 mnl_attr_get_u32(con[TIPC_NLA_CON_SOCK]));
90
91 if (con[TIPC_NLA_CON_FLAG])
92 printf(" via {%u,%u}\n",
93 mnl_attr_get_u32(con[TIPC_NLA_CON_TYPE]),
94 mnl_attr_get_u32(con[TIPC_NLA_CON_INST]));
95 else
96 printf("\n");
97 } else if (attrs[TIPC_NLA_SOCK_HAS_PUBL]) {
98 publ_list(mnl_attr_get_u32(attrs[TIPC_NLA_SOCK_REF]));
99 }
100
101 return MNL_CB_OK;
102 }
103
cmd_socket_list(struct nlmsghdr * nlh,const struct cmd * cmd,struct cmdl * cmdl,void * data)104 static int cmd_socket_list(struct nlmsghdr *nlh, const struct cmd *cmd,
105 struct cmdl *cmdl, void *data)
106 {
107 char buf[MNL_SOCKET_BUFFER_SIZE];
108
109 if (help_flag) {
110 fprintf(stderr, "Usage: %s socket list\n", cmdl->argv[0]);
111 return -EINVAL;
112 }
113
114 if (!(nlh = msg_init(buf, TIPC_NL_SOCK_GET))) {
115 fprintf(stderr, "error, message initialisation failed\n");
116 return -1;
117 }
118
119 return msg_dumpit(nlh, sock_list_cb, NULL);
120 }
121
cmd_socket_help(struct cmdl * cmdl)122 void cmd_socket_help(struct cmdl *cmdl)
123 {
124 fprintf(stderr,
125 "Usage: %s socket COMMAND\n\n"
126 "Commands:\n"
127 " list - List sockets (ports)\n",
128 cmdl->argv[0]);
129 }
130
cmd_socket(struct nlmsghdr * nlh,const struct cmd * cmd,struct cmdl * cmdl,void * data)131 int cmd_socket(struct nlmsghdr *nlh, const struct cmd *cmd, struct cmdl *cmdl,
132 void *data)
133 {
134 const struct cmd cmds[] = {
135 { "list", cmd_socket_list, NULL },
136 { NULL }
137 };
138
139 return run_cmd(nlh, cmd, cmds, cmdl, NULL);
140 }
141