refresh patches before applying upcoming fix
[openwrt/svn-archive/archive.git] / ipv6 / send / patches / 001-libnetfilter_queue_update.patch
1 # Update sendd to:
2 #
3 # - use $DESTDIR for prefix (Debian interest)
4 # - use libnetfilter_queue instead of deprecated libipq
5 #
6 # Under GPLv2 - Copyright (C) 2008 - EADS - Arnaud Ebalard <arno@natisbad.org>
7 --- a/Makefile.config
8 +++ b/Makefile.config
9 @@ -19,7 +19,7 @@ OS=linux
10 #CC=gcc-4.0
11
12 # Where to install
13 -prefix=/usr
14 +prefix=$(DESTDIR)/usr
15
16 # Set to "y" to build MT versions of sendd and cgatool
17 USE_THREADS=n
18 --- a/README
19 +++ b/README
20 @@ -20,7 +20,7 @@ Linux:
21 o CONFIG_NETFILTER, CONFIG_IPV6, CONFIG_IP6_NF_QUEUE, CONFIG_IP6_NF_IPTABLES,
22 CONFIG_IP6_NF_FILTER enabled in your kernel config.
23 o netfilter ip6tables command
24 - o netfilter libipq development library and headers
25 + o netfilter libnetfilter_queue development library and headers
26
27 FreeBSD:
28 o NETGRAPH, NETGRAPH_BPF, NETGRAPH_ETHER, NETGRAPH_SOCKET enabled in
29 --- a/cgatool/Makefile
30 +++ b/cgatool/Makefile
31 @@ -25,7 +25,7 @@ endif
32
33 ifeq ($(USE_CONSOLE),y)
34 ifeq ($(USE_READLINE),y)
35 -LDLIBS += -lreadline -lncurses
36 +LDLIBS += -lreadline
37 endif
38 endif
39
40 --- a/sendd/Makefile
41 +++ b/sendd/Makefile
42 @@ -37,7 +37,7 @@ endif
43
44 ifeq ($(USE_CONSOLE),y)
45 ifeq ($(USE_READLINE),y)
46 -LDLIBS += -lreadline -lncurses
47 +LDLIBS += -lreadline
48 endif
49 endif
50
51 --- a/sendd/os-linux/Makefile
52 +++ b/sendd/os-linux/Makefile
53 @@ -1,23 +1,5 @@
54
55 OBJS += os/addr.o os/ipq.o os/rand.o os/snd_linux.o
56 -OSLIBS= -ldl -lipq
57 +OSLIBS= -lnetfilter_queue
58
59 -OSEXTRA= os/sendd os/snd_upd_fw
60 -
61 -ETCINIT= /etc/init.d
62 -EXTRAINSTALL= $(ETCINIT)/sendd $(ETCINIT)/snd_upd_fw $(ETCINIT)/snd_fw_functions.sh
63 -EXTRAUNINSTALL=$(EXTRAINSTALL)
64 -EXTRACLEAN= os/sendd os/snd_upd_fw os/snd_fw_functions.sh
65 -
66 -$(ETCINIT)/%: os/%
67 - install $< $@
68 -
69 -os/%: os/%.in
70 - sed "s/@etcinit@/\/etc\/init.d/g" $< > $@
71 -
72 -os/%: os/%.in2
73 - @./os/find_ip6tables.sh
74 -
75 -# Sometimes libipq.h is installed in include/libipq.h, other times it is
76 -# installed in include/libipq/libipq.h. This rule helps cpp to find it.
77 -os/ipq.o: CPPFLAGS += -I/usr/include/libipq -I/usr/local/include/libipq
78 +os/ipq.o: CPPFLAGS += -I/usr/include/libnetfilter_queue
79 --- a/sendd/os-linux/ipq.c
80 +++ b/sendd/os-linux/ipq.c
81 @@ -33,7 +33,7 @@
82 #include <sys/select.h>
83 #include <netinet/in.h>
84 #include <linux/netfilter.h>
85 -#include <libipq.h>
86 +#include <libnetfilter_queue.h>
87
88 #include "config.h"
89 #include <applog.h>
90 @@ -42,122 +42,170 @@
91 #include "../sendd_local.h"
92 #include "snd_linux.h"
93
94 -static struct ipq_handle *qh;
95 -
96 extern unsigned if_nametoindex(const char *);
97
98 -static inline void
99 -process_pkt(ipq_packet_msg_t *pkt, struct sbuff *b)
100 -{
101 +struct nfq_handle *h = NULL;
102 +struct nfq_q_handle *qh = NULL;
103 +
104 +/* This is the default queue number used in our init script */
105 +#define SND_DEFAULT_NFQUEUE_NUMBER 13
106 +
107 +/* The sbuff is must be made available to the callback function that will
108 + handle the packet */
109 +struct callback_data {
110 + struct sbuff *b;
111 +};
112 +
113 +struct callback_data process_pkt_data;
114 +
115 +/* nfqueue callback */
116 +static int process_pkt(struct nfq_q_handle *qh, struct nfgenmsg *nfmsg,
117 + struct nfq_data *nfa, void *data)
118 +{
119 + struct callback_data * d = (struct callback_data *)data;
120 + struct nfqnl_msg_packet_hdr *ph;
121 + struct sbuff *b = d->b;
122 + char *pkt_data;
123 int in, ifidx;
124
125 - b->data = pkt->payload;
126 - b->len = pkt->data_len;
127 + b->len = nfq_get_payload(nfa, &pkt_data);
128 + if (b->len == -1) {
129 + applog(LOG_ERR, "%s: nfq_get_payload() failed.", __FUNCTION__);
130 + return 0;
131 + }
132 + b->data = (unsigned char *)pkt_data;
133
134 - if (*(pkt->indev_name)) {
135 + if ((ifidx = nfq_get_indev(nfa)) && ifidx != 0)
136 in = 1;
137 - ifidx = if_nametoindex(pkt->indev_name);
138 - } else if (*(pkt->outdev_name)) {
139 + else if ((ifidx = nfq_get_outdev(nfa)) && ifidx != 0)
140 in = 0;
141 - ifidx = if_nametoindex(pkt->outdev_name);
142 - } else {
143 + else {
144 applog(LOG_ERR, "%s: pkt has neither indev nor outdev",
145 __FUNCTION__);
146 snd_put_buf(b);
147 - return;
148 + return 0;
149 }
150
151 - snd_recv_pkt(b, ifidx, in, pkt);
152 -}
153 + /* Grab packet header to get its id later */
154 + ph = nfq_get_msg_packet_hdr(nfa); /* FIXME Check return value */
155
156 -static void
157 -ipq_recv_pkt(void)
158 -{
159 - int r;
160 - struct sbuff *b = snd_get_buf();
161 + snd_recv_pkt(b, ifidx, in, (void *)ph);
162
163 - if (b == NULL) {
164 - return;
165 - }
166 - if ((r = ipq_read(qh, b->head, b->rem, -1)) < 0) {
167 - applog(LOG_ERR, "%s: ipq_read(): %s", __FUNCTION__,
168 - ipq_errstr());
169 - goto fail;
170 - } else if (r == 0) {
171 - /* timeout */
172 - goto fail;
173 - }
174 -
175 - switch ((r = ipq_message_type(b->head))) {
176 - case NLMSG_ERROR:
177 - applog(LOG_ERR, "%s: nlmsg error: %s", __FUNCTION__,
178 - strerror(ipq_get_msgerr(b->head)));
179 - goto fail;
180 - case IPQM_PACKET:
181 - process_pkt(ipq_get_packet(b->head), b);
182 - return;
183 - default:
184 - break;
185 - }
186 -
187 -fail:
188 - snd_put_buf(b);
189 + return 1;
190 }
191
192 void
193 -linux_ipq_add_fds(fd_set *fds, int *maxfd)
194 +linux_nfq_add_fds(fd_set *fds, int *maxfd)
195 {
196 - FD_SET(qh->fd, fds);
197 - *maxfd = sendd_max(*maxfd, qh->fd);
198 + int fd = nfnl_fd(nfq_nfnlh(h));
199 +
200 + FD_SET(fd, fds);
201 + *maxfd = sendd_max(*maxfd, fd);
202 }
203
204 void
205 -linux_ipq_dispatch_fds(fd_set *fds)
206 +linux_nfq_dispatch_fds(fd_set *fds)
207 {
208 - if (FD_ISSET(qh->fd, fds)) {
209 - ipq_recv_pkt();
210 + int fd = nfnl_fd(nfq_nfnlh(h));
211 + int r;
212 +
213 + if (FD_ISSET(fd, fds)) {
214 + struct sbuff *b = snd_get_buf();
215 +
216 + if (b == NULL) {
217 + return;
218 + }
219 +
220 + if ((r = recv(fd, b->head, b->rem, 0)) && r <= 0) {
221 + if (r < 0) /* not a timeout */
222 + applog(LOG_ERR, "%s: recv failed.",
223 + __FUNCTION__);
224 + snd_put_buf(b);
225 + return;
226 + }
227 +
228 + process_pkt_data.b = b; /* make sbuff available to
229 + callback function */
230 + nfq_handle_packet(h, (char *)b->head, r);
231 }
232 }
233
234 void
235 os_specific_deliver_pkt(void *p, struct sbuff *b, int drop, int changed)
236 {
237 - ipq_packet_msg_t *pkt = p;
238 - void *newpkt = NULL;
239 + struct nfqnl_msg_packet_hdr *ph = (struct nfqnl_msg_packet_hdr *)p;
240 + unsigned char *newpkt = NULL;
241 int plen = 0;
242 + uint32_t id = 0;
243 +
244 + if (ph)
245 + id = ntohl(ph->packet_id);
246
247 if (changed && !drop) {
248 - newpkt = sbuff_data(b);
249 + newpkt = (unsigned char *)b->data;
250 plen = b->len;
251 }
252
253 - ipq_set_verdict(qh, pkt->packet_id, drop ? NF_DROP : NF_ACCEPT,
254 - plen, newpkt);
255 + nfq_set_verdict(qh, id, drop ? NF_DROP : NF_ACCEPT, plen, newpkt);
256 snd_put_buf(b);
257 }
258
259 int
260 -linux_ipq_init(void)
261 +linux_nfq_init(void)
262 {
263 - if ((qh = ipq_create_handle(0, PF_INET6)) == NULL) {
264 - applog(LOG_ERR, "%s: ipq_create_handle() failed: %s",
265 - __FUNCTION__, ipq_errstr());
266 - return (-1);
267 - }
268 - if (ipq_set_mode(qh, IPQ_COPY_PACKET, SND_MAX_PKT) < 0) {
269 - applog(LOG_ERR, "%s: ipq_set_mode() failed: %s",
270 - __FUNCTION__, ipq_errstr());
271 - if (errno == ECONNREFUSED) {
272 - applog(LOG_ERR, "%s: perhaps you need to modprobe "
273 - "ip6_queue?", __FUNCTION__);
274 - }
275 - return (-1);
276 + struct nfnl_handle *nh;
277 + u_int16_t nfqueue_num = SND_DEFAULT_NFQUEUE_NUMBER;
278 +
279 + /* Get netfilter queue connection handle */
280 + h = nfq_open();
281 + if (!h) {
282 + applog(LOG_ERR, "%s: nfq_open() failed.", __FUNCTION__);
283 + return -1;
284 + }
285 +
286 + /* Unbinding existing nfqueue handlers for AF_INET6. We ignore the
287 + return value: http://www.spinics.net/lists/netfilter/msg42063.html.
288 + Note that this call is required, otherwise, nfq_bind_pf() fails. */
289 + nfq_unbind_pf(h, PF_INET6);
290 +
291 + if (nfq_bind_pf(h, PF_INET6) < 0) {
292 + applog(LOG_ERR, "%s: nfq_bind_pf failed.\n", __FUNCTION__);
293 + return -1;
294 + }
295 +
296 + /* Binding this socket to queue number nfqueue_num and installing
297 + our packet handler */
298 + qh = nfq_create_queue(h, nfqueue_num,
299 + (nfq_callback *) &process_pkt,
300 + (void *)&process_pkt_data);
301 + if (!qh) {
302 + applog(LOG_ERR, "%s: nfq_create_queue() failed.\n",
303 + __FUNCTION__);
304 + return -1;
305 + }
306 +
307 + /* Asking for entire copy of queued packets */
308 + if (nfq_set_mode(qh, NFQNL_COPY_PACKET, 0xffff) < 0) { /* XXX was SND_MAX_PKT */
309 + fprintf(stderr, "nfq_set_mode() failed.\n");
310 + return -1;
311 }
312 - return (0);
313 +
314 + /* XXX - Check if we have an interest in setting queue length */
315 +
316 + /* The netlink handle associated with our queue connection handle */
317 + nh = nfq_nfnlh(h);
318 +
319 + return 0;
320 }
321
322 void
323 -linux_ipq_fini(void)
324 +linux_nfq_fini(void)
325 {
326 - ipq_destroy_handle(qh);
327 + /* Remove the binding for our queue handler*/
328 + if (qh != NULL)
329 + nfq_destroy_queue(qh);
330 +
331 + /* Close connection associated with our connection handler */
332 + if (h != NULL)
333 + nfq_close(h);
334 }
335 --- a/sendd/os-linux/snd_linux.c
336 +++ b/sendd/os-linux/snd_linux.c
337 @@ -40,13 +40,13 @@
338 void
339 os_specific_add_fds(fd_set *fds, int *maxfd)
340 {
341 - linux_ipq_add_fds(fds, maxfd);
342 + linux_nfq_add_fds(fds, maxfd);
343 }
344
345 void
346 os_specific_dispatch_fds(fd_set *fds)
347 {
348 - linux_ipq_dispatch_fds(fds);
349 + linux_nfq_dispatch_fds(fds);
350 }
351
352 int
353 @@ -59,7 +59,7 @@ int
354 os_specific_init(void)
355 {
356 if (linux_rand_init() < 0 ||
357 - linux_ipq_init() < 0) {
358 + linux_nfq_init() < 0) {
359 return (-1);
360 }
361 return (0);
362 @@ -68,6 +68,6 @@ os_specific_init(void)
363 void
364 os_specific_fini(void)
365 {
366 - linux_ipq_fini();
367 + linux_nfq_fini();
368 linux_rand_fini();
369 }
370 --- a/sendd/os-linux/snd_linux.h
371 +++ b/sendd/os-linux/snd_linux.h
372 @@ -33,10 +33,10 @@
373 #ifndef _SEND_LINUX_H
374 #define _SEND_LINUX_H
375
376 -extern void linux_ipq_add_fds(fd_set *, int *);
377 -extern void linux_ipq_dispatch_fds(fd_set *);
378 -extern int linux_ipq_init(void);
379 -extern void linux_ipq_fini(void);
380 +extern void linux_nfq_add_fds(fd_set *, int *);
381 +extern void linux_nfq_dispatch_fds(fd_set *);
382 +extern int linux_nfq_init(void);
383 +extern void linux_nfq_fini(void);
384
385 extern void linux_rand_fini(void);
386 extern int linux_rand_init(void);