1 /* 2 * Copyright (c) 1983, 1993 3 * The Regents of the University of California. All rights reserved. 4 * 5 * Redistribution and use in source and binary forms, with or without 6 * modification, are permitted provided that the following conditions 7 * are met: 8 * 1. Redistributions of source code must retain the above copyright 9 * notice, this list of conditions and the following disclaimer. 10 * 2. Redistributions in binary form must reproduce the above copyright 11 * notice, this list of conditions and the following disclaimer in the 12 * documentation and/or other materials provided with the distribution. 13 * 3. All advertising materials mentioning features or use of this software 14 * must display the following acknowledgment: 15 * This product includes software developed by the University of 16 * California, Berkeley and its contributors. 17 * 4. Neither the name of the University nor the names of its contributors 18 * may be used to endorse or promote products derived from this software 19 * without specific prior written permission. 20 * 21 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 22 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 23 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 24 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 25 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 26 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 27 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 28 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 29 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 30 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 31 * SUCH DAMAGE. 32 * 33 * $FreeBSD: src/sbin/routed/parms.c,v 1.7.2.1 2000/08/14 17:00:03 sheldonh Exp $ 34 */ 35 36 #include "defs.h" 37 #include "pathnames.h" 38 #include <sys/stat.h> 39 40 #if !defined(sgi) && !defined(__NetBSD__) 41 static char sccsid[] __attribute__((unused)) = "@(#)if.c 8.1 (Berkeley) 6/5/93"; 42 #elif defined(__NetBSD__) 43 __RCSID("$NetBSD$"); 44 #endif 45 46 47 struct parm *parms; 48 struct intnet *intnets; 49 struct r1net *r1nets; 50 struct tgate *tgates; 51 52 53 /* use configured parameters 54 */ 55 void 56 get_parms(struct interface *ifp) 57 { 58 static int warned_auth_in, warned_auth_out; 59 struct parm *parmp; 60 int i, num_passwds = 0; 61 62 /* get all relevant parameters 63 */ 64 for (parmp = parms; parmp != NULL; parmp = parmp->parm_next) { 65 if (parmp->parm_name[0] == '\0' 66 || !strcmp(ifp->int_name, parmp->parm_name) 67 || (parmp->parm_name[0] == '\n' 68 && on_net(ifp->int_addr, 69 parmp->parm_net, parmp->parm_mask))) { 70 71 /* This group of parameters is relevant, 72 * so get its settings 73 */ 74 ifp->int_state |= parmp->parm_int_state; 75 for (i = 0; i < MAX_AUTH_KEYS; i++) { 76 if (parmp->parm_auth[0].type == RIP_AUTH_NONE 77 || num_passwds >= MAX_AUTH_KEYS) 78 break; 79 memcpy(&ifp->int_auth[num_passwds++], 80 &parmp->parm_auth[i], 81 sizeof(ifp->int_auth[0])); 82 } 83 if (parmp->parm_rdisc_pref != 0) 84 ifp->int_rdisc_pref = parmp->parm_rdisc_pref; 85 if (parmp->parm_rdisc_int != 0) 86 ifp->int_rdisc_int = parmp->parm_rdisc_int; 87 if (parmp->parm_d_metric != 0) 88 ifp->int_d_metric = parmp->parm_d_metric; 89 } 90 } 91 92 /* Set general defaults. 93 * 94 * Default poor-man's router discovery to a metric that will 95 * be heard by old versions of `routed`. They ignored received 96 * routes with metric 15. 97 */ 98 if ((ifp->int_state & IS_PM_RDISC) 99 && ifp->int_d_metric == 0) 100 ifp->int_d_metric = FAKE_METRIC; 101 102 if (ifp->int_rdisc_int == 0) 103 ifp->int_rdisc_int = DefMaxAdvertiseInterval; 104 105 if (!(ifp->int_if_flags & IFF_MULTICAST) 106 && !(ifp->int_state & IS_REMOTE)) 107 ifp->int_state |= IS_BCAST_RDISC; 108 109 if (ifp->int_if_flags & IFF_POINTOPOINT) { 110 ifp->int_state |= IS_BCAST_RDISC; 111 /* By default, point-to-point links should be passive 112 * about router-discovery for the sake of demand-dialing. 113 */ 114 if (0 == (ifp->int_state & GROUP_IS_SOL_OUT)) 115 ifp->int_state |= IS_NO_SOL_OUT; 116 if (0 == (ifp->int_state & GROUP_IS_ADV_OUT)) 117 ifp->int_state |= IS_NO_ADV_OUT; 118 } 119 120 if (0 != (ifp->int_state & (IS_PASSIVE | IS_REMOTE))) 121 ifp->int_state |= IS_NO_RDISC; 122 if (ifp->int_state & IS_PASSIVE) 123 ifp->int_state |= IS_NO_RIP; 124 125 if (!IS_RIP_IN_OFF(ifp->int_state) 126 && ifp->int_auth[0].type != RIP_AUTH_NONE 127 && !(ifp->int_state & IS_NO_RIPV1_IN) 128 && !warned_auth_in) { 129 msglog("Warning: RIPv1 input via %s" 130 " will be accepted without authentication", 131 ifp->int_name); 132 warned_auth_in = 1; 133 } 134 if (!IS_RIP_OUT_OFF(ifp->int_state) 135 && ifp->int_auth[0].type != RIP_AUTH_NONE 136 && !(ifp->int_state & IS_NO_RIPV1_OUT)) { 137 if (!warned_auth_out) { 138 msglog("Warning: RIPv1 output via %s" 139 " will be sent without authentication", 140 ifp->int_name); 141 warned_auth_out = 1; 142 } 143 } 144 } 145 146 147 /* Read a list of gateways from /etc/gateways and add them to our tables. 148 * 149 * This file contains a list of "remote" gateways. That is usually 150 * a gateway which we cannot immediately determine if it is present or 151 * not as we can do for those provided by directly connected hardware. 152 * 153 * If a gateway is marked "passive" in the file, then we assume it 154 * does not understand RIP and assume it is always present. Those 155 * not marked passive are treated as if they were directly connected 156 * and assumed to be broken if they do not send us advertisements. 157 * All remote interfaces are added to our list, and those not marked 158 * passive are sent routing updates. 159 * 160 * A passive interface can also be local, hardware interface exempt 161 * from RIP. 162 */ 163 void 164 gwkludge(void) 165 { 166 FILE *fp; 167 char *p, *lptr; 168 const char *cp; 169 char lbuf[200], net_host[5], dname[64+1+64+1]; 170 char gname[GNAME_LEN+1], qual[9]; 171 struct interface *ifp; 172 naddr dst, netmask, gate; 173 int metric, n, lnum; 174 struct stat sb; 175 u_int state; 176 const char *type; 177 178 179 fp = fopen(_PATH_GATEWAYS, "r"); 180 if (fp == NULL) 181 return; 182 183 if (0 > fstat(fileno(fp), &sb)) { 184 msglog("could not stat() "_PATH_GATEWAYS); 185 fclose(fp); 186 return; 187 } 188 189 for (lnum = 1; ; lnum++) { 190 if (0 == fgets(lbuf, sizeof(lbuf), fp)) 191 break; 192 lptr = lbuf; 193 while (*lptr == ' ') 194 lptr++; 195 p = lptr+strlen(lptr)-1; 196 while (*p == '\n' 197 || (*p == ' ' && (p == lptr+1 || *(p-1) != '\\'))) 198 *p-- = '\0'; 199 if (*lptr == '\0' /* ignore null and comment lines */ 200 || *lptr == '#') 201 continue; 202 203 /* notice newfangled parameter lines 204 */ 205 if (strncasecmp("net", lptr, 3) 206 && strncasecmp("host", lptr, 4)) { 207 cp = parse_parms(lptr, 208 (sb.st_uid == 0 209 && !(sb.st_mode&(S_IRWXG|S_IRWXO)))); 210 if (cp != NULL) 211 msglog("%s in line %d of "_PATH_GATEWAYS, 212 cp, lnum); 213 continue; 214 } 215 216 /* {net | host} XX[/M] XX gateway XX metric DD [passive | external]\n */ 217 qual[0] = '\0'; 218 /* the '64' here must be GNAME_LEN */ 219 n = sscanf(lptr, "%4s %129[^ \t] gateway" 220 " %64[^ / \t] metric %u %8s\n", 221 net_host, dname, gname, &metric, qual); 222 if (n != 4 && n != 5) { 223 msglog("bad "_PATH_GATEWAYS" entry \"%s\"; %d values", 224 lptr, n); 225 continue; 226 } 227 if (metric >= HOPCNT_INFINITY) { 228 msglog("bad metric in "_PATH_GATEWAYS" entry \"%s\"", 229 lptr); 230 continue; 231 } 232 if (!strcasecmp(net_host, "host")) { 233 if (!gethost(dname, &dst)) { 234 msglog("bad host \"%s\" in "_PATH_GATEWAYS 235 " entry \"%s\"", dname, lptr); 236 continue; 237 } 238 netmask = HOST_MASK; 239 } else if (!strcasecmp(net_host, "net")) { 240 if (!getnet(dname, &dst, &netmask)) { 241 msglog("bad net \"%s\" in "_PATH_GATEWAYS 242 " entry \"%s\"", dname, lptr); 243 continue; 244 } 245 if (dst == RIP_DEFAULT) { 246 msglog("bad net \"%s\" in "_PATH_GATEWAYS 247 " entry \"%s\"--cannot be default", 248 dname, lptr); 249 continue; 250 } 251 dst = htonl(dst); /* make network # into IP address */ 252 } else { 253 msglog("bad \"%s\" in "_PATH_GATEWAYS 254 " entry \"%s\"", net_host, lptr); 255 continue; 256 } 257 258 if (!gethost(gname, &gate)) { 259 msglog("bad gateway \"%s\" in "_PATH_GATEWAYS 260 " entry \"%s\"", gname, lptr); 261 continue; 262 } 263 264 if (!strcasecmp(qual, type = "passive")) { 265 /* Passive entries are not placed in our tables, 266 * only the kernel's, so we don't copy all of the 267 * external routing information within a net. 268 * Internal machines should use the default 269 * route to a suitable gateway (like us). 270 */ 271 state = IS_REMOTE | IS_PASSIVE; 272 if (metric == 0) 273 metric = 1; 274 275 } else if (!strcasecmp(qual, type = "external")) { 276 /* External entries are handled by other means 277 * such as EGP, and are placed only in the daemon 278 * tables to prevent overriding them with something 279 * else. 280 */ 281 strcpy(qual,"external"); 282 state = IS_REMOTE | IS_PASSIVE | IS_EXTERNAL; 283 if (metric == 0) 284 metric = 1; 285 286 } else if (!strcasecmp(qual, "active") 287 || qual[0] == '\0') { 288 if (metric != 0) { 289 /* Entries that are neither "passive" nor 290 * "external" are "remote" and must behave 291 * like physical interfaces. If they are not 292 * heard from regularly, they are deleted. 293 */ 294 state = IS_REMOTE; 295 type = "remote"; 296 } else { 297 /* "remote" entries with a metric of 0 298 * are aliases for our own interfaces 299 */ 300 state = IS_REMOTE | IS_PASSIVE | IS_ALIAS; 301 type = "alias"; 302 } 303 304 } else { 305 msglog("bad "_PATH_GATEWAYS" entry \"%s\";" 306 " unknown type %s", lptr, qual); 307 continue; 308 } 309 310 if (0 != (state & (IS_PASSIVE | IS_REMOTE))) 311 state |= IS_NO_RDISC; 312 if (state & IS_PASSIVE) 313 state |= IS_NO_RIP; 314 315 ifp = check_dup(gate,dst,netmask,0); 316 if (ifp != NULL) { 317 msglog("duplicate "_PATH_GATEWAYS" entry \"%s\"",lptr); 318 continue; 319 } 320 321 ifp = (struct interface *)rtmalloc(sizeof(*ifp), "gwkludge()"); 322 memset(ifp, 0, sizeof(*ifp)); 323 324 ifp->int_state = state; 325 if (netmask == HOST_MASK) 326 ifp->int_if_flags = IFF_POINTOPOINT | IFF_UP; 327 else 328 ifp->int_if_flags = IFF_UP; 329 ifp->int_act_time = NEVER; 330 ifp->int_addr = gate; 331 ifp->int_dstaddr = dst; 332 ifp->int_mask = netmask; 333 ifp->int_ripv1_mask = netmask; 334 ifp->int_std_mask = std_mask(gate); 335 ifp->int_net = ntohl(dst); 336 ifp->int_std_net = ifp->int_net & ifp->int_std_mask; 337 ifp->int_std_addr = htonl(ifp->int_std_net); 338 ifp->int_metric = metric; 339 if (!(state & IS_EXTERNAL) 340 && ifp->int_mask != ifp->int_std_mask) 341 ifp->int_state |= IS_SUBNET; 342 sprintf(ifp->int_name, "%s(%s)", type, gname); 343 ifp->int_index = -1; 344 345 if_link(ifp); 346 } 347 348 /* After all of the parameter lines have been read, 349 * apply them to any remote interfaces. 350 */ 351 for (ifp = ifnet; NULL != ifp; ifp = ifp->int_next) { 352 get_parms(ifp); 353 354 tot_interfaces++; 355 if (!IS_RIP_OFF(ifp->int_state)) 356 rip_interfaces++; 357 358 trace_if("Add", ifp); 359 } 360 361 fclose(fp); 362 } 363 364 365 /* like strtok(), but honoring backslash and not changing the source string 366 */ 367 static int /* 0=ok, -1=bad */ 368 parse_quote(char **linep, /* look here */ 369 const char *delims, /* for these delimiters */ 370 char *delimp, /* 0 or put found delimiter here */ 371 char *buf, /* copy token to here */ 372 int lim) /* at most this many bytes */ 373 { 374 char c = '\0', *pc; 375 const char *p; 376 377 378 pc = *linep; 379 if (*pc == '\0') 380 return -1; 381 382 while (lim != 0) { 383 c = *pc++; 384 if (c == '\0') 385 break; 386 387 if (c == '\\' && *pc != '\0') { 388 if ((c = *pc++) == 'n') { 389 c = '\n'; 390 } else if (c == 'r') { 391 c = '\r'; 392 } else if (c == 't') { 393 c = '\t'; 394 } else if (c == 'b') { 395 c = '\b'; 396 } else if (c >= '0' && c <= '7') { 397 c -= '0'; 398 if (*pc >= '0' && *pc <= '7') { 399 c = (c<<3)+(*pc++ - '0'); 400 if (*pc >= '0' && *pc <= '7') 401 c = (c<<3)+(*pc++ - '0'); 402 } 403 } 404 405 } else { 406 for (p = delims; *p != '\0'; ++p) { 407 if (*p == c) 408 goto exit; 409 } 410 } 411 412 *buf++ = c; 413 --lim; 414 } 415 exit: 416 if (lim == 0) 417 return -1; 418 419 *buf = '\0'; /* terminate copy of token */ 420 if (delimp != NULL) 421 *delimp = c; /* return delimiter */ 422 *linep = pc-1; /* say where we ended */ 423 return 0; 424 } 425 426 427 /* Parse password timestamp 428 */ 429 static char * 430 parse_ts(time_t *tp, 431 char **valp, 432 char *val0, 433 char *delimp, 434 char *buf, 435 u_int bufsize) 436 { 437 struct tm tm; 438 #if defined(sgi) || defined(__NetBSD__) 439 char *ptr; 440 #endif 441 442 if (0 > parse_quote(valp, "| ,\n\r", delimp, 443 buf,bufsize) 444 || buf[bufsize-1] != '\0' 445 || buf[bufsize-2] != '\0') { 446 sprintf(buf,"bad timestamp %.25s", val0); 447 return buf; 448 } 449 strcat(buf,"\n"); 450 memset(&tm, 0, sizeof(tm)); 451 #if defined(sgi) || defined(__NetBSD__) 452 ptr = strptime(buf, "%y/%m/%d@%H:%M\n", &tm); 453 if (ptr == NULL || *ptr != '\0') { 454 sprintf(buf,"bad timestamp %.25s", val0); 455 return buf; 456 } 457 #else 458 if (5 != sscanf(buf, "%u/%u/%u@%u:%u\n", 459 &tm.tm_year, &tm.tm_mon, &tm.tm_mday, 460 &tm.tm_hour, &tm.tm_min) 461 || tm.tm_mon < 1 || tm.tm_mon > 12 462 || tm.tm_mday < 1 || tm.tm_mday > 31) { 463 sprintf(buf,"bad timestamp %.25s", val0); 464 return buf; 465 } 466 tm.tm_mon--; 467 if (tm.tm_year <= 37) /* assume small years are in the */ 468 tm.tm_year += 100; /* 3rd millenium */ 469 #endif 470 471 if ((*tp = mktime(&tm)) == -1) { 472 sprintf(buf,"bad timestamp %.25s", val0); 473 return buf; 474 } 475 476 return 0; 477 } 478 479 480 /* Get a password, key ID, and expiration date in the format 481 * passwd|keyID|year/mon/day@hour:min|year/mon/day@hour:min 482 */ 483 static const char * /* 0 or error message */ 484 get_passwd(char *tgt, 485 char *val, 486 struct parm *parmp, 487 u_int16_t type, 488 int safe) /* 1=from secure file */ 489 { 490 static char buf[80]; 491 char *val0, *p, delim; 492 struct auth k, *ap, *ap2; 493 int i; 494 u_long l; 495 496 497 if (!safe) 498 return "ignore unsafe password"; 499 500 for (ap = parmp->parm_auth, i = 0; 501 ap->type != RIP_AUTH_NONE; i++, ap++) { 502 if (i >= MAX_AUTH_KEYS) 503 return "too many passwords"; 504 } 505 506 memset(&k, 0, sizeof(k)); 507 k.type = type; 508 k.end = -1-DAY; 509 510 val0 = val; 511 if (0 > parse_quote(&val, "| ,\n\r", &delim, 512 (char *)k.key, sizeof(k.key))) 513 return tgt; 514 515 if (delim != '|') { 516 if (type == RIP_AUTH_MD5) 517 return "missing Keyid"; 518 } else { 519 val0 = ++val; 520 buf[sizeof(buf)-1] = '\0'; 521 if (0 > parse_quote(&val, "| ,\n\r", &delim, buf,sizeof(buf)) 522 || buf[sizeof(buf)-1] != '\0' 523 || (l = strtoul(buf,&p,0)) > 255 524 || *p != '\0') { 525 sprintf(buf,"bad KeyID \"%.20s\"", val0); 526 return buf; 527 } 528 for (ap2 = parmp->parm_auth; ap2 < ap; ap2++) { 529 if (ap2->keyid == l) { 530 sprintf(buf,"duplicate KeyID \"%.20s\"", val0); 531 return buf; 532 } 533 } 534 k.keyid = (int)l; 535 536 if (delim == '|') { 537 val0 = ++val; 538 if (NULL != (p = parse_ts(&k.start,&val,val0,&delim, 539 buf,sizeof(buf)))) 540 return p; 541 if (delim != '|') 542 return "missing second timestamp"; 543 val0 = ++val; 544 if (NULL != (p = parse_ts(&k.end,&val,val0,&delim, 545 buf,sizeof(buf)))) 546 return p; 547 if ((u_long)k.start > (u_long)k.end) { 548 sprintf(buf,"out of order timestamp %.30s", 549 val0); 550 return buf; 551 } 552 } 553 } 554 if (delim != '\0') 555 return tgt; 556 557 memmove(ap, &k, sizeof(*ap)); 558 return 0; 559 } 560 561 562 static const char * 563 bad_str(const char *estr) 564 { 565 static char buf[100+8]; 566 567 sprintf(buf, "bad \"%.100s\"", estr); 568 return buf; 569 } 570 571 572 /* Parse a set of parameters for an interface. 573 */ 574 const char * /* 0 or error message */ 575 parse_parms(char *line, 576 int safe) /* 1=from secure file */ 577 { 578 #define PARS(str) (!strcasecmp(tgt, str)) 579 #define PARSEQ(str) (!strncasecmp(tgt, str"=", sizeof(str))) 580 #define CKF(g,b) {if (0 != (parm.parm_int_state & ((g) & ~(b)))) break; \ 581 parm.parm_int_state |= (b);} 582 struct parm parm; 583 struct intnet *intnetp; 584 struct r1net *r1netp; 585 struct tgate *tg; 586 naddr addr, mask; 587 char delim, *val0 = NULL, *tgt, *val, *p; 588 const char *msg; 589 char buf[BUFSIZ], buf2[BUFSIZ]; 590 int i; 591 592 593 /* "subnet=x.y.z.u/mask[,metric]" must be alone on the line */ 594 if (!strncasecmp(line, "subnet=", sizeof("subnet=")-1) 595 && *(val = &line[sizeof("subnet=")-1]) != '\0') { 596 if (0 > parse_quote(&val, ",", &delim, buf, sizeof(buf))) 597 return bad_str(line); 598 intnetp = (struct intnet*)rtmalloc(sizeof(*intnetp), 599 "parse_parms subnet"); 600 intnetp->intnet_metric = 1; 601 if (delim == ',') { 602 intnetp->intnet_metric = (int)strtol(val+1,&p,0); 603 if (*p != '\0' 604 || intnetp->intnet_metric <= 0 605 || intnetp->intnet_metric >= HOPCNT_INFINITY) 606 return bad_str(line); 607 } 608 if (!getnet(buf, &intnetp->intnet_addr, &intnetp->intnet_mask) 609 || intnetp->intnet_mask == HOST_MASK 610 || intnetp->intnet_addr == RIP_DEFAULT) { 611 free(intnetp); 612 return bad_str(line); 613 } 614 intnetp->intnet_addr = htonl(intnetp->intnet_addr); 615 intnetp->intnet_next = intnets; 616 intnets = intnetp; 617 return 0; 618 } 619 620 /* "ripv1_mask=x.y.z.u/mask1,mask2" must be alone on the line. 621 * This requires that x.y.z.u/mask1 be considered a subnet of 622 * x.y.z.u/mask2, as if x.y.z.u/mask2 were a class-full network. 623 */ 624 if (!strncasecmp(line, "ripv1_mask=", sizeof("ripv1_mask=")-1) 625 && *(val = &line[sizeof("ripv1_mask=")-1]) != '\0') { 626 if (0 > parse_quote(&val, ",", &delim, buf, sizeof(buf)) 627 || delim == '\0') 628 return bad_str(line); 629 if ((i = (int)strtol(val+1, &p, 0)) <= 0 630 || i > 32 || *p != '\0') 631 return bad_str(line); 632 r1netp = (struct r1net *)rtmalloc(sizeof(*r1netp), 633 "parse_parms ripv1_mask"); 634 r1netp->r1net_mask = HOST_MASK << (32-i); 635 if (!getnet(buf, &r1netp->r1net_net, &r1netp->r1net_match) 636 || r1netp->r1net_net == RIP_DEFAULT 637 || r1netp->r1net_mask > r1netp->r1net_match) { 638 free(r1netp); 639 return bad_str(line); 640 } 641 r1netp->r1net_next = r1nets; 642 r1nets = r1netp; 643 return 0; 644 } 645 646 memset(&parm, 0, sizeof(parm)); 647 648 for (;;) { 649 tgt = line + strspn(line, " ,\n\r"); 650 if (*tgt == '\0' || *tgt == '#') 651 break; 652 line = tgt+strcspn(tgt, "= #,\n\r"); 653 delim = *line; 654 if (delim == '=') { 655 val0 = ++line; 656 if (0 > parse_quote(&line, " #,\n\r",&delim, 657 buf,sizeof(buf))) 658 return bad_str(tgt); 659 } 660 if (delim != '\0') { 661 for (;;) { 662 *line = '\0'; 663 if (delim == '#') 664 break; 665 ++line; 666 if (delim != ' ' 667 || (delim = *line) != ' ') 668 break; 669 } 670 } 671 672 if (PARSEQ("if")) { 673 if (parm.parm_name[0] != '\0' 674 || strlen(buf) > IF_NAME_LEN) 675 return bad_str(tgt); 676 strcpy(parm.parm_name, buf); 677 678 } else if (PARSEQ("addr")) { 679 /* This is a bad idea, because the address based 680 * sets of parameters cannot be checked for 681 * consistency with the interface name parameters. 682 * The parm_net stuff is needed to allow several 683 * -F settings. 684 */ 685 if (!getnet(val0, &addr, &mask) 686 || parm.parm_name[0] != '\0') 687 return bad_str(tgt); 688 parm.parm_net = addr; 689 parm.parm_mask = mask; 690 parm.parm_name[0] = '\n'; 691 692 } else if (PARSEQ("passwd")) { 693 /* since cleartext passwords are so weak allow 694 * them anywhere 695 */ 696 msg = get_passwd(tgt,val0,&parm,RIP_AUTH_PW,1); 697 if (msg) { 698 *val0 = '\0'; 699 return bad_str(msg); 700 } 701 702 } else if (PARSEQ("md5_passwd")) { 703 msg = get_passwd(tgt,val0,&parm,RIP_AUTH_MD5,safe); 704 if (msg) { 705 *val0 = '\0'; 706 return bad_str(msg); 707 } 708 709 } else if (PARS("no_ag")) { 710 parm.parm_int_state |= (IS_NO_AG | IS_NO_SUPER_AG); 711 712 } else if (PARS("no_super_ag")) { 713 parm.parm_int_state |= IS_NO_SUPER_AG; 714 715 } else if (PARS("no_ripv1_in")) { 716 parm.parm_int_state |= IS_NO_RIPV1_IN; 717 718 } else if (PARS("no_ripv2_in")) { 719 parm.parm_int_state |= IS_NO_RIPV2_IN; 720 721 } else if (PARS("ripv2_out")) { 722 if (parm.parm_int_state & IS_NO_RIPV2_OUT) 723 return bad_str(tgt); 724 parm.parm_int_state |= IS_NO_RIPV1_OUT; 725 726 } else if (PARS("ripv2")) { 727 if ((parm.parm_int_state & IS_NO_RIPV2_OUT) 728 || (parm.parm_int_state & IS_NO_RIPV2_IN)) 729 return bad_str(tgt); 730 parm.parm_int_state |= (IS_NO_RIPV1_IN 731 | IS_NO_RIPV1_OUT); 732 733 } else if (PARS("no_rip")) { 734 CKF(IS_PM_RDISC, IS_NO_RIP); 735 736 } else if (PARS("no_rip_mcast")) { 737 parm.parm_int_state |= IS_NO_RIP_MCAST; 738 739 } else if (PARS("no_rdisc")) { 740 CKF((GROUP_IS_SOL_OUT|GROUP_IS_ADV_OUT), IS_NO_RDISC); 741 742 } else if (PARS("no_solicit")) { 743 CKF(GROUP_IS_SOL_OUT, IS_NO_SOL_OUT); 744 745 } else if (PARS("send_solicit")) { 746 CKF(GROUP_IS_SOL_OUT, IS_SOL_OUT); 747 748 } else if (PARS("no_rdisc_adv")) { 749 CKF(GROUP_IS_ADV_OUT, IS_NO_ADV_OUT); 750 751 } else if (PARS("rdisc_adv")) { 752 CKF(GROUP_IS_ADV_OUT, IS_ADV_OUT); 753 754 } else if (PARS("bcast_rdisc")) { 755 parm.parm_int_state |= IS_BCAST_RDISC; 756 757 } else if (PARS("passive")) { 758 CKF((GROUP_IS_SOL_OUT|GROUP_IS_ADV_OUT), IS_NO_RDISC); 759 parm.parm_int_state |= IS_NO_RIP| IS_PASSIVE; 760 761 } else if (PARSEQ("rdisc_pref")) { 762 if (parm.parm_rdisc_pref != 0 763 || (parm.parm_rdisc_pref = (int)strtol(buf,&p,0), 764 *p != '\0')) 765 return bad_str(tgt); 766 767 } else if (PARS("pm_rdisc")) { 768 if (IS_RIP_OUT_OFF(parm.parm_int_state)) 769 return bad_str(tgt); 770 parm.parm_int_state |= IS_PM_RDISC; 771 772 } else if (PARSEQ("rdisc_interval")) { 773 if (parm.parm_rdisc_int != 0 774 || (parm.parm_rdisc_int = (int)strtoul(buf,&p,0), 775 *p != '\0') 776 || parm.parm_rdisc_int < MinMaxAdvertiseInterval 777 || parm.parm_rdisc_int > MaxMaxAdvertiseInterval) 778 return bad_str(tgt); 779 780 } else if (PARSEQ("fake_default")) { 781 if (parm.parm_d_metric != 0 782 || IS_RIP_OUT_OFF(parm.parm_int_state) 783 || (parm.parm_d_metric = (int)strtoul(buf,&p,0), 784 *p != '\0') 785 || parm.parm_d_metric > HOPCNT_INFINITY-1) 786 return bad_str(tgt); 787 788 } else if (PARSEQ("trust_gateway")) { 789 /* look for trust_gateway=x.y.z|net/mask|...) */ 790 p = buf; 791 if (0 > parse_quote(&p, "|", &delim, 792 buf2, sizeof(buf2)) 793 || !gethost(buf2,&addr)) 794 return bad_str(tgt); 795 tg = (struct tgate *)rtmalloc(sizeof(*tg), 796 "parse_parms" 797 "trust_gateway"); 798 memset(tg, 0, sizeof(*tg)); 799 tg->tgate_addr = addr; 800 i = 0; 801 /* The default is to trust all routes. */ 802 while (delim == '|') { 803 p++; 804 if (i >= MAX_TGATE_NETS 805 || 0 > parse_quote(&p, "|", &delim, 806 buf2, sizeof(buf2)) 807 || !getnet(buf2, &tg->tgate_nets[i].net, 808 &tg->tgate_nets[i].mask) 809 || tg->tgate_nets[i].net == RIP_DEFAULT 810 || tg->tgate_nets[i].mask == 0) 811 return bad_str(tgt); 812 i++; 813 } 814 tg->tgate_next = tgates; 815 tgates = tg; 816 parm.parm_int_state |= IS_DISTRUST; 817 818 } else if (PARS("redirect_ok")) { 819 parm.parm_int_state |= IS_REDIRECT_OK; 820 821 } else { 822 return bad_str(tgt); /* error */ 823 } 824 } 825 826 return check_parms(&parm); 827 #undef PARS 828 #undef PARSEQ 829 } 830 831 832 /* check for duplicate parameter specifications */ 833 const char * /* 0 or error message */ 834 check_parms(struct parm *new) 835 { 836 struct parm *parmp, **parmpp; 837 int i, num_passwds; 838 839 /* set implicit values 840 */ 841 if (new->parm_int_state & IS_NO_ADV_IN) 842 new->parm_int_state |= IS_NO_SOL_OUT; 843 if (new->parm_int_state & IS_NO_SOL_OUT) 844 new->parm_int_state |= IS_NO_ADV_IN; 845 846 for (i = num_passwds = 0; i < MAX_AUTH_KEYS; i++) { 847 if (new->parm_auth[i].type != RIP_AUTH_NONE) 848 num_passwds++; 849 } 850 851 /* compare with existing sets of parameters 852 */ 853 for (parmpp = &parms; 854 (parmp = *parmpp) != NULL; 855 parmpp = &parmp->parm_next) { 856 if (strcmp(new->parm_name, parmp->parm_name)) 857 continue; 858 if (!on_net(htonl(parmp->parm_net), 859 new->parm_net, new->parm_mask) 860 && !on_net(htonl(new->parm_net), 861 parmp->parm_net, parmp->parm_mask)) 862 continue; 863 864 for (i = 0; i < MAX_AUTH_KEYS; i++) { 865 if (parmp->parm_auth[i].type != RIP_AUTH_NONE) 866 num_passwds++; 867 } 868 if (num_passwds > MAX_AUTH_KEYS) 869 return "too many conflicting passwords"; 870 871 if ((0 != (new->parm_int_state & GROUP_IS_SOL_OUT) 872 && 0 != (parmp->parm_int_state & GROUP_IS_SOL_OUT) 873 && 0 != ((new->parm_int_state ^ parmp->parm_int_state) 874 & GROUP_IS_SOL_OUT)) 875 || (0 != (new->parm_int_state & GROUP_IS_ADV_OUT) 876 && 0 != (parmp->parm_int_state & GROUP_IS_ADV_OUT) 877 && 0 != ((new->parm_int_state ^ parmp->parm_int_state) 878 & GROUP_IS_ADV_OUT)) 879 || (new->parm_rdisc_pref != 0 880 && parmp->parm_rdisc_pref != 0 881 && new->parm_rdisc_pref != parmp->parm_rdisc_pref) 882 || (new->parm_rdisc_int != 0 883 && parmp->parm_rdisc_int != 0 884 && new->parm_rdisc_int != parmp->parm_rdisc_int)) { 885 return ("conflicting, duplicate router discovery" 886 " parameters"); 887 888 } 889 890 if (new->parm_d_metric != 0 891 && parmp->parm_d_metric != 0 892 && new->parm_d_metric != parmp->parm_d_metric) { 893 return ("conflicting, duplicate poor man's router" 894 " discovery or fake default metric"); 895 } 896 } 897 898 /* link new entry on the so that when the entries are scanned, 899 * they affect the result in the order the operator specified. 900 */ 901 parmp = (struct parm*)rtmalloc(sizeof(*parmp), "check_parms"); 902 memcpy(parmp, new, sizeof(*parmp)); 903 *parmpp = parmp; 904 905 return 0; 906 } 907 908 909 /* get a network number as a name or a number, with an optional "/xx" 910 * netmask. 911 */ 912 int /* 0=bad */ 913 getnet(char *name, 914 naddr *netp, /* network in host byte order */ 915 naddr *maskp) /* masks are always in host order */ 916 { 917 int i; 918 struct netent *np; 919 naddr mask; /* in host byte order */ 920 struct in_addr in; /* a network and so host byte order */ 921 char hname[MAXHOSTNAMELEN+1]; 922 char *mname, *p; 923 924 925 /* Detect and separate "1.2.3.4/24" 926 */ 927 if (NULL != (mname = strrchr(name,'/'))) { 928 i = (int)(mname - name); 929 if (i > (int)sizeof(hname)-1) /* name too long */ 930 return 0; 931 memmove(hname, name, i); 932 hname[i] = '\0'; 933 mname++; 934 name = hname; 935 } 936 937 np = getnetbyname(name); 938 if (np != NULL) { 939 in.s_addr = (naddr)np->n_net; 940 if (0 == (in.s_addr & 0xff000000)) 941 in.s_addr <<= 8; 942 if (0 == (in.s_addr & 0xff000000)) 943 in.s_addr <<= 8; 944 if (0 == (in.s_addr & 0xff000000)) 945 in.s_addr <<= 8; 946 } else if (inet_aton(name, &in) == 1) { 947 in.s_addr = ntohl(in.s_addr); 948 } else if (!mname && !strcasecmp(name,"default")) { 949 in.s_addr = RIP_DEFAULT; 950 } else { 951 return 0; 952 } 953 954 if (!mname) { 955 /* we cannot use the interfaces here because we have not 956 * looked at them yet. 957 */ 958 mask = std_mask(htonl(in.s_addr)); 959 if ((~mask & in.s_addr) != 0) 960 mask = HOST_MASK; 961 } else { 962 mask = (naddr)strtoul(mname, &p, 0); 963 if (*p != '\0' || mask > 32) 964 return 0; 965 if (mask != 0) 966 mask = HOST_MASK << (32-mask); 967 } 968 969 /* must have mask of 0 with default */ 970 if (mask != 0 && in.s_addr == RIP_DEFAULT) 971 return 0; 972 /* no host bits allowed in a network number */ 973 if ((~mask & in.s_addr) != 0) 974 return 0; 975 /* require non-zero network number */ 976 if ((mask & in.s_addr) == 0 && in.s_addr != RIP_DEFAULT) 977 return 0; 978 if (in.s_addr>>24 == 0 && in.s_addr != RIP_DEFAULT) 979 return 0; 980 if (in.s_addr>>24 == 0xff) 981 return 0; 982 983 *netp = in.s_addr; 984 *maskp = mask; 985 return 1; 986 } 987 988 989 int /* 0=bad */ 990 gethost(char *name, 991 naddr *addrp) 992 { 993 struct hostent *hp; 994 struct in_addr in; 995 996 997 /* Try for a number first, even in IRIX where gethostbyname() 998 * is smart. This avoids hitting the name server which 999 * might be sick because routing is. 1000 */ 1001 if (inet_aton(name, &in) == 1) { 1002 /* get a good number, but check that it it makes some 1003 * sense. 1004 */ 1005 if (ntohl(in.s_addr)>>24 == 0 1006 || ntohl(in.s_addr)>>24 == 0xff) 1007 return 0; 1008 *addrp = in.s_addr; 1009 return 1; 1010 } 1011 1012 hp = gethostbyname(name); 1013 if (hp) { 1014 memcpy(addrp, hp->h_addr, sizeof(*addrp)); 1015 return 1; 1016 } 1017 1018 return 0; 1019 } 1020