Ok, heres hopefully the last one in this series for generic netlink ..
cheers,
jamal
[GENL]: Add controller support for new features exposed
Update the controller to spit out the new features being exposed
from the kernel
Signed-off-by: J Hadi Salim <[EMAIL PROTECTED]>
---
commit 241e28d5d5d326d33b2d71752d574e2ae118f671
tree ccda0d9dd9b85180fdd803f79ad11d305f2ffc53
parent 515370c958be14b417e20611258eecbe9fda2382
author Jamal Hadi Salim <[EMAIL PROTECTED]> Wed, 06 Dec 2006 12:30:36 -0500
committer Jamal Hadi Salim <[EMAIL PROTECTED]> Wed, 06 Dec 2006 12:30:36 -0500
genl/ctrl.c | 84 ++-
1 files changed, 82 insertions(+), 2 deletions(-)
diff --git a/genl/ctrl.c b/genl/ctrl.c
index 0d4750d..fe010f3 100644
--- a/genl/ctrl.c
+++ b/genl/ctrl.c
@@ -22,6 +22,7 @@
#include "utils.h"
#include "genl_utils.h"
+#define GENL_MAX_FAM_OPS 256
static int usage(void)
{
fprintf(stderr,"Usage: ctrl \n" \
@@ -108,6 +109,51 @@ errout:
return ret;
}
+void print_ctrl_cmd_flags(FILE *fp, __u32 fl)
+{
+ fprintf(fp, "\n\t\tCapabilities (0x%x):\n ", fl);
+ if (!fl) {
+ fprintf(fp, "\n");
+ return;
+ }
+ fprintf(fp, "\t\t ");
+
+ if (fl & GENL_ADMIN_PERM)
+ fprintf(fp, " requires admin permission;");
+ if (fl & GENL_CMD_CAP_DO)
+ fprintf(fp, " can doit;");
+ if (fl & GENL_CMD_CAP_DUMP)
+ fprintf(fp, " can dumpit;");
+ if (fl & GENL_CMD_CAP_HASPOL)
+ fprintf(fp, " has policy");
+
+ fprintf(fp, "\n");
+}
+
+static int print_ctrl_cmds(FILE *fp, struct rtattr *arg, __u32 ctrl_ver)
+{
+ struct rtattr *tb[CTRL_ATTR_OP_MAX + 1];
+
+ if (arg == NULL)
+ return -1;
+
+ parse_rtattr_nested(tb, CTRL_ATTR_OP_MAX, arg);
+ if (tb[CTRL_ATTR_OP_ID]) {
+ __u32 *id = RTA_DATA(tb[CTRL_ATTR_OP_ID]);
+ fprintf(fp, " ID-0x%x ",*id);
+ }
+ /* we are only gonna do this for newer version of the controller */
+ if (tb[CTRL_ATTR_OP_FLAGS] && ctrl_ver >= 0x2) {
+ __u32 *fl = RTA_DATA(tb[CTRL_ATTR_OP_FLAGS]);
+ print_ctrl_cmd_flags(fp, *fl);
+ }
+ return 0;
+
+}
+
+/*
+ * The controller sends one nlmsg per family
+*/
static int print_ctrl(const struct sockaddr_nl *who, struct nlmsghdr *n,
void *arg)
{
@@ -116,6 +162,7 @@ static int print_ctrl(const struct sockaddr_nl *who, struct
nlmsghdr *n,
int len = n->nlmsg_len;
struct rtattr *attrs;
FILE *fp = (FILE *) arg;
+ __u32 ctrl_v = 0x1;
if (n->nlmsg_type != GENL_ID_CTRL) {
fprintf(stderr, "Not a controller message, nlmsg_len=%d "
@@ -142,13 +189,46 @@ static int print_ctrl(const struct sockaddr_nl *who,
struct nlmsghdr *n,
if (tb[CTRL_ATTR_FAMILY_NAME]) {
char *name = RTA_DATA(tb[CTRL_ATTR_FAMILY_NAME]);
- fprintf(fp, "Name: %s\n",name);
+ fprintf(fp, "\nName: %s\n",name);
}
if (tb[CTRL_ATTR_FAMILY_ID]) {
__u16 *id = RTA_DATA(tb[CTRL_ATTR_FAMILY_ID]);
- fprintf(fp, "ID: 0x%x\n",*id);
+ fprintf(fp, "\tID: 0x%x ",*id);
+ }
+ if (tb[CTRL_ATTR_VERSION]) {
+ __u32 *v = RTA_DATA(tb[CTRL_ATTR_VERSION]);
+ fprintf(fp, " Version: 0x%x ",*v);
+ ctrl_v = *v;
}
+ if (tb[CTRL_ATTR_HDRSIZE]) {
+ __u32 *h = RTA_DATA(tb[CTRL_ATTR_HDRSIZE]);
+ fprintf(fp, " header size: %d ",*h);
+ }
+ if (tb[CTRL_ATTR_MAXATTR]) {
+ __u32 *ma = RTA_DATA(tb[CTRL_ATTR_MAXATTR]);
+ fprintf(fp, " max attribs: %d ",*ma);
+ }
+ /* end of family definitions .. */
+ fprintf(fp,"\n");
+ if (tb[CTRL_ATTR_OPS]) {
+ struct rtattr *tb2[GENL_MAX_FAM_OPS];
+ int i=0;
+ parse_rtattr_nested(tb2, GENL_MAX_FAM_OPS, tb[CTRL_ATTR_OPS]);
+ fprintf(fp, "\tcommands supported: \n");
+ for (i = 0; i < GENL_MAX_FAM_OPS; i++) {
+ if (tb2[i]) {
+ fprintf(fp, "\t\t#%d: ", i);
+ if (0 > print_ctrl_cmds(fp, tb2[i], ctrl_v)) {
+ fprintf(fp, "Error printing command\n");
+ }
+ /* for next command */
+ fprintf(fp,"\n");
+ }
+ }
+ /* end of family::cmds definitions .. */
+ fprintf(fp,"\n");
+ }
fflush(fp);
return 0;
}