summaryrefslogtreecommitdiffstats
path: root/include/libnfnetlink/libnfnetlink.h
blob: 5776da61bf883d843698383ef23d3af6d024da64 (plain)
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
/* libnfnetlink.h: Header file for generic netfilter netlink interface
 *
 * (C) 2002 Harald Welte <laforge@gnumonks.org>
 *
 * 2005-10-29 Pablo Neira Ayuso <pablo@netfilter.org>:
 * 	Fix NFNL_HEADER_LEN
 * 2005-11-13 Pablo Neira Ayuso <pablo@netfilter.org>:
 * 	Define NETLINK_NETFILTER if it's undefined
 */

#ifndef __LIBNFNETLINK_H
#define __LIBNFNETLINK_H

#ifndef aligned_u64
#define aligned_u64 unsigned long long __attribute__((aligned(8)))
#endif

#include <sys/socket.h>	/* for sa_family_t */
#include <linux/netlink.h>
#include <libnfnetlink/linux_nfnetlink.h>

#ifndef NETLINK_NETFILTER
#define NETLINK_NETFILTER 12
#endif

#define NLMSG_TAIL(nlh) \
	(((void *) (nlh)) + NLMSG_ALIGN((nlh)->nlmsg_len))

#define NFNL_HEADER_LEN	(NLMSG_ALIGN(sizeof(struct nlmsghdr))	\
			 +NLMSG_ALIGN(sizeof(struct nfgenmsg)))

#define NFNL_BUFFSIZE		8192

struct nfnlhdr {
	struct nlmsghdr nlh;
	struct nfgenmsg nfmsg;
};

struct nfnl_callback {
	int (*call)(struct nlmsghdr *nlh, struct nfattr *nfa[], void *data);
	void *data;
	u_int16_t attr_count;
};

struct nfnl_handle;
struct nfnl_subsys_handle;

extern int nfnl_fd(struct nfnl_handle *h);

/* get a new library handle */
extern struct nfnl_handle *nfnl_open(void);
extern int nfnl_close(struct nfnl_handle *);

extern struct nfnl_subsys_handle *nfnl_subsys_open(struct nfnl_handle *, 
						   u_int8_t, u_int8_t, 
						   unsigned int);
extern void nfnl_subsys_close(struct nfnl_subsys_handle *);

/* set receive buffer size (for nfnl_catch) */
extern void nfnl_set_rcv_buffer_size(struct nfnl_handle *h, unsigned int size);

/* sending of data */
extern int nfnl_send(struct nfnl_handle *, struct nlmsghdr *);
extern int nfnl_sendmsg(const struct nfnl_handle *, const struct msghdr *msg,
			unsigned int flags);
extern int nfnl_sendiov(const struct nfnl_handle *nfnlh,
			const struct iovec *iov, unsigned int num,
			unsigned int flags);
extern void nfnl_fill_hdr(struct nfnl_subsys_handle *, struct nlmsghdr *,
			  unsigned int, u_int8_t, u_int16_t, u_int16_t,
			  u_int16_t);
extern int nfnl_talk(struct nfnl_handle *, struct nlmsghdr *, pid_t,
                     unsigned, struct nlmsghdr *,
                     int (*)(struct sockaddr_nl *, struct nlmsghdr *, void *),
                     void *);

/* simple challenge/response */
extern int nfnl_listen(struct nfnl_handle *,
                      int (*)(struct sockaddr_nl *, struct nlmsghdr *, void *),
                      void *);

/* receiving */
extern ssize_t nfnl_recv(const struct nfnl_handle *h, unsigned char *buf, size_t len);
extern int nfnl_callback_register(struct nfnl_subsys_handle *,
				  u_int8_t type, struct nfnl_callback *cb);
extern int nfnl_callback_unregister(struct nfnl_subsys_handle *, u_int8_t type);
extern int nfnl_handle_packet(struct nfnl_handle *, char *buf, int len);

/* parsing */
extern struct nfattr *nfnl_parse_hdr(const struct nfnl_handle *nfnlh, 
				     const struct nlmsghdr *nlh,
				     struct nfgenmsg **genmsg);
extern int nfnl_check_attributes(const struct nfnl_handle *nfnlh,
				 const struct nlmsghdr *nlh,
				 struct nfattr *tb[]);
extern struct nlmsghdr *nfnl_get_msg_first(struct nfnl_handle *h,
					   const unsigned char *buf,
					   size_t len);
extern struct nlmsghdr *nfnl_get_msg_next(struct nfnl_handle *h,
					  const unsigned char *buf,
					  size_t len);

/* callback verdict */
enum {
	NFNL_CB_FAILURE = -1,   /* failure */
	NFNL_CB_STOP = 0,       /* stop the query */
	NFNL_CB_CONTINUE = 1,   /* keep iterating */
};

