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 }
00043
00044 static void family_free_data(struct nl_object *c)
00045 {
00046 struct genl_family *family = (struct genl_family *) c;
00047 struct genl_family_op *ops, *tmp;
00048
00049 if (family == NULL)
00050 return;
00051
00052 nl_list_for_each_entry_safe(ops, tmp, &family->gf_ops, o_list) {
00053 nl_list_del(&ops->o_list);
00054 free(ops);
00055 }
00056 }
00057
00058 static int family_clone(struct nl_object *_dst, struct nl_object *_src)
00059 {
00060 struct genl_family *dst = nl_object_priv(_dst);
00061 struct genl_family *src = nl_object_priv(_src);
00062 struct genl_family_op *ops;
00063 int err;
00064
00065 nl_list_for_each_entry(ops, &src->gf_ops, o_list) {
00066 err = genl_family_add_op(dst, ops->o_id, ops->o_flags);
00067 if (err < 0)
00068 return err;
00069 }
00070
00071 return 0;
00072 }
00073
00074 static int family_dump_brief(struct nl_object *obj, struct nl_dump_params *p)
00075 {
00076 struct genl_family *family = (struct genl_family *) obj;
00077
00078 dp_dump(p, "0x%04x %s version %u\n",
00079 family->gf_id, family->gf_name, family->gf_version);
00080
00081 return 1;
00082 }
00083
00084 static struct trans_tbl ops_flags[] = {
00085 __ADD(GENL_ADMIN_PERM, admin-perm)
00086 __ADD(GENL_CMD_CAP_DO, has-doit)
00087 __ADD(GENL_CMD_CAP_DUMP, has-dump)
00088 __ADD(GENL_CMD_CAP_HASPOL, has-policy)
00089 };
00090
00091 static char *ops_flags2str(int flags, char *buf, size_t len)
00092 {
00093 return __flags2str(flags, buf, len, ops_flags, ARRAY_SIZE(ops_flags));
00094 }
00095
00096 static int family_dump_full(struct nl_object *obj, struct nl_dump_params *p)
00097 {
00098 struct genl_family *family = (struct genl_family *) obj;
00099 int line;
00100
00101 line = family_dump_brief(obj, p);
00102 dp_dump_line(p, line++, " hdrsize %u maxattr %u\n",
00103 family->gf_hdrsize, family->gf_maxattr);
00104
00105 if (family->ce_mask & FAMILY_ATTR_OPS) {
00106 struct genl_family_op *op;
00107 char buf[64];
00108
00109 nl_list_for_each_entry(op, &family->gf_ops, o_list) {
00110 ops_flags2str(op->o_flags, buf, sizeof(buf));
00111
00112 genl_op2name(family->gf_id, op->o_id, buf, sizeof(buf));
00113
00114 dp_dump_line(p, line++, " op %s (0x%02x)",
00115 buf, op->o_id);
00116
00117 if (op->o_flags)
00118 dp_dump(p, " <%s>",
00119 ops_flags2str(op->o_flags, buf,
00120 sizeof(buf)));
00121
00122 dp_dump(p, "\n");
00123 }
00124 }
00125
00126 return line;
00127 }
00128
00129 static int family_dump_stats(struct nl_object *obj, struct nl_dump_params *p)
00130 {
00131 return family_dump_full(obj, p);
00132 }
00133
00134 static int family_compare(struct nl_object *_a, struct nl_object *_b,
00135 uint32_t attrs, int flags)
00136 {
00137 struct genl_family *a = (struct genl_family *) _a;
00138 struct genl_family *b = (struct genl_family *) _b;
00139 int diff = 0;
00140
00141 #define FAM_DIFF(ATTR, EXPR) ATTR_DIFF(attrs, FAMILY_ATTR_##ATTR, a, b, EXPR)
00142
00143 diff |= FAM_DIFF(ID, a->gf_id != b->gf_id);
00144 diff |= FAM_DIFF(VERSION, a->gf_version != b->gf_version);
00145 diff |= FAM_DIFF(HDRSIZE, a->gf_hdrsize != b->gf_hdrsize);
00146 diff |= FAM_DIFF(MAXATTR, a->gf_maxattr != b->gf_maxattr);
00147 diff |= FAM_DIFF(NAME, strcmp(a->gf_name, b->gf_name));
00148
00149 #undef FAM_DIFF
00150
00151 return diff;
00152 }
00153
00154
00155
00156
00157
00158
00159
00160 struct genl_family *genl_family_alloc(void)
00161 {
00162 return (struct genl_family *) nl_object_alloc(&genl_family_ops);
00163 }
00164
00165 void genl_family_put(struct genl_family *family)
00166 {
00167 nl_object_put((struct nl_object *) family);
00168 }
00169
00170
00171
00172
00173
00174
00175
00176
00177 unsigned int genl_family_get_id(struct genl_family *family)
00178 {
00179 if (family->ce_mask & FAMILY_ATTR_ID)
00180 return family->gf_id;
00181 else
00182 return GENL_ID_GENERATE;
00183 }
00184
00185 void genl_family_set_id(struct genl_family *family, unsigned int id)
00186 {
00187 family->gf_id = id;
00188 family->ce_mask |= FAMILY_ATTR_ID;
00189 }
00190
00191 char *genl_family_get_name(struct genl_family *family)
00192 {
00193 if (family->ce_mask & FAMILY_ATTR_NAME)
00194 return family->gf_name;
00195 else
00196 return NULL;
00197 }
00198
00199 void genl_family_set_name(struct genl_family *family, const char *name)
00200 {
00201 strncpy(family->gf_name, name, GENL_NAMSIZ-1);
00202 family->ce_mask |= FAMILY_ATTR_NAME;
00203 }
00204
00205 uint8_t genl_family_get_version(struct genl_family *family)
00206 {
00207 if (family->ce_mask & FAMILY_ATTR_VERSION)
00208 return family->gf_version;
00209 else
00210 return 0;
00211 }
00212
00213 void genl_family_set_version(struct genl_family *family, uint8_t version)
00214 {
00215 family->gf_version = version;
00216 family->ce_mask |= FAMILY_ATTR_VERSION;
00217 }
00218
00219 uint32_t genl_family_get_hdrsize(struct genl_family *family)
00220 {
00221 if (family->ce_mask & FAMILY_ATTR_HDRSIZE)
00222 return family->gf_hdrsize;
00223 else
00224 return 0;
00225 }
00226
00227 void genl_family_set_hdrsize(struct genl_family *family, uint32_t hdrsize)
00228 {
00229 family->gf_hdrsize = hdrsize;
00230 family->ce_mask |= FAMILY_ATTR_HDRSIZE;
00231 }
00232
00233 uint32_t genl_family_get_maxattr(struct genl_family *family)
00234 {
00235 if (family->ce_mask & FAMILY_ATTR_MAXATTR)
00236 return family->gf_maxattr;
00237 else
00238 return family->gf_maxattr;
00239 }
00240
00241 void genl_family_set_maxattr(struct genl_family *family, uint32_t maxattr)
00242 {
00243 family->gf_maxattr = maxattr;
00244 family->ce_mask |= FAMILY_ATTR_MAXATTR;
00245 }
00246
00247 int genl_family_add_op(struct genl_family *family, int id, int flags)
00248 {
00249 struct genl_family_op *op;
00250
00251 op = calloc(1, sizeof(*op));
00252 if (op == NULL)
00253 return nl_errno(ENOMEM);
00254
00255 op->o_id = id;
00256 op->o_flags = flags;
00257
00258 nl_list_add_tail(&op->o_list, &family->gf_ops);
00259 family->ce_mask |= FAMILY_ATTR_OPS;
00260
00261 return 0;
00262 }
00263
00264
00265
00266
00267 struct nl_object_ops genl_family_ops = {
00268 .oo_name = "genl/family",
00269 .oo_size = sizeof(struct genl_family),
00270 .oo_constructor = family_constructor,
00271 .oo_free_data = family_free_data,
00272 .oo_clone = family_clone,
00273 .oo_dump[NL_DUMP_BRIEF] = family_dump_brief,
00274 .oo_dump[NL_DUMP_FULL] = family_dump_full,
00275 .oo_dump[NL_DUMP_STATS] = family_dump_stats,
00276 #if 0
00277 .oo_dump[NL_DUMP_XML] = addr_dump_xml,
00278 .oo_dump[NL_DUMP_ENV] = addr_dump_env,
00279 #endif
00280 .oo_compare = family_compare,
00281 .oo_id_attrs = FAMILY_ATTR_ID,
00282 };
00283
00284
00285