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 <CMD>\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;
 }

Reply via email to