fix networking
[openwrt.git] / openwrt / package / l2tpd / patches / 03-jacco-pty.patch
1 diff -ruN l2tpd-0.70pre-old/l2tpd.c l2tpd-0.70pre-new/l2tpd.c
2 --- l2tpd-0.70pre-old/l2tpd.c 2005-12-16 12:34:12.000000000 +0100
3 +++ l2tpd-0.70pre-new/l2tpd.c 2005-12-16 12:34:54.000000000 +0100
4 @@ -16,6 +16,7 @@
5 */
6
7 #include <stdlib.h>
8 +#include <sys/types.h>
9 #include <sys/utsname.h>
10 #include <sys/stat.h>
11 #include <sys/wait.h>
12 @@ -274,8 +275,8 @@
13
14 int start_pppd (struct call *c, struct ppp_opts *opts)
15 {
16 - char a, b;
17 - char tty[80];
18 + /* char a, b; */
19 + char *tty;
20 char *stropt[80];
21 struct ppp_opts *p;
22 #ifdef USE_KERNEL
23 @@ -324,12 +325,45 @@
24 else
25 {
26 #endif
27 - if ((c->fd = getPtyMaster (&a, &b)) < 0)
28 + c->fd = open("/dev/ptmx", O_RDWR);
29 + if (c->fd == -1)
30 + {
31 + log (LOG_WARN, "%s: unable to open /dev/ptmx to allocate pty\n",
32 + __FUNCTION__);
33 + return -EINVAL;
34 + } else
35 + {
36 + if (grantpt(c->fd))
37 + {
38 + log (LOG_WARN, "%s: unable to grantpt() on pty\n",
39 + __FUNCTION__);
40 + close(c->fd);
41 + return -EINVAL;
42 + }
43 + if (unlockpt(c->fd))
44 + {
45 + log (LOG_WARN, "%s: unable to unlockpt() on pty\n",
46 + __FUNCTION__);
47 + close(c->fd);
48 + return -EINVAL;
49 + }
50 + tty = ptsname(c->fd);
51 + if (tty == NULL)
52 + {
53 + log (LOG_WARN, "%s: unable to obtain name of slave tty\n",
54 + __FUNCTION__);
55 + close(c->fd);
56 + return -EINVAL;
57 + }
58 + }
59 +
60 +
61 + /* if ((c->fd = getPtyMaster (&a, &b)) < 0)
62 {
63 log (LOG_WARN, "%s: unable to allocate pty, abandoning!\n",
64 __FUNCTION__);
65 return -EINVAL;
66 - }
67 + } */
68
69 /* set fd opened above to not echo so we don't see read our own packets
70 back of the file descriptor that we just wrote them to */
71 @@ -338,8 +372,14 @@
72 ptyconf.c_cflag &= ~(ICANON | ECHO);
73 tcsetattr (c->fd, TCSANOW, &ptyconf);
74
75 - snprintf (tty, sizeof (tty), "/dev/tty%c%c", a, b);
76 +/* snprintf (tty, sizeof (tty), "/dev/tty%c%c", a, b); */
77 fd2 = open (tty, O_RDWR);
78 + if (fd2 == -1)
79 + {
80 + log (LOG_WARN, "%s: unable to open slave tty %s\n", __FUNCTION__, tty);
81 + close(c->fd);
82 + return -EINVAL;
83 + }
84
85 #ifdef USE_KERNEL
86 }
87 diff -ruN l2tpd-0.70pre-old/l2tpd.c.orig l2tpd-0.70pre-new/l2tpd.c.orig
88 --- l2tpd-0.70pre-old/l2tpd.c.orig 1970-01-01 01:00:00.000000000 +0100
89 +++ l2tpd-0.70pre-new/l2tpd.c.orig 2005-12-16 12:14:24.000000000 +0100
90 @@ -0,0 +1,1104 @@
91 +/*
92 + * $Id$
93 + *
94 + * Layer Two Tunnelling Protocol Daemon
95 + * Copyright (C) 1998 Adtran, Inc.
96 + * Copyright (C) 2002 Jeff McAdams
97 + *
98 + * Mark Spencer
99 + *
100 + * This software is distributed under the terms
101 + * of the GPL, which you should have received
102 + * along with this source.
103 + *
104 + * Main Daemon source.
105 + *
106 + */
107 +
108 +#include <stdlib.h>
109 +#include <sys/utsname.h>
110 +#include <sys/stat.h>
111 +#include <sys/wait.h>
112 +#include <stdio.h>
113 +#include <errno.h>
114 +#include <unistd.h>
115 +#include <time.h>
116 +#if (__GLIBC__ < 2)
117 +# if defined(FREEBSD)
118 +# include <sys/signal.h>
119 +# elif defined(LINUX)
120 +# include <bsd/signal.h>
121 +# elif defined(SOLARIS)
122 +# include <signal.h>
123 +# endif
124 +#else
125 +# include <signal.h>
126 +#endif
127 +#include <netdb.h>
128 +#include <string.h>
129 +#include <fcntl.h>
130 +#include <netinet/in.h>
131 +#include <arpa/inet.h>
132 +#ifdef USE_KERNEL
133 +#include <sys/ioctl.h>
134 +#endif
135 +#include "l2tp.h"
136 +
137 +struct tunnel_list tunnels;
138 +int max_tunnels = DEF_MAX_TUNNELS;
139 +struct utsname uts;
140 +int ppd = 1; /* Packet processing delay */
141 +int control_fd; /* descriptor of control area */
142 +char *args;
143 +
144 +char *dial_no_tmp; /* jz: Dialnumber for Outgoing Call */
145 +int switch_io = 0; /* jz: Switch for Incoming or Outgoing Call */
146 +
147 +void init_tunnel_list (struct tunnel_list *t)
148 +{
149 + t->head = NULL;
150 + t->count = 0;
151 + t->calls = 0;
152 +}
153 +
154 +/* Now sends to syslog instead - MvO */
155 +void show_status (void)
156 +{
157 + struct schedule_entry *se;
158 + struct tunnel *t;
159 + struct call *c;
160 + struct lns *tlns;
161 + struct lac *tlac;
162 + struct host *h;
163 + int s = 0;
164 + log (LOG_WARN, "====== l2tpd statistics ========\n");
165 + log (LOG_WARN, " Scheduler entries:\n");
166 + se = events;
167 + while (se)
168 + {
169 + s++;
170 + t = (struct tunnel *) se->data;
171 + tlac = (struct lac *) se->data;
172 + c = (struct call *) se->data;
173 + if (se->func == &hello)
174 + {
175 + log (LOG_WARN, "%d: HELLO to %d\n", s, t->tid);
176 + }
177 + else if (se->func == &magic_lac_dial)
178 + {
179 + log (LOG_WARN, "%d: Magic dial on %s\n", s, tlac->entname);
180 + }
181 + else if (se->func == &send_zlb)
182 + {
183 + log (LOG_WARN, "%d: Send payload ZLB on call %d:%d\n", s,
184 + c->container->tid, c->cid);
185 + }
186 + else if (se->func == &dethrottle)
187 + {
188 + log (LOG_WARN, "%d: Dethrottle call %d:%d\n", s, c->container->tid,
189 + c->cid);
190 + }
191 + else
192 + log (LOG_WARN, "%d: Unknown event\n", s);
193 + se = se->next;
194 + };
195 + log (LOG_WARN, "Total Events scheduled: %d\n", s);
196 + log (LOG_WARN, "Number of tunnels open: %d\n", tunnels.count);
197 + t = tunnels.head;
198 + while (t)
199 + {
200 + log (LOG_WARN, "Tunnel %s, ID = %d (local), %d (remote) to %s:%d\n"
201 + " control_seq_num = %d, control_rec_seq_num = %d,\n"
202 + " cLr = %d\n",
203 + (t->lac ? t->lac->entname : (t->lns ? t->lns->entname : "")),
204 + t->ourtid, t->tid, IPADDY (t->peer.sin_addr),
205 + ntohs (t->peer.sin_port), t->control_seq_num,
206 + t->control_rec_seq_num, t->cLr);
207 + c = t->call_head;
208 + while (c)
209 + {
210 + log (LOG_WARN,
211 + "Call %s, ID = %d (local), %d (remote), serno = %u,\n"
212 + " data_seq_num = %d, data_rec_seq_num = %d,\n"
213 + " pLr = %d, tx = %u bytes (%u), rx= %u bytes (%u)\n",
214 + (c->lac ? c->lac->
215 + entname : (c->lns ? c->lns->entname : "")), c->ourcid,
216 + c->cid, c->serno, c->data_seq_num, c->data_rec_seq_num,
217 + c->pLr, c->tx_bytes, c->tx_pkts, c->rx_bytes, c->rx_pkts);
218 + c = c->next;
219 + }
220 + t = t->next;
221 + }
222 + log (LOG_WARN, "==========Config File===========\n");
223 + tlns = lnslist;
224 + while (tlns)
225 + {
226 + log (LOG_WARN, "LNS entry %s\n",
227 + tlns->entname[0] ? tlns->entname : "(unnamed)");
228 + tlns = tlns->next;
229 + };
230 + tlac = laclist;
231 + while (tlac)
232 + {
233 + log (LOG_WARN, "LAC entry %s, LNS is/are:",
234 + tlac->entname[0] ? tlac->entname : "(unnamed)");
235 + h = tlac->lns;
236 + if (h)
237 + {
238 + while (h)
239 + {
240 + log (LOG_WARN, " %s", h->hostname);
241 + h = h->next;
242 + }
243 + }
244 + else
245 + log (LOG_WARN, " [none]");
246 + log (LOG_WARN, "\n");
247 + tlac = tlac->next;
248 + };
249 + log (LOG_WARN, "================================\n");
250 +}
251 +
252 +void null_handler(int sig)
253 +{
254 + /* FIXME
255 + * A sighup is received when a call is terminated, unknown origine ..
256 + * I catch it and ll looks good, but ..
257 + */
258 +}
259 +
260 +void status_handler (int sig)
261 +{
262 + show_status ();
263 +}
264 +
265 +void child_handler (int signal)
266 +{
267 + /*
268 + * Oops, somebody we launched was killed.
269 + * It's time to reap them and close that call.
270 + * But first, we have to find out what PID died.
271 + * unfortunately, pppd will
272 + */
273 + struct tunnel *t;
274 + struct call *c;
275 + pid_t pid;
276 + int status;
277 + t = tunnels.head;
278 + /* Keep looping until all are cleared */
279 + for(;;)
280 + {
281 + pid = waitpid (-1, &status, WNOHANG);
282 + if (pid < 1)
283 + {
284 + /*
285 + * Oh well, nobody there. Maybe we reaped it
286 + * somewhere else already
287 + */
288 + return;
289 + }
290 + while (t)
291 + {
292 + c = t->call_head;
293 + while (c)
294 + {
295 + if (c->pppd == pid)
296 + {
297 + if ( WIFEXITED( status ) )
298 + {
299 + log (LOG_DEBUG, "%s : pppd exited for call %d with code %d\n", __FUNCTION__,
300 + c->cid, WEXITSTATUS( status ) );
301 + }
302 + else if( WIFSIGNALED( status ) )
303 + {
304 + log (LOG_DEBUG, "%s : pppd terminated for call %d by signal %d\n", __FUNCTION__,
305 + c->cid, WTERMSIG( status ) );
306 + }
307 + else
308 + {
309 + log (LOG_DEBUG, "%s : pppd exited for call %d for unknown reason\n", __FUNCTION__,
310 + c->cid );
311 + }
312 + c->needclose = -1;
313 + /*
314 + * OK...pppd died, we can go ahead and close the pty for
315 + * it
316 + */
317 + close (c->fd);
318 + c->fd = -1;
319 + return;
320 + }
321 + c = c->next;
322 + }
323 + t = t->next;
324 + }
325 + }
326 +}
327 +
328 +void death_handler (int signal)
329 +{
330 + /*
331 + * If we get here, somebody terminated us with a kill or a control-c.
332 + * we call call_close on each tunnel twice to get a StopCCN out
333 + * for each one (we can't pause to make sure it's received.
334 + * Then we close the connections
335 + */
336 + struct tunnel *st, *st2;
337 + int sec;
338 + log (LOG_CRIT, "%s: Fatal signal %d received\n", __FUNCTION__, signal);
339 + st = tunnels.head;
340 + while (st)
341 + {
342 + st2 = st->next;
343 + strcpy (st->self->errormsg, "Server closing");
344 + sec = st->self->closing;
345 + if (st->lac)
346 + st->lac->redial = 0;
347 + call_close (st->self);
348 + if (!sec)
349 + {
350 + st->self->closing = -1;
351 + call_close (st->self);
352 + }
353 + st = st2;
354 + }
355 +
356 + /* erase pid file */
357 + unlink (gconfig.pidfile);
358 +
359 + /* erase control pipe */
360 + unlink(CONTROL_PIPE);
361 +
362 + exit (1);
363 +}
364 +
365 +int start_pppd (struct call *c, struct ppp_opts *opts)
366 +{
367 + char a, b;
368 + char tty[80];
369 + char *stropt[80];
370 + struct ppp_opts *p;
371 +#ifdef USE_KERNEL
372 + struct l2tp_call_opts co;
373 +#endif
374 + int pos = 1;
375 + int fd2;
376 +#ifdef DEBUG_PPPD
377 + int x;
378 +#endif
379 + struct termios ptyconf;
380 + char *str;
381 + p = opts;
382 + stropt[0] = strdup (PPPD);
383 + while (p)
384 + {
385 + stropt[pos] = (char *) malloc (strlen (p->option) + 1);
386 + strncpy (stropt[pos], p->option, strlen (p->option) + 1);
387 + pos++;
388 + p = p->next;
389 + }
390 + stropt[pos] = NULL;
391 + if (c->pppd > 0)
392 + {
393 + log (LOG_WARN, "%s: PPP already started on call!\n", __FUNCTION__);
394 + return -EINVAL;
395 + }
396 + if (c->fd > -1)
397 + {
398 + log (LOG_WARN, "%s: file descriptor already assigned!\n",
399 + __FUNCTION__);
400 + return -EINVAL;
401 + }
402 +#ifdef USE_KERNEL
403 + if (kernel_support)
404 + {
405 + co.ourtid = c->container->ourtid;
406 + co.ourcid = c->ourcid;
407 + ioctl (server_socket, L2TPIOCGETCALLOPTS, &co);
408 + stropt[pos++] = strdup ("channel");
409 + stropt[pos] = (char *) malloc (10);
410 + snprintf (stropt[pos], 10, "%d", co.id);
411 + pos++;
412 + stropt[pos] = NULL;
413 + }
414 + else
415 + {
416 +#endif
417 + if ((c->fd = getPtyMaster (&a, &b)) < 0)
418 + {
419 + log (LOG_WARN, "%s: unable to allocate pty, abandoning!\n",
420 + __FUNCTION__);
421 + return -EINVAL;
422 + }
423 +
424 + /* set fd opened above to not echo so we don't see read our own packets
425 + back of the file descriptor that we just wrote them to */
426 + tcgetattr (c->fd, &ptyconf);
427 + *(c->oldptyconf) = ptyconf;
428 + ptyconf.c_cflag &= ~(ICANON | ECHO);
429 + tcsetattr (c->fd, TCSANOW, &ptyconf);
430 +
431 + snprintf (tty, sizeof (tty), "/dev/tty%c%c", a, b);
432 + fd2 = open (tty, O_RDWR);
433 +
434 +#ifdef USE_KERNEL
435 + }
436 +#endif
437 + str = stropt[0];
438 +#ifdef DEBUG_PPPD
439 + log (LOG_DEBUG, "%s: I'm running: ", __FUNCTION__);
440 + for (x = 0; stropt[x]; x++)
441 + {
442 + log (LOG_DEBUG, "\"%s\" ", stropt[x]);
443 + };
444 + log (LOG_DEBUG, "\n");
445 +#endif
446 + c->pppd = fork ();
447 + if (c->pppd < 0)
448 + {
449 + log (LOG_WARN, "%s: unable to fork(), abandoning!\n", __FUNCTION__);
450 + return -EINVAL;
451 + }
452 + else if (!c->pppd)
453 + {
454 + struct call *sc;
455 + struct tunnel *st;
456 +
457 + close (0);
458 + close (1);
459 + close (2);
460 +#ifdef USE_KERNEL
461 + if (!kernel_support && (fd2 < 0))
462 +#else
463 + if (fd2 < 0)
464 +#endif
465 + {
466 + log (LOG_WARN, "%s: Unable to open %s to launch pppd!\n",
467 + __FUNCTION__, tty);
468 + exit (1);
469 + }
470 + dup2 (fd2, 0);
471 + dup2 (fd2, 1);
472 +
473 +
474 + /* close all the calls pty fds */
475 + st = tunnels.head;
476 + while (st)
477 + {
478 + sc = st->call_head;
479 + while (sc)
480 + {
481 + close (sc->fd);
482 + sc = sc->next;
483 + }
484 + st = st->next;
485 + }
486 +
487 + /* close the UDP socket fd */
488 + close (server_socket);
489 +
490 + /* close the control pipe fd */
491 + close (control_fd);
492 +
493 + if( c->dialing[0] )
494 + {
495 + setenv( "CALLER_ID", c->dialing, 1 );
496 + }
497 + execv (PPPD, stropt);
498 + log (LOG_WARN, "%s: Exec of %s failed!\n", __FUNCTION__, PPPD);
499 + exit (1);
500 + };
501 + close (fd2);
502 + pos = 0;
503 + while (stropt[pos])
504 + {
505 + free (stropt[pos]);
506 + pos++;
507 + };
508 + return 0;
509 +}
510 +
511 +void destroy_tunnel (struct tunnel *t)
512 +{
513 + /*
514 + * Immediately destroy a tunnel (and all its calls)
515 + * and free its resources. This may be called
516 + * by the tunnel itself,so it needs to be
517 + * "suicide safe"
518 + */
519 +
520 + struct call *c, *me;
521 + struct tunnel *p;
522 + struct timeval tv;
523 + if (!t)
524 + return;
525 +
526 + /*
527 + * Save ourselves until the very
528 + * end, since we might be calling this ourselves.
529 + * We must divorce ourself from the tunnel
530 + * structure, however, to avoid recursion
531 + * because of the logic of the destroy_call
532 + */
533 + me = t->self;
534 +
535 + /*
536 + * Destroy all the member calls
537 + */
538 + c = t->call_head;
539 + while (c)
540 + {
541 + destroy_call (c);
542 + c = c->next;
543 + };
544 + /*
545 + * Remove ourselves from the list of tunnels
546 + */
547 +
548 + if (tunnels.head == t)
549 + {
550 + tunnels.head = t->next;
551 + tunnels.count--;
552 + }
553 + else
554 + {
555 + p = tunnels.head;
556 + if (p)
557 + {
558 + while (p->next && (p->next != t))
559 + p = p->next;
560 + if (p->next)
561 + {
562 + p->next = t->next;
563 + tunnels.count--;
564 + }
565 + else
566 + {
567 + log (LOG_WARN,
568 + "%s: unable to locate tunnel in tunnel list\n",
569 + __FUNCTION__);
570 + }
571 + }
572 + else
573 + {
574 + log (LOG_WARN, "%s: tunnel list is empty!\n", __FUNCTION__);
575 + }
576 + }
577 + if (t->lac)
578 + {
579 + t->lac->t = NULL;
580 + if (t->lac->redial && (t->lac->rtimeout > 0) && !t->lac->rsched &&
581 + t->lac->active)
582 + {
583 + log (LOG_LOG, "%s: Will redial in %d seconds\n", __FUNCTION__,
584 + t->lac->rtimeout);
585 + tv.tv_sec = t->lac->rtimeout;
586 + tv.tv_usec = 0;
587 + t->lac->rsched = schedule (tv, magic_lac_dial, t->lac);
588 + }
589 + }
590 + /* XXX L2TP/IPSec: remove relevant SAs here? NTB 20011010
591 + * XXX But what if another tunnel is using same SA?
592 + */
593 + if (t->lns)
594 + t->lns->t = NULL;
595 + free (t);
596 + free (me);
597 +}
598 +
599 +struct tunnel *l2tp_call (char *host, int port, struct lac *lac,
600 + struct lns *lns)
601 +{
602 + /*
603 + * Establish a tunnel from us to host
604 + * on port port
605 + */
606 + struct call *tmp = NULL;
607 + struct hostent *hp;
608 + unsigned int addr;
609 + port = htons (port);
610 + hp = gethostbyname (host);
611 + if (!hp)
612 + {
613 + log (LOG_WARN, "%s: gethostbyname() failed for %s.\n", __FUNCTION__,
614 + host);
615 + return NULL;
616 + }
617 + bcopy (hp->h_addr, &addr, hp->h_length);
618 + /* Force creation of a new tunnel
619 + and set it's tid to 0 to cause
620 + negotiation to occur */
621 + /* XXX L2TP/IPSec: Set up SA to addr:port here? NTB 20011010
622 + */
623 + tmp = get_call (0, 0, addr, port);
624 + if (!tmp)
625 + {
626 + log (LOG_WARN, "%s: Unable to create tunnel to %s.\n", __FUNCTION__,
627 + host);
628 + return NULL;
629 + }
630 + tmp->container->tid = 0;
631 + tmp->container->lac = lac;
632 + tmp->container->lns = lns;
633 + tmp->lac = lac;
634 + tmp->lns = lns;
635 + if (lac)
636 + lac->t = tmp->container;
637 + if (lns)
638 + lns->t = tmp->container;
639 + /*
640 + * Since our state is 0, we will establish a tunnel now
641 + */
642 + log (LOG_LOG, "%s:Connecting to host %s, port %d\n", __FUNCTION__, host,
643 + ntohs (port));
644 + control_finish (tmp->container, tmp);
645 + return tmp->container;
646 +}
647 +
648 +void magic_lac_tunnel (void *data)
649 +{
650 + struct lac *lac;
651 + lac = (struct lac *) data;
652 + if (!lac)
653 + {
654 + log (LOG_WARN, "%s: magic_lac_tunnel: called on NULL lac!\n",
655 + __FUNCTION__);
656 + return;
657 + }
658 + if (lac->lns)
659 + {
660 + /* FIXME: I should try different LNS's if I get failures */
661 + l2tp_call (lac->lns->hostname, lac->lns->port, lac, NULL);
662 + return;
663 + }
664 + else if (deflac && deflac->lns)
665 + {
666 + l2tp_call (deflac->lns->hostname, deflac->lns->port, lac, NULL);
667 + return;
668 + }
669 + else
670 + {
671 + log (LOG_WARN, "%s: Unable to find hostname to dial for '%s'\n",
672 + __FUNCTION__, lac->entname);
673 + return;
674 + }
675 +}
676 +
677 +struct call *lac_call (int tid, struct lac *lac, struct lns *lns)
678 +{
679 + struct tunnel *t = tunnels.head;
680 + struct call *tmp;
681 + while (t)
682 + {
683 + if (t->ourtid == tid)
684 + {
685 + tmp = new_call (t);
686 + if (!tmp)
687 + {
688 + log (LOG_WARN, "%s: unable to create new call\n",
689 + __FUNCTION__);
690 + return NULL;
691 + }
692 + tmp->next = t->call_head;
693 + t->call_head = tmp;
694 + t->count++;
695 + tmp->cid = 0;
696 + tmp->lac = lac;
697 + tmp->lns = lns;
698 + if (lac)
699 + lac->c = tmp;
700 + log (LOG_LOG, "%s: Calling on tunnel %d\n", __FUNCTION__, tid);
701 + strcpy (tmp->dial_no, dial_no_tmp); /* jz: copy dialnumber to tmp->dial_no */
702 + control_finish (t, tmp);
703 + return tmp;
704 + }
705 + t = t->next;
706 + };
707 + log (LOG_DEBUG, "%s: No such tunnel %d to generate call.\n", __FUNCTION__,
708 + tid);
709 + return NULL;
710 +}
711 +
712 +void magic_lac_dial (void *data)
713 +{
714 + struct lac *lac;
715 + lac = (struct lac *) data;
716 +
717 + if (!lac)
718 + {
719 + log (LOG_WARN, "%s : called on NULL lac!\n", __FUNCTION__);
720 + return;
721 + }
722 + if (!lac->active)
723 + {
724 + log (LOG_DEBUG, "%s: LAC %s not active", __FUNCTION__, lac->entname);
725 + return;
726 + }
727 + lac->rsched = NULL;
728 + lac->rtries++;
729 + if (lac->rmax && (lac->rtries > lac->rmax))
730 + {
731 + log (LOG_LOG, "%s: maximum retries exceeded.\n", __FUNCTION__);
732 + return;
733 + }
734 + if (!lac->t)
735 + {
736 +#ifdef DEGUG_MAGIC
737 + log (LOG_DEBUG, "%s : tunnel not up! Connecting!\n", __FUNCTION__);
738 +#endif
739 + magic_lac_tunnel (lac);
740 + return;
741 + }
742 + lac_call (lac->t->ourtid, lac, NULL);
743 +}
744 +
745 +void lac_hangup (int cid)
746 +{
747 + struct tunnel *t = tunnels.head;
748 + struct call *tmp;
749 + while (t)
750 + {
751 + tmp = t->call_head;
752 + while (tmp)
753 + {
754 + if (tmp->ourcid == cid)
755 + {
756 + log (LOG_LOG,
757 + "%s :Hanging up call %d, Local: %d, Remote: %d\n",
758 + __FUNCTION__, tmp->serno, tmp->ourcid, tmp->cid);
759 + strcpy (tmp->errormsg, "Goodbye!");
760 +/* tmp->needclose = -1; */
761 + kill (tmp->pppd, SIGTERM);
762 + return;
763 + }
764 + tmp = tmp->next;
765 + }
766 + t = t->next;
767 + };
768 + log (LOG_DEBUG, "%s : No such call %d to hang up.\n", __FUNCTION__, cid);
769 + return;
770 +}
771 +
772 +void lac_disconnect (int tid)
773 +{
774 + struct tunnel *t = tunnels.head;
775 + while (t)
776 + {
777 + if (t->ourtid == tid)
778 + {
779 + log (LOG_LOG,
780 + "%s: Disconnecting from %s, Local: %d, Remote: %d\n",
781 + __FUNCTION__, IPADDY (t->peer.sin_addr), t->ourtid, t->tid);
782 + t->self->needclose = -1;
783 + strcpy (t->self->errormsg, "Goodbye!");
784 + call_close (t->self);
785 + return;
786 + }
787 + t = t->next;
788 + };
789 + log (LOG_DEBUG, "%s: No such tunnel %d to hang up.\n", __FUNCTION__, tid);
790 + return;
791 +}
792 +
793 +struct tunnel *new_tunnel ()
794 +{
795 + struct tunnel *tmp = malloc (sizeof (struct tunnel));
796 + char entropy_buf[2] = "\0";
797 + if (!tmp)
798 + return NULL;
799 + tmp->control_seq_num = 0;
800 + tmp->control_rec_seq_num = 0;
801 + tmp->cLr = 0;
802 + tmp->call_head = NULL;
803 + tmp->next = NULL;
804 + tmp->debug = -1;
805 + tmp->tid = -1;
806 + tmp->hello = NULL;
807 +#ifndef TESTING
808 +/* while(get_call((tmp->ourtid = rand() & 0xFFFF),0,0,0)); */
809 +#ifdef USE_KERNEL
810 + if (kernel_support)
811 + tmp->ourtid = ioctl (server_socket, L2TPIOCADDTUNNEL, 0);
812 + else
813 +#endif
814 +/* tmp->ourtid = rand () & 0xFFFF; */
815 + /* get_entropy((char *)&tmp->ourtid, 2); */
816 + get_entropy(entropy_buf, 2);
817 + {
818 + int *temp;
819 + temp = (int *)entropy_buf;
820 + tmp->ourtid = *temp & 0xFFFF;
821 +#ifdef DEBUG_ENTROPY
822 + log(LOG_DEBUG, "ourtid = %u, entropy_buf = %hx\n", tmp->ourtid, *temp);
823 +#endif
824 + }
825 +#else
826 + tmp->ourtid = 0x6227;
827 +#endif
828 + tmp->nego = 0;
829 + tmp->count = 0;
830 + tmp->state = 0; /* Nothing */
831 + tmp->peer.sin_family = AF_INET;
832 + tmp->peer.sin_port = 0;
833 + bzero (&(tmp->peer.sin_addr), sizeof (tmp->peer.sin_addr));
834 + tmp->sanity = -1;
835 + tmp->qtid = -1;
836 + tmp->ourfc = ASYNC_FRAMING | SYNC_FRAMING;
837 + tmp->ourbc = 0;
838 + tmp->ourtb = (((_u64) rand ()) << 32) | ((_u64) rand ());
839 + tmp->fc = -1; /* These really need to be specified by the peer */
840 + tmp->bc = -1; /* And we want to know if they forgot */
841 + tmp->hostname[0] = 0;
842 + tmp->vendor[0] = 0;
843 + tmp->secret[0] = 0;
844 + if (!(tmp->self = new_call (tmp)))
845 + {
846 + free (tmp);
847 + return NULL;
848 + };
849 + tmp->ourrws = DEFAULT_RWS_SIZE;
850 + tmp->self->ourfbit = FBIT;
851 + tmp->lac = NULL;
852 + tmp->lns = NULL;
853 + tmp->chal_us.state = 0;
854 + tmp->chal_us.secret[0] = 0;
855 + memset (tmp->chal_us.reply, 0, MD_SIG_SIZE);
856 + tmp->chal_them.state = 0;
857 + tmp->chal_them.secret[0] = 0;
858 + memset (tmp->chal_them.reply, 0, MD_SIG_SIZE);
859 + tmp->chal_them.vector = (unsigned char *) malloc (VECTOR_SIZE);
860 + tmp->chal_us.vector = NULL;
861 + tmp->hbit = 0;
862 + return tmp;
863 +}
864 +
865 +void do_control ()
866 +{
867 + char buf[1024];
868 + char *host, *tunstr, *callstr, *tmpstr;
869 + struct lac *lac;
870 + int call;
871 + int tunl;
872 + int cnt = -1;
873 + while (cnt)
874 + {
875 + cnt = read (control_fd, buf, sizeof (buf));
876 + if (cnt > 0)
877 + {
878 + if (buf[cnt - 1] == '\n')
879 + buf[--cnt] = 0;
880 +#ifdef DEBUG_CONTROL
881 + log (LOG_DEBUG, "%s: Got message \"%s\" (%d bytes long)\n",
882 + __FUNCTION__, buf, cnt);
883 +#endif
884 + switch (buf[0])
885 + {
886 + case 't':
887 + host = strchr (buf, ' ');
888 + if(!host)
889 + goto out;
890 + host++;
891 +#ifdef DEBUG_CONTROL
892 + log (LOG_DEBUG, "%s: Attempting to tunnel to %s\n",
893 + __FUNCTION__, host);
894 +#endif
895 + l2tp_call (host, UDP_LISTEN_PORT, NULL, NULL);
896 + break;
897 + case 'c': /* option 'c' for incoming call */
898 + case 'o': /* option 'o' for outgoing call */
899 + tunstr = strchr (buf, ' ');
900 + if(!tunstr)
901 + goto out;
902 + tunstr++;
903 +
904 + if(buf[0] == 'c')
905 + switch_io = 1; /* Switch for Incoming Calls */
906 + else {
907 + switch_io = 0; /* Switch for Outgoing Calls */
908 + tmpstr = strchr(tunstr, ' ');
909 + if(!tmpstr)
910 + goto out;
911 + strncpy(dial_no_tmp,tmpstr, sizeof(*dial_no_tmp));
912 + }
913 +
914 + lac = laclist;
915 + while (lac)
916 + {
917 + if (!strcasecmp (lac->entname, tunstr))
918 + {
919 + lac->active = -1;
920 + lac->rtries = 0;
921 + if (!lac->c)
922 + magic_lac_dial (lac);
923 + else
924 + log (LOG_DEBUG,
925 + "%s: Session '%s' already active!\n",
926 + __FUNCTION__, lac->entname);
927 + break;
928 + }
929 + lac = lac->next;
930 + }
931 + if (lac)
932 + break;
933 + tunl = atoi (tunstr);
934 + if (!tunl)
935 + {
936 + log (LOG_DEBUG, "%s: No such tunnel '%s'\n", __FUNCTION__,
937 + tunstr);
938 + break;
939 + }
940 +#ifdef DEBUG_CONTROL
941 + log (LOG_DEBUG, "%s: Attempting to call on tunnel %d\n",
942 + __FUNCTION__, tunl);
943 +#endif
944 + lac_call (tunl, NULL, NULL);
945 + break;
946 + case 'h':
947 + callstr = strchr (buf, ' ');
948 + if(!callstr)
949 + goto out;
950 + callstr++;
951 +
952 + call = atoi (callstr);
953 +#ifdef DEBUG_CONTROL
954 + log (LOG_DEBUG, "%s: Attempting to call %d\n", __FUNCTION__,
955 + call);
956 +#endif
957 + lac_hangup (call);
958 + break;
959 + case 'd':
960 + tunstr = strchr (buf, ' ');
961 + if(!tunstr)
962 + goto out;
963 + tunstr++;
964 +
965 + lac = laclist;
966 + while (lac)
967 + {
968 + if (!strcasecmp (lac->entname, tunstr))
969 + {
970 + lac->active = 0;
971 + lac->rtries = 0;
972 + if (lac->t)
973 + lac_disconnect (lac->t->ourtid);
974 + else
975 + log (LOG_DEBUG, "%s: Session '%s' not up\n",
976 + __FUNCTION__, lac->entname);
977 + break;
978 + }
979 + lac = lac->next;
980 + }
981 + if (lac)
982 + break;
983 + tunl = atoi (tunstr);
984 + if (!tunl)
985 + {
986 + log (LOG_DEBUG, "%s: No such tunnel '%s'\n", __FUNCTION__,
987 + tunstr);
988 + break;
989 + }
990 +#ifdef DEBUG_CONTROL
991 + log (LOG_DEBUG, "%s: Attempting to disconnect tunnel %d\n",
992 + __FUNCTION__, tunl);
993 +#endif
994 + lac_disconnect (tunl);
995 + break;
996 + case 's':
997 + show_status ();
998 + break;
999 + default:
1000 + log (LOG_DEBUG, "%s: Unknown command %c\n", __FUNCTION__,
1001 + buf[0]);
1002 + }
1003 + }
1004 + }
1005 +
1006 +out:
1007 + /* Otherwise select goes nuts */
1008 + close (control_fd);
1009 + control_fd = open (CONTROL_PIPE, O_RDONLY | O_NONBLOCK, 0600);
1010 +}
1011 +
1012 +void usage(void) {
1013 + printf("Usage: l2tpd -D -c [config file] -s [secret file] -p [pid file]\n");
1014 + printf("\n");
1015 + exit(1);
1016 +}
1017 +
1018 +void init_args(int argc, char *argv[]) {
1019 + int i=0;
1020 + gconfig.daemon=1;
1021 + memset(gconfig.altauthfile,0,STRLEN);
1022 + memset(gconfig.altconfigfile,0,STRLEN);
1023 + memset(gconfig.authfile,0,STRLEN);
1024 + memset(gconfig.configfile,0,STRLEN);
1025 + memset(gconfig.pidfile,0,STRLEN);
1026 + strncpy(gconfig.altauthfile,ALT_DEFAULT_AUTH_FILE,
1027 + sizeof(gconfig.altauthfile) - 1);
1028 + strncpy(gconfig.altconfigfile,ALT_DEFAULT_CONFIG_FILE,
1029 + sizeof(gconfig.altconfigfile) - 1);
1030 + strncpy(gconfig.authfile,DEFAULT_AUTH_FILE,
1031 + sizeof(gconfig.authfile) - 1);
1032 + strncpy(gconfig.configfile,DEFAULT_CONFIG_FILE,
1033 + sizeof(gconfig.configfile) - 1);
1034 + strncpy(gconfig.pidfile,DEFAULT_PID_FILE,
1035 + sizeof(gconfig.pidfile) - 1);
1036 + for (i = 1; i < argc; i++) {
1037 + if(! strncmp(argv[i],"-c",2)) {
1038 + if(++i == argc)
1039 + usage();
1040 + else
1041 + strncpy(gconfig.configfile,argv[i],
1042 + sizeof(gconfig.configfile) - 1);
1043 + }
1044 + else if (! strncmp(argv[i],"-D",2)) {
1045 + gconfig.daemon=0;
1046 + }
1047 + else if (! strncmp(argv[i],"-s",2)) {
1048 + if(++i == argc)
1049 + usage();
1050 + else
1051 + strncpy(gconfig.authfile,argv[i],
1052 + sizeof(gconfig.authfile) - 1);
1053 + }
1054 + else if (! strncmp(argv[i],"-p",2)) {
1055 + if(++i == argc)
1056 + usage();
1057 + else
1058 + strncpy(gconfig.pidfile,argv[i],
1059 + sizeof(gconfig.pidfile) - 1);
1060 + }
1061 + else {
1062 + usage();
1063 + }
1064 + }
1065 +}
1066 +
1067 +
1068 +void daemonize() {
1069 + int pid=0;
1070 + int i,l;
1071 + char buf[STRLEN];
1072 +
1073 + if((pid = fork()) < 0) {
1074 + log(LOG_LOG, "%s: Unable to fork ()\n",__FUNCTION__);
1075 + close(server_socket);
1076 + exit(1);
1077 + }
1078 + else if (pid)
1079 + exit(0);
1080 +
1081 +
1082 + close(0);
1083 + close(1);
1084 + close(2);
1085 + dup2(open("/dev/null", O_RDONLY), 0);
1086 + dup2(open("/dev/null", O_RDONLY), 1);
1087 + dup2(open("/dev/null", O_RDONLY), 2);
1088 +
1089 + /* Read previous pid file. */
1090 + if((i = open(gconfig.pidfile,O_RDONLY)) > 0) {
1091 + l=read(i,buf,sizeof(buf)-1);
1092 + if (l >= 0) {
1093 + buf[l] = '\0';
1094 + pid = atoi(buf);
1095 + }
1096 + close(i);
1097 +
1098 + /* if pid is read and process exist exit */
1099 + if(pid && !kill(pid, 0)) {
1100 + log(LOG_LOG, "%s: There's already a l2tpd server running.\n",
1101 + __FUNCTION__);
1102 + close(server_socket);
1103 + exit(1);
1104 + }
1105 +
1106 + /* remove stalled pid file */
1107 + unlink(gconfig.pidfile);
1108 + }
1109 +
1110 + pid = setsid();
1111 +
1112 + /* create new pid file */
1113 + if ((i = open (gconfig.pidfile, O_WRONLY | O_CREAT, 0644)) >= 0) {
1114 + snprintf (buf, sizeof(buf), "%d", (int)getpid());
1115 + write (i, buf, strlen(buf));
1116 + close (i);
1117 + }
1118 + else {
1119 + log(LOG_LOG, "%s: could not write pid file %s error %d",
1120 + __FUNCTION__, gconfig.pidfile, i);
1121 + close(server_socket);
1122 + exit(1);
1123 + }
1124 +}
1125 +
1126 +
1127 +void init (int argc,char *argv[])
1128 +{
1129 + struct lac *lac;
1130 + struct in_addr listenaddr;
1131 +
1132 + init_args (argc,argv);
1133 + srand( time(NULL) );
1134 + rand_source = 0;
1135 + init_addr ();
1136 + if (init_config ())
1137 + {
1138 + log (LOG_CRIT, "%s: Unable to load config file\n", __FUNCTION__);
1139 + exit (1);
1140 + }
1141 + if (uname (&uts))
1142 + {
1143 + log (LOG_CRIT, "%s : Unable to determine host system\n",
1144 + __FUNCTION__);
1145 + exit (1);
1146 + }
1147 + init_tunnel_list (&tunnels);
1148 + if (init_network ())
1149 + exit (1);
1150 + if (gconfig.daemon)
1151 + daemonize ();
1152 + signal (SIGTERM, &death_handler);
1153 + signal (SIGINT, &death_handler);
1154 + signal (SIGCHLD, &child_handler);
1155 + signal (SIGUSR1, &status_handler);
1156 + signal (SIGHUP, &null_handler);
1157 + init_scheduler ();
1158 + mkfifo (CONTROL_PIPE, 0600);
1159 + control_fd = open (CONTROL_PIPE, O_RDONLY | O_NONBLOCK, 0600);
1160 + if (control_fd < 0)
1161 + {
1162 + log (LOG_CRIT, "%s: Unable to open " CONTROL_PIPE " for reading.",
1163 + __FUNCTION__);
1164 + exit (1);
1165 + }
1166 + log (LOG_LOG, "l2tpd version " SERVER_VERSION " started on %s PID:%d\n",
1167 + hostname, getpid ());
1168 + listenaddr.s_addr = gconfig.listenaddr;
1169 + log (LOG_LOG, "%s version %s on a %s, listening on IP address %s, port %d\n", uts.sysname,
1170 + uts.release, uts.machine, inet_ntoa(listenaddr), gconfig.port);
1171 + lac = laclist;
1172 + while (lac)
1173 + {
1174 + if (lac->autodial)
1175 + {
1176 +#ifdef DEBUG_MAGIC
1177 + log (LOG_DEBUG, "%s: Autodialing '%s'\n", __FUNCTION__,
1178 + lac->entname[0] ? lac->entname : "(unnamed)");
1179 +#endif
1180 + lac->active = -1;
1181 + switch_io = 1; /* If we're a LAC, autodials will be ICRQ's */
1182 + magic_lac_dial (lac);
1183 + }
1184 + lac = lac->next;
1185 + }
1186 +}
1187 +
1188 +int main (int argc, char *argv[])
1189 +{
1190 + init(argc,argv);
1191 + dial_no_tmp = calloc (128, sizeof (char));
1192 + network_thread ();
1193 + return 0;
1194 +}
This page took 0.094837 seconds and 5 git commands to generate.