libnl-tiny: Generic Netlink multicast groups support
[openwrt/openwrt.git] / package / libs / libnl-tiny / src / 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 struct nl_object_ops genl_family_ops;
27 /** @endcond */
28
29 static void family_constructor(struct nl_object *c)
30 {
31 struct genl_family *family = (struct genl_family *) c;
32
33 nl_init_list_head(&family->gf_ops);
34 nl_init_list_head(&family->gf_mc_grps);
35 }
36
37 static void family_free_data(struct nl_object *c)
38 {
39 struct genl_family *family = (struct genl_family *) c;
40 struct genl_family_op *ops, *tmp;
41 struct genl_family_grp *grp, *t_grp;
42
43 if (family == NULL)
44 return;
45
46 nl_list_for_each_entry_safe(ops, tmp, &family->gf_ops, o_list) {
47 nl_list_del(&ops->o_list);
48 free(ops);
49 }
50
51 nl_list_for_each_entry_safe(grp, t_grp, &family->gf_mc_grps, list) {
52 nl_list_del(&grp->list);
53 free(grp);
54 }
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 struct genl_family_grp *grp;
64 int err;
65
66 nl_list_for_each_entry(ops, &src->gf_ops, o_list) {
67 err = genl_family_add_op(dst, ops->o_id, ops->o_flags);
68 if (err < 0)
69 return err;
70 }
71
72 nl_list_for_each_entry(grp, &src->gf_mc_grps, list) {
73 err = genl_family_add_grp(dst, grp->id, grp->name);
74 if (err < 0)
75 return err;
76 }
77
78
79 return 0;
80 }
81
82 static int family_compare(struct nl_object *_a, struct nl_object *_b,
83 uint32_t attrs, int flags)
84 {
85 struct genl_family *a = (struct genl_family *) _a;
86 struct genl_family *b = (struct genl_family *) _b;
87 int diff = 0;
88
89 #define FAM_DIFF(ATTR, EXPR) ATTR_DIFF(attrs, FAMILY_ATTR_##ATTR, a, b, EXPR)
90
91 diff |= FAM_DIFF(ID, a->gf_id != b->gf_id);
92 diff |= FAM_DIFF(VERSION, a->gf_version != b->gf_version);
93 diff |= FAM_DIFF(HDRSIZE, a->gf_hdrsize != b->gf_hdrsize);
94 diff |= FAM_DIFF(MAXATTR, a->gf_maxattr != b->gf_maxattr);
95 diff |= FAM_DIFF(NAME, strcmp(a->gf_name, b->gf_name));
96
97 #undef FAM_DIFF
98
99 return diff;
100 }
101
102
103 /**
104 * @name Family Object
105 * @{
106 */
107
108 struct genl_family *genl_family_alloc(void)
109 {
110 return (struct genl_family *) nl_object_alloc(&genl_family_ops);
111 }
112
113 void genl_family_put(struct genl_family *family)
114 {
115 nl_object_put((struct nl_object *) family);
116 }
117
118 /** @} */
119
120
121 int genl_family_add_op(struct genl_family *family, int id, int flags)
122 {
123 struct genl_family_op *op;
124
125 op = calloc(1, sizeof(*op));
126 if (op == NULL)
127 return -NLE_NOMEM;
128
129 op->o_id = id;
130 op->o_flags = flags;
131
132 nl_list_add_tail(&op->o_list, &family->gf_ops);
133 family->ce_mask |= FAMILY_ATTR_OPS;
134
135 return 0;
136 }
137
138 int genl_family_add_grp(struct genl_family *family, uint32_t id,
139 const char *name)
140 {
141 struct genl_family_grp *grp;
142
143 grp = calloc(1, sizeof(*grp));
144 if (grp == NULL)
145 return -NLE_NOMEM;
146
147 grp->id = id;
148 strncpy(grp->name, name, GENL_NAMSIZ - 1);
149
150 nl_list_add_tail(&grp->list, &family->gf_mc_grps);
151
152 return 0;
153 }
154
155 /** @} */
156
157 /** @cond SKIP */
158 struct nl_object_ops genl_family_ops = {
159 .oo_name = "genl/family",
160 .oo_size = sizeof(struct genl_family),
161 .oo_constructor = family_constructor,
162 .oo_free_data = family_free_data,
163 .oo_clone = family_clone,
164 .oo_compare = family_compare,
165 .oo_id_attrs = FAMILY_ATTR_ID,
166 };
167 /** @endcond */
168
169 /** @} */