Home | History | Annotate | Download | only in genl
      1 /*
      2  * lib/genl/family.c		Generic Netlink Family
      3  *
      4  *	This library is free software; you can redistribute it and/or
      5  *	modify it under the terms of the GNU Lesser General Public
      6  *	License as published by the Free Software Foundation version 2.1
      7  *	of the License.
      8  *
      9  * Copyright (c) 2003-2006 Thomas Graf <tgraf (at) suug.ch>
     10  */
     11 
     12 /**
     13  * @ingroup genl
     14  * @defgroup genl_family Generic Netlink Family
     15  * @brief
     16  *
     17  * @{
     18  */
     19 
     20 #include <netlink-generic.h>
     21 #include <netlink/netlink.h>
     22 #include <netlink/genl/genl.h>
     23 #include <netlink/genl/family.h>
     24 #include <netlink/utils.h>
     25 
     26 /** @cond SKIP */
     27 #define FAMILY_ATTR_ID		0x01
     28 #define FAMILY_ATTR_NAME	0x02
     29 #define FAMILY_ATTR_VERSION	0x04
     30 #define FAMILY_ATTR_HDRSIZE	0x08
     31 #define FAMILY_ATTR_MAXATTR	0x10
     32 #define FAMILY_ATTR_OPS		0x20
     33 
     34 struct nl_object_ops genl_family_ops;
     35 /** @endcond */
     36 
     37 static void family_constructor(struct nl_object *c)
     38 {
     39 	struct genl_family *family = (struct genl_family *) c;
     40 
     41 	nl_init_list_head(&family->gf_ops);
     42 }
     43 
     44 static void family_free_data(struct nl_object *c)
     45 {
     46 	struct genl_family *family = (struct genl_family *) c;
     47 	struct genl_family_op *ops, *tmp;
     48 
     49 	if (family == NULL)
     50 		return;
     51 
     52 	nl_list_for_each_entry_safe(ops, tmp, &family->gf_ops, o_list) {
     53 		nl_list_del(&ops->o_list);
     54 		free(ops);
     55 	}
     56 }
     57 
     58 static int family_clone(struct nl_object *_dst, struct nl_object *_src)
     59 {
     60 	struct genl_family *dst = nl_object_priv(_dst);
     61 	struct genl_family *src = nl_object_priv(_src);
     62 	struct genl_family_op *ops;
     63 	int err;
     64 
     65 	nl_list_for_each_entry(ops, &src->gf_ops, o_list) {
     66 		err = genl_family_add_op(dst, ops->o_id, ops->o_flags);
     67 		if (err < 0)
     68 			return err;
     69 	}
     70 
     71 	return 0;
     72 }
     73 
     74 static void family_dump_line(struct nl_object *obj, struct nl_dump_params *p)
     75 {
     76 	struct genl_family *family = (struct genl_family *) obj;
     77 
     78 	nl_dump(p, "0x%04x %s version %u\n",
     79 		family->gf_id, family->gf_name, family->gf_version);
     80 }
     81 
     82 static struct trans_tbl ops_flags[] = {
     83 	__ADD(GENL_ADMIN_PERM, admin-perm)
     84 	__ADD(GENL_CMD_CAP_DO, has-doit)
     85 	__ADD(GENL_CMD_CAP_DUMP, has-dump)
     86 	__ADD(GENL_CMD_CAP_HASPOL, has-policy)
     87 };
     88 
     89 static char *ops_flags2str(int flags, char *buf, size_t len)
     90 {
     91 	return __flags2str(flags, buf, len, ops_flags, ARRAY_SIZE(ops_flags));
     92 }
     93 
     94 static void family_dump_details(struct nl_object *obj, struct nl_dump_params *p)
     95 {
     96 	struct genl_family *family = (struct genl_family *) obj;
     97 
     98 	family_dump_line(obj, p);
     99 	nl_dump_line(p, "    hdrsize %u maxattr %u\n",
    100 		     family->gf_hdrsize, family->gf_maxattr);
    101 
    102 	if (family->ce_mask & FAMILY_ATTR_OPS) {
    103 		struct genl_family_op *op;
    104 		char buf[64];
    105 
    106 		nl_list_for_each_entry(op, &family->gf_ops, o_list) {
    107 			ops_flags2str(op->o_flags, buf, sizeof(buf));
    108 
    109 			genl_op2name(family->gf_id, op->o_id, buf, sizeof(buf));
    110 
    111 			nl_dump_line(p, "      op %s (0x%02x)", buf, op->o_id);
    112 
    113 			if (op->o_flags)
    114 				nl_dump(p, " <%s>",
    115 					ops_flags2str(op->o_flags, buf,
    116 						      sizeof(buf)));
    117 
    118 			nl_dump(p, "\n");
    119 		}
    120 	}
    121 }
    122 
    123 static void family_dump_stats(struct nl_object *obj, struct nl_dump_params *p)
    124 {
    125 	family_dump_details(obj, p);
    126 }
    127 
    128 static int family_compare(struct nl_object *_a, struct nl_object *_b,
    129 			  uint32_t attrs, int flags)
    130 {
    131 	struct genl_family *a = (struct genl_family *) _a;
    132 	struct genl_family *b = (struct genl_family *) _b;
    133 	int diff = 0;
    134 
    135 #define FAM_DIFF(ATTR, EXPR) ATTR_DIFF(attrs, FAMILY_ATTR_##ATTR, a, b, EXPR)
    136 
    137 	diff |= FAM_DIFF(ID,		a->gf_id != b->gf_id);
    138 	diff |= FAM_DIFF(VERSION,	a->gf_version != b->gf_version);
    139 	diff |= FAM_DIFF(HDRSIZE,	a->gf_hdrsize != b->gf_hdrsize);
    140 	diff |= FAM_DIFF(MAXATTR,	a->gf_maxattr != b->gf_maxattr);
    141 	diff |= FAM_DIFF(NAME,		strcmp(a->gf_name, b->gf_name));
    142 
    143 #undef FAM_DIFF
    144 
    145 	return diff;
    146 }
    147 
    148 
    149 /**
    150  * @name Family Object
    151  * @{
    152  */
    153 
    154 struct genl_family *genl_family_alloc(void)
    155 {
    156 	return (struct genl_family *) nl_object_alloc(&genl_family_ops);
    157 }
    158 
    159 void genl_family_put(struct genl_family *family)
    160 {
    161 	nl_object_put((struct nl_object *) family);
    162 }
    163 
    164 /** @} */
    165 
    166 /**
    167  * @name Attributes
    168  * @{
    169  */
    170 
    171 unsigned int genl_family_get_id(struct genl_family *family)
    172 {
    173 	if (family->ce_mask & FAMILY_ATTR_ID)
    174 		return family->gf_id;
    175 	else
    176 		return GENL_ID_GENERATE;
    177 }
    178 
    179 void genl_family_set_id(struct genl_family *family, unsigned int id)
    180 {
    181 	family->gf_id = id;
    182 	family->ce_mask |= FAMILY_ATTR_ID;
    183 }
    184 
    185 char *genl_family_get_name(struct genl_family *family)
    186 {
    187 	if (family->ce_mask & FAMILY_ATTR_NAME)
    188 		return family->gf_name;
    189 	else
    190 		return NULL;
    191 }
    192 
    193 void genl_family_set_name(struct genl_family *family, const char *name)
    194 {
    195 	strncpy(family->gf_name, name, GENL_NAMSIZ-1);
    196 	family->ce_mask |= FAMILY_ATTR_NAME;
    197 }
    198 
    199 uint8_t genl_family_get_version(struct genl_family *family)
    200 {
    201 	if (family->ce_mask & FAMILY_ATTR_VERSION)
    202 		return family->gf_version;
    203 	else
    204 		return 0;
    205 }
    206 
    207 void genl_family_set_version(struct genl_family *family, uint8_t version)
    208 {
    209 	family->gf_version = version;
    210 	family->ce_mask |= FAMILY_ATTR_VERSION;
    211 }
    212 
    213 uint32_t genl_family_get_hdrsize(struct genl_family *family)
    214 {
    215 	if (family->ce_mask & FAMILY_ATTR_HDRSIZE)
    216 		return family->gf_hdrsize;
    217 	else
    218 		return 0;
    219 }
    220 
    221 void genl_family_set_hdrsize(struct genl_family *family, uint32_t hdrsize)
    222 {
    223 	family->gf_hdrsize = hdrsize;
    224 	family->ce_mask |= FAMILY_ATTR_HDRSIZE;
    225 }
    226 
    227 uint32_t genl_family_get_maxattr(struct genl_family *family)
    228 {
    229 	if (family->ce_mask & FAMILY_ATTR_MAXATTR)
    230 		return family->gf_maxattr;
    231 	else
    232 		return family->gf_maxattr;
    233 }
    234 
    235 void genl_family_set_maxattr(struct genl_family *family, uint32_t maxattr)
    236 {
    237 	family->gf_maxattr = maxattr;
    238 	family->ce_mask |= FAMILY_ATTR_MAXATTR;
    239 }
    240 
    241 int genl_family_add_op(struct genl_family *family, int id, int flags)
    242 {
    243 	struct genl_family_op *op;
    244 
    245 	op = calloc(1, sizeof(*op));
    246 	if (op == NULL)
    247 		return -NLE_NOMEM;
    248 
    249 	op->o_id = id;
    250 	op->o_flags = flags;
    251 
    252 	nl_list_add_tail(&op->o_list, &family->gf_ops);
    253 	family->ce_mask |= FAMILY_ATTR_OPS;
    254 
    255 	return 0;
    256 }
    257 
    258 /** @} */
    259 
    260 /** @cond SKIP */
    261 struct nl_object_ops genl_family_ops = {
    262 	.oo_name		= "genl/family",
    263 	.oo_size		= sizeof(struct genl_family),
    264 	.oo_constructor		= family_constructor,
    265 	.oo_free_data		= family_free_data,
    266 	.oo_clone		= family_clone,
    267 	.oo_dump = {
    268 	    [NL_DUMP_LINE]	= family_dump_line,
    269 	    [NL_DUMP_DETAILS]	= family_dump_details,
    270 	    [NL_DUMP_STATS]	= family_dump_stats,
    271 	},
    272 	.oo_compare		= family_compare,
    273 	.oo_id_attrs		= FAMILY_ATTR_ID,
    274 };
    275 /** @endcond */
    276 
    277 /** @} */
    278