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
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
|
// SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause
#ifndef __YNL_C_H
#define __YNL_C_H 1
#include <stdbool.h>
#include <stddef.h>
#include <linux/genetlink.h>
#include <linux/types.h>
#include "ynl-priv.h"
enum ynl_error_code {
YNL_ERROR_NONE = 0,
__YNL_ERRNO_END = 4096,
YNL_ERROR_INTERNAL,
YNL_ERROR_DUMP_INTER,
YNL_ERROR_EXPECT_ACK,
YNL_ERROR_EXPECT_MSG,
YNL_ERROR_UNEXPECT_MSG,
YNL_ERROR_ATTR_MISSING,
YNL_ERROR_ATTR_INVALID,
YNL_ERROR_UNKNOWN_NTF,
YNL_ERROR_INV_RESP,
YNL_ERROR_INPUT_INVALID,
YNL_ERROR_INPUT_TOO_BIG,
YNL_ERROR_SUBMSG_KEY,
};
/**
* struct ynl_error - error encountered by YNL
* @code: errno (low values) or YNL error code (enum ynl_error_code)
* @attr_offs: offset of bad attribute (for very advanced users)
* @msg: error message
*
* Error information for when YNL operations fail.
* Users should interact with the err member of struct ynl_sock directly.
* The main exception to that rule is ynl_sock_create().
*/
struct ynl_error {
enum ynl_error_code code;
unsigned int attr_offs;
char msg[512];
};
/**
* struct ynl_family - YNL family info
* Family description generated by codegen. Pass to ynl_sock_create().
*/
struct ynl_family {
/* private: */
const char *name;
size_t hdr_len;
bool is_classic;
__u16 classic_id;
const struct ynl_ntf_info *ntf_info;
unsigned int ntf_info_size;
};
/**
* struct ynl_sock - YNL wrapped netlink socket
* @err: YNL error descriptor, cleared on every request.
*/
struct ynl_sock {
struct ynl_error err;
/* private: */
const struct ynl_family *family;
int socket;
__u32 seq;
__u32 portid;
__u16 family_id;
unsigned int n_mcast_groups;
struct {
unsigned int id;
char name[GENL_NAMSIZ];
} *mcast_groups;
struct ynl_ntf_base_type *ntf_first;
struct ynl_ntf_base_type **ntf_last_next;
struct nlmsghdr *nlh;
const struct ynl_policy_nest *req_policy;
size_t req_hdr_len;
unsigned char *tx_buf;
unsigned char *rx_buf;
unsigned char raw_buf[];
};
/**
* struct ynl_string - parsed individual string
* @len: length of the string (excluding terminating character)
* @str: value of the string
*
* Parsed and nul-terminated string. This struct is only used for arrays of
* strings. Non-array string members are placed directly in respective types.
*/
struct ynl_string {
unsigned int len;
char str[];
};
struct ynl_sock *
ynl_sock_create(const struct ynl_family *yf, struct ynl_error *e);
void ynl_sock_destroy(struct ynl_sock *ys);
#define ynl_dump_foreach(dump, iter) \
for (typeof(dump->obj) *iter = &dump->obj; \
!ynl_dump_obj_is_last(iter); \
iter = ynl_dump_obj_next(iter))
/**
* ynl_dump_empty() - does the dump have no entries
* @dump: pointer to the dump list, as returned by a dump call
*
* Check if the dump is empty, i.e. contains no objects.
* Dump calls return NULL on error, and terminator element if empty.
*/
static inline bool ynl_dump_empty(void *dump)
{
return dump == (void *)YNL_LIST_END;
}
int ynl_subscribe(struct ynl_sock *ys, const char *grp_name);
int ynl_socket_get_fd(struct ynl_sock *ys);
int ynl_ntf_check(struct ynl_sock *ys);
/**
* ynl_has_ntf() - check if socket has *parsed* notifications
* @ys: active YNL socket
*
* Note that this does not take into account notifications sitting
* in netlink socket, just the notifications which have already been
* read and parsed (e.g. during a ynl_ntf_check() call).
*/
static inline bool ynl_has_ntf(struct ynl_sock *ys)
{
return ys->ntf_last_next != &ys->ntf_first;
}
struct ynl_ntf_base_type *ynl_ntf_dequeue(struct ynl_sock *ys);
void ynl_ntf_free(struct ynl_ntf_base_type *ntf);
#endif
|