family.c

00001 /*
00002  * lib/genl/family.c            Generic Netlink Family
00003  *
00004  *      This library is free software; you can redistribute it and/or
00005  *      modify it under the terms of the GNU Lesser General Public
00006  *      License as published by the Free Software Foundation version 2.1
00007  *      of the License.
00008  *
00009  * Copyright (c) 2003-2006 Thomas Graf <tgraf@suug.ch>
00010  */
00011 
00012 /**
00013  * @ingroup genl
00014  * @defgroup genl_family Generic Netlink Family
00015  * @brief
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 /** @cond SKIP */
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 /** @endcond */
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  * @name Family Object
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  * @name Attributes
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 /** @cond SKIP */
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 /** @endcond */
00315 
00316 /** @} */