fix xl2tpd build
[openwrt/svn-archive/packages.git] / net / xl2tpd / patches / 120-kernel-mode-l2tp.patch
1 --- a/Makefile
2 +++ b/Makefile
3 @@ -62,8 +62,8 @@
4 # are packages seperately (eg kernel-headers on Fedora)
5 # Note: 2.6.23+ support still needs some changes in the xl2tpd source
6 #
7 -#OSFLAGS+= -DUSE_KERNEL
8 -#
9 +# Kernel mode fixed by sigwall <fionov@gmail.com>
10 +OSFLAGS+= -DUSE_KERNEL
11 #
12 # Uncomment the next line for FreeBSD
13 #
14 --- a/call.c
15 +++ b/call.c
16 @@ -680,6 +680,8 @@
17 st->peer.sin_port = port;
18 st->refme = refme;
19 st->refhim = refhim;
20 + st->udp_fd = -1;
21 + st->pppox_fd = -1;
22 bcopy (&addr, &st->peer.sin_addr, sizeof (addr));
23 st->next = tunnels.head;
24 tunnels.head = st;
25 --- a/control.c
26 +++ b/control.c
27 @@ -596,6 +596,9 @@
28 if (gconfig.debug_state)
29 l2tp_log (LOG_DEBUG, "%s: sending SCCCN\n", __FUNCTION__);
30 control_xmit (buf);
31 +
32 + connect_pppol2tp(t);
33 +
34 /* Schedule a HELLO */
35 tv.tv_sec = HELLO_DELAY;
36 tv.tv_usec = 0;
37 @@ -608,6 +611,7 @@
38 "Connection established to %s, %d. Local: %d, Remote: %d (ref=%u/%u).\n",
39 IPADDY (t->peer.sin_addr),
40 ntohs (t->peer.sin_port), t->ourtid, t->tid, t->refme, t->refhim);
41 +
42 if (t->lac)
43 {
44 /* This is part of a LAC, so we want to go ahead
45 @@ -635,6 +639,9 @@
46 IPADDY (t->peer.sin_addr),
47 ntohs (t->peer.sin_port), t->ourtid, t->tid, t->refme, t->refhim,
48 t->lns->entname);
49 +
50 + connect_pppol2tp(t);
51 +
52 /* Schedule a HELLO */
53 tv.tv_sec = HELLO_DELAY;
54 tv.tv_usec = 0;
55 --- a/l2tp.h
56 +++ b/l2tp.h
57 @@ -167,6 +167,8 @@
58 int ourrws; /* Receive Window Size */
59 int rxspeed; /* Receive bps */
60 int txspeed; /* Transmit bps */
61 + int udp_fd; /* UDP fd */
62 + int pppox_fd; /* PPPOX tunnel fd */
63 struct call *self;
64 struct lns *lns; /* LNS that owns us */
65 struct lac *lac; /* LAC that owns us */
66 @@ -220,6 +222,7 @@
67 extern int ppd;
68 extern int switch_io; /* jz */
69 extern int control_fd;
70 +extern int connect_pppol2tp(struct tunnel *t);
71 extern int start_pppd (struct call *c, struct ppp_opts *);
72 extern void magic_lac_dial (void *);
73 extern int get_entropy (unsigned char *, int);
74 --- a/linux/include/linux/if_pppol2tp.h
75 +++ b/linux/include/linux/if_pppol2tp.h
76 @@ -2,7 +2,7 @@
77 * Linux PPP over L2TP (PPPoL2TP) Socket Implementation (RFC 2661)
78 *
79 * This file supplies definitions required by the PPP over L2TP driver
80 - * (pppol2tp.c). All version information wrt this file is located in pppol2tp.c
81 + * (l2tp_ppp.c). All version information wrt this file is located in l2tp_ppp.c
82 *
83 * License:
84 * This program is free software; you can redistribute it and/or
85 @@ -15,18 +15,13 @@
86 #ifndef __LINUX_IF_PPPOL2TP_H
87 #define __LINUX_IF_PPPOL2TP_H
88
89 -#include <asm/types.h>
90 -
91 -#ifdef __KERNEL__
92 -#include <linux/in.h>
93 -#endif
94 +#include <linux/types.h>
95
96 /* Structure used to connect() the socket to a particular tunnel UDP
97 - * socket.
98 + * socket over IPv4.
99 */
100 -struct pppol2tp_addr
101 -{
102 - pid_t pid; /* pid that owns the fd.
103 +struct pppol2tp_addr {
104 + __kernel_pid_t pid; /* pid that owns the fd.
105 * 0 => current */
106 int fd; /* FD of UDP socket to use */
107
108 @@ -36,6 +31,45 @@
109 __u16 d_tunnel, d_session; /* For sending outgoing packets */
110 };
111
112 +/* Structure used to connect() the socket to a particular tunnel UDP
113 + * socket over IPv6.
114 + */
115 +struct pppol2tpin6_addr {
116 + __kernel_pid_t pid; /* pid that owns the fd.
117 + * 0 => current */
118 + int fd; /* FD of UDP socket to use */
119 +
120 + __u16 s_tunnel, s_session; /* For matching incoming packets */
121 + __u16 d_tunnel, d_session; /* For sending outgoing packets */
122 +
123 + struct sockaddr_in6 addr; /* IP address and port to send to */
124 +};
125 +
126 +/* The L2TPv3 protocol changes tunnel and session ids from 16 to 32
127 + * bits. So we need a different sockaddr structure.
128 + */
129 +struct pppol2tpv3_addr {
130 + __kernel_pid_t pid; /* pid that owns the fd.
131 + * 0 => current */
132 + int fd; /* FD of UDP or IP socket to use */
133 +
134 + struct sockaddr_in addr; /* IP address and port to send to */
135 +
136 + __u32 s_tunnel, s_session; /* For matching incoming packets */
137 + __u32 d_tunnel, d_session; /* For sending outgoing packets */
138 +};
139 +
140 +struct pppol2tpv3in6_addr {
141 + __kernel_pid_t pid; /* pid that owns the fd.
142 + * 0 => current */
143 + int fd; /* FD of UDP or IP socket to use */
144 +
145 + __u32 s_tunnel, s_session; /* For matching incoming packets */
146 + __u32 d_tunnel, d_session; /* For sending outgoing packets */
147 +
148 + struct sockaddr_in6 addr; /* IP address and port to send to */
149 +};
150 +
151 /* Socket options:
152 * DEBUG - bitmask of debug message categories
153 * SENDSEQ - 0 => don't send packets with sequence numbers
154 @@ -66,4 +100,4 @@
155
156
157
158 -#endif
159 +#endif /* __LINUX_IF_PPPOL2TP_H */
160 --- a/network.c
161 +++ b/network.c
162 @@ -45,6 +45,7 @@
163 server.sin_family = AF_INET;
164 server.sin_addr.s_addr = gconfig.listenaddr;
165 server.sin_port = htons (gconfig.port);
166 + int flags;
167 if ((server_socket = socket (PF_INET, SOCK_DGRAM, 0)) < 0)
168 {
169 l2tp_log (LOG_CRIT, "%s: Unable to allocate socket. Terminating.\n",
170 @@ -52,6 +53,10 @@
171 return -EINVAL;
172 };
173
174 + flags = 1;
175 + setsockopt(server_socket, SOL_SOCKET, SO_REUSEADDR, &flags, sizeof(flags));
176 + setsockopt(server_socket, SOL_SOCKET, SO_NO_CHECK, &flags, sizeof(flags));
177 +
178 if (bind (server_socket, (struct sockaddr *) &server, sizeof (server)))
179 {
180 close (server_socket);
181 @@ -321,6 +326,11 @@
182
183 while (tun)
184 {
185 + if (tun->udp_fd > -1) {
186 + if (tun->udp_fd > max)
187 + max = tun->udp_fd;
188 + FD_SET (tun->udp_fd, readfds);
189 + }
190 call = tun->call_head;
191 while (call)
192 {
193 @@ -390,6 +400,8 @@
194 struct iovec iov;
195 char cbuf[256];
196 unsigned int refme, refhim;
197 + int * currentfd;
198 + int server_socket_processed;
199
200 /* This one buffer can be recycled for everything except control packets */
201 buf = new_buf (MAX_RECV_SIZE);
202 @@ -428,7 +440,21 @@
203 {
204 do_control ();
205 }
206 - if (FD_ISSET (server_socket, &readfds))
207 + server_socket_processed = 0;
208 + currentfd = NULL;
209 + st = tunnels.head;
210 + while (st || !server_socket_processed) {
211 + if (st && (st->udp_fd == -1)) {
212 + st=st->next;
213 + continue;
214 + }
215 + if (st) {
216 + currentfd = &st->udp_fd;
217 + } else {
218 + currentfd = &server_socket;
219 + server_socket_processed = 1;
220 + }
221 + if (FD_ISSET (*currentfd, &readfds))
222 {
223 /*
224 * Okay, now we're ready for reading and processing new data.
225 @@ -457,12 +483,19 @@
226 msgh.msg_flags = 0;
227
228 /* Receive one packet. */
229 - recvsize = recvmsg(server_socket, &msgh, 0);
230 + recvsize = recvmsg(*currentfd, &msgh, 0);
231
232 if (recvsize < MIN_PAYLOAD_HDR_LEN)
233 {
234 if (recvsize < 0)
235 {
236 + if (errno == ECONNREFUSED) {
237 + close(*currentfd);
238 + }
239 + if ((errno == ECONNREFUSED) ||
240 + (errno == EBADF)) {
241 + *currentfd = -1;
242 + }
243 if (errno != EAGAIN)
244 l2tp_log (LOG_WARNING,
245 "%s: recvfrom returned error %d (%s)\n",
246 @@ -567,6 +600,8 @@
247 }
248 };
249 }
250 + if (st) st=st->next;
251 + }
252
253 /*
254 * finished obvious sources, look for data from PPP connections.
255 @@ -639,3 +674,82 @@
256 }
257
258 }
259 +
260 +int connect_pppol2tp(struct tunnel *t) {
261 +#ifdef USE_KERNEL
262 + if (kernel_support) {
263 + int ufd = -1, fd2 = -1;
264 + int flags;
265 + struct sockaddr_pppol2tp sax;
266 +
267 + struct sockaddr_in server;
268 + server.sin_family = AF_INET;
269 + server.sin_addr.s_addr = gconfig.listenaddr;
270 + server.sin_port = htons (gconfig.port);
271 + if ((ufd = socket (PF_INET, SOCK_DGRAM, 0)) < 0)
272 + {
273 + l2tp_log (LOG_CRIT, "%s: Unable to allocate UDP socket. Terminating.\n",
274 + __FUNCTION__);
275 + return -EINVAL;
276 + };
277 +
278 + flags=1;
279 + setsockopt(ufd, SOL_SOCKET, SO_REUSEADDR, &flags, sizeof(flags));
280 + setsockopt(ufd, SOL_SOCKET, SO_NO_CHECK, &flags, sizeof(flags));
281 +
282 + if (bind (ufd, (struct sockaddr *) &server, sizeof (server)))
283 + {
284 + close (ufd);
285 + l2tp_log (LOG_CRIT, "%s: Unable to bind UDP socket: %s. Terminating.\n",
286 + __FUNCTION__, strerror(errno), errno);
287 + return -EINVAL;
288 + };
289 + server = t->peer;
290 + flags = fcntl(ufd, F_GETFL);
291 + if (flags == -1 || fcntl(ufd, F_SETFL, flags | O_NONBLOCK) == -1) {
292 + l2tp_log (LOG_WARNING, "%s: Unable to set UDP socket nonblock.\n",
293 + __FUNCTION__);
294 + return -EINVAL;
295 + }
296 + if (connect (ufd, (struct sockaddr *) &server, sizeof(server)) < 0) {
297 + l2tp_log (LOG_CRIT, "%s: Unable to connect UDP peer. Terminating.\n",
298 + __FUNCTION__);
299 + return -EINVAL;
300 + }
301 +
302 + t->udp_fd=ufd;
303 +
304 + fd2 = socket(AF_PPPOX, SOCK_DGRAM, PX_PROTO_OL2TP);
305 + if (fd2 < 0) {
306 + l2tp_log (LOG_WARNING, "%s: Unable to allocate PPPoL2TP socket.\n",
307 + __FUNCTION__);
308 + return -EINVAL;
309 + }
310 + flags = fcntl(fd2, F_GETFL);
311 + if (flags == -1 || fcntl(fd2, F_SETFL, flags | O_NONBLOCK) == -1) {
312 + l2tp_log (LOG_WARNING, "%s: Unable to set PPPoL2TP socket nonblock.\n",
313 + __FUNCTION__);
314 + return -EINVAL;
315 + }
316 + sax.sa_family = AF_PPPOX;
317 + sax.sa_protocol = PX_PROTO_OL2TP;
318 + sax.pppol2tp.pid = 0;
319 + sax.pppol2tp.fd = t->udp_fd;
320 + sax.pppol2tp.addr.sin_addr.s_addr = t->peer.sin_addr.s_addr;
321 + sax.pppol2tp.addr.sin_port = t->peer.sin_port;
322 + sax.pppol2tp.addr.sin_family = AF_INET;
323 + sax.pppol2tp.s_tunnel = t->ourtid;
324 + sax.pppol2tp.s_session = 0;
325 + sax.pppol2tp.d_tunnel = t->tid;
326 + sax.pppol2tp.d_session = 0;
327 + if ((connect(fd2, (struct sockaddr *)&sax, sizeof(sax))) < 0) {
328 + l2tp_log (LOG_WARNING, "%s: Unable to connect PPPoL2TP socket. %d %s\n",
329 + __FUNCTION__, errno, strerror(errno));
330 + close(fd2);
331 + return -EINVAL;
332 + }
333 + t->pppox_fd = fd2;
334 + }
335 +#endif
336 + return 0;
337 +}
338 --- a/xl2tpd.c
339 +++ b/xl2tpd.c
340 @@ -278,7 +278,11 @@
341 struct tunnel *st, *st2;
342 int sec;
343 l2tp_log (LOG_CRIT, "%s: Fatal signal %d received\n", __FUNCTION__, signal);
344 +#ifdef USE_KERNEL
345 + if (kernel_support || signal != SIGTERM) {
346 +#else
347 if (signal != SIGTERM) {
348 +#endif
349 st = tunnels.head;
350 while (st)
351 {
352 @@ -349,7 +353,7 @@
353 int flags;
354 #endif
355 int pos = 1;
356 - int fd2;
357 + int fd2 = -1;
358 #ifdef DEBUG_PPPD
359 int x;
360 #endif
361 @@ -397,7 +401,7 @@
362 sax.sa_family = AF_PPPOX;
363 sax.sa_protocol = PX_PROTO_OL2TP;
364 sax.pppol2tp.pid = 0;
365 - sax.pppol2tp.fd = server_socket;
366 + sax.pppol2tp.fd = c->container->udp_fd;
367 sax.pppol2tp.addr.sin_addr.s_addr = c->container->peer.sin_addr.s_addr;
368 sax.pppol2tp.addr.sin_port = c->container->peer.sin_port;
369 sax.pppol2tp.addr.sin_family = AF_INET;
370 @@ -408,6 +412,7 @@
371 if (connect(fd2, (struct sockaddr *)&sax, sizeof(sax)) < 0) {
372 l2tp_log (LOG_WARNING, "%s: Unable to connect PPPoL2TP socket.\n",
373 __FUNCTION__);
374 + close(fd2);
375 return -EINVAL;
376 }
377 stropt[pos++] = strdup ("plugin");
378 @@ -484,7 +489,7 @@
379 dup2 (fd2, 0);
380 dup2 (fd2, 1);
381 close(fd2);
382 -
383 + }
384 /* close all the calls pty fds */
385 st = tunnels.head;
386 while (st)
387 @@ -492,12 +497,17 @@
388 sc = st->call_head;
389 while (sc)
390 {
391 - close (sc->fd);
392 +#ifdef USE_KERNEL
393 + if (kernel_support) {
394 + close(st->udp_fd); /* tunnel UDP fd */
395 + close(st->pppox_fd); /* tunnel PPPoX fd */
396 + } else
397 +#endif
398 + close (sc->fd); /* call pty fd */
399 sc = sc->next;
400 }
401 st = st->next;
402 }
403 - }
404
405 /* close the UDP socket fd */
406 close (server_socket);
407 @@ -615,6 +625,10 @@
408 the memory pointed to by t->chal_us.vector at some other place */
409 if (t->chal_them.vector)
410 free (t->chal_them.vector);
411 + if (t->pppox_fd > -1 )
412 + close (t->pppox_fd);
413 + if (t->udp_fd > -1 )
414 + close (t->udp_fd);
415 free (t);
416 free (me);
417 }