libmnl
1.0.3
|
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 }