]> git.proxmox.com Git - mirror_iproute2.git/blobdiff - genl/ctrl.c
drop unneeded include of syslog.h
[mirror_iproute2.git] / genl / ctrl.c
index fe010f3f0d9a0ae709a319f6760653875d79443d..0d9c5f2517b78b978e413e1443be371859e851a5 100644 (file)
@@ -6,13 +6,13 @@
  *             as published by the Free Software Foundation; either version
  *             2 of the License, or (at your option) any later version.
  *
- * Authors:  J Hadi Salim (hadi@cyberus.ca)
+ * Authors:    J Hadi Salim (hadi@cyberus.ca)
+ *             Johannes Berg (johannes@sipsolutions.net)
  */
 
 #include <stdio.h>
 #include <stdlib.h>
 #include <unistd.h>
-#include <syslog.h>
 #include <fcntl.h>
 #include <sys/socket.h>
 #include <netinet/in.h>
@@ -23,6 +23,8 @@
 #include "genl_utils.h"
 
 #define GENL_MAX_FAM_OPS       256
+#define GENL_MAX_FAM_GRPS      256
+
 static int usage(void)
 {
        fprintf(stderr,"Usage: ctrl <CMD>\n" \
@@ -39,23 +41,20 @@ static int usage(void)
 int genl_ctrl_resolve_family(const char *family)
 {
        struct rtnl_handle rth;
-       struct nlmsghdr *nlh;
-       struct genlmsghdr *ghdr;
        int ret = 0;
        struct {
                struct nlmsghdr         n;
+               struct genlmsghdr       g;
                char                    buf[4096];
-       } req;
-
-       memset(&req, 0, sizeof(req));
-
-       nlh = &req.n;
-       nlh->nlmsg_len = NLMSG_LENGTH(GENL_HDRLEN);
-       nlh->nlmsg_flags = NLM_F_REQUEST | NLM_F_ACK;
-       nlh->nlmsg_type = GENL_ID_CTRL;
-
-       ghdr = NLMSG_DATA(&req.n);
-       ghdr->cmd = CTRL_CMD_GETFAMILY;
+       } req = {
+               .n.nlmsg_len = NLMSG_LENGTH(GENL_HDRLEN),
+               .n.nlmsg_flags = NLM_F_REQUEST | NLM_F_ACK,
+               .n.nlmsg_type = GENL_ID_CTRL,
+               .g.cmd = CTRL_CMD_GETFAMILY,
+       };
+       struct nlmsghdr *nlh = &req.n;
+       struct genlmsghdr *ghdr = &req.g;
+       struct nlmsghdr *answer = NULL;
 
        if (rtnl_open_byproto(&rth, 0, NETLINK_GENERIC) < 0) {
                fprintf(stderr, "Cannot open generic netlink socket\n");
@@ -64,25 +63,24 @@ int genl_ctrl_resolve_family(const char *family)
 
        addattr_l(nlh, 128, CTRL_ATTR_FAMILY_NAME, family, strlen(family) + 1);
 
-       if (rtnl_talk(&rth, nlh, 0, 0, nlh, NULL, NULL) < 0) {
+       if (rtnl_talk(&rth, nlh, &answer) < 0) {
                fprintf(stderr, "Error talking to the kernel\n");
                goto errout;
        }
 
        {
                struct rtattr *tb[CTRL_ATTR_MAX + 1];
-               struct genlmsghdr *ghdr = NLMSG_DATA(nlh);
-               int len = nlh->nlmsg_len;
+               int len = answer->nlmsg_len;
                struct rtattr *attrs;
 
-               if (nlh->nlmsg_type !=  GENL_ID_CTRL) {
+               if (answer->nlmsg_type !=  GENL_ID_CTRL) {
                        fprintf(stderr, "Not a controller message, nlmsg_len=%d "
-                               "nlmsg_type=0x%x\n", nlh->nlmsg_len, nlh->nlmsg_type);
+                               "nlmsg_type=0x%x\n", answer->nlmsg_len, answer->nlmsg_type);
                        goto errout;
                }
 
                if (ghdr->cmd != CTRL_CMD_NEWFAMILY) {
-                       fprintf(stderr, "Unkown controller command %d\n", ghdr->cmd);
+                       fprintf(stderr, "Unknown controller command %d\n", ghdr->cmd);
                        goto errout;
                }
 
@@ -90,10 +88,11 @@ int genl_ctrl_resolve_family(const char *family)
 
                if (len < 0) {
                        fprintf(stderr, "wrong controller message len %d\n", len);
+                       free(answer);
                        return -1;
                }
 
-               attrs = (struct rtattr *) ((char *) ghdr + GENL_HDRLEN);
+               attrs = (struct rtattr *) ((char *) answer + NLMSG_LENGTH(GENL_HDRLEN));
                parse_rtattr(tb, CTRL_ATTR_MAX, attrs, len);
 
                if (tb[CTRL_ATTR_FAMILY_ID] == NULL) {
@@ -101,15 +100,16 @@ int genl_ctrl_resolve_family(const char *family)
                        goto errout;
                }
 
-               ret = *(__u16 *) RTA_DATA(tb[CTRL_ATTR_FAMILY_ID]);
+               ret = rta_getattr_u16(tb[CTRL_ATTR_FAMILY_ID]);
        }
 
 errout:
+       free(answer);
        rtnl_close(&rth);
        return ret;
 }
 
-void print_ctrl_cmd_flags(FILE *fp, __u32 fl)
+static void print_ctrl_cmd_flags(FILE *fp, __u32 fl)
 {
        fprintf(fp, "\n\t\tCapabilities (0x%x):\n ", fl);
        if (!fl) {
@@ -129,7 +129,7 @@ void print_ctrl_cmd_flags(FILE *fp, __u32 fl)
 
        fprintf(fp, "\n");
 }
-       
+
 static int print_ctrl_cmds(FILE *fp, struct rtattr *arg, __u32 ctrl_ver)
 {
        struct rtattr *tb[CTRL_ATTR_OP_MAX + 1];
@@ -151,18 +151,39 @@ static int print_ctrl_cmds(FILE *fp, struct rtattr *arg, __u32 ctrl_ver)
 
 }
 
+static int print_ctrl_grp(FILE *fp, struct rtattr *arg, __u32 ctrl_ver)
+{
+       struct rtattr *tb[CTRL_ATTR_MCAST_GRP_MAX + 1];
+
+       if (arg == NULL)
+               return -1;
+
+       parse_rtattr_nested(tb, CTRL_ATTR_MCAST_GRP_MAX, arg);
+       if (tb[2]) {
+               __u32 *id = RTA_DATA(tb[CTRL_ATTR_MCAST_GRP_ID]);
+               fprintf(fp, " ID-0x%x ",*id);
+       }
+       if (tb[1]) {
+               char *name = RTA_DATA(tb[CTRL_ATTR_MCAST_GRP_NAME]);
+               fprintf(fp, " name: %s ", name);
+       }
+       return 0;
+
+}
+
 /*
  * The controller sends one nlmsg per family
 */
-static int print_ctrl(const struct sockaddr_nl *who, struct nlmsghdr *n,
-                     void *arg)
+static int print_ctrl(const struct sockaddr_nl *who,
+                     struct rtnl_ctrl_data *ctrl,
+                     struct nlmsghdr *n, void *arg)
 {
        struct rtattr *tb[CTRL_ATTR_MAX + 1];
        struct genlmsghdr *ghdr = NLMSG_DATA(n);
        int len = n->nlmsg_len;
        struct rtattr *attrs;
        FILE *fp = (FILE *) arg;
-       __u32 ctrl_v = 0x1; 
+       __u32 ctrl_v = 0x1;
 
        if (n->nlmsg_type !=  GENL_ID_CTRL) {
                fprintf(stderr, "Not a controller message, nlmsg_len=%d "
@@ -172,8 +193,10 @@ static int print_ctrl(const struct sockaddr_nl *who, struct nlmsghdr *n,
 
        if (ghdr->cmd != CTRL_CMD_GETFAMILY &&
            ghdr->cmd != CTRL_CMD_DELFAMILY &&
-           ghdr->cmd != CTRL_CMD_NEWFAMILY) {
-               fprintf(stderr, "Unkown controller command %d\n", ghdr->cmd);
+           ghdr->cmd != CTRL_CMD_NEWFAMILY &&
+           ghdr->cmd != CTRL_CMD_NEWMCAST_GRP &&
+           ghdr->cmd != CTRL_CMD_DELMCAST_GRP) {
+               fprintf(stderr, "Unknown controller command %d\n", ghdr->cmd);
                return 0;
        }
 
@@ -229,31 +252,56 @@ static int print_ctrl(const struct sockaddr_nl *who, struct nlmsghdr *n,
                /* end of family::cmds definitions .. */
                fprintf(fp,"\n");
        }
+
+       if (tb[CTRL_ATTR_MCAST_GROUPS]) {
+               struct rtattr *tb2[GENL_MAX_FAM_GRPS + 1];
+               int i;
+
+               parse_rtattr_nested(tb2, GENL_MAX_FAM_GRPS,
+                                   tb[CTRL_ATTR_MCAST_GROUPS]);
+               fprintf(fp, "\tmulticast groups:\n");
+
+               for (i = 0; i < GENL_MAX_FAM_GRPS; i++) {
+                       if (tb2[i]) {
+                               fprintf(fp, "\t\t#%d: ", i);
+                               if (0 > print_ctrl_grp(fp, tb2[i], ctrl_v))
+                                       fprintf(fp, "Error printing group\n");
+                               /* for next group */
+                               fprintf(fp,"\n");
+                       }
+               }
+
+               /* end of family::groups definitions .. */
+               fprintf(fp,"\n");
+       }
+
        fflush(fp);
        return 0;
 }
 
+static int print_ctrl2(const struct sockaddr_nl *who,
+                     struct nlmsghdr *n, void *arg)
+{
+       return print_ctrl(who, NULL, n, arg);
+}
+
 static int ctrl_list(int cmd, int argc, char **argv)
 {
        struct rtnl_handle rth;
-       struct nlmsghdr *nlh;
-       struct genlmsghdr *ghdr;
        int ret = -1;
        char d[GENL_NAMSIZ];
        struct {
                struct nlmsghdr         n;
+               struct genlmsghdr       g;
                char                    buf[4096];
-       } req;
-
-       memset(&req, 0, sizeof(req));
-
-       nlh = &req.n;
-       nlh->nlmsg_len = NLMSG_LENGTH(GENL_HDRLEN);
-       nlh->nlmsg_flags = NLM_F_REQUEST | NLM_F_ACK;
-       nlh->nlmsg_type = GENL_ID_CTRL;
-
-       ghdr = NLMSG_DATA(&req.n);
-       ghdr->cmd = CTRL_CMD_GETFAMILY;
+       } req = {
+               .n.nlmsg_len = NLMSG_LENGTH(GENL_HDRLEN),
+               .n.nlmsg_flags = NLM_F_REQUEST | NLM_F_ACK,
+               .n.nlmsg_type = GENL_ID_CTRL,
+               .g.cmd = CTRL_CMD_GETFAMILY,
+       };
+       struct nlmsghdr *nlh = &req.n;
+       struct nlmsghdr *answer = NULL;
 
        if (rtnl_open_byproto(&rth, 0, NETLINK_GENERIC) < 0) {
                fprintf(stderr, "Cannot open generic netlink socket\n");
@@ -268,7 +316,7 @@ static int ctrl_list(int cmd, int argc, char **argv)
 
                if (matches(*argv, "name") == 0) {
                        NEXT_ARG();
-                       strncpy(d, *argv, sizeof (d) - 1);
+                       strlcpy(d, *argv, sizeof(d));
                        addattr_l(nlh, 128, CTRL_ATTR_FAMILY_NAME,
                                  d, strlen(d) + 1);
                } else if (matches(*argv, "id") == 0) {
@@ -286,12 +334,12 @@ static int ctrl_list(int cmd, int argc, char **argv)
                        goto ctrl_done;
                }
 
-               if (rtnl_talk(&rth, nlh, 0, 0, nlh, NULL, NULL) < 0) {
+               if (rtnl_talk(&rth, nlh, &answer) < 0) {
                        fprintf(stderr, "Error talking to the kernel\n");
                        goto ctrl_done;
                }
 
-               if (print_ctrl(NULL, nlh, (void *) stdout) < 0) {
+               if (print_ctrl2(NULL, answer, (void *) stdout) < 0) {
                        fprintf(stderr, "Dump terminated\n");
                        goto ctrl_done;
                }
@@ -302,17 +350,18 @@ static int ctrl_list(int cmd, int argc, char **argv)
                nlh->nlmsg_flags = NLM_F_ROOT|NLM_F_MATCH|NLM_F_REQUEST;
                nlh->nlmsg_seq = rth.dump = ++rth.seq;
 
-               if (rtnl_send(&rth, (const char *) nlh, nlh->nlmsg_len) < 0) {
+               if (rtnl_send(&rth, nlh, nlh->nlmsg_len) < 0) {
                        perror("Failed to send dump request\n");
                        goto ctrl_done;
                }
 
-               rtnl_dump_filter(&rth, print_ctrl, stdout, NULL, NULL);
+               rtnl_dump_filter(&rth, print_ctrl2, stdout);
 
         }
 
        ret = 0;
 ctrl_done:
+       free(answer);
        rtnl_close(&rth);
        return ret;
 }
@@ -351,7 +400,7 @@ static int parse_ctrl(struct genl_util *a, int argc, char **argv)
        if (matches(*argv, "help") == 0)
                return usage();
 
-       fprintf(stderr, "ctrl command \"%s\" is unknown, try \"ctrl -help\".\n",
+       fprintf(stderr, "ctrl command \"%s\" is unknown, try \"ctrl help\".\n",
                *argv);
 
        return -1;
@@ -360,5 +409,5 @@ static int parse_ctrl(struct genl_util *a, int argc, char **argv)
 struct genl_util ctrl_genl_util = {
        .name = "ctrl",
        .parse_genlopt = parse_ctrl,
-       .print_genlopt = print_ctrl,
+       .print_genlopt = print_ctrl2,
 };