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