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