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 | };