Tizen 2.1 base
[platform/upstream/libnl2.git] / lib / genl / family.c
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@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         nl_init_list_head(&family->gf_mc_grps);
43 }
44
45 static void family_free_data(struct nl_object *c)
46 {
47         struct genl_family *family = (struct genl_family *) c;
48         struct genl_family_op *ops, *tmp;
49         struct genl_family_grp *grp, *t_grp;
50
51         if (family == NULL)
52                 return;
53
54         nl_list_for_each_entry_safe(ops, tmp, &family->gf_ops, o_list) {
55                 nl_list_del(&ops->o_list);
56                 free(ops);
57         }
58
59         nl_list_for_each_entry_safe(grp, t_grp, &family->gf_mc_grps, list) {
60                 nl_list_del(&grp->list);
61                 free(grp);
62         }
63
64 }
65
66 static int family_clone(struct nl_object *_dst, struct nl_object *_src)
67 {
68         struct genl_family *dst = nl_object_priv(_dst);
69         struct genl_family *src = nl_object_priv(_src);
70         struct genl_family_op *ops;
71         struct genl_family_grp *grp;
72         int err;
73
74         nl_list_for_each_entry(ops, &src->gf_ops, o_list) {
75                 err = genl_family_add_op(dst, ops->o_id, ops->o_flags);
76                 if (err < 0)
77                         return err;
78         }
79
80         nl_list_for_each_entry(grp, &src->gf_mc_grps, list) {
81                 err = genl_family_add_grp(dst, grp->id, grp->name);
82                 if (err < 0)
83                         return err;
84         }
85
86         
87         return 0;
88 }
89
90 static void family_dump_line(struct nl_object *obj, struct nl_dump_params *p)
91 {
92         struct genl_family *family = (struct genl_family *) obj;
93
94         nl_dump(p, "0x%04x %s version %u\n",
95                 family->gf_id, family->gf_name, family->gf_version);
96 }
97
98 static struct trans_tbl ops_flags[] = {
99         __ADD(GENL_ADMIN_PERM, admin-perm)
100         __ADD(GENL_CMD_CAP_DO, has-doit)
101         __ADD(GENL_CMD_CAP_DUMP, has-dump)
102         __ADD(GENL_CMD_CAP_HASPOL, has-policy)
103 };
104
105 static char *ops_flags2str(int flags, char *buf, size_t len)
106 {
107         return __flags2str(flags, buf, len, ops_flags, ARRAY_SIZE(ops_flags));
108 }
109
110 static void family_dump_details(struct nl_object *obj, struct nl_dump_params *p)
111 {
112         struct genl_family_grp *grp;
113         struct genl_family *family = (struct genl_family *) obj;
114
115         family_dump_line(obj, p);
116         nl_dump_line(p, "    hdrsize %u maxattr %u\n",
117                      family->gf_hdrsize, family->gf_maxattr);
118
119         if (family->ce_mask & FAMILY_ATTR_OPS) {
120                 struct genl_family_op *op;
121                 char buf[64];
122
123                 nl_list_for_each_entry(op, &family->gf_ops, o_list) {
124                         ops_flags2str(op->o_flags, buf, sizeof(buf));
125
126                         genl_op2name(family->gf_id, op->o_id, buf, sizeof(buf));
127
128                         nl_dump_line(p, "      op %s (0x%02x)", buf, op->o_id);
129
130                         if (op->o_flags)
131                                 nl_dump(p, " <%s>",
132                                         ops_flags2str(op->o_flags, buf,
133                                                       sizeof(buf)));
134
135                         nl_dump(p, "\n");
136                 }
137         }
138
139         nl_list_for_each_entry(grp, &family->gf_mc_grps, list) {
140                 nl_dump_line(p, "      grp %s (0x%02x)\n", grp->name, grp->id);
141         }
142
143 }
144
145 static void family_dump_stats(struct nl_object *obj, struct nl_dump_params *p)
146 {
147         family_dump_details(obj, p);
148 }
149
150 static int family_compare(struct nl_object *_a, struct nl_object *_b,
151                           uint32_t attrs, int flags)
152 {
153         struct genl_family *a = (struct genl_family *) _a;
154         struct genl_family *b = (struct genl_family *) _b;
155         int diff = 0;
156
157 #define FAM_DIFF(ATTR, EXPR) ATTR_DIFF(attrs, FAMILY_ATTR_##ATTR, a, b, EXPR)
158
159         diff |= FAM_DIFF(ID,            a->gf_id != b->gf_id);
160         diff |= FAM_DIFF(VERSION,       a->gf_version != b->gf_version);
161         diff |= FAM_DIFF(HDRSIZE,       a->gf_hdrsize != b->gf_hdrsize);
162         diff |= FAM_DIFF(MAXATTR,       a->gf_maxattr != b->gf_maxattr);
163         diff |= FAM_DIFF(NAME,          strcmp(a->gf_name, b->gf_name));
164
165 #undef FAM_DIFF
166
167         return diff;
168 }
169
170
171 /**
172  * @name Family Object
173  * @{
174  */
175
176 struct genl_family *genl_family_alloc(void)
177 {
178         return (struct genl_family *) nl_object_alloc(&genl_family_ops);
179 }
180
181 void genl_family_put(struct genl_family *family)
182 {
183         nl_object_put((struct nl_object *) family);
184 }
185
186 /** @} */
187
188 /**
189  * @name Attributes
190  * @{
191  */
192
193 unsigned int genl_family_get_id(struct genl_family *family)
194 {
195         if (family->ce_mask & FAMILY_ATTR_ID)
196                 return family->gf_id;
197         else
198                 return GENL_ID_GENERATE;
199 }
200
201 void genl_family_set_id(struct genl_family *family, unsigned int id)
202 {
203         family->gf_id = id;
204         family->ce_mask |= FAMILY_ATTR_ID;
205 }
206
207 char *genl_family_get_name(struct genl_family *family)
208 {
209         if (family->ce_mask & FAMILY_ATTR_NAME)
210                 return family->gf_name;
211         else
212                 return NULL;
213 }
214
215 void genl_family_set_name(struct genl_family *family, const char *name)
216 {
217         strncpy(family->gf_name, name, GENL_NAMSIZ-1);
218         family->ce_mask |= FAMILY_ATTR_NAME;
219 }
220
221 uint8_t genl_family_get_version(struct genl_family *family)
222 {
223         if (family->ce_mask & FAMILY_ATTR_VERSION)
224                 return family->gf_version;
225         else
226                 return 0;
227 }
228
229 void genl_family_set_version(struct genl_family *family, uint8_t version)
230 {
231         family->gf_version = version;
232         family->ce_mask |= FAMILY_ATTR_VERSION;
233 }
234
235 uint32_t genl_family_get_hdrsize(struct genl_family *family)
236 {
237         if (family->ce_mask & FAMILY_ATTR_HDRSIZE)
238                 return family->gf_hdrsize;
239         else
240                 return 0;
241 }
242
243 void genl_family_set_hdrsize(struct genl_family *family, uint32_t hdrsize)
244 {
245         family->gf_hdrsize = hdrsize;
246         family->ce_mask |= FAMILY_ATTR_HDRSIZE;
247 }
248
249 uint32_t genl_family_get_maxattr(struct genl_family *family)
250 {
251         if (family->ce_mask & FAMILY_ATTR_MAXATTR)
252                 return family->gf_maxattr;
253         else
254                 return family->gf_maxattr;
255 }
256
257 void genl_family_set_maxattr(struct genl_family *family, uint32_t maxattr)
258 {
259         family->gf_maxattr = maxattr;
260         family->ce_mask |= FAMILY_ATTR_MAXATTR;
261 }
262
263 int genl_family_add_op(struct genl_family *family, int id, int flags)
264 {
265         struct genl_family_op *op;
266
267         op = calloc(1, sizeof(*op));
268         if (op == NULL)
269                 return -NLE_NOMEM;
270
271         op->o_id = id;
272         op->o_flags = flags;
273
274         nl_list_add_tail(&op->o_list, &family->gf_ops);
275         family->ce_mask |= FAMILY_ATTR_OPS;
276
277         return 0;
278 }
279
280 int genl_family_add_grp(struct genl_family *family, uint32_t id,
281                         const char *name)
282 {
283         struct genl_family_grp *grp;  
284
285         grp = calloc(1, sizeof(*grp));
286         if (grp == NULL)
287                 return -NLE_NOMEM;
288
289         grp->id = id;
290         strncpy(grp->name, name, GENL_NAMSIZ - 1);
291
292         nl_list_add_tail(&grp->list, &family->gf_mc_grps);
293
294         return 0;
295 }
296
297 /** @} */
298
299 /** @cond SKIP */
300 struct nl_object_ops genl_family_ops = {
301         .oo_name                = "genl/family",
302         .oo_size                = sizeof(struct genl_family),
303         .oo_constructor         = family_constructor,
304         .oo_free_data           = family_free_data,
305         .oo_clone               = family_clone,
306         .oo_dump = {
307             [NL_DUMP_LINE]      = family_dump_line,
308             [NL_DUMP_DETAILS]   = family_dump_details,
309             [NL_DUMP_STATS]     = family_dump_stats,
310         },
311         .oo_compare             = family_compare,
312         .oo_id_attrs            = FAMILY_ATTR_ID,
313 };
314 /** @endcond */
315
316 /** @} */