fix sendd
[packages.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 @@ -32,8 +32,9 @@
82  
83  #include <sys/select.h>
84  #include <netinet/in.h>
85 +#include <linux/types.h>
86  #include <linux/netfilter.h>
87 -#include <libipq.h>
88 +#include <libnetfilter_queue.h>
89  
90  #include "config.h"
91  #include <applog.h>
92 @@ -42,122 +43,170 @@
93  #include "../sendd_local.h"
94  #include "snd_linux.h"
95  
96 -static struct ipq_handle *qh;
97 -
98  extern unsigned if_nametoindex(const char *);
99  
100 -static inline void
101 -process_pkt(ipq_packet_msg_t *pkt, struct sbuff *b)
102 -{
103 +struct nfq_handle *h = NULL;
104 +struct nfq_q_handle *qh = NULL;
105 +
106 +/* This is the default queue number used in our init script */
107 +#define SND_DEFAULT_NFQUEUE_NUMBER 13
108 +
109 +/* The sbuff is must be made available to the callback function that will
110 +   handle the packet */
111 +struct callback_data {
112 +       struct sbuff *b;
113 +};
114 +
115 +struct callback_data process_pkt_data;
116 +
117 +/* nfqueue callback */
118 +static int process_pkt(struct nfq_q_handle *qh, struct nfgenmsg *nfmsg,
119 +                      struct nfq_data *nfa, void *data)
120 +{
121 +       struct callback_data * d = (struct callback_data *)data;
122 +       struct nfqnl_msg_packet_hdr *ph;
123 +       struct sbuff *b = d->b;
124 +       char *pkt_data;
125         int in, ifidx;
126  
127 -       b->data = pkt->payload;
128 -       b->len = pkt->data_len;
129 +       b->len = nfq_get_payload(nfa, &pkt_data);
130 +       if (b->len == -1) {
131 +               applog(LOG_ERR, "%s: nfq_get_payload() failed.", __FUNCTION__);
132 +               return 0;
133 +       }
134 +       b->data = (unsigned char *)pkt_data;
135  
136 -       if (*(pkt->indev_name)) {
137 +       if ((ifidx = nfq_get_indev(nfa)) && ifidx != 0)
138                 in = 1;
139 -               ifidx = if_nametoindex(pkt->indev_name);
140 -       } else if (*(pkt->outdev_name)) {
141 +       else if ((ifidx = nfq_get_outdev(nfa)) && ifidx != 0)
142                 in = 0;
143 -               ifidx = if_nametoindex(pkt->outdev_name);
144 -       } else {
145 +       else {
146                 applog(LOG_ERR, "%s: pkt has neither indev nor outdev",
147                        __FUNCTION__);
148                 snd_put_buf(b);
149 -               return;
150 +               return 0;
151         }
152  
153 -       snd_recv_pkt(b, ifidx, in, pkt);
154 -}
155 +       /* Grab packet header to get its id later */
156 +       ph = nfq_get_msg_packet_hdr(nfa); /* FIXME Check return value */
157  
158 -static void
159 -ipq_recv_pkt(void)
160 -{
161 -       int r;
162 -       struct sbuff *b = snd_get_buf();
163 +       snd_recv_pkt(b, ifidx, in, (void *)ph);
164  
165 -       if (b == NULL) {
166 -               return;
167 -       }
168 -       if ((r = ipq_read(qh, b->head, b->rem, -1)) < 0) {
169 -               applog(LOG_ERR, "%s: ipq_read(): %s", __FUNCTION__,
170 -                      ipq_errstr());
171 -               goto fail;
172 -       } else if (r == 0) {
173 -               /* timeout */
174 -               goto fail;
175 -       }
176 -
177 -       switch ((r = ipq_message_type(b->head))) {
178 -       case NLMSG_ERROR:
179 -               applog(LOG_ERR, "%s: nlmsg error: %s", __FUNCTION__,
180 -                      strerror(ipq_get_msgerr(b->head)));
181 -               goto fail;
182 -       case IPQM_PACKET:
183 -               process_pkt(ipq_get_packet(b->head), b);
184 -               return;
185 -       default:
186 -               break;
187 -       }
188 -
189 -fail:
190 -       snd_put_buf(b);
191 +       return 1;
192  }
193  
194  void
195 -linux_ipq_add_fds(fd_set *fds, int *maxfd)
196 +linux_nfq_add_fds(fd_set *fds, int *maxfd)
197  {
198 -       FD_SET(qh->fd, fds);
199 -       *maxfd = sendd_max(*maxfd, qh->fd);
200 +       int fd = nfnl_fd(nfq_nfnlh(h));
201 +
202 +       FD_SET(fd, fds);
203 +       *maxfd = sendd_max(*maxfd, fd);
204  }
205  
206  void
207 -linux_ipq_dispatch_fds(fd_set *fds)
208 +linux_nfq_dispatch_fds(fd_set *fds)
209  {
210 -       if (FD_ISSET(qh->fd, fds)) {
211 -               ipq_recv_pkt();
212 +       int fd = nfnl_fd(nfq_nfnlh(h));
213 +       int r;
214 +
215 +       if (FD_ISSET(fd, fds)) {
216 +               struct sbuff *b = snd_get_buf();
217 +
218 +               if (b == NULL) {
219 +                       return;
220 +               }
221 +
222 +               if ((r = recv(fd, b->head, b->rem, 0)) && r <= 0) {
223 +                       if (r < 0) /* not a timeout */
224 +                               applog(LOG_ERR, "%s: recv failed.",
225 +                                      __FUNCTION__);
226 +                       snd_put_buf(b);
227 +                       return;
228 +               }
229 +
230 +               process_pkt_data.b = b; /* make sbuff available to
231 +                                          callback function */
232 +               nfq_handle_packet(h, (char *)b->head, r);
233         }
234  }
235  
236  void
237  os_specific_deliver_pkt(void *p, struct sbuff *b, int drop, int changed)
238  {
239 -       ipq_packet_msg_t *pkt = p;
240 -       void *newpkt = NULL;
241 +       struct nfqnl_msg_packet_hdr *ph = (struct nfqnl_msg_packet_hdr *)p;
242 +       unsigned char *newpkt = NULL;
243         int plen = 0;
244 +       uint32_t id = 0;
245 +
246 +       if (ph)
247 +               id = ntohl(ph->packet_id);
248  
249         if (changed && !drop) {
250 -               newpkt = sbuff_data(b);
251 +               newpkt = (unsigned char *)b->data;
252                 plen = b->len;
253         }
254  
255 -       ipq_set_verdict(qh, pkt->packet_id, drop ? NF_DROP : NF_ACCEPT,
256 -                       plen, newpkt);
257 +       nfq_set_verdict(qh, id, drop ? NF_DROP : NF_ACCEPT, plen, newpkt);
258         snd_put_buf(b);
259  }
260  
261  int
262 -linux_ipq_init(void)
263 +linux_nfq_init(void)
264  {
265 -       if ((qh = ipq_create_handle(0, PF_INET6)) == NULL) {
266 -               applog(LOG_ERR, "%s: ipq_create_handle() failed: %s",
267 -                      __FUNCTION__, ipq_errstr());
268 -               return (-1);
269 -       }
270 -       if (ipq_set_mode(qh, IPQ_COPY_PACKET, SND_MAX_PKT) < 0) {
271 -               applog(LOG_ERR, "%s: ipq_set_mode() failed: %s",
272 -                      __FUNCTION__, ipq_errstr());
273 -               if (errno == ECONNREFUSED) {
274 -                       applog(LOG_ERR, "%s: perhaps you need to modprobe "
275 -                              "ip6_queue?", __FUNCTION__);
276 -               }
277 -               return (-1);
278 +       struct nfnl_handle *nh;
279 +       u_int16_t nfqueue_num = SND_DEFAULT_NFQUEUE_NUMBER;
280 +
281 +       /* Get netfilter queue connection handle */
282 +       h = nfq_open();
283 +       if (!h) {
284 +               applog(LOG_ERR, "%s: nfq_open() failed.", __FUNCTION__);
285 +               return -1;
286 +       }
287 +
288 +       /* Unbinding existing nfqueue handlers for AF_INET6. We ignore the
289 +          return value: http://www.spinics.net/lists/netfilter/msg42063.html.
290 +          Note that this call is required, otherwise, nfq_bind_pf() fails. */
291 +       nfq_unbind_pf(h, PF_INET6);
292 +
293 +       if (nfq_bind_pf(h, PF_INET6) < 0) {
294 +               applog(LOG_ERR, "%s: nfq_bind_pf failed.\n", __FUNCTION__);
295 +               return -1;
296 +       }
297 +
298 +       /* Binding this socket to queue number nfqueue_num and installing
299 +          our packet handler */
300 +       qh = nfq_create_queue(h, nfqueue_num,
301 +                             (nfq_callback *) &process_pkt,
302 +                             (void *)&process_pkt_data);
303 +       if (!qh) {
304 +               applog(LOG_ERR, "%s: nfq_create_queue() failed.\n",
305 +                      __FUNCTION__);
306 +               return -1;
307 +       }
308 +
309 +       /* Asking for entire copy of queued packets */
310 +       if (nfq_set_mode(qh, NFQNL_COPY_PACKET, 0xffff) < 0) { /* XXX was SND_MAX_PKT */
311 +               fprintf(stderr, "nfq_set_mode() failed.\n");
312 +               return -1;
313         }
314 -       return (0);
315 +
316 +       /* XXX - Check if we have an interest in setting queue length */
317 +
318 +       /* The netlink handle associated with our queue connection handle */
319 +       nh = nfq_nfnlh(h);
320 +
321 +       return 0;
322  }
323  
324  void
325 -linux_ipq_fini(void)
326 +linux_nfq_fini(void)
327  {
328 -       ipq_destroy_handle(qh);
329 +       /* Remove the binding for our queue handler*/
330 +       if (qh != NULL)
331 +               nfq_destroy_queue(qh);
332 +
333 +       /* Close connection associated with our connection handler */
334 +       if (h != NULL)
335 +               nfq_close(h);
336  }
337 --- a/sendd/os-linux/snd_linux.c
338 +++ b/sendd/os-linux/snd_linux.c
339 @@ -40,13 +40,13 @@
340  void
341  os_specific_add_fds(fd_set *fds, int *maxfd)
342  {
343 -       linux_ipq_add_fds(fds, maxfd);
344 +       linux_nfq_add_fds(fds, maxfd);
345  }
346  
347  void
348  os_specific_dispatch_fds(fd_set *fds)
349  {
350 -       linux_ipq_dispatch_fds(fds);
351 +       linux_nfq_dispatch_fds(fds);
352  }
353  
354  int
355 @@ -59,7 +59,7 @@ int
356  os_specific_init(void)
357  {
358         if (linux_rand_init() < 0 ||
359 -           linux_ipq_init() < 0) {
360 +           linux_nfq_init() < 0) {
361                 return (-1);
362         }
363         return (0);
364 @@ -68,6 +68,6 @@ os_specific_init(void)
365  void
366  os_specific_fini(void)
367  {
368 -       linux_ipq_fini();
369 +       linux_nfq_fini();
370         linux_rand_fini();
371  }
372 --- a/sendd/os-linux/snd_linux.h
373 +++ b/sendd/os-linux/snd_linux.h
374 @@ -33,10 +33,10 @@
375  #ifndef        _SEND_LINUX_H
376  #define        _SEND_LINUX_H
377  
378 -extern void linux_ipq_add_fds(fd_set *, int *);
379 -extern void linux_ipq_dispatch_fds(fd_set *);
380 -extern int linux_ipq_init(void);
381 -extern void linux_ipq_fini(void);
382 +extern void linux_nfq_add_fds(fd_set *, int *);
383 +extern void linux_nfq_dispatch_fds(fd_set *);
384 +extern int linux_nfq_init(void);
385 +extern void linux_nfq_fini(void);
386  
387  extern void linux_rand_fini(void);
388  extern int linux_rand_init(void);