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
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
|
/*
* netlink/handlers.c default netlink message handlers
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation version 2.1
* of the License.
*
* Copyright (c) 2003-2006 Thomas Graf <tgraf@suug.ch>
*/
#ifndef NETLINK_HANDLERS_H_
#define NETLINK_HANDLERS_H_
#include <stdio.h>
#include <stdint.h>
#include <sys/types.h>
#include <netlink/netlink-compat.h>
#include <netlink/netlink-kernel.h>
#include <netlink/types.h>
#ifdef __cplusplus
extern "C" {
#endif
struct nl_sock;
struct nl_msg;
struct nl_cb;
/**
* @name Callback Typedefs
* @{
*/
/**
* nl_recvmsgs() callback for message processing customization
* @ingroup cb
* @arg msg netlink message being processed
* @arg arg argument passwd on through caller
*/
typedef int (*nl_recvmsg_msg_cb_t)(struct nl_msg *msg, void *arg);
/**
* nl_recvmsgs() callback for error message processing customization
* @ingroup cb
* @arg nla netlink address of the peer
* @arg nlerr netlink error message being processed
* @arg arg argument passed on through caller
*/
typedef int (*nl_recvmsg_err_cb_t)(struct sockaddr_nl *nla,
struct nlmsgerr *nlerr, void *arg);
/** @} */
/**
* Callback actions
* @ingroup cb
*/
enum nl_cb_action {
/** Proceed with wathever would come next */
NL_OK,
/** Skip this message */
NL_SKIP,
/** Stop parsing altogether and discard remaining messages */
NL_STOP,
};
/**
* Callback kinds
* @ingroup cb
*/
enum nl_cb_kind {
/** Default handlers (quiet) */
NL_CB_DEFAULT,
/** Verbose default handlers (error messages printed) */
NL_CB_VERBOSE,
/** Debug handlers for debugging */
NL_CB_DEBUG,
/** Customized handler specified by the user */
NL_CB_CUSTOM,
__NL_CB_KIND_MAX,
};
#define NL_CB_KIND_MAX (__NL_CB_KIND_MAX - 1)
/**
* Callback types
* @ingroup cb
*/
enum nl_cb_type {
/** Message is valid */
NL_CB_VALID,
/** Last message in a series of multi part messages received */
NL_CB_FINISH,
/** Report received that data was lost */
NL_CB_OVERRUN,
/** Message wants to be skipped */
NL_CB_SKIPPED,
/** Message is an acknowledge */
NL_CB_ACK,
/** Called for every message received */
NL_CB_MSG_IN,
/** Called for every message sent out except for nl_sendto() */
NL_CB_MSG_OUT,
/** Message is malformed and invalid */
NL_CB_INVALID,
/** Called instead of internal sequence number checking */
NL_CB_SEQ_CHECK,
/** Sending of an acknowledge message has been requested */
NL_CB_SEND_ACK,
__NL_CB_TYPE_MAX,
};
#define NL_CB_TYPE_MAX (__NL_CB_TYPE_MAX - 1)
struct nl_cb
{
nl_recvmsg_msg_cb_t cb_set[NL_CB_TYPE_MAX+1];
void * cb_args[NL_CB_TYPE_MAX+1];
nl_recvmsg_err_cb_t cb_err;
void * cb_err_arg;
/** May be used to replace nl_recvmsgs with your own implementation
* in all internal calls to nl_recvmsgs. */
int (*cb_recvmsgs_ow)(struct nl_sock *,
struct nl_cb *);
/** Overwrite internal calls to nl_recv, must return the number of
* octets read and allocate a buffer for the received data. */
int (*cb_recv_ow)(struct nl_sock *,
struct sockaddr_nl *,
unsigned char **,
struct ucred **);
/** Overwrites internal calls to nl_send, must send the netlink
* message. */
int (*cb_send_ow)(struct nl_sock *,
struct nl_msg *);
int cb_refcnt;
};
extern struct nl_cb * nl_cb_alloc(enum nl_cb_kind);
extern struct nl_cb * nl_cb_clone(struct nl_cb *);
extern void nl_cb_put(struct nl_cb *);
extern int nl_cb_set(struct nl_cb *, enum nl_cb_type, enum nl_cb_kind,
nl_recvmsg_msg_cb_t, void *);
extern int nl_cb_err(struct nl_cb *, enum nl_cb_kind, nl_recvmsg_err_cb_t,
void *);
static inline struct nl_cb *nl_cb_get(struct nl_cb *cb)
{
cb->cb_refcnt++;
return cb;
}
/**
* Set up a all callbacks
* @arg cb callback set
* @arg kind kind of callback
* @arg func callback function
* @arg arg argument to be passwd to callback function
*
* @return 0 on success or a negative error code
*/
static inline int nl_cb_set_all(struct nl_cb *cb, enum nl_cb_kind kind,
nl_recvmsg_msg_cb_t func, void *arg)
{
int i, err;
for (i = 0; i <= NL_CB_TYPE_MAX; i++) {
err = nl_cb_set(cb, i, kind, func, arg);
if (err < 0)
return err;
}
return 0;
}
/**
* @name Overwriting
* @{
*/
/**
* Overwrite internal calls to nl_recvmsgs()
* @arg cb callback set
* @arg func replacement callback for nl_recvmsgs()
*/
static inline void nl_cb_overwrite_recvmsgs(struct nl_cb *cb,
int (*func)(struct nl_sock *, struct nl_cb *))
{
cb->cb_recvmsgs_ow = func;
}
/**
* Overwrite internal calls to nl_recv()
* @arg cb callback set
* @arg func replacement callback for nl_recv()
*/
static inline void nl_cb_overwrite_recv(struct nl_cb *cb,
int (*func)(struct nl_sock *, struct sockaddr_nl *,
unsigned char **, struct ucred **))
{
cb->cb_recv_ow = func;
}
/**
* Overwrite internal calls to nl_send()
* @arg cb callback set
* @arg func replacement callback for nl_send()
*/
static inline void nl_cb_overwrite_send(struct nl_cb *cb,
int (*func)(struct nl_sock *, struct nl_msg *))
{
cb->cb_send_ow = func;
}
/** @} */
#ifdef __cplusplus
}
#endif
#endif
|