/* join a certain netlink multicast group */
extern int nfnl_join(const struct nfnl_handle *nfnlh, unsigned int group);

/* process a netlink message */
extern int nfnl_process(struct nfnl_handle *h,
			const unsigned char *buf,
			size_t len);

/* iterator API */

extern struct nfnl_iterator *
nfnl_iterator_create(const struct nfnl_handle *h,
		     const char *buf,
		     size_t len);

extern void nfnl_iterator_destroy(struct nfnl_iterator *it);

extern int nfnl_iterator_process(struct nfnl_handle *h,
				 struct nfnl_iterator *it);

extern int nfnl_iterator_next(const struct nfnl_handle *h,
			      struct nfnl_iterator *it);

/* replacement for nfnl_listen */
extern int nfnl_catch(struct nfnl_handle *h);

/* replacement for nfnl_talk */
extern int nfnl_query(struct nfnl_handle *h, struct nlmsghdr *nlh);

#define nfnl_attr_present(tb, attr)			\
	(tb[attr-1])

#define nfnl_get_data(tb, attr, type)			\
	({	type __ret = 0;				\
	 if (tb[attr-1])				\
	 __ret = *(type *)NFA_DATA(tb[attr-1]);		\
	 __ret;						\
	 })

#define nfnl_get_pointer_to_data(tb, attr, type)	\
	({	type *__ret = NULL;			\
	 if (tb[attr-1])				\
	 __ret = NFA_DATA(tb[attr-1]);			\
	 __ret;						\
	 })

/* nfnl attribute handling functions */
extern int nfnl_addattr_l(struct nlmsghdr *, int, int, const void *, int);
extern int nfnl_addattr16(struct nlmsghdr *, int, int, u_int16_t);
extern int nfnl_addattr32(struct nlmsghdr *, int, int, u_int32_t);
extern int nfnl_nfa_addattr_l(struct nfattr *, int, int, const void *, int);
extern int nfnl_nfa_addattr16(struct nfattr *, int, int, u_int16_t);
extern int nfnl_nfa_addattr32(struct nfattr *, int, int, u_int32_t);
extern int nfnl_parse_attr(struct nfattr **, int, struct nfattr *, int);
#define nfnl_parse_nested(tb, max, nfa) \
	nfnl_parse_attr((tb), (max), NFA_DATA((nfa)), NFA_PAYLOAD((nfa)))
#define nfnl_nest(nlh, bufsize, type) 				\
({	struct nfattr *__start = NLMSG_TAIL(nlh);		\
	nfnl_addattr_l(nlh, bufsize, type, NULL, 0); 	\
	__start; })
#define nfnl_nest_end(nlh, tail) 				\
({	(tail)->nfa_len = (void *) NLMSG_TAIL(nlh) - (void *) tail; })

extern void nfnl_build_nfa_iovec(struct iovec *iov, struct nfattr *nfa, 
				 u_int16_t type, u_int32_t len,
				 unsigned char *val);
extern unsigned int nfnl_rcvbufsiz(const struct nfnl_handle *h, 
				   unsigned int size);


extern void nfnl_dump_packet(struct nlmsghdr *, int, char *);

/*
 * index to interface name API
 */

#ifndef IFNAMSIZ
#define IFNAMSIZ 16
#endif

struct nlif_handle;

struct nlif_handle *nlif_open(void);
void nlif_close(struct nlif_handle *orig);
int nlif_fd(struct nlif_handle *nlif_handle);
int nlif_query(struct nlif_handle *nlif_handle);
int nlif_catch(struct nlif_handle *nlif_handle);
int nlif_index2name(struct nlif_handle *nlif_handle, 
		    unsigned int if_index, 
		    char *name);

/* Pablo: What is the equivalence of be64_to_cpu in userspace?
 * 
 * Harald: Good question.  I don't think there's a standard way [yet?], 
 * so I'd suggest manually implementing it by "#if little endian" bitshift
 * operations in C (at least for now).
 *
 * All the payload of any nfattr will always be in network byte order.
 * This would allow easy transport over a real network in the future 
 * (e.g. jamal's netlink2).
 *
 * Pablo: I've called it __be64_to_cpu instead of be64_to_cpu, since maybe 
 * there will one in the userspace headers someday. We don't want to
 * pollute POSIX space naming,
 */

#include <byteswap.h>
#if __BYTE_ORDER == __BIG_ENDIAN
#  define __be64_to_cpu(x)	(x)
# else
# if __BYTE_ORDER == __LITTLE_ENDIAN
#  define __be64_to_cpu(x)	__bswap_64(x)
# endif
#endif

#endif /* __LIBNFNETLINK_H */