libnl 1.1
|
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 /** @} */