1 | /*
2 | * Layer Two Tunnelling Protocol Daemon
3 | * Copyright (C) 1998 Adtran, Inc.
4 | *
5 | * Mark Spencer
6 | *
7 | * This software is distributed under the terms
8 | * of the GPL, which you should have received
9 | * along with this source.
10 | *
11 | * File format handling
12 | *
13 | */
14 |
15 | #include <stdio.h>
16 | #include <string.h>
17 | #include <unistd.h>
18 | #include <stdlib.h>
19 | #include <netdb.h>
20 | #include <netinet/in.h>
21 |
22 | #include "l2tp.h"
23 | struct lns *lnslist;
24 | struct lac *laclist;
25 | struct lns *deflns;
26 | struct lac *deflac;
27 | struct global gconfig;
28 | char filerr[STRLEN];
29 |
30 | int parse_config (FILE *);
31 | struct keyword words[];
32 | int init_config ()
33 | {
34 | FILE *f;
35 | int returnedValue;
36 |
37 | gconfig.port = UDP_LISTEN_PORT;
38 | lnslist = NULL;
39 | laclist = NULL;
40 | deflac = (struct lac *) malloc (sizeof (struct lac));
41 | f = fopen (CONFIG_FILE, "r");
42 | if (f)
43 | {
44 | strncpy (gconfig.authfile, DEFAULT_AUTH_FILE,
45 | sizeof (gconfig.authfile));
46 | }
47 | else
48 | {
49 | f = fopen (ALT_CONFIG_FILE, "r");
50 | if (f)
51 | {
52 | strncpy (gconfig.authfile, ALT_DEFAULT_AUTH_FILE,
53 | sizeof (gconfig.authfile));
54 | }
55 | else
56 | {
57 | log (LOG_CRIT, "%s: Unable to open config file %s or %s\n",
58 | __FUNCTION__, CONFIG_FILE, ALT_CONFIG_FILE);
59 | return -1;
60 | }
61 |
62 | }
63 | returnedValue = parse_config (f);
64 | fclose (f);
65 | return (returnedValue);
66 | filerr[0] = 0;
67 | };
68 |
69 | struct lns *new_lns ()
70 | {
71 | struct lns *tmp;
72 | tmp = (struct lns *) malloc (sizeof (struct lns));
73 | if (!tmp)
74 | {
75 | log (LOG_CRIT, "%s: Unable to allocate memory for new LNS\n",
76 | __FUNCTION__);
77 | return NULL;
78 | }
79 | tmp->next = NULL;
80 | tmp->exclusive = 0;
81 | tmp->localaddr = 0;
82 | tmp->tun_rws = DEFAULT_RWS_SIZE;
83 | tmp->call_rws = DEFAULT_RWS_SIZE;
84 | tmp->hbit = 0;
85 | tmp->lbit = 0;
86 | tmp->authpeer = 0;
87 | tmp->authself = -1;
88 | tmp->authname[0] = 0;
89 | tmp->peername[0] = 0;
90 | tmp->hostname[0] = 0;
91 | tmp->entname[0] = 0;
92 | tmp->range = NULL;
93 | tmp->lacs = NULL;
94 | tmp->passwdauth = 0;
95 | tmp->pap_require = 0;
96 | tmp->pap_refuse = 0;
97 | tmp->chap_require = 0;
98 | tmp->chap_refuse = 0;
99 | tmp->idle = 0;
100 | tmp->pridns = 0;
101 | tmp->secdns = 0;
102 | tmp->priwins = 0;
103 | tmp->secwins = 0;
104 | tmp->proxyarp = 0;
105 | tmp->proxyauth = 0;
106 | tmp->challenge = 0;
107 | tmp->debug = 0;
108 | tmp->pppoptfile[0] = 0;
109 | tmp->t = NULL;
110 | return tmp;
111 | }
112 |
113 | struct lac *new_lac ()
114 | {
115 | struct lac *tmp;
116 | tmp = (struct lac *) malloc (sizeof (struct lac));
117 | if (!tmp)
118 | {
119 | log (LOG_CRIT, "%s: Unable to allocate memory for lac entry!\n",
120 | __FUNCTION__);
121 | return NULL;
122 | }
123 | tmp->next = NULL;
124 | tmp->rsched = NULL;
125 | tmp->localaddr = 0;
126 | tmp->remoteaddr = 0;
127 | tmp->lns = 0;
128 | tmp->tun_rws = DEFAULT_RWS_SIZE;
129 | tmp->call_rws = DEFAULT_RWS_SIZE;
130 | tmp->hbit = 0;
131 | tmp->lbit = 0;
132 | tmp->authpeer = 0;
133 | tmp->authself = -1;
134 | tmp->authname[0] = 0;
135 | tmp->peername[0] = 0;
136 | tmp->hostname[0] = 0;
137 | tmp->entname[0] = 0;
138 | tmp->pap_require = 0;
139 | tmp->pap_refuse = 0;
140 | tmp->chap_require = 0;
141 | tmp->chap_refuse = 0;
142 | tmp->t = NULL;
143 | tmp->redial = 0;
144 | tmp->rtries = 0;
145 | tmp->rmax = 0;
146 | tmp->challenge = 0;
147 | tmp->autodial = 0;
148 | tmp->rtimeout = 30;
149 | tmp->active = 0;
150 | tmp->debug = 0;
151 | tmp->pppoptfile[0] = 0;
152 | tmp->defaultroute = 0;
153 | return tmp;
154 | }
155 |
156 | int yesno (char *value)
157 | {
158 | if (!strcasecmp (value, "yes") || !strcasecmp (value, "y") ||
159 | !strcasecmp (value, "true"))
160 | return 1;
161 | else if (!strcasecmp (value, "no") || !strcasecmp (value, "n") ||
162 | !strcasecmp (value, "false"))
163 | return 0;
164 | else
165 | return -1;
166 | }
167 |
168 | int set_boolean (char *word, char *value, int *ptr)
169 | {
170 | int val;
171 | #ifdef DEBUG_FILE
172 | log (LOG_DEBUG, "set_%s: %s flag to '%s'\n", word, word, value);
173 | #endif /* ; */
174 | if ((val = yesno (value)) < 0)
175 | {
176 | snprintf (filerr, sizeof (filerr), "%s must be 'yes' or 'no'\n",
177 | word);
178 | return -1;
179 | }
180 | *ptr = val;
181 | return 0;
182 | }
183 |
184 | int set_int (char *word, char *value, int *ptr)
185 | {
186 | int val;
187 | #ifdef DEBUG_FILE
188 | log (LOG_DEBUG, "set_%s: %s flag to '%s'\n", word, word, value);
189 | #endif /* ; */
190 | if ((val = atoi (value)) < 0)
191 | {
192 | snprintf (filerr, sizeof (filerr), "%s must be a number\n", word);
193 | return -1;
194 | }
195 | *ptr = val;
196 | return 0;
197 | }
198 |
199 | int set_string (char *word, char *value, char *ptr, int len)
200 | {
201 | #ifdef DEBUG_FILE
202 | log (LOG_DEBUG, "set_%s: %s flag to '%s'\n", word, word, value);
203 | #endif /* ; */
204 | strncpy (ptr, value, len);
205 | return 0;
206 | }
207 |
208 | int set_port (char *word, char *value, int context, void *item)
209 | {
210 | switch (context & ~CONTEXT_DEFAULT)
211 | {
212 | case CONTEXT_GLOBAL:
213 | #ifdef DEBUG_FILE
214 | log (LOG_DEBUG, "set_port: Setting global port number to %s\n",
215 | value);
216 | #endif
217 | set_int (word, value, &(((struct global *) item)->port));
218 | break;
219 | default:
220 | snprintf (filerr, sizeof (filerr), "'%s' not valid in this context\n",
221 | word);
222 | return -1;
223 | }
224 | return 0;
225 | }
226 |
227 | int set_rtimeout (char *word, char *value, int context, void *item)
228 | {
229 | if (atoi (value) < 1)
230 | {
231 | snprintf (filerr, sizeof (filerr),
232 | "rtimeout value must be at least 1\n");
233 | return -1;
234 | }
235 | switch (context & ~CONTEXT_DEFAULT)
236 | {
237 | case CONTEXT_LAC:
238 | #ifdef DEBUG_FILE
239 | log (LOG_DEBUG, "set_rtimeout: Setting redial timeout to %s\n",
240 | value);
241 | #endif
242 | set_int (word, value, &(((struct lac *) item)->rtimeout));
243 | break;
244 | default:
245 | snprintf (filerr, sizeof (filerr), "'%s' not valid in this context\n",
246 | word);
247 | return -1;
248 | }
249 | return 0;
250 | }
251 |
252 | int set_rws (char *word, char *value, int context, void *item)
253 | {
254 | if (atoi (value) < -1)
255 | {
256 | snprintf (filerr, sizeof (filerr),
257 | "receive window size must be at least -1\n");
258 | return -1;
259 | }
260 | switch (context & ~CONTEXT_DEFAULT)
261 | {
262 | case CONTEXT_LAC:
263 | if (word[0] == 'c')
264 | set_int (word, value, &(((struct lac *) item)->call_rws));
265 | if (word[0] == 't')
266 | {
267 | set_int (word, value, &(((struct lac *) item)->tun_rws));
268 | if (((struct lac *) item)->tun_rws < 1)
269 | {
270 | snprintf (filerr, sizeof (filerr),
271 | "receive window size for tunnels must be at least 1\n");
272 | return -1;
273 | }
274 | }
275 | break;
276 | case CONTEXT_LNS:
277 | if (word[0] == 'c')
278 | set_int (word, value, &(((struct lns *) item)->call_rws));
279 | if (word[0] == 't')
280 | {
281 | set_int (word, value, &(((struct lns *) item)->tun_rws));
282 | if (((struct lns *) item)->tun_rws < 1)
283 | {
284 | snprintf (filerr, sizeof (filerr),
285 | "receive window size for tunnels must be at least 1\n");
286 | return -1;
287 | }
288 | }
289 | break;
290 | default:
291 | snprintf (filerr, sizeof (filerr), "'%s' not valid in this context\n",
292 | word);
293 | return -1;
294 | }
295 | return 0;
296 | }
297 |
298 | int set_rmax (char *word, char *value, int context, void *item)
299 | {
300 | if (atoi (value) < 1)
301 | {
302 | snprintf (filerr, sizeof (filerr), "rmax value must be at least 1\n");
303 | return -1;
304 | }
305 | switch (context & ~CONTEXT_DEFAULT)
306 | {
307 | case CONTEXT_LAC:
308 | #ifdef DEBUG_FILE
309 | log (LOG_DEBUG, "set_rmax: Setting max redials to %s\n", value);
310 | #endif
311 | set_int (word, value, &(((struct lac *) item)->rmax));
312 | break;
313 | default:
314 | snprintf (filerr, sizeof (filerr), "'%s' not valid in this context\n",
315 | word);
316 | return -1;
317 | }
318 | return 0;
319 | }
320 |
321 | int set_authfile (char *word, char *value, int context, void *item)
322 | {
323 | if (!strlen (value))
324 | {
325 | snprintf (filerr, sizeof (filerr),
326 | "no filename specified for authentication\n");
327 | return -1;
328 | }
329 | switch (context & ~CONTEXT_DEFAULT)
330 | {
331 | case CONTEXT_GLOBAL:
332 | #ifdef DEBUG_FILE
333 | log (LOG_DEBUG, "set_authfile: Setting global auth file to '%s'\n",
334 | value);
335 | #endif /* ; */
336 | strncpy (((struct global *) item)->authfile, value,
337 | sizeof (((struct global *)item)->authfile));
338 | break;
339 | default:
340 | snprintf (filerr, sizeof (filerr), "'%s' not valid in this context\n",
341 | word);
342 | return -1;
343 | }
344 | return 0;
345 | }
346 |
347 | int set_autodial (char *word, char *value, int context, void *item)
348 | {
349 | switch (context & ~CONTEXT_DEFAULT)
350 | {
351 | case CONTEXT_LAC:
352 | if (set_boolean (word, value, &(((struct lac *) item)->autodial)))
353 | return -1;
354 | break;
355 | default:
356 | snprintf (filerr, sizeof (filerr), "'%s' not valid in this context\n",
357 | word);
358 | return -1;
359 | }
360 | return 0;
361 | }
362 |
363 | int set_flow (char *word, char *value, int context, void *item)
364 | {
365 | int v;
366 | set_boolean (word, value, &v);
367 | if (v < 0)
368 | return -1;
369 | switch (context & ~CONTEXT_DEFAULT)
370 | {
371 | case CONTEXT_LAC:
372 | if (v)
373 | {
374 | if (((struct lac *) item)->call_rws < 0)
375 | ((struct lac *) item)->call_rws = 0;
376 | }
377 | else
378 | {
379 | ((struct lac *) item)->call_rws = -1;
380 | }
381 | break;
382 | case CONTEXT_LNS:
383 | if (v)
384 | {
385 | if (((struct lns *) item)->call_rws < 0)
386 | ((struct lns *) item)->call_rws = 0;
387 | }
388 | else
389 | {
390 | ((struct lns *) item)->call_rws = -1;
391 | }
392 | break;
393 | default:
394 | snprintf (filerr, sizeof (filerr), "'%s' not valid in this context\n",
395 | word);
396 | return -1;
397 | }
398 | return 0;
399 | }
400 |
401 | int set_defaultroute (char *word, char *value, int context, void *item)
402 | {
403 | switch (context & ~CONTEXT_DEFAULT)
404 | {
405 | case CONTEXT_LAC:
406 | if (set_boolean (word, value, &(((struct lac *) item)->defaultroute)))
407 | return -1;
408 | break;
409 | default:
410 | snprintf (filerr, sizeof (filerr), "'%s' not valid in this context\n",
411 | word);
412 | return -1;
413 | }
414 | return 0;
415 | }
416 |
417 | int set_authname (char *word, char *value, int context, void *item)
418 | {
419 | struct lac *l = (struct lac *) item;
420 | struct lns *n = (struct lns *) item;
421 | switch (context & ~CONTEXT_DEFAULT)
422 | {
423 | case CONTEXT_LNS:
424 | if (set_string (word, value, n->authname, sizeof (n->authname)))
425 | return -1;
426 | break;
427 | case CONTEXT_LAC:
428 | if (set_string (word, value, l->authname, sizeof (l->authname)))
429 | return -1;
430 | break;
431 | default:
432 | snprintf (filerr, sizeof (filerr), "'%s' not valid in this context\n",
433 | word);
434 | return -1;
435 | }
436 | return 0;
437 | }
438 |
439 | int set_hostname (char *word, char *value, int context, void *item)
440 | {
441 | struct lac *l = (struct lac *) item;
442 | struct lns *n = (struct lns *) item;
443 | switch (context & ~CONTEXT_DEFAULT)
444 | {
445 | case CONTEXT_LNS:
446 | if (set_string (word, value, n->hostname, sizeof (n->hostname)))
447 | return -1;
448 | break;
449 | case CONTEXT_LAC:
450 | if (set_string (word, value, l->hostname, sizeof (l->hostname)))
451 | return -1;
452 | break;
453 | default:
454 | snprintf (filerr, sizeof (filerr), "'%s' not valid in this context\n",
455 | word);
456 | return -1;
457 | }
458 | return 0;
459 | }
460 |
461 | int set_passwdauth (char *word, char *value, int context, void *item)
462 | {
463 | switch (context & ~CONTEXT_DEFAULT)
464 | {
465 | case CONTEXT_LNS:
466 | if (set_boolean (word, value, &(((struct lns *) item)->passwdauth)))
467 | return -1;
468 | break;
469 | default:
470 | snprintf (filerr, sizeof (filerr), "'%s' not valid in this context\n",
471 | word);
472 | return -1;
473 | }
474 | return 0;
475 | }
476 |
477 | int set_hbit (char *word, char *value, int context, void *item)
478 | {
479 | switch (context & ~CONTEXT_DEFAULT)
480 | {
481 | case CONTEXT_LAC:
482 | if (set_boolean (word, value, &(((struct lac *) item)->hbit)))
483 | return -1;
484 | break;
485 | case CONTEXT_LNS:
486 | if (set_boolean (word, value, &(((struct lns *) item)->hbit)))
487 | return -1;
488 | break;
489 | default:
490 | snprintf (filerr, sizeof (filerr), "'%s' not valid in this context\n",
491 | word);
492 | return -1;
493 | }
494 | return 0;
495 | }
496 |
497 | int set_challenge (char *word, char *value, int context, void *item)
498 | {
499 | switch (context & ~CONTEXT_DEFAULT)
500 | {
501 | case CONTEXT_LAC:
502 | if (set_boolean (word, value, &(((struct lac *) item)->challenge)))
503 | return -1;
504 | break;
505 | case CONTEXT_LNS:
506 | if (set_boolean (word, value, &(((struct lns *) item)->challenge)))
507 | return -1;
508 | break;
509 | default:
510 | snprintf (filerr, sizeof (filerr), "'%s' not valid in this context\n",
511 | word);
512 | return -1;
513 | }
514 | return 0;
515 | }
516 |
517 | int set_lbit (char *word, char *value, int context, void *item)
518 | {
519 | switch (context & ~CONTEXT_DEFAULT)
520 | {
521 | case CONTEXT_LAC:
522 | if (set_boolean (word, value, &(((struct lac *) item)->lbit)))
523 | return -1;
524 | break;
525 | case CONTEXT_LNS:
526 | if (set_boolean (word, value, &(((struct lns *) item)->lbit)))
527 | return -1;
528 | break;
529 | default:
530 | snprintf (filerr, sizeof (filerr), "'%s' not valid in this context\n",
531 | word);
532 | return -1;
533 | }
534 | return 0;
535 | }
536 |
537 |
538 | int set_debug (char *word, char *value, int context, void *item)
539 | {
540 | switch (context & ~CONTEXT_DEFAULT)
541 | {
542 | case CONTEXT_LAC:
543 | if (set_boolean (word, value, &(((struct lac *) item)->debug)))
544 | return -1;
545 | break;
546 | case CONTEXT_LNS:
547 | if (set_boolean (word, value, &(((struct lns *) item)->debug)))
548 | return -1;
549 | break;
550 | default:
551 | snprintf (filerr, sizeof (filerr), "'%s' not valid in this context\n",
552 | word);
553 | return -1;
554 | }
555 | return 0;
556 | }
557 |
558 | int set_pppoptfile (char *word, char *value, int context, void *item)
559 | {
560 | struct lac *l = (struct lac *) item;
561 | struct lns *n = (struct lns *) item;
562 | switch (context & ~CONTEXT_DEFAULT)
563 | {
564 | case CONTEXT_LNS:
565 | if (set_string (word, value, n->pppoptfile, sizeof (n->pppoptfile)))
566 | return -1;
567 | break;
568 | case CONTEXT_LAC:
569 | if (set_string (word, value, l->pppoptfile, sizeof (l->pppoptfile)))
570 | return -1;
571 | break;
572 | default:
573 | snprintf (filerr, sizeof (filerr), "'%s' not valid in this context\n",
574 | word);
575 | return -1;
576 | }
577 | return 0;
578 | }
579 |
580 | int set_papchap (char *word, char *value, int context, void *item)
581 | {
582 | int result;
583 | char *c;
584 | struct lac *l = (struct lac *) item;
585 | struct lns *n = (struct lns *) item;
586 | if (set_boolean (word, value, &result))
587 | return -1;
588 | c = strchr (word, ' ');
589 | c++;
590 | switch (context & ~CONTEXT_DEFAULT)
591 | {
592 | case CONTEXT_LAC:
593 | if (c[0] == 'p') /* PAP */
594 | if (word[2] == 'f')
595 | l->pap_refuse = result;
596 | else
597 | l->pap_require = result;
598 | else if (c[0] == 'a') /* Authentication */
599 | if (word[2] == 'f')
600 | l->authself = result;
601 | else
602 | l->authpeer = result;
603 | else /* CHAP */ if (word[2] == 'f')
604 | l->chap_refuse = result;
605 | else
606 | l->chap_require = result;
607 | break;
608 | case CONTEXT_LNS:
609 | if (c[0] == 'p') /* PAP */
610 | if (word[2] == 'f')
611 | n->pap_refuse = result;
612 | else
613 | n->pap_require = result;
614 | else if (c[0] == 'a') /* Authentication */
615 | if (word[2] == 'f')
616 | n->authself = !result;
617 | else
618 | n->authpeer = result;
619 | else /* CHAP */ if (word[2] == 'f')
620 | n->chap_refuse = result;
621 | else
622 | n->chap_require = result;
623 | break;
624 | default:
625 | snprintf (filerr, sizeof (filerr), "'%s' not valid in this context\n",
626 | word);
627 | return -1;
628 | }
629 | return 0;
630 | }
631 |
632 | int set_redial (char *word, char *value, int context, void *item)
633 | {
634 | switch (context & ~CONTEXT_DEFAULT)
635 | {
636 | case CONTEXT_LAC:
637 | if (set_boolean (word, value, &(((struct lac *) item)->redial)))
638 | return -1;
639 | break;
640 | default:
641 | snprintf (filerr, sizeof (filerr), "'%s' not valid in this context\n",
642 | word);
643 | return -1;
644 | }
645 | return 0;
646 | }
647 |
648 | int set_accesscontrol (char *word, char *value, int context, void *item)
649 | {
650 | switch (context & ~CONTEXT_DEFAULT)
651 | {
652 | case CONTEXT_GLOBAL:
653 | if (set_boolean
654 | (word, value, &(((struct global *) item)->accesscontrol)))
655 | return -1;
656 | break;
657 | default:
658 | snprintf (filerr, sizeof (filerr), "'%s' not valid in this context\n",
659 | word);
660 | return -1;
661 | }
662 | return 0;
663 | }
664 |
665 | int set_userspace (char *word, char *value, int context, void *item)
666 | {
667 | switch (context & ~CONTEXT_DEFAULT)
668 | {
669 | case CONTEXT_GLOBAL:
670 | if (set_boolean
671 | (word, value, &(((struct global *) item)->forceuserspace)))
672 | return -1;
673 | break;
674 | default:
675 | snprintf (filerr, sizeof (filerr), "'%s' not valid in this context\n",
676 | word);
677 | return -1;
678 | }
679 | return 0;
680 | }
681 |
682 | struct iprange *set_range (char *word, char *value, struct iprange *in)
683 | {
684 | char *c, *d;
685 | struct iprange *ipr, *p;
686 | struct hostent *hp;
687 | c = strchr (value, '-');
688 | if (c)
689 | {
690 | d = c + 1;
691 | *c = 0;
692 | while ((c >= value) && (*c < 33))
693 | *(c--) = 0;
694 | while (*d && (*d < 33))
695 | d++;
696 | }
697 | if (!strlen (value) || (c && !strlen (d)))
698 | {
699 | snprintf (filerr, sizeof (filerr),
700 | "format is '%s <host or ip> - <host or ip>'\n", word);
701 | return NULL;
702 | }
703 | ipr = (struct iprange *) malloc (sizeof (struct iprange));
704 | ipr->next = NULL;
705 | hp = gethostbyname (value);
706 | if (!hp)
707 | {
708 | snprintf (filerr, sizeof (filerr), "Unknown host %s\n", value);
709 | free (ipr);
710 | return NULL;
711 | }
712 | bcopy (hp->h_addr, &ipr->start, sizeof (unsigned int));
713 | if (c)
714 | {
715 | hp = gethostbyname (d);
716 | if (!hp)
717 | {
718 | snprintf (filerr, sizeof (filerr), "Unknown host %s\n", d);
719 | free (ipr);
720 | return NULL;
721 | }
722 | bcopy (hp->h_addr, &ipr->end, sizeof (unsigned int));
723 | }
724 | else
725 | ipr->end = ipr->start;
726 | if (ntohl (ipr->start) > ntohl (ipr->end))
727 | {
728 | snprintf (filerr, sizeof (filerr), "start is greater than end!\n");
729 | free (ipr);
730 | return NULL;
731 | }
732 | if (word[0] == 'n')
733 | ipr->sense = SENSE_DENY;
734 | else
735 | ipr->sense = SENSE_ALLOW;
736 | p = in;
737 | if (p)
738 | {
739 | while (p->next)
740 | p = p->next;
741 | p->next = ipr;
742 | return in;
743 | }
744 | else
745 | return ipr;
746 | }
747 |
748 | int set_iprange (char *word, char *value, int context, void *item)
749 | {
750 | struct lns *lns = (struct lns *) item;
751 | switch (context & ~CONTEXT_DEFAULT)
752 | {
753 | case CONTEXT_LNS:
754 | break;
755 | default:
756 | snprintf (filerr, sizeof (filerr), "'%s' not valid in this context\n",
757 | word);
758 | return -1;
759 | }
760 | lns->range = set_range (word, value, lns->range);
761 | if (!lns->range)
762 | return -1;
763 | #ifdef DEBUG_FILE
764 | log (LOG_DEBUG, "range start = %x, end = %x, sense=%ud\n",
765 | ntohl (ipr->start), ntohl (ipr->end), ipr->sense);
766 | #endif
767 | return 0;
768 | }
769 |
770 | int set_lac (char *word, char *value, int context, void *item)
771 | {
772 | struct lns *lns = (struct lns *) item;
773 | switch (context & ~CONTEXT_DEFAULT)
774 | {
775 | case CONTEXT_LNS:
776 | break;
777 | default:
778 | snprintf (filerr, sizeof (filerr), "'%s' not valid in this context\n",
779 | word);
780 | return -1;
781 | }
782 | lns->lacs = set_range (word, value, lns->lacs);
783 | if (!lns->lacs)
784 | return -1;
785 | #ifdef DEBUG_FILE
786 | log (LOG_DEBUG, "lac start = %x, end = %x, sense=%ud\n",
787 | ntohl (ipr->start), ntohl (ipr->end), ipr->sense);
788 | #endif
789 | return 0;
790 | }
791 |
792 | int set_exclusive (char *word, char *value, int context, void *item)
793 | {
794 | switch (context & ~CONTEXT_DEFAULT)
795 | {
796 | case CONTEXT_LNS:
797 | if (set_boolean (word, value, &(((struct lns *) item)->exclusive)))
798 | return -1;
799 | break;
800 | default:
801 | snprintf (filerr, sizeof (filerr), "'%s' not valid in this context\n",
802 | word);
803 | return -1;
804 | }
805 | return 0;
806 | }
807 |
808 | int set_ip (char *word, char *value, unsigned int *addr)
809 | {
810 | struct hostent *hp;
811 | hp = gethostbyname (value);
812 | if (!hp)
813 | {
814 | snprintf (filerr, sizeof (filerr), "%s: host '%s' not found\n",
815 | __FUNCTION__, value);
816 | return -1;
817 | }
818 | bcopy (hp->h_addr, addr, sizeof (unsigned int));
819 | return 0;
820 | }
821 |
822 | int set_localaddr (char *word, char *value, int context, void *item)
823 | {
824 | struct lac *l;
825 | struct lns *n;
826 | switch (context & ~CONTEXT_DEFAULT)
827 | {
828 | case CONTEXT_LAC:
829 | l = (struct lac *) item;
830 | return set_ip (word, value, &(l->localaddr));
831 | case CONTEXT_LNS:
832 | n = (struct lns *) item;
833 | return set_ip (word, value, &(n->localaddr));
834 | default:
835 | snprintf (filerr, sizeof (filerr), "'%s' not valid in this context\n",
836 | word);
837 | return -1;
838 | }
839 | return 0;
840 | }
841 |
842 | int set_remoteaddr (char *word, char *value, int context, void *item)
843 | {
844 | struct lac *l;
845 | switch (context & ~CONTEXT_DEFAULT)
846 | {
847 | case CONTEXT_LAC:
848 | l = (struct lac *) item;
849 | return set_ip (word, value, &(l->remoteaddr));
850 | default:
851 | snprintf (filerr, sizeof (filerr), "'%s' not valid in this context\n",
852 | word);
853 | return -1;
854 | }
855 | return 0;
856 | }
857 |
858 | int set_lns (char *word, char *value, int context, void *item)
859 | {
860 | struct hostent *hp;
861 | struct lac *l;
862 | struct host *ipr, *pos;
863 | char *d;
864 | switch (context & ~CONTEXT_DEFAULT)
865 | {
866 | case CONTEXT_LAC:
867 | #ifdef DEBUG_FILE
868 | log (LOG_DEBUG, "set_lns: setting LNS to '%s'\n", value);
869 | #endif
870 | l = (struct lac *) item;
871 | d = strchr (value, ':');
872 | if (d)
873 | {
874 | d[0] = 0;
875 | d++;
876 | }
877 | hp = gethostbyname (value);
878 | if (!hp)
879 | {
880 | snprintf (filerr, sizeof (filerr), "no such host '%s'\n", value);
881 | return -1;
882 | }
883 | ipr = malloc (sizeof (struct host));
884 | ipr->next = NULL;
885 | pos = l->lns;
886 | if (!pos)
887 | {
888 | l->lns = ipr;
889 | }
890 | else
891 | {
892 | while (pos->next)
893 | pos = pos->next;
894 | pos->next = ipr;
895 | }
896 | strncpy (ipr->hostname, value, sizeof (ipr->hostname));
897 | if (d)
898 | ipr->port = atoi (d);
899 | else
900 | ipr->port = UDP_LISTEN_PORT;
901 | break;
902 | default:
903 | snprintf (filerr, sizeof (filerr), "'%s' not valid in this context\n",
904 | word);
905 | return -1;
906 | }
907 | return 0;
908 | }
909 |
910 | int parse_config (FILE * f)
911 | {
912 | /* Read in the configuration file handed to us */
913 | /* FIXME: I should check for incompatible options */
914 | int context = 0;
915 | char buf[STRLEN];
916 | char *s, *d, *t;
917 | int linenum = 0;
918 | int def = 0;
919 | struct keyword *kw;
920 | void *data = NULL;
921 | struct lns *tl;
922 | struct lac *tc;
923 | while (!feof (f))
924 | {
925 | fgets (buf, sizeof (buf), f);
926 | if (feof (f))
927 | break;
928 | linenum++;
929 | s = buf;
930 | /* Strip comments */
931 | while (*s && *s != ';')
932 | s++;
933 | *s = 0;
934 | s = buf;
935 | if (!strlen (buf))
936 | continue;
937 | while ((*s < 33) && *s)
938 | s++; /* Skip over beginning white space */
939 | t = s + strlen (s);
940 | while ((t >= s) && (*t < 33))
941 | *(t--) = 0; /* Ditch trailing white space */
942 | if (!strlen (s))
943 | continue;
944 | if (s[0] == '[')
945 | {
946 | /* We've got a context description */
947 | if (!(t = strchr (s, ']')))
948 | {
949 | log (LOG_CRIT, "parse_config: line %d: No closing bracket\n",
950 | linenum);
951 | return -1;
952 | }
953 | t[0] = 0;
954 | s++;
955 | if ((d = strchr (s, ' ')))
956 | {
957 | /* There's a parameter */
958 | d[0] = 0;
959 | d++;
960 | }
961 | if (d && !strcasecmp (d, "default"))
962 | def = CONTEXT_DEFAULT;
963 | else
964 | def = 0;
965 | if (!strcasecmp (s, "global"))
966 | {
967 | context = CONTEXT_GLOBAL;
968 | #ifdef DEBUG_FILE
969 | log (LOG_DEBUG,
970 | "parse_config: global context descriptor %s\n",
971 | d ? d : "");
972 | #endif
973 | data = &gconfig;
974 | }
975 | else if (!strcasecmp (s, "lns"))
976 | {
977 | context = CONTEXT_LNS;
978 | if (def)
979 | {
980 | if (!deflns)
981 | {
982 | deflns = new_lns ();
983 | strncpy (deflns->entname, "default",
984 | sizeof (deflns->entname));
985 | }
986 | data = deflns;
987 | continue;
988 | }
989 | data = NULL;
990 | tl = lnslist;
991 | if (d)
992 | {
993 | while (tl)
994 | {
995 | if (!strcasecmp (d, tl->entname))
996 | break;
997 | tl = tl->next;
998 | }
999 | if (tl)
1000 | data = tl;
1001 | }
1002 | if (!data)
1003 | {
1004 | data = new_lns ();
1005 | if (!data)
1006 | return -1;
1007 | ((struct lns *) data)->next = lnslist;
1008 | lnslist = (struct lns *) data;
1009 | }
1010 | if (d)
1011 | strncpy (((struct lns *) data)->entname,
1012 | d, sizeof (((struct lns *) data)->entname));
1013 | #ifdef DEBUG_FILE
1014 | log (LOG_DEBUG, "parse_config: lns context descriptor %s\n",
1015 | d ? d : "");
1016 | #endif
1017 | }
1018 | else if (!strcasecmp (s, "lac"))
1019 | {
1020 | context = CONTEXT_LAC;
1021 | if (def)
1022 | {
1023 | if (!deflac)
1024 | {
1025 | deflac = new_lac ();
1026 | strncpy (deflac->entname, "default",
1027 | sizeof (deflac->entname));
1028 | }
1029 | data = deflac;
1030 | continue;
1031 | }
1032 | data = NULL;
1033 | tc = laclist;
1034 | if (d)
1035 | {
1036 | while (tc)
1037 | {
1038 | if (!strcasecmp (d, tc->entname))
1039 | break;
1040 | tc = tc->next;
1041 | }
1042 | if (tc)
1043 | data = tc;
1044 | }
1045 | if (!data)
1046 | {
1047 | data = new_lac ();
1048 | if (!data)
1049 | return -1;
1050 | ((struct lac *) data)->next = laclist;
1051 | laclist = (struct lac *) data;
1052 | }
1053 | if (d)
1054 | strncpy (((struct lac *) data)->entname,
1055 | d, sizeof (((struct lac *) data)->entname));
1056 | #ifdef DEBUG_FILE
1057 | log (LOG_DEBUG, "parse_config: lac context descriptor %s\n",
1058 | d ? d : "");
1059 | #endif
1060 | }
1061 | else
1062 | {
1063 | log (LOG_WARN,
1064 | "parse_config: line %d: unknown context '%s'\n", linenum,
1065 | s);
1066 | return -1;
1067 | }
1068 | }
1069 | else
1070 | {
1071 | if (!context)
1072 | {
1073 | log (LOG_WARN,
1074 | "parse_config: line %d: data '%s' occurs with no context\n",
1075 | linenum, s);
1076 | return -1;
1077 | }
1078 | if (!(t = strchr (s, '=')))
1079 | {
1080 | log (LOG_WARN, "parse_config: line %d: no '=' in data\n",
1081 | linenum);
1082 | return -1;
1083 | }
1084 | d = t;
1085 | d--;
1086 | t++;
1087 | while ((d >= s) && (*d < 33))
1088 | d--;
1089 | d++;
1090 | *d = 0;
1091 | while (*t && (*t < 33))
1092 | t++;
1093 | #ifdef DEBUG_FILE
1094 | log (LOG_DEBUG, "parse_config: field is %s, value is %s\n", s, t);
1095 | #endif
1096 | /* Okay, bit twidling is done. Let's handle this */
1097 | for (kw = words; kw->keyword; kw++)
1098 | {
1099 | if (!strcasecmp (s, kw->keyword))
1100 | {
1101 | if (kw->handler (s, t, context | def, data))
1102 | {
1103 | log (LOG_WARN, "parse_config: line %d: %s", linenum,
1104 | filerr);
1105 | return -1;
1106 | }
1107 | break;
1108 | }
1109 | }
1110 | if (!kw->keyword)
1111 | {
1112 | log (LOG_CRIT, "parse_config: line %d: Unknown field '%s'\n",
1113 | linenum, s);
1114 | return -1;
1115 | }
1116 | }
1117 | }
1118 | return 0;
1119 | }
1120 |
1121 | struct keyword words[] = {
1122 | {"port", &set_port},
1123 | {"auth file", &set_authfile},
1124 | {"exclusive", &set_exclusive},
1125 | {"autodial", &set_autodial},
1126 | {"redial", &set_redial},
1127 | {"redial timeout", &set_rtimeout},
1128 | {"lns", &set_lns},
1129 | {"max redials", &set_rmax},
1130 | {"access control", &set_accesscontrol},
1131 | {"force userspace", &set_userspace},
1132 | {"ip range", &set_iprange},
1133 | {"no ip range", &set_iprange},
1134 | {"lac", &set_lac},
1135 | {"no lac", &set_lac},
1136 | {"local ip", &set_localaddr},
1137 | {"remote ip", &set_remoteaddr},
1138 | {"defaultroute", &set_defaultroute},
1139 | {"length bit", &set_lbit},
1140 | {"hidden bit", &set_hbit},
1141 | {"require pap", &set_papchap},
1142 | {"require chap", &set_papchap},
1143 | {"require authentication", &set_papchap},
1144 | {"require auth", &set_papchap},
1145 | {"refuse pap", &set_papchap},
1146 | {"refuse chap", &set_papchap},
1147 | {"refuse authentication", &set_papchap},
1148 | {"refuse auth", &set_papchap},
1149 | {"unix authentication", &set_passwdauth},
1150 | {"unix auth", &set_passwdauth},
1151 | {"name", &set_authname},
1152 | {"hostname", &set_hostname},
1153 | {"ppp debug", &set_debug},
1154 | {"pppoptfile", &set_pppoptfile},
1155 | {"call rws", &set_rws},
1156 | {"tunnel rws", &set_rws},
1157 | {"flow bit", &set_flow},
1158 | {"challenge", &set_challenge},
1159 | {NULL, NULL}
1160 | };