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