88aaad9b772903e88124a164e43a2d4e4d4984b3
[openwrt.git] / package / 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 }
35
36 static void family_free_data(struct nl_object *c)
37 {
38         struct genl_family *family = (struct genl_family *) c;
39         struct genl_family_op *ops, *tmp;
40
41         if (family == NULL)
42                 return;
43
44         nl_list_for_each_entry_safe(ops, tmp, &family->gf_ops, o_list) {
45                 nl_list_del(&ops->o_list);
46                 free(ops);
47         }
48 }
49
50 static int family_clone(struct nl_object *_dst, struct nl_object *_src)
51 {
52         struct genl_family *dst = nl_object_priv(_dst);
53         struct genl_family *src = nl_object_priv(_src);
54         struct genl_family_op *ops;
55         int err;
56
57         nl_list_for_each_entry(ops, &src->gf_ops, o_list) {
58                 err = genl_family_add_op(dst, ops->o_id, ops->o_flags);
59                 if (err < 0)
60                         return err;
61         }
62         
63         return 0;
64 }
65
66 static int family_compare(struct nl_object *_a, struct nl_object *_b,
67                           uint32_t attrs, int flags)
68 {
69         struct genl_family *a = (struct genl_family *) _a;
70         struct genl_family *b = (struct genl_family *) _b;
71         int diff = 0;
72
73 #define FAM_DIFF(ATTR, EXPR) ATTR_DIFF(attrs, FAMILY_ATTR_##ATTR, a, b, EXPR)
74
75         diff |= FAM_DIFF(ID,            a->gf_id != b->gf_id);
76         diff |= FAM_DIFF(VERSION,       a->gf_version != b->gf_version);
77         diff |= FAM_DIFF(HDRSIZE,       a->gf_hdrsize != b->gf_hdrsize);
78         diff |= FAM_DIFF(MAXATTR,       a->gf_maxattr != b->gf_maxattr);
79         diff |= FAM_DIFF(NAME,          strcmp(a->gf_name, b->gf_name));
80
81 #undef FAM_DIFF
82
83         return diff;
84 }
85
86
87 /**
88  * @name Family Object
89  * @{
90  */
91
92 struct genl_family *genl_family_alloc(void)
93 {
94         return (struct genl_family *) nl_object_alloc(&genl_family_ops);
95 }
96
97 void genl_family_put(struct genl_family *family)
98 {
99         nl_object_put((struct nl_object *) family);
100 }
101
102 /** @} */
103
104
105 int genl_family_add_op(struct genl_family *family, int id, int flags)
106 {
107         struct genl_family_op *op;
108
109         op = calloc(1, sizeof(*op));
110         if (op == NULL)
111                 return -NLE_NOMEM;
112
113         op->o_id = id;
114         op->o_flags = flags;
115
116         nl_list_add_tail(&op->o_list, &family->gf_ops);
117         family->ce_mask |= FAMILY_ATTR_OPS;
118
119         return 0;
120 }
121
122 /** @} */
123
124 /** @cond SKIP */
125 struct nl_object_ops genl_family_ops = {
126         .oo_name                = "genl/family",
127         .oo_size                = sizeof(struct genl_family),
128         .oo_constructor         = family_constructor,
129         .oo_free_data           = family_free_data,
130         .oo_clone               = family_clone,
131         .oo_compare             = family_compare,
132         .oo_id_attrs            = FAMILY_ATTR_ID,
133 };
134 /** @endcond */
135
136 /** @} */