libnl 1.1
lib/genl/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 }
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  * @name Family Object
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  * @name Attributes
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 /** @cond SKIP */
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 /** @endcond */
00284 
00285 /** @} */