Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
freebsd
GitHub Repository: freebsd/freebsd-src
Path: blob/main/sys/netlink/netlink_message_writer.h
39475 views
1
/*-
2
* SPDX-License-Identifier: BSD-2-Clause
3
*
4
* Copyright (c) 2021 Ng Peng Nam Sean
5
* Copyright (c) 2022 Alexander V. Chernikov <[email protected]>
6
*
7
* Redistribution and use in source and binary forms, with or without
8
* modification, are permitted provided that the following conditions
9
* are met:
10
* 1. Redistributions of source code must retain the above copyright
11
* notice, this list of conditions and the following disclaimer.
12
* 2. Redistributions in binary form must reproduce the above copyright
13
* notice, this list of conditions and the following disclaimer in the
14
* documentation and/or other materials provided with the distribution.
15
*
16
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
17
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
18
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
19
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
20
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
21
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
22
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
23
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
24
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
25
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
26
* SUCH DAMAGE.
27
*/
28
29
#ifndef _NETLINK_NETLINK_MESSAGE_WRITER_H_
30
#define _NETLINK_NETLINK_MESSAGE_WRITER_H_
31
32
#ifdef _KERNEL
33
34
#include <netinet/in.h>
35
36
/*
37
* It is not meant to be included directly
38
*/
39
40
struct nl_buf;
41
struct nl_writer;
42
typedef bool nl_writer_cb(struct nl_writer *nw);
43
44
struct nl_writer {
45
struct nl_buf *buf; /* Underlying storage pointer */
46
struct nlmsghdr *hdr; /* Pointer to the currently-filled msg */
47
nl_writer_cb *cb; /* Callback to flush data */
48
union {
49
struct nlpcb *nlp;
50
struct {
51
uint16_t proto;
52
uint16_t id;
53
int priv;
54
} group;
55
};
56
u_int num_messages; /* Number of messages in the buffer */
57
int malloc_flag; /* M_WAITOK or M_NOWAIT */
58
bool ignore_limit; /* If true, ignores RCVBUF limit */
59
bool enomem; /* True if ENOMEM occured */
60
bool suppress_ack; /* If true, don't send NLMSG_ERR */
61
};
62
63
#define NLMSG_SMALL 128
64
#define NLMSG_LARGE 2048
65
66
/* Message and attribute writing */
67
#if defined(NETLINK) || defined(NETLINK_MODULE)
68
/* Provide optimized calls to the functions inside the same linking unit */
69
70
bool _nl_writer_unicast(struct nl_writer *, size_t, struct nlpcb *nlp, bool);
71
bool _nl_writer_group(struct nl_writer *, size_t, uint16_t, uint16_t, int,
72
bool);
73
bool _nlmsg_flush(struct nl_writer *nw);
74
void _nlmsg_ignore_limit(struct nl_writer *nw);
75
76
bool _nlmsg_refill_buffer(struct nl_writer *nw, size_t required_len);
77
bool _nlmsg_add(struct nl_writer *nw, uint32_t portid, uint32_t seq,
78
uint16_t type, uint16_t flags, uint32_t len);
79
bool _nlmsg_end(struct nl_writer *nw);
80
void _nlmsg_abort(struct nl_writer *nw);
81
82
bool _nlmsg_end_dump(struct nl_writer *nw, int error, struct nlmsghdr *hdr);
83
84
85
static inline bool
86
nl_writer_unicast(struct nl_writer *nw, size_t size, struct nlpcb *nlp,
87
bool waitok)
88
{
89
return (_nl_writer_unicast(nw, size, nlp, waitok));
90
}
91
92
static inline bool
93
nl_writer_group(struct nl_writer *nw, size_t size, uint16_t proto,
94
uint16_t group_id, int priv, bool waitok)
95
{
96
return (_nl_writer_group(nw, size, proto, group_id, priv, waitok));
97
}
98
99
static inline bool
100
nlmsg_flush(struct nl_writer *nw)
101
{
102
return (_nlmsg_flush(nw));
103
}
104
105
static inline void
106
nlmsg_ignore_limit(struct nl_writer *nw)
107
{
108
_nlmsg_ignore_limit(nw);
109
}
110
111
static inline bool
112
nlmsg_refill_buffer(struct nl_writer *nw, size_t required_size)
113
{
114
return (_nlmsg_refill_buffer(nw, required_size));
115
}
116
117
static inline bool
118
nlmsg_add(struct nl_writer *nw, uint32_t portid, uint32_t seq, uint16_t type,
119
uint16_t flags, uint32_t len)
120
{
121
return (_nlmsg_add(nw, portid, seq, type, flags, len));
122
}
123
124
static inline bool
125
nlmsg_end(struct nl_writer *nw)
126
{
127
return (_nlmsg_end(nw));
128
}
129
130
static inline void
131
nlmsg_abort(struct nl_writer *nw)
132
{
133
return (_nlmsg_abort(nw));
134
}
135
136
static inline bool
137
nlmsg_end_dump(struct nl_writer *nw, int error, struct nlmsghdr *hdr)
138
{
139
return (_nlmsg_end_dump(nw, error, hdr));
140
}
141
142
#else
143
/* Provide access to the functions via netlink_glue.c */
144
145
bool nl_writer_unicast(struct nl_writer *, size_t, struct nlpcb *, bool waitok);
146
bool nl_writer_group(struct nl_writer *, size_t, uint16_t, uint16_t, int,
147
bool waitok);
148
bool nlmsg_flush(struct nl_writer *nw);
149
void nlmsg_ignore_limit(struct nl_writer *nw);
150
151
bool nlmsg_refill_buffer(struct nl_writer *nw, size_t required_size);
152
bool nlmsg_add(struct nl_writer *nw, uint32_t portid, uint32_t seq,
153
uint16_t type, uint16_t flags, uint32_t len);
154
bool nlmsg_end(struct nl_writer *nw);
155
void nlmsg_abort(struct nl_writer *nw);
156
157
bool nlmsg_end_dump(struct nl_writer *nw, int error, struct nlmsghdr *hdr);
158
159
#endif /* defined(NETLINK) || defined(NETLINK_MODULE) */
160
161
static inline bool
162
nlmsg_reply(struct nl_writer *nw, const struct nlmsghdr *hdr, int payload_len)
163
{
164
return (nlmsg_add(nw, hdr->nlmsg_pid, hdr->nlmsg_seq, hdr->nlmsg_type,
165
hdr->nlmsg_flags, payload_len));
166
}
167
168
/*
169
* KPI similar to mtodo():
170
* current (uncompleted) header is guaranteed to be contiguous,
171
* but can be reallocated, thus pointers may need to be readjusted.
172
*/
173
u_int nlattr_save_offset(const struct nl_writer *nw);
174
175
static inline void *
176
_nlattr_restore_offset(const struct nl_writer *nw, int off)
177
{
178
return ((void *)((char *)nw->hdr + off));
179
}
180
#define nlattr_restore_offset(_ns, _off, _t) ((_t *)_nlattr_restore_offset(_ns, _off))
181
182
static inline void
183
nlattr_set_len(const struct nl_writer *nw, int off)
184
{
185
struct nlattr *nla = nlattr_restore_offset(nw, off, struct nlattr);
186
nla->nla_len = nlattr_save_offset(nw) - off;
187
}
188
189
void *nlmsg_reserve_data_raw(struct nl_writer *nw, size_t sz);
190
#define nlmsg_reserve_object(_ns, _t) ((_t *)nlmsg_reserve_data_raw(_ns, sizeof(_t)))
191
#define nlmsg_reserve_data(_ns, _sz, _t) ((_t *)nlmsg_reserve_data_raw(_ns, _sz))
192
193
static inline int
194
nlattr_add_nested(struct nl_writer *nw, uint16_t nla_type)
195
{
196
int off = nlattr_save_offset(nw);
197
struct nlattr *nla = nlmsg_reserve_data(nw, sizeof(struct nlattr), struct nlattr);
198
if (__predict_false(nla == NULL))
199
return (0);
200
nla->nla_type = nla_type;
201
return (off);
202
}
203
204
static inline void *
205
_nlmsg_reserve_attr(struct nl_writer *nw, uint16_t nla_type, uint16_t sz)
206
{
207
sz += sizeof(struct nlattr);
208
209
struct nlattr *nla = nlmsg_reserve_data(nw, sz, struct nlattr);
210
if (__predict_false(nla == NULL))
211
return (NULL);
212
nla->nla_type = nla_type;
213
nla->nla_len = sz;
214
215
return ((void *)(nla + 1));
216
}
217
#define nlmsg_reserve_attr(_ns, _at, _t) ((_t *)_nlmsg_reserve_attr(_ns, _at, NLA_ALIGN(sizeof(_t))))
218
219
bool nlattr_add(struct nl_writer *nw, uint16_t attr_type, uint16_t attr_len,
220
const void *data);
221
222
static inline bool
223
nlattr_add_raw(struct nl_writer *nw, const struct nlattr *nla_src)
224
{
225
MPASS(nla_src->nla_len >= sizeof(struct nlattr));
226
227
return (nlattr_add(nw, nla_src->nla_type,
228
nla_src->nla_len - sizeof(struct nlattr),
229
(const void *)(nla_src + 1)));
230
}
231
232
static inline bool
233
nlattr_add_bool(struct nl_writer *nw, uint16_t attrtype, bool value)
234
{
235
return (nlattr_add(nw, attrtype, sizeof(bool), &value));
236
}
237
238
static inline bool
239
nlattr_add_u8(struct nl_writer *nw, uint16_t attrtype, uint8_t value)
240
{
241
return (nlattr_add(nw, attrtype, sizeof(uint8_t), &value));
242
}
243
244
static inline bool
245
nlattr_add_u16(struct nl_writer *nw, uint16_t attrtype, uint16_t value)
246
{
247
return (nlattr_add(nw, attrtype, sizeof(uint16_t), &value));
248
}
249
250
static inline bool
251
nlattr_add_u32(struct nl_writer *nw, uint16_t attrtype, uint32_t value)
252
{
253
return (nlattr_add(nw, attrtype, sizeof(uint32_t), &value));
254
}
255
256
static inline bool
257
nlattr_add_u64(struct nl_writer *nw, uint16_t attrtype, uint64_t value)
258
{
259
return (nlattr_add(nw, attrtype, sizeof(uint64_t), &value));
260
}
261
262
static inline bool
263
nlattr_add_s8(struct nl_writer *nw, uint16_t attrtype, int8_t value)
264
{
265
return (nlattr_add(nw, attrtype, sizeof(int8_t), &value));
266
}
267
268
static inline bool
269
nlattr_add_s16(struct nl_writer *nw, uint16_t attrtype, int16_t value)
270
{
271
return (nlattr_add(nw, attrtype, sizeof(int16_t), &value));
272
}
273
274
static inline bool
275
nlattr_add_s32(struct nl_writer *nw, uint16_t attrtype, int32_t value)
276
{
277
return (nlattr_add(nw, attrtype, sizeof(int32_t), &value));
278
}
279
280
static inline bool
281
nlattr_add_s64(struct nl_writer *nw, uint16_t attrtype, int64_t value)
282
{
283
return (nlattr_add(nw, attrtype, sizeof(int64_t), &value));
284
}
285
286
static inline bool
287
nlattr_add_time_t(struct nl_writer *nw, uint16_t attrtype, time_t value)
288
{
289
return (nlattr_add(nw, attrtype, sizeof(time_t), &value));
290
}
291
292
static inline bool
293
nlattr_add_flag(struct nl_writer *nw, uint16_t attrtype)
294
{
295
return (nlattr_add(nw, attrtype, 0, NULL));
296
}
297
298
static inline bool
299
nlattr_add_string(struct nl_writer *nw, uint16_t attrtype, const char *str)
300
{
301
return (nlattr_add(nw, attrtype, strlen(str) + 1, str));
302
}
303
304
static inline bool
305
nlattr_add_in_addr(struct nl_writer *nw, uint16_t attrtype,
306
const struct in_addr *in)
307
{
308
return (nlattr_add(nw, attrtype, sizeof(*in), in));
309
}
310
311
static inline bool
312
nlattr_add_in6_addr(struct nl_writer *nw, uint16_t attrtype,
313
const struct in6_addr *in6)
314
{
315
return (nlattr_add(nw, attrtype, sizeof(*in6), in6));
316
}
317
#endif
318
#endif
319
320