]>
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)
10 * Johannes Berg (johannes@sipsolutions.net)
18 #include <sys/socket.h>
19 #include <netinet/in.h>
20 #include <arpa/inet.h>
24 #include "genl_utils.h"
26 #define GENL_MAX_FAM_OPS 256
27 #define GENL_MAX_FAM_GRPS 256
29 static int usage(void)
31 fprintf(stderr
,"Usage: ctrl <CMD>\n" \
32 "CMD := get <PARMS> | list | monitor\n" \
33 "PARMS := name <name> | id <id>\n" \
37 "\tctrl get name foobar\n" \
38 "\tctrl get id 0xF\n");
42 int genl_ctrl_resolve_family(const char *family
)
44 struct rtnl_handle rth
;
46 struct genlmsghdr
*ghdr
;
53 memset(&req
, 0, sizeof(req
));
56 nlh
->nlmsg_len
= NLMSG_LENGTH(GENL_HDRLEN
);
57 nlh
->nlmsg_flags
= NLM_F_REQUEST
| NLM_F_ACK
;
58 nlh
->nlmsg_type
= GENL_ID_CTRL
;
60 ghdr
= NLMSG_DATA(&req
.n
);
61 ghdr
->cmd
= CTRL_CMD_GETFAMILY
;
63 if (rtnl_open_byproto(&rth
, 0, NETLINK_GENERIC
) < 0) {
64 fprintf(stderr
, "Cannot open generic netlink socket\n");
68 addattr_l(nlh
, 128, CTRL_ATTR_FAMILY_NAME
, family
, strlen(family
) + 1);
70 if (rtnl_talk(&rth
, nlh
, 0, 0, nlh
) < 0) {
71 fprintf(stderr
, "Error talking to the kernel\n");
76 struct rtattr
*tb
[CTRL_ATTR_MAX
+ 1];
77 struct genlmsghdr
*ghdr
= NLMSG_DATA(nlh
);
78 int len
= nlh
->nlmsg_len
;
81 if (nlh
->nlmsg_type
!= GENL_ID_CTRL
) {
82 fprintf(stderr
, "Not a controller message, nlmsg_len=%d "
83 "nlmsg_type=0x%x\n", nlh
->nlmsg_len
, nlh
->nlmsg_type
);
87 if (ghdr
->cmd
!= CTRL_CMD_NEWFAMILY
) {
88 fprintf(stderr
, "Unknown controller command %d\n", ghdr
->cmd
);
92 len
-= NLMSG_LENGTH(GENL_HDRLEN
);
95 fprintf(stderr
, "wrong controller message len %d\n", len
);
99 attrs
= (struct rtattr
*) ((char *) ghdr
+ GENL_HDRLEN
);
100 parse_rtattr(tb
, CTRL_ATTR_MAX
, attrs
, len
);
102 if (tb
[CTRL_ATTR_FAMILY_ID
] == NULL
) {
103 fprintf(stderr
, "Missing family id TLV\n");
107 ret
= rta_getattr_u16(tb
[CTRL_ATTR_FAMILY_ID
]);
115 static void print_ctrl_cmd_flags(FILE *fp
, __u32 fl
)
117 fprintf(fp
, "\n\t\tCapabilities (0x%x):\n ", fl
);
122 fprintf(fp
, "\t\t ");
124 if (fl
& GENL_ADMIN_PERM
)
125 fprintf(fp
, " requires admin permission;");
126 if (fl
& GENL_CMD_CAP_DO
)
127 fprintf(fp
, " can doit;");
128 if (fl
& GENL_CMD_CAP_DUMP
)
129 fprintf(fp
, " can dumpit;");
130 if (fl
& GENL_CMD_CAP_HASPOL
)
131 fprintf(fp
, " has policy");
136 static int print_ctrl_cmds(FILE *fp
, struct rtattr
*arg
, __u32 ctrl_ver
)
138 struct rtattr
*tb
[CTRL_ATTR_OP_MAX
+ 1];
143 parse_rtattr_nested(tb
, CTRL_ATTR_OP_MAX
, arg
);
144 if (tb
[CTRL_ATTR_OP_ID
]) {
145 __u32
*id
= RTA_DATA(tb
[CTRL_ATTR_OP_ID
]);
146 fprintf(fp
, " ID-0x%x ",*id
);
148 /* we are only gonna do this for newer version of the controller */
149 if (tb
[CTRL_ATTR_OP_FLAGS
] && ctrl_ver
>= 0x2) {
150 __u32
*fl
= RTA_DATA(tb
[CTRL_ATTR_OP_FLAGS
]);
151 print_ctrl_cmd_flags(fp
, *fl
);
157 static int print_ctrl_grp(FILE *fp
, struct rtattr
*arg
, __u32 ctrl_ver
)
159 struct rtattr
*tb
[CTRL_ATTR_MCAST_GRP_MAX
+ 1];
164 parse_rtattr_nested(tb
, CTRL_ATTR_MCAST_GRP_MAX
, arg
);
166 __u32
*id
= RTA_DATA(tb
[CTRL_ATTR_MCAST_GRP_ID
]);
167 fprintf(fp
, " ID-0x%x ",*id
);
170 char *name
= RTA_DATA(tb
[CTRL_ATTR_MCAST_GRP_NAME
]);
171 fprintf(fp
, " name: %s ", name
);
178 * The controller sends one nlmsg per family
180 static int print_ctrl(const struct sockaddr_nl
*who
,
181 struct rtnl_ctrl_data
*ctrl
,
182 struct nlmsghdr
*n
, void *arg
)
184 struct rtattr
*tb
[CTRL_ATTR_MAX
+ 1];
185 struct genlmsghdr
*ghdr
= NLMSG_DATA(n
);
186 int len
= n
->nlmsg_len
;
187 struct rtattr
*attrs
;
188 FILE *fp
= (FILE *) arg
;
191 if (n
->nlmsg_type
!= GENL_ID_CTRL
) {
192 fprintf(stderr
, "Not a controller message, nlmsg_len=%d "
193 "nlmsg_type=0x%x\n", n
->nlmsg_len
, n
->nlmsg_type
);
197 if (ghdr
->cmd
!= CTRL_CMD_GETFAMILY
&&
198 ghdr
->cmd
!= CTRL_CMD_DELFAMILY
&&
199 ghdr
->cmd
!= CTRL_CMD_NEWFAMILY
&&
200 ghdr
->cmd
!= CTRL_CMD_NEWMCAST_GRP
&&
201 ghdr
->cmd
!= CTRL_CMD_DELMCAST_GRP
) {
202 fprintf(stderr
, "Unknown controller command %d\n", ghdr
->cmd
);
206 len
-= NLMSG_LENGTH(GENL_HDRLEN
);
209 fprintf(stderr
, "wrong controller message len %d\n", len
);
213 attrs
= (struct rtattr
*) ((char *) ghdr
+ GENL_HDRLEN
);
214 parse_rtattr(tb
, CTRL_ATTR_MAX
, attrs
, len
);
216 if (tb
[CTRL_ATTR_FAMILY_NAME
]) {
217 char *name
= RTA_DATA(tb
[CTRL_ATTR_FAMILY_NAME
]);
218 fprintf(fp
, "\nName: %s\n",name
);
220 if (tb
[CTRL_ATTR_FAMILY_ID
]) {
221 __u16
*id
= RTA_DATA(tb
[CTRL_ATTR_FAMILY_ID
]);
222 fprintf(fp
, "\tID: 0x%x ",*id
);
224 if (tb
[CTRL_ATTR_VERSION
]) {
225 __u32
*v
= RTA_DATA(tb
[CTRL_ATTR_VERSION
]);
226 fprintf(fp
, " Version: 0x%x ",*v
);
229 if (tb
[CTRL_ATTR_HDRSIZE
]) {
230 __u32
*h
= RTA_DATA(tb
[CTRL_ATTR_HDRSIZE
]);
231 fprintf(fp
, " header size: %d ",*h
);
233 if (tb
[CTRL_ATTR_MAXATTR
]) {
234 __u32
*ma
= RTA_DATA(tb
[CTRL_ATTR_MAXATTR
]);
235 fprintf(fp
, " max attribs: %d ",*ma
);
237 /* end of family definitions .. */
239 if (tb
[CTRL_ATTR_OPS
]) {
240 struct rtattr
*tb2
[GENL_MAX_FAM_OPS
];
242 parse_rtattr_nested(tb2
, GENL_MAX_FAM_OPS
, tb
[CTRL_ATTR_OPS
]);
243 fprintf(fp
, "\tcommands supported: \n");
244 for (i
= 0; i
< GENL_MAX_FAM_OPS
; i
++) {
246 fprintf(fp
, "\t\t#%d: ", i
);
247 if (0 > print_ctrl_cmds(fp
, tb2
[i
], ctrl_v
)) {
248 fprintf(fp
, "Error printing command\n");
250 /* for next command */
255 /* end of family::cmds definitions .. */
259 if (tb
[CTRL_ATTR_MCAST_GROUPS
]) {
260 struct rtattr
*tb2
[GENL_MAX_FAM_GRPS
+ 1];
263 parse_rtattr_nested(tb2
, GENL_MAX_FAM_GRPS
,
264 tb
[CTRL_ATTR_MCAST_GROUPS
]);
265 fprintf(fp
, "\tmulticast groups:\n");
267 for (i
= 0; i
< GENL_MAX_FAM_GRPS
; i
++) {
269 fprintf(fp
, "\t\t#%d: ", i
);
270 if (0 > print_ctrl_grp(fp
, tb2
[i
], ctrl_v
))
271 fprintf(fp
, "Error printing group\n");
277 /* end of family::groups definitions .. */
285 static int print_ctrl2(const struct sockaddr_nl
*who
,
286 struct nlmsghdr
*n
, void *arg
)
288 return print_ctrl(who
, NULL
, n
, arg
);
291 static int ctrl_list(int cmd
, int argc
, char **argv
)
293 struct rtnl_handle rth
;
294 struct nlmsghdr
*nlh
;
295 struct genlmsghdr
*ghdr
;
303 memset(&req
, 0, sizeof(req
));
306 nlh
->nlmsg_len
= NLMSG_LENGTH(GENL_HDRLEN
);
307 nlh
->nlmsg_flags
= NLM_F_REQUEST
| NLM_F_ACK
;
308 nlh
->nlmsg_type
= GENL_ID_CTRL
;
310 ghdr
= NLMSG_DATA(&req
.n
);
311 ghdr
->cmd
= CTRL_CMD_GETFAMILY
;
313 if (rtnl_open_byproto(&rth
, 0, NETLINK_GENERIC
) < 0) {
314 fprintf(stderr
, "Cannot open generic netlink socket\n");
318 if (cmd
== CTRL_CMD_GETFAMILY
) {
320 fprintf(stderr
, "Wrong number of params\n");
324 if (matches(*argv
, "name") == 0) {
326 strncpy(d
, *argv
, sizeof (d
) - 1);
327 addattr_l(nlh
, 128, CTRL_ATTR_FAMILY_NAME
,
329 } else if (matches(*argv
, "id") == 0) {
332 if (get_u16(&id
, *argv
, 0)) {
333 fprintf(stderr
, "Illegal \"id\"\n");
337 addattr_l(nlh
, 128, CTRL_ATTR_FAMILY_ID
, &id
, 2);
340 fprintf(stderr
, "Wrong params\n");
344 if (rtnl_talk(&rth
, nlh
, 0, 0, nlh
) < 0) {
345 fprintf(stderr
, "Error talking to the kernel\n");
349 if (print_ctrl2(NULL
, nlh
, (void *) stdout
) < 0) {
350 fprintf(stderr
, "Dump terminated\n");
356 if (cmd
== CTRL_CMD_UNSPEC
) {
357 nlh
->nlmsg_flags
= NLM_F_ROOT
|NLM_F_MATCH
|NLM_F_REQUEST
;
358 nlh
->nlmsg_seq
= rth
.dump
= ++rth
.seq
;
360 if (rtnl_send(&rth
, nlh
, nlh
->nlmsg_len
) < 0) {
361 perror("Failed to send dump request\n");
365 rtnl_dump_filter(&rth
, print_ctrl2
, stdout
);
375 static int ctrl_listen(int argc
, char **argv
)
377 struct rtnl_handle rth
;
379 if (rtnl_open_byproto(&rth
, nl_mgrp(GENL_ID_CTRL
), NETLINK_GENERIC
) < 0) {
380 fprintf(stderr
, "Canot open generic netlink socket\n");
384 if (rtnl_listen(&rth
, print_ctrl
, (void *) stdout
) < 0)
390 static int parse_ctrl(struct genl_util
*a
, int argc
, char **argv
)
394 fprintf(stderr
, "wrong controller params\n");
398 if (matches(*argv
, "monitor") == 0)
399 return ctrl_listen(argc
-1, argv
+1);
400 if (matches(*argv
, "get") == 0)
401 return ctrl_list(CTRL_CMD_GETFAMILY
, argc
-1, argv
+1);
402 if (matches(*argv
, "list") == 0 ||
403 matches(*argv
, "show") == 0 ||
404 matches(*argv
, "lst") == 0)
405 return ctrl_list(CTRL_CMD_UNSPEC
, argc
-1, argv
+1);
406 if (matches(*argv
, "help") == 0)
409 fprintf(stderr
, "ctrl command \"%s\" is unknown, try \"ctrl help\".\n",
415 struct genl_util ctrl_genl_util
= {
417 .parse_genlopt
= parse_ctrl
,
418 .print_genlopt
= print_ctrl2
,