1 /* SPDX-License-Identifier: LGPL-2.1-only */
2 /*
3 * lib/data.c Abstract Data
4 *
5 * This library is free software; you can redistribute it and/or
6 * modify it under the terms of the GNU Lesser General Public
7 * License as published by the Free Software Foundation version 2.1
8 * of the License.
9 *
10 * Copyright (c) 2003-2012 Thomas Graf <tgraf@suug.ch>
11 */
12
13 /**
14 * @ingroup core_types
15 * @defgroup data Abstract Data
16 *
17 * Abstract data type representing a binary data blob.
18 *
19 * Related sections in the development guide:
20 * - @core_doc{_abstract_data, Abstract Data}
21 *
22 * @{
23 *
24 * Header
25 * ------
26 * ~~~~{.c}
27 * #include <netlink/data.h>
28 * ~~~~
29 */
30
31 #include <netlink-private/netlink.h>
32 #include <netlink/netlink.h>
33 #include <netlink/utils.h>
34 #include <linux/socket.h>
35
36 /**
37 * @name General
38 * @{
39 */
40
41 /**
42 * Allocate a new abstract data object.
43 * @arg buf Data buffer containing the actual data.
44 * @arg size Size of data buffer.
45 *
46 * Allocates a new abstract data and copies the specified data
47 * buffer into the new handle.
48 *
49 * @return Newly allocated data handle or NULL
50 */
nl_data_alloc(const void * buf,size_t size)51 struct nl_data *nl_data_alloc(const void *buf, size_t size)
52 {
53 struct nl_data *data;
54
55 data = calloc(1, sizeof(*data));
56 if (!data)
57 goto errout;
58
59 data->d_data = calloc(1, size);
60 if (!data->d_data) {
61 free(data);
62 goto errout;
63 }
64
65 data->d_size = size;
66
67 if (buf)
68 memcpy(data->d_data, buf, size);
69
70 return data;
71 errout:
72 return NULL;
73 }
74
75 /**
76 * Allocate abstract data object based on netlink attribute.
77 * @arg nla Netlink attribute of unspecific type.
78 *
79 * Allocates a new abstract data and copies the payload of the
80 * attribute to the abstract data object.
81 *
82 * @see nla_data_alloc
83 * @return Newly allocated data handle or NULL
84 */
nl_data_alloc_attr(const struct nlattr * nla)85 struct nl_data *nl_data_alloc_attr(const struct nlattr *nla)
86 {
87 return nl_data_alloc(nla_data(nla), nla_len(nla));
88 }
89
90 /**
91 * Clone an abstract data object.
92 * @arg src Abstract data object
93 *
94 * @return Cloned object or NULL
95 */
nl_data_clone(const struct nl_data * src)96 struct nl_data *nl_data_clone(const struct nl_data *src)
97 {
98 return nl_data_alloc(src->d_data, src->d_size);
99 }
100
101 /**
102 * Append data to an abstract data object.
103 * @arg data Abstract data object.
104 * @arg buf Data buffer containing the data to be appended.
105 * @arg size Size of data to be apppended.
106 *
107 * Reallocates an abstract data and copies the specified data
108 * buffer into the new handle.
109 *
110 * @return 0 on success or a negative error code
111 */
nl_data_append(struct nl_data * data,const void * buf,size_t size)112 int nl_data_append(struct nl_data *data, const void *buf, size_t size)
113 {
114 if (size > 0) {
115 char *d_data = realloc(data->d_data, data->d_size + size);
116 if (!d_data)
117 return -NLE_NOMEM;
118
119 if (buf)
120 memcpy(d_data + data->d_size, buf, size);
121 else
122 memset(d_data + data->d_size, 0, size);
123
124 data->d_data = d_data;
125 data->d_size += size;
126 }
127
128 return 0;
129 }
130
131 /**
132 * Free an abstract data object.
133 * @arg data Abstract data object.
134 */
nl_data_free(struct nl_data * data)135 void nl_data_free(struct nl_data *data)
136 {
137 if (data)
138 free(data->d_data);
139
140 free(data);
141 }
142
143 /** @} */
144
145 /**
146 * @name Attribute Access
147 * @{
148 */
149
150 /**
151 * Get data buffer of abstract data object.
152 * @arg data Abstract data object.
153 * @return Data buffer or NULL if empty.
154 */
nl_data_get(const struct nl_data * data)155 void *nl_data_get(const struct nl_data *data)
156 {
157 if (data->d_size > 0)
158 return (void*)data->d_data;
159 return NULL;
160 }
161
162 /**
163 * Get size of data buffer of abstract data object.
164 * @arg data Abstract data object.
165 * @return Size of data buffer.
166 */
nl_data_get_size(const struct nl_data * data)167 size_t nl_data_get_size(const struct nl_data *data)
168 {
169 return data->d_size;
170 }
171
172 /** @} */
173
174 /**
175 * @name Misc
176 * @{
177 */
178
179 /**
180 * Compare two abstract data objects.
181 * @arg a Abstract data object.
182 * @arg b Another abstract data object.
183 * @return An integer less than, equal to, or greater than zero if
184 * a is found, respectively, to be less than, to match, or
185 * be greater than b.
186 */
nl_data_cmp(const struct nl_data * a,const struct nl_data * b)187 int nl_data_cmp(const struct nl_data *a, const struct nl_data *b)
188 {
189 const void *a_ = nl_data_get(a);
190 const void *b_ = nl_data_get(b);
191
192 if (a_ && b_)
193 return memcmp(a_, b_, nl_data_get_size(a));
194 else
195 return -1;
196 }
197
198 /** @} */
199 /** @} */
200