]>
git.proxmox.com Git - mirror_iproute2.git/blob - genl/ctrl.c
2 * ctrl.c generic netlink controller
4 * This program is free software; you can distribute 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.
9 * Authors: J Hadi Salim (hadi@cyberus.ca)
17 #include <sys/socket.h>
18 #include <netinet/in.h>
19 #include <arpa/inet.h>
23 #include "genl_utils.h"
25 static int usage(void)
27 fprintf(stderr
,"Usage: ctrl <CMD>\n" \
28 "CMD := get <PARMS> | list | monitor\n" \
29 "PARMS := name <name> | id <id>\n" \
33 "\tctrl get name foobar\n" \
34 "\tctrl get id 0xF\n");
38 int genl_ctrl_resolve_family(const char *family
)
40 struct rtnl_handle rth
;
42 struct genlmsghdr
*ghdr
;
49 memset(&req
, 0, sizeof(req
));
52 nlh
->nlmsg_len
= NLMSG_LENGTH(GENL_HDRLEN
);
53 nlh
->nlmsg_flags
= NLM_F_REQUEST
| NLM_F_ACK
;
54 nlh
->nlmsg_type
= GENL_ID_CTRL
;
56 ghdr
= NLMSG_DATA(&req
.n
);
57 ghdr
->cmd
= CTRL_CMD_GETFAMILY
;
59 if (rtnl_open_byproto(&rth
, 0, NETLINK_GENERIC
) < 0) {
60 fprintf(stderr
, "Cannot open generic netlink socket\n");
64 addattr_l(nlh
, 128, CTRL_ATTR_FAMILY_NAME
, family
, strlen(family
) + 1);
66 if (rtnl_talk(&rth
, nlh
, 0, 0, nlh
, NULL
, NULL
) < 0) {
67 fprintf(stderr
, "Error talking to the kernel\n");
72 struct rtattr
*tb
[CTRL_ATTR_MAX
+ 1];
73 struct genlmsghdr
*ghdr
= NLMSG_DATA(nlh
);
74 int len
= nlh
->nlmsg_len
;
77 if (nlh
->nlmsg_type
!= GENL_ID_CTRL
) {
78 fprintf(stderr
, "Not a controller message, nlmsg_len=%d "
79 "nlmsg_type=0x%x\n", nlh
->nlmsg_len
, nlh
->nlmsg_type
);
83 if (ghdr
->cmd
!= CTRL_CMD_NEWFAMILY
) {
84 fprintf(stderr
, "Unkown controller command %d\n", ghdr
->cmd
);
88 len
-= NLMSG_LENGTH(GENL_HDRLEN
);
91 fprintf(stderr
, "wrong controller message len %d\n", len
);
95 attrs
= (struct rtattr
*) ((char *) ghdr
+ GENL_HDRLEN
);
96 parse_rtattr(tb
, CTRL_ATTR_MAX
, attrs
, len
);
98 if (tb
[CTRL_ATTR_FAMILY_ID
] == NULL
) {
99 fprintf(stderr
, "Missing family id TLV\n");
103 ret
= *(__u16
*) RTA_DATA(tb
[CTRL_ATTR_FAMILY_ID
]);
111 static int print_ctrl(const struct sockaddr_nl
*who
, struct nlmsghdr
*n
,
114 struct rtattr
*tb
[CTRL_ATTR_MAX
+ 1];
115 struct genlmsghdr
*ghdr
= NLMSG_DATA(n
);
116 int len
= n
->nlmsg_len
;
117 struct rtattr
*attrs
;
118 FILE *fp
= (FILE *) arg
;
120 if (n
->nlmsg_type
!= GENL_ID_CTRL
) {
121 fprintf(stderr
, "Not a controller message, nlmsg_len=%d "
122 "nlmsg_type=0x%x\n", n
->nlmsg_len
, n
->nlmsg_type
);
126 if (ghdr
->cmd
!= CTRL_CMD_GETFAMILY
&&
127 ghdr
->cmd
!= CTRL_CMD_DELFAMILY
&&
128 ghdr
->cmd
!= CTRL_CMD_NEWFAMILY
) {
129 fprintf(stderr
, "Unkown controller command %d\n", ghdr
->cmd
);
133 len
-= NLMSG_LENGTH(GENL_HDRLEN
);
136 fprintf(stderr
, "wrong controller message len %d\n", len
);
140 attrs
= (struct rtattr
*) ((char *) ghdr
+ GENL_HDRLEN
);
141 parse_rtattr(tb
, CTRL_ATTR_MAX
, attrs
, len
);
143 if (tb
[CTRL_ATTR_FAMILY_NAME
]) {
144 char *name
= RTA_DATA(tb
[CTRL_ATTR_FAMILY_NAME
]);
145 fprintf(fp
, "Name: %s\n",name
);
147 if (tb
[CTRL_ATTR_FAMILY_ID
]) {
148 __u16
*id
= RTA_DATA(tb
[CTRL_ATTR_FAMILY_ID
]);
149 fprintf(fp
, "ID: 0x%x\n",*id
);
156 static int ctrl_list(int cmd
, int argc
, char **argv
)
158 struct rtnl_handle rth
;
159 struct nlmsghdr
*nlh
;
160 struct genlmsghdr
*ghdr
;
168 memset(&req
, 0, sizeof(req
));
171 nlh
->nlmsg_len
= NLMSG_LENGTH(GENL_HDRLEN
);
172 nlh
->nlmsg_flags
= NLM_F_REQUEST
| NLM_F_ACK
;
173 nlh
->nlmsg_type
= GENL_ID_CTRL
;
175 ghdr
= NLMSG_DATA(&req
.n
);
176 ghdr
->cmd
= CTRL_CMD_GETFAMILY
;
178 if (rtnl_open_byproto(&rth
, 0, NETLINK_GENERIC
) < 0) {
179 fprintf(stderr
, "Cannot open generic netlink socket\n");
183 if (cmd
== CTRL_CMD_GETFAMILY
) {
185 fprintf(stderr
, "Wrong number of params\n");
189 if (matches(*argv
, "name") == 0) {
191 strncpy(d
, *argv
, sizeof (d
) - 1);
192 addattr_l(nlh
, 128, CTRL_ATTR_FAMILY_NAME
,
194 } else if (matches(*argv
, "id") == 0) {
197 if (get_u16(&id
, *argv
, 0)) {
198 fprintf(stderr
, "Illegal \"id\"\n");
202 addattr_l(nlh
, 128, CTRL_ATTR_FAMILY_ID
, &id
, 2);
205 fprintf(stderr
, "Wrong params\n");
209 if (rtnl_talk(&rth
, nlh
, 0, 0, nlh
, NULL
, NULL
) < 0) {
210 fprintf(stderr
, "Error talking to the kernel\n");
214 if (print_ctrl(NULL
, nlh
, (void *) stdout
) < 0) {
215 fprintf(stderr
, "Dump terminated\n");
221 if (cmd
== CTRL_CMD_UNSPEC
) {
222 nlh
->nlmsg_flags
= NLM_F_ROOT
|NLM_F_MATCH
|NLM_F_REQUEST
;
223 nlh
->nlmsg_seq
= rth
.dump
= ++rth
.seq
;
225 if (rtnl_send(&rth
, (const char *) nlh
, nlh
->nlmsg_len
) < 0) {
226 perror("Failed to send dump request\n");
230 rtnl_dump_filter(&rth
, print_ctrl
, stdout
, NULL
, NULL
);
240 static int ctrl_listen(int argc
, char **argv
)
242 struct rtnl_handle rth
;
244 if (rtnl_open_byproto(&rth
, nl_mgrp(GENL_ID_CTRL
), NETLINK_GENERIC
) < 0) {
245 fprintf(stderr
, "Canot open generic netlink socket\n");
249 if (rtnl_listen(&rth
, print_ctrl
, (void *) stdout
) < 0)
255 static int parse_ctrl(struct genl_util
*a
, int argc
, char **argv
)
259 fprintf(stderr
, "wrong controller params\n");
263 if (matches(*argv
, "monitor") == 0)
264 return ctrl_listen(argc
-1, argv
+1);
265 if (matches(*argv
, "get") == 0)
266 return ctrl_list(CTRL_CMD_GETFAMILY
, argc
-1, argv
+1);
267 if (matches(*argv
, "list") == 0 ||
268 matches(*argv
, "show") == 0 ||
269 matches(*argv
, "lst") == 0)
270 return ctrl_list(CTRL_CMD_UNSPEC
, argc
-1, argv
+1);
271 if (matches(*argv
, "help") == 0)
274 fprintf(stderr
, "ctrl command \"%s\" is unknown, try \"ctrl -help\".\n",
280 struct genl_util ctrl_genl_util
= {
282 .parse_genlopt
= parse_ctrl
,
283 .print_genlopt
= print_ctrl
,