xl2tpd: Remove modprobe invocation from kernel-mode patch
[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 @@ -45,6 +91,7 @@ int init_network (void)
112 server.sin_family = AF_INET;
113 server.sin_addr.s_addr = gconfig.listenaddr;
114 server.sin_port = htons (gconfig.port);
115 + int flags;
116 if ((server_socket = socket (PF_INET, SOCK_DGRAM, 0)) < 0)
117 {
118 l2tp_log (LOG_CRIT, "%s: Unable to allocate socket. Terminating.\n",
119 @@ -52,6 +99,10 @@ int init_network (void)
120 return -EINVAL;
121 };
122
123 + flags = 1;
124 + setsockopt(server_socket, SOL_SOCKET, SO_REUSEADDR, &flags, sizeof(flags));
125 + setsockopt(server_socket, SOL_SOCKET, SO_NO_CHECK, &flags, sizeof(flags));
126 +
127 if (bind (server_socket, (struct sockaddr *) &server, sizeof (server)))
128 {
129 close (server_socket);
130 @@ -321,6 +373,11 @@ int build_fdset (fd_set *readfds)
131
132 while (tun)
133 {
134 + if (tun->udp_fd > -1) {
135 + if (tun->udp_fd > max)
136 + max = tun->udp_fd;
137 + FD_SET (tun->udp_fd, readfds);
138 + }
139 call = tun->call_head;
140 while (call)
141 {
142 @@ -390,6 +447,8 @@ void network_thread ()
143 struct iovec iov;
144 char cbuf[256];
145 unsigned int refme, refhim;
146 + int * currentfd;
147 + int server_socket_processed;
148
149 /* This one buffer can be recycled for everything except control packets */
150 buf = new_buf (MAX_RECV_SIZE);
151 @@ -428,7 +487,21 @@ void network_thread ()
152 {
153 do_control ();
154 }
155 - if (FD_ISSET (server_socket, &readfds))
156 + server_socket_processed = 0;
157 + currentfd = NULL;
158 + st = tunnels.head;
159 + while (st || !server_socket_processed) {
160 + if (st && (st->udp_fd == -1)) {
161 + st=st->next;
162 + continue;
163 + }
164 + if (st) {
165 + currentfd = &st->udp_fd;
166 + } else {
167 + currentfd = &server_socket;
168 + server_socket_processed = 1;
169 + }
170 + if (FD_ISSET (*currentfd, &readfds))
171 {
172 /*
173 * Okay, now we're ready for reading and processing new data.
174 @@ -457,12 +530,19 @@ void network_thread ()
175 msgh.msg_flags = 0;
176
177 /* Receive one packet. */
178 - recvsize = recvmsg(server_socket, &msgh, 0);
179 + recvsize = recvmsg(*currentfd, &msgh, 0);
180
181 if (recvsize < MIN_PAYLOAD_HDR_LEN)
182 {
183 if (recvsize < 0)
184 {
185 + if (errno == ECONNREFUSED) {
186 + close(*currentfd);
187 + }
188 + if ((errno == ECONNREFUSED) ||
189 + (errno == EBADF)) {
190 + *currentfd = -1;
191 + }
192 if (errno != EAGAIN)
193 l2tp_log (LOG_WARNING,
194 "%s: recvfrom returned error %d (%s)\n",
195 @@ -567,6 +647,8 @@ void network_thread ()
196 }
197 };
198 }
199 + if (st) st=st->next;
200 + }
201
202 /*
203 * finished obvious sources, look for data from PPP connections.
204 @@ -639,3 +721,82 @@ void network_thread ()
205 }
206
207 }
208 +
209 +int connect_pppol2tp(struct tunnel *t) {
210 +#ifdef USE_KERNEL
211 + if (kernel_support) {
212 + int ufd = -1, fd2 = -1;
213 + int flags;
214 + struct sockaddr_pppol2tp sax;
215 +
216 + struct sockaddr_in server;
217 + server.sin_family = AF_INET;
218 + server.sin_addr.s_addr = gconfig.listenaddr;
219 + server.sin_port = htons (gconfig.port);
220 + if ((ufd = socket (PF_INET, SOCK_DGRAM, 0)) < 0)
221 + {
222 + l2tp_log (LOG_CRIT, "%s: Unable to allocate UDP socket. Terminating.\n",
223 + __FUNCTION__);
224 + return -EINVAL;
225 + };
226 +
227 + flags=1;
228 + setsockopt(ufd, SOL_SOCKET, SO_REUSEADDR, &flags, sizeof(flags));
229 + setsockopt(ufd, SOL_SOCKET, SO_NO_CHECK, &flags, sizeof(flags));
230 +
231 + if (bind (ufd, (struct sockaddr *) &server, sizeof (server)))
232 + {
233 + close (ufd);
234 + l2tp_log (LOG_CRIT, "%s: Unable to bind UDP socket: %s. Terminating.\n",
235 + __FUNCTION__, strerror(errno), errno);
236 + return -EINVAL;
237 + };
238 + server = t->peer;
239 + flags = fcntl(ufd, F_GETFL);
240 + if (flags == -1 || fcntl(ufd, F_SETFL, flags | O_NONBLOCK) == -1) {
241 + l2tp_log (LOG_WARNING, "%s: Unable to set UDP socket nonblock.\n",
242 + __FUNCTION__);
243 + return -EINVAL;
244 + }
245 + if (connect (ufd, (struct sockaddr *) &server, sizeof(server)) < 0) {
246 + l2tp_log (LOG_CRIT, "%s: Unable to connect UDP peer. Terminating.\n",
247 + __FUNCTION__);
248 + return -EINVAL;
249 + }
250 +
251 + t->udp_fd=ufd;
252 +
253 + fd2 = socket(AF_PPPOX, SOCK_DGRAM, PX_PROTO_OL2TP);
254 + if (fd2 < 0) {
255 + l2tp_log (LOG_WARNING, "%s: Unable to allocate PPPoL2TP socket.\n",
256 + __FUNCTION__);
257 + return -EINVAL;
258 + }
259 + flags = fcntl(fd2, F_GETFL);
260 + if (flags == -1 || fcntl(fd2, F_SETFL, flags | O_NONBLOCK) == -1) {
261 + l2tp_log (LOG_WARNING, "%s: Unable to set PPPoL2TP socket nonblock.\n",
262 + __FUNCTION__);
263 + return -EINVAL;
264 + }
265 + sax.sa_family = AF_PPPOX;
266 + sax.sa_protocol = PX_PROTO_OL2TP;
267 + sax.pppol2tp.pid = 0;
268 + sax.pppol2tp.fd = t->udp_fd;
269 + sax.pppol2tp.addr.sin_addr.s_addr = t->peer.sin_addr.s_addr;
270 + sax.pppol2tp.addr.sin_port = t->peer.sin_port;
271 + sax.pppol2tp.addr.sin_family = AF_INET;
272 + sax.pppol2tp.s_tunnel = t->ourtid;
273 + sax.pppol2tp.s_session = 0;
274 + sax.pppol2tp.d_tunnel = t->tid;
275 + sax.pppol2tp.d_session = 0;
276 + if ((connect(fd2, (struct sockaddr *)&sax, sizeof(sax))) < 0) {
277 + l2tp_log (LOG_WARNING, "%s: Unable to connect PPPoL2TP socket. %d %s\n",
278 + __FUNCTION__, errno, strerror(errno));
279 + close(fd2);
280 + return -EINVAL;
281 + }
282 + t->pppox_fd = fd2;
283 + }
284 +#endif
285 + return 0;
286 +}
287 diff --git a/xl2tpd.c b/xl2tpd.c
288 index 307ac2e..3fb6dd7 100644
289 --- a/xl2tpd.c
290 +++ b/xl2tpd.c
291 @@ -278,7 +278,11 @@ void death_handler (int signal)
292 struct tunnel *st, *st2;
293 int sec;
294 l2tp_log (LOG_CRIT, "%s: Fatal signal %d received\n", __FUNCTION__, signal);
295 +#ifdef USE_KERNEL
296 + if (kernel_support || signal != SIGTERM) {
297 +#else
298 if (signal != SIGTERM) {
299 +#endif
300 st = tunnels.head;
301 while (st)
302 {
303 @@ -349,7 +353,7 @@ int start_pppd (struct call *c, struct ppp_opts *opts)
304 int flags;
305 #endif
306 int pos = 1;
307 - int fd2;
308 + int fd2 = -1;
309 #ifdef DEBUG_PPPD
310 int x;
311 #endif
312 @@ -397,7 +401,7 @@ int start_pppd (struct call *c, struct ppp_opts *opts)
313 sax.sa_family = AF_PPPOX;
314 sax.sa_protocol = PX_PROTO_OL2TP;
315 sax.pppol2tp.pid = 0;
316 - sax.pppol2tp.fd = server_socket;
317 + sax.pppol2tp.fd = c->container->udp_fd;
318 sax.pppol2tp.addr.sin_addr.s_addr = c->container->peer.sin_addr.s_addr;
319 sax.pppol2tp.addr.sin_port = c->container->peer.sin_port;
320 sax.pppol2tp.addr.sin_family = AF_INET;
321 @@ -408,6 +412,7 @@ int start_pppd (struct call *c, struct ppp_opts *opts)
322 if (connect(fd2, (struct sockaddr *)&sax, sizeof(sax)) < 0) {
323 l2tp_log (LOG_WARNING, "%s: Unable to connect PPPoL2TP socket.\n",
324 __FUNCTION__);
325 + close(fd2);
326 return -EINVAL;
327 }
328 stropt[pos++] = strdup ("plugin");
329 @@ -484,7 +489,7 @@ int start_pppd (struct call *c, struct ppp_opts *opts)
330 dup2 (fd2, 0);
331 dup2 (fd2, 1);
332 close(fd2);
333 -
334 + }
335 /* close all the calls pty fds */
336 st = tunnels.head;
337 while (st)
338 @@ -492,12 +497,17 @@ int start_pppd (struct call *c, struct ppp_opts *opts)
339 sc = st->call_head;
340 while (sc)
341 {
342 - close (sc->fd);
343 +#ifdef USE_KERNEL
344 + if (kernel_support) {
345 + close(st->udp_fd); /* tunnel UDP fd */
346 + close(st->pppox_fd); /* tunnel PPPoX fd */
347 + } else
348 +#endif
349 + close (sc->fd); /* call pty fd */
350 sc = sc->next;
351 }
352 st = st->next;
353 }
354 - }
355
356 /* close the UDP socket fd */
357 close (server_socket);
358 @@ -615,6 +625,10 @@ void destroy_tunnel (struct tunnel *t)
359 the memory pointed to by t->chal_us.vector at some other place */
360 if (t->chal_them.vector)
361 free (t->chal_them.vector);
362 + if (t->pppox_fd > -1 )
363 + close (t->pppox_fd);
364 + if (t->udp_fd > -1 )
365 + close (t->udp_fd);
366 free (t);
367 free (me);
368 }