1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
|
#ifndef NCR_UTILS_H
#define NCR_UTILS_H
#include <linux/kernel.h>
#include <linux/netlink.h>
#define NCR_MAX_ATTR_SIZE 4096
struct nlattr;
struct ncr_out {
void *buf, *p;
size_t left;
void __user *arg;
size_t output_size_offset, fixed_size;
u32 orig_output_size;
};
#define __NCR_VERIFY_FIXED_SIZE(fixed) \
(BUILD_BUG_ON(sizeof(*(fixed)) != NLA_ALIGN(sizeof(*(fixed)))))
#define __NCR_VERIFY_TB(tb) (BUILD_BUG_ON(ARRAY_SIZE(tb) != NCR_ATTR_MAX + 1))
extern u32 __ncr_u32_type_check;
#define __OUT_SIZE_OFF(fixed) \
((void)(&(fixed)->output_size == &__ncr_u32_type_check), \
(char *)&(fixed)->output_size - (char *)(fixed))
/**
* Load *@fixed and a sequence of netlink-like attributes from @arg. @fixed
* contains "input_size", which is an u32 filled with total input size,
* including the attributes, which are parsed into @tb.
*/
#define NCR_GET_INPUT_ARGS(fixed, tb, arg) \
(__NCR_VERIFY_FIXED_SIZE(fixed), \
__NCR_VERIFY_TB(tb), \
__ncr_get_input_args(fixed, tb, sizeof(*(fixed)), \
&(fixed)->input_size, arg))
void *__ncr_get_input_args(void *fixed, struct nlattr *tb[], size_t fixed_size,
u32 *input_size_ptr, const void __user *arg);
/**
* Load *@fixed and a sequence of netlink-like attributes from @arg. @fixed
* contains "input_size", which is an u32 filled with total input size,
* including the attributes, which are parsed into @tb. In addition, indicate
* to the user through u32 "output_size" that no output attributes will be
* returned.
*/
#define NCR_GET_INPUT_ARGS_NO_OUTPUT(fixed, tb, arg) \
(__NCR_VERIFY_FIXED_SIZE(fixed), \
__NCR_VERIFY_TB(tb), \
__ncr_get_input_args_no_output(fixed, tb, sizeof(*(fixed)), \
&(fixed)->input_size, \
__OUT_SIZE_OFF(fixed), arg))
void *__ncr_get_input_args_no_output(void *fixed, struct nlattr *tb[],
size_t fixed_size, u32 *input_size_ptr,
size_t output_size_offset,
void __user *arg);
/**
* Return a new output attribute context for attributes of *@fixed. @fixed
* contains "output_size", an u32 containing total output size, including
* @fixed. Store @arg for later ncr_out_finish().
*/
#define NCR_OUT_INIT(out, fixed, arg) \
(__NCR_VERIFY_FIXED_SIZE(fixed), \
__ncr_out_init((out), (fixed), sizeof(*(fixed)), \
__OUT_SIZE_OFF(fixed), (arg)))
int __ncr_out_init(struct ncr_out *out, const void *fixed, size_t fixed_size,
size_t output_size_offset, void __user *arg);
/**
* Write attributes from @out to user space and update user-space output_size.
*/
int ncr_out_finish(struct ncr_out *out);
void ncr_out_free(struct ncr_out *out);
int ncr_out_put(struct ncr_out *out, int attrtype, int attrlen,
const void *data);
static inline int ncr_out_put_u32(struct ncr_out *out, int attrtype, u32 value)
{
return ncr_out_put(out, attrtype, sizeof(value), &value);
}
static inline int ncr_out_put_string(struct ncr_out *out, int attrtype,
const char *value)
{
return ncr_out_put(out, attrtype, strlen(value) + 1, value);
}
struct nlattr *ncr_out_reserve(struct ncr_out *out, int attrtype, int attrlen);
struct nlattr *ncr_out_begin_buffer(struct ncr_out *out, int attrtype);
void ncr_out_commit_buffer(struct ncr_out *out, int attrlen);
#endif
|