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