00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020 #include <netlink-generic.h>
00021 #include <netlink/netlink.h>
00022 #include <netlink/genl/genl.h>
00023 #include <netlink/genl/family.h>
00024 #include <netlink/utils.h>
00025
00026
00027 #define FAMILY_ATTR_ID 0x01
00028 #define FAMILY_ATTR_NAME 0x02
00029 #define FAMILY_ATTR_VERSION 0x04
00030 #define FAMILY_ATTR_HDRSIZE 0x08
00031 #define FAMILY_ATTR_MAXATTR 0x10
00032 #define FAMILY_ATTR_OPS 0x20
00033
00034 struct nl_object_ops genl_family_ops;
00035
00036
00037 static void family_constructor(struct nl_object *c)
00038 {
00039 struct genl_family *family = (struct genl_family *) c;
00040
00041 nl_init_list_head(&family->gf_ops);
00042 nl_init_list_head(&family->gf_mc_grps);
00043 }
00044
00045 static void family_free_data(struct nl_object *c)
00046 {
00047 struct genl_family *family = (struct genl_family *) c;
00048 struct genl_family_op *ops, *tmp;
00049 struct genl_family_grp *grp, *t_grp;
00050
00051 if (family == NULL)
00052 return;
00053
00054 nl_list_for_each_entry_safe(ops, tmp, &family->gf_ops, o_list) {
00055 nl_list_del(&ops->o_list);
00056 free(ops);
00057 }
00058
00059 nl_list_for_each_entry_safe(grp, t_grp, &family->gf_mc_grps, list) {
00060 nl_list_del(&grp->list);
00061 free(grp);
00062 }
00063
00064 }
00065
00066 static int family_clone(struct nl_object *_dst, struct nl_object *_src)
00067 {
00068 struct genl_family *dst = nl_object_priv(_dst);
00069 struct genl_family *src = nl_object_priv(_src);
00070 struct genl_family_op *ops;
00071 struct genl_family_grp *grp;
00072 int err;
00073
00074 nl_list_for_each_entry(ops, &src->gf_ops, o_list) {
00075 err = genl_family_add_op(dst, ops->o_id, ops->o_flags);
00076 if (err < 0)
00077 return err;
00078 }
00079
00080 nl_list_for_each_entry(grp, &src->gf_mc_grps, list) {
00081 err = genl_family_add_grp(dst, grp->id, grp->name);
00082 if (err < 0)
00083 return err;
00084 }
00085
00086
00087 return 0;
00088 }
00089
00090 static void family_dump_line(struct nl_object *obj, struct nl_dump_params *p)
00091 {
00092 struct genl_family *family = (struct genl_family *) obj;
00093
00094 nl_dump(p, "0x%04x %s version %u\n",
00095 family->gf_id, family->gf_name, family->gf_version);
00096 }
00097
00098 static const struct trans_tbl ops_flags[] = {
00099 __ADD(GENL_ADMIN_PERM, admin-perm)
00100 __ADD(GENL_CMD_CAP_DO, has-doit)
00101 __ADD(GENL_CMD_CAP_DUMP, has-dump)
00102 __ADD(GENL_CMD_CAP_HASPOL, has-policy)
00103 };
00104
00105 static char *ops_flags2str(int flags, char *buf, size_t len)
00106 {
00107 return __flags2str(flags, buf, len, ops_flags, ARRAY_SIZE(ops_flags));
00108 }
00109
00110 static void family_dump_details(struct nl_object *obj, struct nl_dump_params *p)
00111 {
00112 struct genl_family_grp *grp;
00113 struct genl_family *family = (struct genl_family *) obj;
00114
00115 family_dump_line(obj, p);
00116 nl_dump_line(p, " hdrsize %u maxattr %u\n",
00117 family->gf_hdrsize, family->gf_maxattr);
00118
00119 if (family->ce_mask & FAMILY_ATTR_OPS) {
00120 struct genl_family_op *op;
00121 char buf[64];
00122
00123 nl_list_for_each_entry(op, &family->gf_ops, o_list) {
00124 ops_flags2str(op->o_flags, buf, sizeof(buf));
00125
00126 genl_op2name(family->gf_id, op->o_id, buf, sizeof(buf));
00127
00128 nl_dump_line(p, " op %s (0x%02x)", buf, op->o_id);
00129
00130 if (op->o_flags)
00131 nl_dump(p, " <%s>",
00132 ops_flags2str(op->o_flags, buf,
00133 sizeof(buf)));
00134
00135 nl_dump(p, "\n");
00136 }
00137 }
00138
00139 nl_list_for_each_entry(grp, &family->gf_mc_grps, list) {
00140 nl_dump_line(p, " grp %s (0x%02x)\n", grp->name, grp->id);
00141 }
00142
00143 }
00144
00145 static void family_dump_stats(struct nl_object *obj, struct nl_dump_params *p)
00146 {
00147 family_dump_details(obj, p);
00148 }
00149
00150 static int family_compare(struct nl_object *_a, struct nl_object *_b,
00151 uint32_t attrs, int flags)
00152 {
00153 struct genl_family *a = (struct genl_family *) _a;
00154 struct genl_family *b = (struct genl_family *) _b;
00155 int diff = 0;
00156
00157 #define FAM_DIFF(ATTR, EXPR) ATTR_DIFF(attrs, FAMILY_ATTR_##ATTR, a, b, EXPR)
00158
00159 diff |= FAM_DIFF(ID, a->gf_id != b->gf_id);
00160 diff |= FAM_DIFF(VERSION, a->gf_version != b->gf_version);
00161 diff |= FAM_DIFF(HDRSIZE, a->gf_hdrsize != b->gf_hdrsize);
00162 diff |= FAM_DIFF(MAXATTR, a->gf_maxattr != b->gf_maxattr);
00163 diff |= FAM_DIFF(NAME, strcmp(a->gf_name, b->gf_name));
00164
00165 #undef FAM_DIFF
00166
00167 return diff;
00168 }
00169
00170
00171
00172
00173
00174
00175
00176 struct genl_family *genl_family_alloc(void)
00177 {
00178 return (struct genl_family *) nl_object_alloc(&genl_family_ops);
00179 }
00180
00181 void genl_family_put(struct genl_family *family)
00182 {
00183 nl_object_put((struct nl_object *) family);
00184 }
00185
00186
00187
00188
00189
00190
00191
00192
00193 unsigned int genl_family_get_id(struct genl_family *family)
00194 {
00195 if (family->ce_mask & FAMILY_ATTR_ID)
00196 return family->gf_id;
00197 else
00198 return GENL_ID_GENERATE;
00199 }
00200
00201 void genl_family_set_id(struct genl_family *family, unsigned int id)
00202 {
00203 family->gf_id = id;
00204 family->ce_mask |= FAMILY_ATTR_ID;
00205 }
00206
00207 char *genl_family_get_name(struct genl_family *family)
00208 {
00209 if (family->ce_mask & FAMILY_ATTR_NAME)
00210 return family->gf_name;
00211 else
00212 return NULL;
00213 }
00214
00215 void genl_family_set_name(struct genl_family *family, const char *name)
00216 {
00217 strncpy(family->gf_name, name, GENL_NAMSIZ-1);
00218 family->ce_mask |= FAMILY_ATTR_NAME;
00219 }
00220
00221 uint8_t genl_family_get_version(struct genl_family *family)
00222 {
00223 if (family->ce_mask & FAMILY_ATTR_VERSION)
00224 return family->gf_version;
00225 else
00226 return 0;
00227 }
00228
00229 void genl_family_set_version(struct genl_family *family, uint8_t version)
00230 {
00231 family->gf_version = version;
00232 family->ce_mask |= FAMILY_ATTR_VERSION;
00233 }
00234
00235 uint32_t genl_family_get_hdrsize(struct genl_family *family)
00236 {
00237 if (family->ce_mask & FAMILY_ATTR_HDRSIZE)
00238 return family->gf_hdrsize;
00239 else
00240 return 0;
00241 }
00242
00243 void genl_family_set_hdrsize(struct genl_family *family, uint32_t hdrsize)
00244 {
00245 family->gf_hdrsize = hdrsize;
00246 family->ce_mask |= FAMILY_ATTR_HDRSIZE;
00247 }
00248
00249 uint32_t genl_family_get_maxattr(struct genl_family *family)
00250 {
00251 if (family->ce_mask & FAMILY_ATTR_MAXATTR)
00252 return family->gf_maxattr;
00253 else
00254 return family->gf_maxattr;
00255 }
00256
00257 void genl_family_set_maxattr(struct genl_family *family, uint32_t maxattr)
00258 {
00259 family->gf_maxattr = maxattr;
00260 family->ce_mask |= FAMILY_ATTR_MAXATTR;
00261 }
00262
00263 int genl_family_add_op(struct genl_family *family, int id, int flags)
00264 {
00265 struct genl_family_op *op;
00266
00267 op = calloc(1, sizeof(*op));
00268 if (op == NULL)
00269 return -NLE_NOMEM;
00270
00271 op->o_id = id;
00272 op->o_flags = flags;
00273
00274 nl_list_add_tail(&op->o_list, &family->gf_ops);
00275 family->ce_mask |= FAMILY_ATTR_OPS;
00276
00277 return 0;
00278 }
00279
00280 int genl_family_add_grp(struct genl_family *family, uint32_t id,
00281 const char *name)
00282 {
00283 struct genl_family_grp *grp;
00284
00285 grp = calloc(1, sizeof(*grp));
00286 if (grp == NULL)
00287 return -NLE_NOMEM;
00288
00289 grp->id = id;
00290 strncpy(grp->name, name, GENL_NAMSIZ - 1);
00291
00292 nl_list_add_tail(&grp->list, &family->gf_mc_grps);
00293
00294 return 0;
00295 }
00296
00297
00298
00299
00300 struct nl_object_ops genl_family_ops = {
00301 .oo_name = "genl/family",
00302 .oo_size = sizeof(struct genl_family),
00303 .oo_constructor = family_constructor,
00304 .oo_free_data = family_free_data,
00305 .oo_clone = family_clone,
00306 .oo_dump = {
00307 [NL_DUMP_LINE] = family_dump_line,
00308 [NL_DUMP_DETAILS] = family_dump_details,
00309 [NL_DUMP_STATS] = family_dump_stats,
00310 },
00311 .oo_compare = family_compare,
00312 .oo_id_attrs = FAMILY_ATTR_ID,
00313 };
00314
00315
00316