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