Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
torvalds
GitHub Repository: torvalds/linux
Path: blob/master/tools/net/ynl/lib/ynl-priv.h
29271 views
1
/* SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause */
2
#ifndef __YNL_C_PRIV_H
3
#define __YNL_C_PRIV_H 1
4
5
#include <stdbool.h>
6
#include <stddef.h>
7
#include <linux/types.h>
8
9
struct ynl_parse_arg;
10
11
/*
12
* YNL internals / low level stuff
13
*/
14
15
enum ynl_policy_type {
16
YNL_PT_REJECT = 1,
17
YNL_PT_IGNORE,
18
YNL_PT_NEST,
19
YNL_PT_FLAG,
20
YNL_PT_BINARY,
21
YNL_PT_U8,
22
YNL_PT_U16,
23
YNL_PT_U32,
24
YNL_PT_U64,
25
YNL_PT_UINT,
26
YNL_PT_NUL_STR,
27
YNL_PT_BITFIELD32,
28
YNL_PT_SUBMSG,
29
};
30
31
enum ynl_parse_result {
32
YNL_PARSE_CB_ERROR = -1,
33
YNL_PARSE_CB_STOP = 0,
34
YNL_PARSE_CB_OK = 1,
35
};
36
37
#define YNL_SOCKET_BUFFER_SIZE (1 << 17)
38
39
#define YNL_ARRAY_SIZE(array) (sizeof(array) ? \
40
sizeof(array) / sizeof(array[0]) : 0)
41
42
typedef int (*ynl_parse_cb_t)(const struct nlmsghdr *nlh,
43
struct ynl_parse_arg *yarg);
44
45
struct ynl_policy_attr {
46
enum ynl_policy_type type:8;
47
__u8 is_submsg:1;
48
__u8 is_selector:1;
49
__u16 selector_type;
50
unsigned int len;
51
const char *name;
52
const struct ynl_policy_nest *nest;
53
};
54
55
struct ynl_policy_nest {
56
unsigned int max_attr;
57
const struct ynl_policy_attr *table;
58
};
59
60
struct ynl_parse_arg {
61
struct ynl_sock *ys;
62
const struct ynl_policy_nest *rsp_policy;
63
void *data;
64
};
65
66
struct ynl_dump_list_type {
67
struct ynl_dump_list_type *next;
68
unsigned char data[] __attribute__((aligned(8)));
69
};
70
extern struct ynl_dump_list_type *YNL_LIST_END;
71
72
static inline bool ynl_dump_obj_is_last(void *obj)
73
{
74
unsigned long uptr = (unsigned long)obj;
75
76
uptr -= offsetof(struct ynl_dump_list_type, data);
77
return uptr == (unsigned long)YNL_LIST_END;
78
}
79
80
static inline void *ynl_dump_obj_next(void *obj)
81
{
82
unsigned long uptr = (unsigned long)obj;
83
struct ynl_dump_list_type *list;
84
85
uptr -= offsetof(struct ynl_dump_list_type, data);
86
list = (struct ynl_dump_list_type *)uptr;
87
uptr = (unsigned long)list->next;
88
uptr += offsetof(struct ynl_dump_list_type, data);
89
90
return (void *)uptr;
91
}
92
93
struct ynl_ntf_base_type {
94
__u16 family;
95
__u8 cmd;
96
struct ynl_ntf_base_type *next;
97
void (*free)(struct ynl_ntf_base_type *ntf);
98
unsigned char data[] __attribute__((aligned(8)));
99
};
100
101
struct nlmsghdr *ynl_msg_start_req(struct ynl_sock *ys, __u32 id, __u16 flags);
102
struct nlmsghdr *ynl_msg_start_dump(struct ynl_sock *ys, __u32 id);
103
104
struct nlmsghdr *
105
ynl_gemsg_start_req(struct ynl_sock *ys, __u32 id, __u8 cmd, __u8 version);
106
struct nlmsghdr *
107
ynl_gemsg_start_dump(struct ynl_sock *ys, __u32 id, __u8 cmd, __u8 version);
108
109
int ynl_submsg_failed(struct ynl_parse_arg *yarg, const char *field_name,
110
const char *sel_name);
111
112
/* YNL specific helpers used by the auto-generated code */
113
114
struct ynl_req_state {
115
struct ynl_parse_arg yarg;
116
ynl_parse_cb_t cb;
117
__u32 rsp_cmd;
118
};
119
120
struct ynl_dump_state {
121
struct ynl_parse_arg yarg;
122
void *first;
123
struct ynl_dump_list_type *last;
124
size_t alloc_sz;
125
ynl_parse_cb_t cb;
126
__u32 rsp_cmd;
127
};
128
129
struct ynl_ntf_info {
130
const struct ynl_policy_nest *policy;
131
ynl_parse_cb_t cb;
132
size_t alloc_sz;
133
void (*free)(struct ynl_ntf_base_type *ntf);
134
};
135
136
int ynl_exec(struct ynl_sock *ys, struct nlmsghdr *req_nlh,
137
struct ynl_req_state *yrs);
138
int ynl_exec_dump(struct ynl_sock *ys, struct nlmsghdr *req_nlh,
139
struct ynl_dump_state *yds);
140
141
void ynl_error_unknown_notification(struct ynl_sock *ys, __u8 cmd);
142
int ynl_error_parse(struct ynl_parse_arg *yarg, const char *msg);
143
144
/* Netlink message handling helpers */
145
146
#define YNL_MSG_OVERFLOW 1
147
148
static inline struct nlmsghdr *ynl_nlmsg_put_header(void *buf)
149
{
150
struct nlmsghdr *nlh = (struct nlmsghdr *)buf;
151
152
memset(nlh, 0, sizeof(*nlh));
153
nlh->nlmsg_len = NLMSG_HDRLEN;
154
155
return nlh;
156
}
157
158
static inline unsigned int ynl_nlmsg_data_len(const struct nlmsghdr *nlh)
159
{
160
return nlh->nlmsg_len - NLMSG_HDRLEN;
161
}
162
163
static inline void *ynl_nlmsg_data(const struct nlmsghdr *nlh)
164
{
165
return (unsigned char *)nlh + NLMSG_HDRLEN;
166
}
167
168
static inline void *
169
ynl_nlmsg_data_offset(const struct nlmsghdr *nlh, unsigned int offset)
170
{
171
return (unsigned char *)nlh + NLMSG_HDRLEN + offset;
172
}
173
174
static inline void *ynl_nlmsg_end_addr(const struct nlmsghdr *nlh)
175
{
176
return (char *)nlh + nlh->nlmsg_len;
177
}
178
179
static inline void *
180
ynl_nlmsg_put_extra_header(struct nlmsghdr *nlh, unsigned int size)
181
{
182
void *tail = ynl_nlmsg_end_addr(nlh);
183
184
nlh->nlmsg_len += NLMSG_ALIGN(size);
185
return tail;
186
}
187
188
/* Netlink attribute helpers */
189
190
static inline unsigned int ynl_attr_type(const struct nlattr *attr)
191
{
192
return attr->nla_type & NLA_TYPE_MASK;
193
}
194
195
static inline unsigned int ynl_attr_data_len(const struct nlattr *attr)
196
{
197
return attr->nla_len - NLA_HDRLEN;
198
}
199
200
static inline void *ynl_attr_data(const struct nlattr *attr)
201
{
202
return (unsigned char *)attr + NLA_HDRLEN;
203
}
204
205
static inline void *ynl_attr_data_end(const struct nlattr *attr)
206
{
207
return (char *)ynl_attr_data(attr) + ynl_attr_data_len(attr);
208
}
209
210
#define ynl_attr_for_each(attr, nlh, fixed_hdr_sz) \
211
for ((attr) = ynl_attr_first(nlh, (nlh)->nlmsg_len, \
212
NLMSG_HDRLEN + fixed_hdr_sz); attr; \
213
(attr) = ynl_attr_next(ynl_nlmsg_end_addr(nlh), attr))
214
215
#define ynl_attr_for_each_nested_off(attr, outer, offset) \
216
for ((attr) = ynl_attr_first(outer, outer->nla_len, \
217
sizeof(struct nlattr) + offset); \
218
attr; \
219
(attr) = ynl_attr_next(ynl_attr_data_end(outer), attr))
220
221
#define ynl_attr_for_each_nested(attr, outer) \
222
ynl_attr_for_each_nested_off(attr, outer, 0)
223
224
#define ynl_attr_for_each_payload(start, len, attr) \
225
for ((attr) = ynl_attr_first(start, len, 0); attr; \
226
(attr) = ynl_attr_next(start + len, attr))
227
228
static inline struct nlattr *
229
ynl_attr_if_good(const void *end, struct nlattr *attr)
230
{
231
if (attr + 1 > (const struct nlattr *)end)
232
return NULL;
233
if (ynl_attr_data_end(attr) > end)
234
return NULL;
235
return attr;
236
}
237
238
static inline struct nlattr *
239
ynl_attr_next(const void *end, const struct nlattr *prev)
240
{
241
struct nlattr *attr;
242
243
attr = (struct nlattr *)((char *)prev + NLA_ALIGN(prev->nla_len));
244
return ynl_attr_if_good(end, attr);
245
}
246
247
static inline struct nlattr *
248
ynl_attr_first(const void *start, size_t len, size_t skip)
249
{
250
struct nlattr *attr;
251
252
attr = (struct nlattr *)((char *)start + NLMSG_ALIGN(skip));
253
return ynl_attr_if_good((char *)start + len, attr);
254
}
255
256
static inline bool
257
__ynl_attr_put_overflow(struct nlmsghdr *nlh, size_t size)
258
{
259
bool o;
260
261
/* ynl_msg_start() stashed buffer length in nlmsg_pid. */
262
o = nlh->nlmsg_len + NLA_HDRLEN + NLMSG_ALIGN(size) > nlh->nlmsg_pid;
263
if (o)
264
/* YNL_MSG_OVERFLOW is < NLMSG_HDRLEN, all subsequent checks
265
* are guaranteed to fail.
266
*/
267
nlh->nlmsg_pid = YNL_MSG_OVERFLOW;
268
return o;
269
}
270
271
static inline struct nlattr *
272
ynl_attr_nest_start(struct nlmsghdr *nlh, unsigned int attr_type)
273
{
274
struct nlattr *attr;
275
276
if (__ynl_attr_put_overflow(nlh, 0))
277
return (struct nlattr *)ynl_nlmsg_end_addr(nlh) - 1;
278
279
attr = (struct nlattr *)ynl_nlmsg_end_addr(nlh);
280
attr->nla_type = attr_type | NLA_F_NESTED;
281
nlh->nlmsg_len += NLA_HDRLEN;
282
283
return attr;
284
}
285
286
static inline void
287
ynl_attr_nest_end(struct nlmsghdr *nlh, struct nlattr *attr)
288
{
289
attr->nla_len = (char *)ynl_nlmsg_end_addr(nlh) - (char *)attr;
290
}
291
292
static inline void
293
ynl_attr_put(struct nlmsghdr *nlh, unsigned int attr_type,
294
const void *value, size_t size)
295
{
296
struct nlattr *attr;
297
298
if (__ynl_attr_put_overflow(nlh, size))
299
return;
300
301
attr = (struct nlattr *)ynl_nlmsg_end_addr(nlh);
302
attr->nla_type = attr_type;
303
attr->nla_len = NLA_HDRLEN + size;
304
305
memcpy(ynl_attr_data(attr), value, size);
306
307
nlh->nlmsg_len += NLMSG_ALIGN(attr->nla_len);
308
}
309
310
static inline void
311
ynl_attr_put_str(struct nlmsghdr *nlh, unsigned int attr_type, const char *str)
312
{
313
struct nlattr *attr;
314
size_t len;
315
316
len = strlen(str);
317
if (__ynl_attr_put_overflow(nlh, len))
318
return;
319
320
attr = (struct nlattr *)ynl_nlmsg_end_addr(nlh);
321
attr->nla_type = attr_type;
322
323
strcpy((char *)ynl_attr_data(attr), str);
324
attr->nla_len = NLA_HDRLEN + NLA_ALIGN(len);
325
326
nlh->nlmsg_len += NLMSG_ALIGN(attr->nla_len);
327
}
328
329
static inline const char *ynl_attr_get_str(const struct nlattr *attr)
330
{
331
return (const char *)ynl_attr_data(attr);
332
}
333
334
static inline __s8 ynl_attr_get_s8(const struct nlattr *attr)
335
{
336
return *(__s8 *)ynl_attr_data(attr);
337
}
338
339
static inline __s16 ynl_attr_get_s16(const struct nlattr *attr)
340
{
341
return *(__s16 *)ynl_attr_data(attr);
342
}
343
344
static inline __s32 ynl_attr_get_s32(const struct nlattr *attr)
345
{
346
return *(__s32 *)ynl_attr_data(attr);
347
}
348
349
static inline __s64 ynl_attr_get_s64(const struct nlattr *attr)
350
{
351
__s64 tmp;
352
353
memcpy(&tmp, (unsigned char *)(attr + 1), sizeof(tmp));
354
return tmp;
355
}
356
357
static inline __u8 ynl_attr_get_u8(const struct nlattr *attr)
358
{
359
return *(__u8 *)ynl_attr_data(attr);
360
}
361
362
static inline __u16 ynl_attr_get_u16(const struct nlattr *attr)
363
{
364
return *(__u16 *)ynl_attr_data(attr);
365
}
366
367
static inline __u32 ynl_attr_get_u32(const struct nlattr *attr)
368
{
369
return *(__u32 *)ynl_attr_data(attr);
370
}
371
372
static inline __u64 ynl_attr_get_u64(const struct nlattr *attr)
373
{
374
__u64 tmp;
375
376
memcpy(&tmp, (unsigned char *)(attr + 1), sizeof(tmp));
377
return tmp;
378
}
379
380
static inline void
381
ynl_attr_put_s8(struct nlmsghdr *nlh, unsigned int attr_type, __s8 value)
382
{
383
ynl_attr_put(nlh, attr_type, &value, sizeof(value));
384
}
385
386
static inline void
387
ynl_attr_put_s16(struct nlmsghdr *nlh, unsigned int attr_type, __s16 value)
388
{
389
ynl_attr_put(nlh, attr_type, &value, sizeof(value));
390
}
391
392
static inline void
393
ynl_attr_put_s32(struct nlmsghdr *nlh, unsigned int attr_type, __s32 value)
394
{
395
ynl_attr_put(nlh, attr_type, &value, sizeof(value));
396
}
397
398
static inline void
399
ynl_attr_put_s64(struct nlmsghdr *nlh, unsigned int attr_type, __s64 value)
400
{
401
ynl_attr_put(nlh, attr_type, &value, sizeof(value));
402
}
403
404
static inline void
405
ynl_attr_put_u8(struct nlmsghdr *nlh, unsigned int attr_type, __u8 value)
406
{
407
ynl_attr_put(nlh, attr_type, &value, sizeof(value));
408
}
409
410
static inline void
411
ynl_attr_put_u16(struct nlmsghdr *nlh, unsigned int attr_type, __u16 value)
412
{
413
ynl_attr_put(nlh, attr_type, &value, sizeof(value));
414
}
415
416
static inline void
417
ynl_attr_put_u32(struct nlmsghdr *nlh, unsigned int attr_type, __u32 value)
418
{
419
ynl_attr_put(nlh, attr_type, &value, sizeof(value));
420
}
421
422
static inline void
423
ynl_attr_put_u64(struct nlmsghdr *nlh, unsigned int attr_type, __u64 value)
424
{
425
ynl_attr_put(nlh, attr_type, &value, sizeof(value));
426
}
427
428
static inline __u64 ynl_attr_get_uint(const struct nlattr *attr)
429
{
430
switch (ynl_attr_data_len(attr)) {
431
case 4:
432
return ynl_attr_get_u32(attr);
433
case 8:
434
return ynl_attr_get_u64(attr);
435
default:
436
return 0;
437
}
438
}
439
440
static inline __s64 ynl_attr_get_sint(const struct nlattr *attr)
441
{
442
switch (ynl_attr_data_len(attr)) {
443
case 4:
444
return ynl_attr_get_s32(attr);
445
case 8:
446
return ynl_attr_get_s64(attr);
447
default:
448
return 0;
449
}
450
}
451
452
static inline void
453
ynl_attr_put_uint(struct nlmsghdr *nlh, __u16 type, __u64 data)
454
{
455
if ((__u32)data == (__u64)data)
456
ynl_attr_put_u32(nlh, type, data);
457
else
458
ynl_attr_put_u64(nlh, type, data);
459
}
460
461
static inline void
462
ynl_attr_put_sint(struct nlmsghdr *nlh, __u16 type, __s64 data)
463
{
464
if ((__s32)data == (__s64)data)
465
ynl_attr_put_s32(nlh, type, data);
466
else
467
ynl_attr_put_s64(nlh, type, data);
468
}
469
470
int __ynl_attr_validate(struct ynl_parse_arg *yarg, const struct nlattr *attr,
471
unsigned int type);
472
473
static inline int ynl_attr_validate(struct ynl_parse_arg *yarg,
474
const struct nlattr *attr)
475
{
476
return __ynl_attr_validate(yarg, attr, ynl_attr_type(attr));
477
}
478
#endif
479
480