7 #include <libmnl/libmnl.h>
8 #include <linux/genetlink.h>
10 static int parse_mc_grps_cb(
const struct nlattr *attr,
void *data)
12 const struct nlattr **tb = data;
13 int type = mnl_attr_get_type(attr);
16 if (mnl_attr_type_valid(attr, CTRL_ATTR_MCAST_GRP_MAX) < 0)
20 case CTRL_ATTR_MCAST_GRP_ID:
21 if (mnl_attr_validate(attr, MNL_TYPE_U32) < 0) {
22 perror(
"mnl_attr_validate");
26 case CTRL_ATTR_MCAST_GRP_NAME:
27 if (mnl_attr_validate(attr, MNL_TYPE_STRING) < 0) {
28 perror(
"mnl_attr_validate");
37 static void parse_genl_mc_grps(
struct nlattr *nested)
41 mnl_attr_for_each_nested(pos, nested) {
42 struct nlattr *tb[CTRL_ATTR_MCAST_GRP_MAX+1] = {};
44 mnl_attr_parse_nested(pos, parse_mc_grps_cb, tb);
45 if (tb[CTRL_ATTR_MCAST_GRP_ID]) {
47 mnl_attr_get_u32(tb[CTRL_ATTR_MCAST_GRP_ID]));
49 if (tb[CTRL_ATTR_MCAST_GRP_NAME]) {
51 mnl_attr_get_str(tb[CTRL_ATTR_MCAST_GRP_NAME]));
57 static int parse_family_ops_cb(
const struct nlattr *attr,
void *data)
59 const struct nlattr **tb = data;
60 int type = mnl_attr_get_type(attr);
62 if (mnl_attr_type_valid(attr, CTRL_ATTR_OP_MAX) < 0)
67 if (mnl_attr_validate(attr, MNL_TYPE_U32) < 0) {
68 perror(
"mnl_attr_validate");
72 case CTRL_ATTR_OP_MAX:
81 static void parse_genl_family_ops(
struct nlattr *nested)
85 mnl_attr_for_each_nested(pos, nested) {
86 struct nlattr *tb[CTRL_ATTR_OP_MAX+1] = {};
88 mnl_attr_parse_nested(pos, parse_family_ops_cb, tb);
89 if (tb[CTRL_ATTR_OP_ID]) {
91 mnl_attr_get_u32(tb[CTRL_ATTR_OP_ID]));
93 if (tb[CTRL_ATTR_OP_MAX]) {
100 static int data_attr_cb(
const struct nlattr *attr,
void *data)
102 const struct nlattr **tb = data;
103 int type = mnl_attr_get_type(attr);
105 if (mnl_attr_type_valid(attr, CTRL_ATTR_MAX) < 0)
109 case CTRL_ATTR_FAMILY_NAME:
110 if (mnl_attr_validate(attr, MNL_TYPE_STRING) < 0) {
111 perror(
"mnl_attr_validate");
115 case CTRL_ATTR_FAMILY_ID:
116 if (mnl_attr_validate(attr, MNL_TYPE_U16) < 0) {
117 perror(
"mnl_attr_validate");
121 case CTRL_ATTR_VERSION:
122 case CTRL_ATTR_HDRSIZE:
123 case CTRL_ATTR_MAXATTR:
124 if (mnl_attr_validate(attr, MNL_TYPE_U32) < 0) {
125 perror(
"mnl_attr_validate");
130 case CTRL_ATTR_MCAST_GROUPS:
131 if (mnl_attr_validate(attr, MNL_TYPE_NESTED) < 0) {
132 perror(
"mnl_attr_validate");
141 static int data_cb(
const struct nlmsghdr *nlh,
void *data)
143 struct nlattr *tb[CTRL_ATTR_MAX+1] = {};
144 struct genlmsghdr *genl = mnl_nlmsg_get_payload(nlh);
146 mnl_attr_parse(nlh,
sizeof(*genl), data_attr_cb, tb);
147 if (tb[CTRL_ATTR_FAMILY_NAME]) {
149 mnl_attr_get_str(tb[CTRL_ATTR_FAMILY_NAME]));
151 if (tb[CTRL_ATTR_FAMILY_ID]) {
153 mnl_attr_get_u16(tb[CTRL_ATTR_FAMILY_ID]));
155 if (tb[CTRL_ATTR_VERSION]) {
156 printf(
"version=%u\t",
157 mnl_attr_get_u32(tb[CTRL_ATTR_VERSION]));
159 if (tb[CTRL_ATTR_HDRSIZE]) {
160 printf(
"hdrsize=%u\t",
161 mnl_attr_get_u32(tb[CTRL_ATTR_HDRSIZE]));
163 if (tb[CTRL_ATTR_MAXATTR]) {
164 printf(
"maxattr=%u\t",
165 mnl_attr_get_u32(tb[CTRL_ATTR_MAXATTR]));
168 if (tb[CTRL_ATTR_OPS]) {
170 parse_genl_family_ops(tb[CTRL_ATTR_OPS]);
172 if (tb[CTRL_ATTR_MCAST_GROUPS]) {
174 parse_genl_mc_grps(tb[CTRL_ATTR_MCAST_GROUPS]);
180 int main(
int argc,
char *argv[])
183 char buf[MNL_SOCKET_BUFFER_SIZE];
184 struct nlmsghdr *nlh;
185 struct genlmsghdr *genl;
187 unsigned int seq, portid;
190 printf(
"%s [family name]\n", argv[0]);
194 nlh = mnl_nlmsg_put_header(buf);
195 nlh->nlmsg_type = GENL_ID_CTRL;
196 nlh->nlmsg_flags = NLM_F_REQUEST | NLM_F_ACK;
197 nlh->nlmsg_seq = seq = time(NULL);
199 genl = mnl_nlmsg_put_extra_header(nlh,
sizeof(
struct genlmsghdr));
200 genl->cmd = CTRL_CMD_GETFAMILY;
203 mnl_attr_put_u32(nlh, CTRL_ATTR_FAMILY_ID, GENL_ID_CTRL);
205 mnl_attr_put_strz(nlh, CTRL_ATTR_FAMILY_NAME, argv[1]);
207 nlh->nlmsg_flags |= NLM_F_DUMP;
209 nl = mnl_socket_open(NETLINK_GENERIC);
211 perror(
"mnl_socket_open");
215 if (mnl_socket_bind(nl, 0, MNL_SOCKET_AUTOPID) < 0) {
216 perror(
"mnl_socket_bind");
219 portid = mnl_socket_get_portid(nl);
221 if (mnl_socket_sendto(nl, nlh, nlh->nlmsg_len) < 0) {
222 perror(
"mnl_socket_sendto");
226 ret = mnl_socket_recvfrom(nl, buf,
sizeof(buf));
228 ret = mnl_cb_run(buf, ret, seq, portid, data_cb, NULL);
231 ret = mnl_socket_recvfrom(nl, buf,
sizeof(buf));
238 mnl_socket_close(nl);