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 "cmdl.h"
21#include "msg.h"
22#include "socket.h"
23
24#define PORTID_STR_LEN 45
25
26static 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
46static 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
64static 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 %x:%u", node,
88 mnl_attr_get_u32(con[TIPC_NLA_CON_SOCK]));
89
90 if (con[TIPC_NLA_CON_FLAG])
91 printf(" via {%u,%u}\n",
92 mnl_attr_get_u32(con[TIPC_NLA_CON_TYPE]),
93 mnl_attr_get_u32(con[TIPC_NLA_CON_INST]));
94 else
95 printf("\n");
96 } else if (attrs[TIPC_NLA_SOCK_HAS_PUBL]) {
97 publ_list(mnl_attr_get_u32(attrs[TIPC_NLA_SOCK_REF]));
98 }
99
100 return MNL_CB_OK;
101}
102
103static int cmd_socket_list(struct nlmsghdr *nlh, const struct cmd *cmd,
104 struct cmdl *cmdl, void *data)
105{
106 char buf[MNL_SOCKET_BUFFER_SIZE];
107
108 if (help_flag) {
109 fprintf(stderr, "Usage: %s socket list\n", cmdl->argv[0]);
110 return -EINVAL;
111 }
112
113 if (!(nlh = msg_init(buf, TIPC_NL_SOCK_GET))) {
114 fprintf(stderr, "error, message initialisation failed\n");
115 return -1;
116 }
117
118 return msg_dumpit(nlh, sock_list_cb, NULL);
119}
120
121void cmd_socket_help(struct cmdl *cmdl)
122{
123 fprintf(stderr,
124 "Usage: %s socket COMMAND\n\n"
125 "Commands:\n"
126 " list - List sockets (ports)\n",
127 cmdl->argv[0]);
128}
129
130int cmd_socket(struct nlmsghdr *nlh, const struct cmd *cmd, struct cmdl *cmdl,
131 void *data)
132{
133 const struct cmd cmds[] = {
134 { "list", cmd_socket_list, NULL },
135 { NULL }
136 };
137
138 return run_cmd(nlh, cmd, cmds, cmdl, NULL);
139}
140