libmnl  1.0.3
genl-family-get.c
00001 /* This example is placed in the public domain. */
00002 #include <stdio.h>
00003 #include <stdlib.h>
00004 #include <unistd.h>
00005 #include <time.h>
00006 
00007 #include <libmnl/libmnl.h>
00008 #include <linux/genetlink.h>
00009 
00010 static int parse_mc_grps_cb(const struct nlattr *attr, void *data)
00011 {
00012         const struct nlattr **tb = data;
00013         int type = mnl_attr_get_type(attr);
00014 
00015         /* skip unsupported attribute in user-space */
00016         if (mnl_attr_type_valid(attr, CTRL_ATTR_MCAST_GRP_MAX) < 0)
00017                 return MNL_CB_OK;
00018 
00019         switch(type) {
00020         case CTRL_ATTR_MCAST_GRP_ID:
00021                 if (mnl_attr_validate(attr, MNL_TYPE_U32) < 0) {
00022                         perror("mnl_attr_validate");
00023                         return MNL_CB_ERROR;
00024                 }
00025                 break;
00026         case CTRL_ATTR_MCAST_GRP_NAME:
00027                 if (mnl_attr_validate(attr, MNL_TYPE_STRING) < 0) {
00028                         perror("mnl_attr_validate");
00029                         return MNL_CB_ERROR;
00030                 }
00031                 break;
00032         }
00033         tb[type] = attr;
00034         return MNL_CB_OK;
00035 }
00036 
00037 static void parse_genl_mc_grps(struct nlattr *nested)
00038 {
00039         struct nlattr *pos;
00040 
00041         mnl_attr_for_each_nested(pos, nested) {
00042                 struct nlattr *tb[CTRL_ATTR_MCAST_GRP_MAX+1] = {};
00043 
00044                 mnl_attr_parse_nested(pos, parse_mc_grps_cb, tb);
00045                 if (tb[CTRL_ATTR_MCAST_GRP_ID]) {
00046                         printf("id-0x%x ",
00047                                 mnl_attr_get_u32(tb[CTRL_ATTR_MCAST_GRP_ID]));
00048                 }
00049                 if (tb[CTRL_ATTR_MCAST_GRP_NAME]) {
00050                         printf("name: %s ",
00051                                 mnl_attr_get_str(tb[CTRL_ATTR_MCAST_GRP_NAME]));
00052                 }
00053                 printf("\n");
00054         }
00055 }
00056 
00057 static int parse_family_ops_cb(const struct nlattr *attr, void *data)
00058 {
00059         const struct nlattr **tb = data;
00060         int type = mnl_attr_get_type(attr);
00061 
00062         if (mnl_attr_type_valid(attr, CTRL_ATTR_OP_MAX) < 0)
00063                 return MNL_CB_OK;
00064 
00065         switch(type) {
00066         case CTRL_ATTR_OP_ID:
00067                 if (mnl_attr_validate(attr, MNL_TYPE_U32) < 0) {
00068                         perror("mnl_attr_validate");
00069                         return MNL_CB_ERROR;
00070                 }
00071                 break;
00072         case CTRL_ATTR_OP_MAX:
00073                 break;
00074         default:
00075                 return MNL_CB_OK;
00076         }
00077         tb[type] = attr;
00078         return MNL_CB_OK;
00079 }
00080 
00081 static void parse_genl_family_ops(struct nlattr *nested)
00082 {
00083         struct nlattr *pos;
00084 
00085         mnl_attr_for_each_nested(pos, nested) {
00086                 struct nlattr *tb[CTRL_ATTR_OP_MAX+1] = {};
00087 
00088                 mnl_attr_parse_nested(pos, parse_family_ops_cb, tb);
00089                 if (tb[CTRL_ATTR_OP_ID]) {
00090                         printf("id-0x%x ",
00091                                 mnl_attr_get_u32(tb[CTRL_ATTR_OP_ID]));
00092                 }
00093                 if (tb[CTRL_ATTR_OP_MAX]) {
00094                         printf("flags ");
00095                 }
00096                 printf("\n");
00097         }
00098 }
00099 
00100 static int data_attr_cb(const struct nlattr *attr, void *data)
00101 {
00102         const struct nlattr **tb = data;
00103         int type = mnl_attr_get_type(attr);
00104 
00105         if (mnl_attr_type_valid(attr, CTRL_ATTR_MAX) < 0)
00106                 return MNL_CB_OK;
00107 
00108         switch(type) {
00109         case CTRL_ATTR_FAMILY_NAME:
00110                 if (mnl_attr_validate(attr, MNL_TYPE_STRING) < 0) {
00111                         perror("mnl_attr_validate");
00112                         return MNL_CB_ERROR;
00113                 }
00114                 break;
00115         case CTRL_ATTR_FAMILY_ID:
00116                 if (mnl_attr_validate(attr, MNL_TYPE_U16) < 0) {
00117                         perror("mnl_attr_validate");
00118                         return MNL_CB_ERROR;
00119                 }
00120                 break;
00121         case CTRL_ATTR_VERSION:
00122         case CTRL_ATTR_HDRSIZE:
00123         case CTRL_ATTR_MAXATTR:
00124                 if (mnl_attr_validate(attr, MNL_TYPE_U32) < 0) {
00125                         perror("mnl_attr_validate");
00126                         return MNL_CB_ERROR;
00127                 }
00128                 break;
00129         case CTRL_ATTR_OPS:
00130         case CTRL_ATTR_MCAST_GROUPS:
00131                 if (mnl_attr_validate(attr, MNL_TYPE_NESTED) < 0) {
00132                         perror("mnl_attr_validate");
00133                         return MNL_CB_ERROR;
00134                 }
00135                 break;
00136         }
00137         tb[type] = attr;
00138         return MNL_CB_OK;
00139 }
00140 
00141 static int data_cb(const struct nlmsghdr *nlh, void *data)
00142 {
00143         struct nlattr *tb[CTRL_ATTR_MAX+1] = {};
00144         struct genlmsghdr *genl = mnl_nlmsg_get_payload(nlh);
00145 
00146         mnl_attr_parse(nlh, sizeof(*genl), data_attr_cb, tb);
00147         if (tb[CTRL_ATTR_FAMILY_NAME]) {
00148                 printf("name=%s\t",
00149                         mnl_attr_get_str(tb[CTRL_ATTR_FAMILY_NAME]));
00150         }
00151         if (tb[CTRL_ATTR_FAMILY_ID]) {
00152                 printf("id=%u\t",
00153                         mnl_attr_get_u16(tb[CTRL_ATTR_FAMILY_ID]));
00154         }
00155         if (tb[CTRL_ATTR_VERSION]) {
00156                 printf("version=%u\t",
00157                         mnl_attr_get_u32(tb[CTRL_ATTR_VERSION]));
00158         }
00159         if (tb[CTRL_ATTR_HDRSIZE]) {
00160                 printf("hdrsize=%u\t",
00161                         mnl_attr_get_u32(tb[CTRL_ATTR_HDRSIZE]));
00162         }
00163         if (tb[CTRL_ATTR_MAXATTR]) {
00164                 printf("maxattr=%u\t",
00165                         mnl_attr_get_u32(tb[CTRL_ATTR_MAXATTR]));
00166         }
00167         printf("\n");
00168         if (tb[CTRL_ATTR_OPS]) {
00169                 printf("ops:\n");
00170                 parse_genl_family_ops(tb[CTRL_ATTR_OPS]);
00171         }
00172         if (tb[CTRL_ATTR_MCAST_GROUPS]) {
00173                 printf("grps:\n");
00174                 parse_genl_mc_grps(tb[CTRL_ATTR_MCAST_GROUPS]);
00175         }
00176         printf("\n");
00177         return MNL_CB_OK;
00178 }
00179 
00180 int main(int argc, char *argv[])
00181 {
00182         struct mnl_socket *nl;
00183         char buf[MNL_SOCKET_BUFFER_SIZE];
00184         struct nlmsghdr *nlh;
00185         struct genlmsghdr *genl;
00186         int ret;
00187         unsigned int seq, portid;
00188 
00189         if (argc > 2) {
00190                 printf("%s [family name]\n", argv[0]);
00191                 exit(EXIT_FAILURE);
00192         }
00193 
00194         nlh = mnl_nlmsg_put_header(buf);
00195         nlh->nlmsg_type = GENL_ID_CTRL;
00196         nlh->nlmsg_flags = NLM_F_REQUEST | NLM_F_ACK;
00197         nlh->nlmsg_seq = seq = time(NULL);
00198 
00199         genl = mnl_nlmsg_put_extra_header(nlh, sizeof(struct genlmsghdr));
00200         genl->cmd = CTRL_CMD_GETFAMILY;
00201         genl->version = 1;
00202 
00203         mnl_attr_put_u32(nlh, CTRL_ATTR_FAMILY_ID, GENL_ID_CTRL);
00204         if (argc >= 2)
00205                 mnl_attr_put_strz(nlh, CTRL_ATTR_FAMILY_NAME, argv[1]);
00206         else
00207                 nlh->nlmsg_flags |= NLM_F_DUMP;
00208 
00209         nl = mnl_socket_open(NETLINK_GENERIC);
00210         if (nl == NULL) {
00211                 perror("mnl_socket_open");
00212                 exit(EXIT_FAILURE);
00213         }
00214 
00215         if (mnl_socket_bind(nl, 0, MNL_SOCKET_AUTOPID) < 0) {
00216                 perror("mnl_socket_bind");
00217                 exit(EXIT_FAILURE);
00218         }
00219         portid = mnl_socket_get_portid(nl);
00220 
00221         if (mnl_socket_sendto(nl, nlh, nlh->nlmsg_len) < 0) {
00222                 perror("mnl_socket_send");
00223                 exit(EXIT_FAILURE);
00224         }
00225 
00226         ret = mnl_socket_recvfrom(nl, buf, sizeof(buf));
00227         while (ret > 0) {
00228                 ret = mnl_cb_run(buf, ret, seq, portid, data_cb, NULL);
00229                 if (ret <= 0)
00230                         break;
00231                 ret = mnl_socket_recvfrom(nl, buf, sizeof(buf));
00232         }
00233         if (ret == -1) {
00234                 perror("error");
00235                 exit(EXIT_FAILURE);
00236         }
00237 
00238         mnl_socket_close(nl);
00239 
00240         return 0;
00241 }