parms.c revision 19880
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 acknowledgement: 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 34#if !defined(lint) && !defined(sgi) && !defined(__NetBSD__) 35static char sccsid[] = "@(#)if.c 8.1 (Berkeley) 6/5/93"; 36#elif defined(__NetBSD__) 37static char rcsid[] = "$NetBSD$"; 38#endif 39#ident "$Revision: 1.10 $" 40 41#include "defs.h" 42#include "pathnames.h" 43 44 45struct parm *parms; 46struct intnet *intnets; 47struct tgate *tgates; 48 49 50/* use configured parameters 51 */ 52void 53get_parms(struct interface *ifp) 54{ 55 static warned_auth_in, warned_auth_out; 56 struct parm *parmp; 57 58 /* get all relevant parameters 59 */ 60 for (parmp = parms; parmp != 0; parmp = parmp->parm_next) { 61 if (parmp->parm_name[0] == '\0' 62 || !strcmp(ifp->int_name, parmp->parm_name) 63 || (parmp->parm_name[0] == '\n' 64 && on_net(ifp->int_addr, 65 parmp->parm_net, parmp->parm_mask))) { 66 67 /* This group of parameters is relevant, 68 * so get its settings 69 */ 70 ifp->int_state |= parmp->parm_int_state; 71 if (parmp->parm_auth.type != RIP_AUTH_NONE) 72 bcopy(&parmp->parm_auth, &ifp->int_auth, 73 sizeof(ifp->int_auth)); 74 if (parmp->parm_rdisc_pref != 0) 75 ifp->int_rdisc_pref = parmp->parm_rdisc_pref; 76 if (parmp->parm_rdisc_int != 0) 77 ifp->int_rdisc_int = parmp->parm_rdisc_int; 78 if (parmp->parm_d_metric != 0) 79 ifp->int_d_metric = parmp->parm_d_metric; 80 } 81 } 82 83 /* Set general defaults. 84 * 85 * Default poor-man's router discovery to a metric that will 86 * be heard by old versions of `routed`. They ignored received 87 * routes with metric 15. 88 */ 89 if ((ifp->int_state & IS_PM_RDISC) 90 && ifp->int_d_metric == 0) 91 ifp->int_d_metric = FAKE_METRIC; 92 93 if (ifp->int_rdisc_int == 0) 94 ifp->int_rdisc_int = DefMaxAdvertiseInterval; 95 96 if (!(ifp->int_if_flags & IFF_MULTICAST) 97 && !(ifp->int_state & IS_REMOTE)) 98 ifp->int_state |= IS_BCAST_RDISC; 99 100 if (ifp->int_if_flags & IFF_POINTOPOINT) { 101 ifp->int_state |= IS_BCAST_RDISC; 102 /* By default, point-to-point links should be passive 103 * about router-discovery for the sake of demand-dialing. 104 */ 105 if (0 == (ifp->int_state & GROUP_IS_SOL)) 106 ifp->int_state |= IS_NO_SOL_OUT; 107 if (0 == (ifp->int_state & GROUP_IS_ADV)) 108 ifp->int_state |= IS_NO_ADV_OUT; 109 } 110 111 if (0 != (ifp->int_state & (IS_PASSIVE | IS_REMOTE))) 112 ifp->int_state |= IS_NO_RDISC; 113 if (ifp->int_state & IS_PASSIVE) 114 ifp->int_state |= IS_NO_RIP; 115 116 if (!IS_RIP_IN_OFF(ifp->int_state) 117 && ifp->int_auth.type != RIP_AUTH_NONE 118 && !(ifp->int_state & IS_NO_RIPV1_IN) 119 && !warned_auth_in) { 120 msglog("Warning: RIPv1 input via %s" 121 " will be accepted without authentication", 122 ifp->int_name); 123 warned_auth_in = 1; 124 } 125 if (!IS_RIP_OUT_OFF(ifp->int_state) 126 && ifp->int_auth.type != RIP_AUTH_NONE 127 && !(ifp->int_state & IS_NO_RIPV1_OUT) 128 && !warned_auth_out) { 129 msglog("Warning: RIPv1 output via %s" 130 " will be sent without authentication", 131 ifp->int_name); 132 warned_auth_out = 1; 133 ifp->int_auth.type = RIP_AUTH_NONE; 134 } 135} 136 137 138/* Read a list of gateways from /etc/gateways and add them to our tables. 139 * 140 * This file contains a list of "remote" gateways. That is usually 141 * a gateway which we cannot immediately determine if it is present or 142 * not as we can do for those provided by directly connected hardware. 143 * 144 * If a gateway is marked "passive" in the file, then we assume it 145 * does not understand RIP and assume it is always present. Those 146 * not marked passive are treated as if they were directly connected 147 * and assumed to be broken if they do not send us advertisements. 148 * All remote interfaces are added to our list, and those not marked 149 * passive are sent routing updates. 150 * 151 * A passive interface can also be local, hardware interface exempt 152 * from RIP. 153 */ 154void 155gwkludge(void) 156{ 157 FILE *fp; 158 char *p, *lptr; 159 char lbuf[200], net_host[5], dname[64+1+64+1], gname[64+1], qual[9]; 160 struct interface *ifp; 161 naddr dst, netmask, gate; 162 int metric, n; 163 u_int state; 164 char *type; 165 166 167 fp = fopen(_PATH_GATEWAYS, "r"); 168 if (fp == 0) 169 return; 170 171 for (;;) { 172 if (0 == fgets(lbuf, sizeof(lbuf)-1, fp)) 173 break; 174 lptr = lbuf; 175 while (*lptr == ' ') 176 lptr++; 177 if (*lptr == '\n' /* ignore null and comment lines */ 178 || *lptr == '#') 179 continue; 180 p = lptr+strlen(lptr)-1; 181 while (*p == '\n' || *p == ' ') 182 *p-- = '\0'; 183 184 /* notice newfangled parameter lines 185 */ 186 if (strncasecmp("net", lptr, 3) 187 && strncasecmp("host", lptr, 4)) { 188 p = parse_parms(lptr); 189 if (p != 0) { 190 if (strcasecmp(p,lptr)) 191 msglog("bad %s in "_PATH_GATEWAYS 192 " entry \"%s\"", p, lptr); 193 else 194 msglog("bad \"%s\" in "_PATH_GATEWAYS, 195 lptr); 196 } 197 continue; 198 } 199 200/* {net | host} XX[/M] XX gateway XX metric DD [passive | external]\n */ 201 qual[0] = '\0'; 202 n = sscanf(lptr, "%4s %129[^ \t] gateway" 203 " %64[^ / \t] metric %u %8s\n", 204 net_host, dname, gname, &metric, qual); 205 if (n != 4 && n != 5) { 206 msglog("bad "_PATH_GATEWAYS" entry \"%s\"; %d values", 207 lptr, n); 208 continue; 209 } 210 if (metric >= HOPCNT_INFINITY) { 211 msglog("bad metric in "_PATH_GATEWAYS" entry \"%s\"", 212 lptr); 213 continue; 214 } 215 if (!strcasecmp(net_host, "host")) { 216 if (!gethost(dname, &dst)) { 217 msglog("bad host \"%s\" in "_PATH_GATEWAYS 218 " entry \"%s\"", dname, lptr); 219 continue; 220 } 221 netmask = HOST_MASK; 222 } else if (!strcasecmp(net_host, "net")) { 223 if (!getnet(dname, &dst, &netmask)) { 224 msglog("bad net \"%s\" in "_PATH_GATEWAYS 225 " entry \"%s\"", dname, lptr); 226 continue; 227 } 228 } else { 229 msglog("bad \"%s\" in "_PATH_GATEWAYS 230 " entry \"%s\"", lptr); 231 continue; 232 } 233 234 if (!gethost(gname, &gate)) { 235 msglog("bad gateway \"%s\" in "_PATH_GATEWAYS 236 " entry \"%s\"", gname, lptr); 237 continue; 238 } 239 240 if (!strcasecmp(qual, type = "passive")) { 241 /* Passive entries are not placed in our tables, 242 * only the kernel's, so we don't copy all of the 243 * external routing information within a net. 244 * Internal machines should use the default 245 * route to a suitable gateway (like us). 246 */ 247 state = IS_REMOTE | IS_PASSIVE; 248 if (metric == 0) 249 metric = 1; 250 251 } else if (!strcasecmp(qual, type = "external")) { 252 /* External entries are handled by other means 253 * such as EGP, and are placed only in the daemon 254 * tables to prevent overriding them with something 255 * else. 256 */ 257 strcpy(qual,"external"); 258 state = IS_REMOTE | IS_PASSIVE | IS_EXTERNAL; 259 if (metric == 0) 260 metric = 1; 261 262 } else if (!strcasecmp(qual, "active") 263 || qual[0] == '\0') { 264 if (metric != 0) { 265 /* Entries that are neither "passive" nor 266 * "external" are "remote" and must behave 267 * like physical interfaces. If they are not 268 * heard from regularly, they are deleted. 269 */ 270 state = IS_REMOTE; 271 type = "remote"; 272 } else { 273 /* "remote" entries with a metric of 0 274 * are aliases for our own interfaces 275 */ 276 state = IS_REMOTE | IS_PASSIVE | IS_ALIAS; 277 type = "alias"; 278 } 279 280 } else { 281 msglog("bad "_PATH_GATEWAYS" entry \"%s\";" 282 " unknown type %s", lptr, qual); 283 continue; 284 } 285 286 if (0 != (state & (IS_PASSIVE | IS_REMOTE))) 287 state |= IS_NO_RDISC; 288 if (state & IS_PASSIVE) 289 state |= IS_NO_RIP; 290 291 ifp = check_dup(gate,dst,netmask,0); 292 if (ifp != 0) { 293 msglog("duplicate "_PATH_GATEWAYS" entry \"%s\"",lptr); 294 continue; 295 } 296 297 ifp = (struct interface *)malloc(sizeof(*ifp)); 298 bzero(ifp, sizeof(*ifp)); 299 300 ifp->int_state = state; 301 if (netmask == HOST_MASK) 302 ifp->int_if_flags = IFF_POINTOPOINT | IFF_UP_RUNNING; 303 else 304 ifp->int_if_flags = IFF_UP_RUNNING; 305 ifp->int_act_time = NEVER; 306 ifp->int_addr = gate; 307 ifp->int_dstaddr = dst; 308 ifp->int_mask = netmask; 309 ifp->int_ripv1_mask = netmask; 310 ifp->int_std_mask = std_mask(gate); 311 ifp->int_net = ntohl(dst); 312 ifp->int_std_net = ifp->int_net & ifp->int_std_mask; 313 ifp->int_std_addr = htonl(ifp->int_std_net); 314 ifp->int_metric = metric; 315 if (!(state & IS_EXTERNAL) 316 && ifp->int_mask != ifp->int_std_mask) 317 ifp->int_state |= IS_SUBNET; 318 (void)sprintf(ifp->int_name, "%s(%s)", type, gname); 319 ifp->int_index = -1; 320 321 if_link(ifp); 322 } 323 324 /* After all of the parameter lines have been read, 325 * apply them to any remote interfaces. 326 */ 327 for (ifp = ifnet; 0 != ifp; ifp = ifp->int_next) { 328 get_parms(ifp); 329 330 tot_interfaces++; 331 if (!IS_RIP_OFF(ifp->int_state)) 332 rip_interfaces++; 333 334 trace_if("Add", ifp); 335 } 336} 337 338 339/* strtok(), but honoring backslash 340 */ 341static int /* -1=bad */ 342parse_quote(char **linep, 343 char *delims, 344 char *delimp, 345 char *buf, 346 int lim) 347{ 348 char c, *pc, *p; 349 350 351 pc = *linep; 352 if (*pc == '\0') 353 return -1; 354 355 for (;;) { 356 if (lim == 0) 357 return -1; 358 c = *pc++; 359 if (c == '\0') 360 break; 361 362 if (c == '\\' && pc != '\0') { 363 if ((c = *pc++) == 'n') { 364 c = '\n'; 365 } else if (c == 'r') { 366 c = '\r'; 367 } else if (c == 't') { 368 c = '\t'; 369 } else if (c == 'b') { 370 c = '\b'; 371 } else if (c >= '0' && c <= '7') { 372 c -= '0'; 373 if (*pc >= '0' && *pc <= '7') { 374 c = (c<<3)+(*pc++ - '0'); 375 if (*pc >= '0' && *pc <= '7') 376 c = (c<<3)+(*pc++ - '0'); 377 } 378 } 379 380 } else { 381 for (p = delims; *p != '\0'; ++p) { 382 if (*p == c) 383 goto exit; 384 } 385 } 386 387 *buf++ = c; 388 --lim; 389 } 390exit: 391 if (delimp != 0) 392 *delimp = c; 393 *linep = pc-1; 394 if (lim != 0) 395 *buf = '\0'; 396 return 0; 397} 398 399 400/* Parse password timestamp 401 */ 402static char * 403parse_ts(time_t *tp, 404 char **valp, 405 char *val0, 406 char *delimp, 407 char *buf, 408 u_int bufsize) 409{ 410 struct tm tm; 411 412 if (0 > parse_quote(valp, "| ,\n\r", delimp, 413 buf,bufsize) 414 || buf[bufsize-1] != '\0' 415 || buf[bufsize-2] != '\0') { 416 sprintf(buf,"timestamp %.25s", val0); 417 return buf; 418 } 419 strcat(buf,"\n"); 420 bzero(&tm, sizeof(tm)); 421 if (5 != sscanf(buf, "%u/%u/%u@%u:%u\n", 422 &tm.tm_year, &tm.tm_mon, &tm.tm_mday, 423 &tm.tm_hour, &tm.tm_min)) { 424 sprintf(buf,"timestamp %.25s", val0); 425 return buf; 426 } 427 if (tm.tm_year <= 37) 428 tm.tm_year += 100; 429 430 if ((*tp = mktime(&tm)) == -1) { 431 sprintf(buf,"timestamp %.25s", val0); 432 return buf; 433 } 434 435 return 0; 436} 437 438 439/* Get one or more password, key ID's, and expiration dates in 440 * the format 441 * passwd|keyID|year/mon/day@hour:min|year/mon/day@hour:min|passwd|... 442 */ 443static char * /* 0 or error message */ 444get_passwds(char *tgt, 445 char *val, 446 struct parm *parmp, 447 u_char type) 448{ 449 static char buf[80]; 450 char *val0, *p, delim; 451 struct auth_key *akp, *akp2; 452 int i; 453 u_long l; 454 455 456 if (parmp->parm_auth.type != RIP_AUTH_NONE) 457 return "duplicate authentication"; 458 parmp->parm_auth.type = type; 459 460 bzero(buf, sizeof(buf)); 461 462 akp = parmp->parm_auth.keys; 463 for (i = 0; i < MAX_AUTH_KEYS; i++, val++, akp++) { 464 if ((delim = *val) == '\0') 465 break; 466 val0 = val; 467 if (0 > parse_quote(&val, "| ,\n\r", &delim, 468 (char *)akp->key, sizeof(akp->key))) 469 return tgt; 470 471 akp->end = -1; 472 473 if (delim != '|') { 474 if (type == RIP_AUTH_MD5) 475 return "missing Keyid"; 476 break; 477 } 478 val0 = ++val; 479 if (0 > parse_quote(&val, "| ,\n\r", &delim, buf,sizeof(buf)) 480 || buf[sizeof(buf)-1] != '\0' 481 || (l = strtoul(buf,&p,0)) > 255 482 || *p != '\0') { 483 sprintf(buf,"KeyID \"%.20s\"", val0); 484 return buf; 485 } 486 for (akp2 = parmp->parm_auth.keys; akp2 < akp; akp2++) { 487 if (akp2->keyid == l) { 488 *val = '\0'; 489 sprintf(buf,"duplicate KeyID \"%.20s\"", val0); 490 return buf; 491 } 492 } 493 akp->keyid = (int)l; 494 495 if (delim != '|') 496 break; 497 498 val0 = ++val; 499 if (0 != (p = parse_ts(&akp->start,&val,val0,&delim, 500 buf,sizeof(buf)))) 501 return p; 502 if (delim != '|') 503 return "missing second timestamp"; 504 val0 = ++val; 505 if (0 != (p = parse_ts(&akp->end,&val,val0,&delim, 506 buf,sizeof(buf)))) 507 return p; 508 if ((u_long)akp->start > (u_long)akp->end) { 509 sprintf(buf,"out of order timestamp %.30s",val0); 510 return buf; 511 } 512 513 if (delim != '|') 514 break; 515 } 516 517 return (delim != '\0') ? tgt : 0; 518} 519 520 521/* Parse a set of parameters for an interface. 522 */ 523char * /* 0 or error message */ 524parse_parms(char *line) 525{ 526#define PARS(str) (!strcasecmp(tgt, str)) 527#define PARSEQ(str) (!strncasecmp(tgt, str"=", sizeof(str))) 528#define CKF(g,b) {if (0 != (parm.parm_int_state & ((g) & ~(b)))) break; \ 529 parm.parm_int_state |= (b);} 530 struct parm parm; 531 struct intnet *intnetp; 532 struct tgate *tg; 533 naddr addr, mask; 534 char delim, *val0, *tgt, *val, *p; 535 char buf[64]; 536 537 538 /* "subnet=x.y.z.u/mask,metric" must be alone on the line */ 539 if (!strncasecmp(line, "subnet=", sizeof("subnet=")-1) 540 && *(val = &line[sizeof("subnet=")]) != '\0') { 541 intnetp = (struct intnet*)malloc(sizeof(*intnetp)); 542 intnetp->intnet_metric = 1; 543 if ((p = strrchr(val,','))) { 544 *p++ = '\0'; 545 intnetp->intnet_metric = (int)strtol(p,&p,0); 546 if (*p != '\0' 547 || intnetp->intnet_metric <= 0 548 || intnetp->intnet_metric >= HOPCNT_INFINITY) 549 return line; 550 } 551 if (!getnet(val, &intnetp->intnet_addr, &intnetp->intnet_mask) 552 || intnetp->intnet_mask == HOST_MASK 553 || intnetp->intnet_addr == RIP_DEFAULT) { 554 free(intnetp); 555 return line; 556 } 557 intnetp->intnet_next = intnets; 558 intnets = intnetp; 559 return 0; 560 } 561 562 bzero(&parm, sizeof(parm)); 563 564 tgt = "null"; 565 for (;;) { 566 tgt = line + strspn(line, " ,\n\r"); 567 if (*tgt == '\0') 568 break; 569 570 line += strcspn(tgt, "= ,\n\r"); 571 delim = *line; 572 if (delim == '=') { 573 val0 = ++line; 574 if (0 > parse_quote(&line," ,\n\r",&delim, 575 buf,sizeof(buf))) 576 return tgt; 577 } 578 if (delim != '\0') 579 *line++ = '\0'; 580 581 if (PARSEQ("if")) { 582 if (parm.parm_name[0] != '\0' 583 || strlen(buf) > IFNAMSIZ) 584 return tgt; 585 strcpy(parm.parm_name, buf); 586 587 } else if (PARSEQ("addr")) { 588 /* This is a bad idea, because the address based 589 * sets of parameters cannot be checked for 590 * consistency with the interface name parameters. 591 * The parm_net stuff is needed to allow several 592 * -F settings. 593 */ 594 if (!getnet(val, &addr, &mask) 595 || parm.parm_name[0] != '\0') 596 return tgt; 597 parm.parm_net = addr; 598 parm.parm_mask = mask; 599 parm.parm_name[0] = '\n'; 600 601 } else if (PARSEQ("passwd")) { 602 tgt = get_passwds(tgt, val0, &parm, RIP_AUTH_PW); 603 if (tgt) 604 return tgt; 605 606 } else if (PARSEQ("md5_passwd")) { 607 tgt = get_passwds(tgt, val0, &parm, RIP_AUTH_MD5); 608 if (tgt) 609 return tgt; 610 611 } else if (PARS("no_ag")) { 612 parm.parm_int_state |= (IS_NO_AG | IS_NO_SUPER_AG); 613 614 } else if (PARS("no_super_ag")) { 615 parm.parm_int_state |= IS_NO_SUPER_AG; 616 617 } else if (PARS("no_ripv1_in")) { 618 parm.parm_int_state |= IS_NO_RIPV1_IN; 619 620 } else if (PARS("no_ripv2_in")) { 621 parm.parm_int_state |= IS_NO_RIPV2_IN; 622 623 } else if (PARS("ripv2_out")) { 624 if (parm.parm_int_state & IS_NO_RIPV2_OUT) 625 return tgt; 626 parm.parm_int_state |= IS_NO_RIPV1_OUT; 627 628 } else if (PARS("ripv2")) { 629 if ((parm.parm_int_state & IS_NO_RIPV2_OUT) 630 || (parm.parm_int_state & IS_NO_RIPV2_IN)) 631 return tgt; 632 parm.parm_int_state |= (IS_NO_RIPV1_IN 633 | IS_NO_RIPV1_OUT); 634 635 } else if (PARS("no_rip")) { 636 CKF(IS_PM_RDISC, IS_NO_RIP); 637 638 } else if (PARS("no_rdisc")) { 639 CKF((GROUP_IS_SOL|GROUP_IS_ADV), IS_NO_RDISC); 640 641 } else if (PARS("no_solicit")) { 642 CKF(GROUP_IS_SOL, IS_NO_SOL_OUT); 643 644 } else if (PARS("send_solicit")) { 645 CKF(GROUP_IS_SOL, IS_SOL_OUT); 646 647 } else if (PARS("no_rdisc_adv")) { 648 CKF(GROUP_IS_ADV, IS_NO_ADV_OUT); 649 650 } else if (PARS("rdisc_adv")) { 651 CKF(GROUP_IS_ADV, IS_ADV_OUT); 652 653 } else if (PARS("bcast_rdisc")) { 654 parm.parm_int_state |= IS_BCAST_RDISC; 655 656 } else if (PARS("passive")) { 657 CKF((GROUP_IS_SOL|GROUP_IS_ADV), IS_NO_RDISC); 658 parm.parm_int_state |= IS_NO_RIP; 659 660 } else if (PARSEQ("rdisc_pref")) { 661 if (parm.parm_rdisc_pref != 0 662 || (parm.parm_rdisc_pref = (int)strtoul(buf, &p,0), 663 *p != '\0')) 664 return tgt; 665 666 } else if (PARS("pm_rdisc")) { 667 if (IS_RIP_OUT_OFF(parm.parm_int_state)) 668 return tgt; 669 parm.parm_int_state |= IS_PM_RDISC; 670 671 } else if (PARSEQ("rdisc_interval")) { 672 if (parm.parm_rdisc_int != 0 673 || (parm.parm_rdisc_int = (int)strtoul(buf,&p,0), 674 *p != '\0') 675 || parm.parm_rdisc_int < MinMaxAdvertiseInterval 676 || parm.parm_rdisc_int > MaxMaxAdvertiseInterval) 677 return tgt; 678 679 } else if (PARSEQ("fake_default")) { 680 if (parm.parm_d_metric != 0 681 || IS_RIP_OUT_OFF(parm.parm_int_state) 682 || (parm.parm_d_metric = (int)strtoul(buf,&p,0), 683 *p != '\0') 684 || parm.parm_d_metric > HOPCNT_INFINITY-1) 685 return tgt; 686 687 } else if (PARSEQ("trust_gateway")) { 688 if (!gethost(buf,&addr)) 689 return tgt; 690 tg = (struct tgate *)malloc(sizeof(*tg)); 691 tg->tgate_next = tgates; 692 tg->tgate_addr = addr; 693 tgates = tg; 694 parm.parm_int_state |= IS_DISTRUST; 695 696 } else { 697 return tgt; /* error */ 698 } 699 } 700 701 return check_parms(&parm); 702#undef PARS 703#undef PARSEQ 704} 705 706 707/* check for duplicate parameter specifications */ 708char * /* 0 or error message */ 709check_parms(struct parm *new) 710{ 711 struct parm *parmp; 712 713 /* set implicit values 714 */ 715 if (new->parm_int_state & IS_NO_ADV_IN) 716 new->parm_int_state |= IS_NO_SOL_OUT; 717 718 /* compare with existing sets of parameters 719 */ 720 for (parmp = parms; parmp != 0; parmp = parmp->parm_next) { 721 if (strcmp(new->parm_name, parmp->parm_name)) 722 continue; 723 if (!on_net(htonl(parmp->parm_net), 724 new->parm_net, new->parm_mask) 725 && !on_net(htonl(new->parm_net), 726 parmp->parm_net, parmp->parm_mask)) 727 continue; 728 729 if (parmp->parm_auth.type != RIP_AUTH_NONE 730 && new->parm_auth.type != RIP_AUTH_NONE 731 && bcmp(&parmp->parm_auth, &new->parm_auth, 732 sizeof(parmp->parm_auth))) { 733 return "conflicting, duplicate authentication"; 734 } 735 736 if ((0 != (new->parm_int_state & GROUP_IS_SOL) 737 && 0 != (parmp->parm_int_state & GROUP_IS_SOL) 738 && 0 != ((new->parm_int_state ^ parmp->parm_int_state) 739 && GROUP_IS_SOL)) 740 || (0 != (new->parm_int_state & GROUP_IS_ADV) 741 && 0 != (parmp->parm_int_state & GROUP_IS_ADV) 742 && 0 != ((new->parm_int_state ^ parmp->parm_int_state) 743 && GROUP_IS_ADV)) 744 || (new->parm_rdisc_pref != 0 745 && parmp->parm_rdisc_pref != 0 746 && new->parm_rdisc_pref != parmp->parm_rdisc_pref) 747 || (new->parm_rdisc_int != 0 748 && parmp->parm_rdisc_int != 0 749 && new->parm_rdisc_int != parmp->parm_rdisc_int)) { 750 return ("conflicting, duplicate router discovery" 751 " parameters"); 752 753 } 754 755 if (new->parm_d_metric != 0 756 && parmp->parm_d_metric != 0 757 && new->parm_d_metric != parmp->parm_d_metric) { 758 return ("conflicting, duplicate poor man's router" 759 " discovery or fake default metric"); 760 } 761 } 762 763 parmp = (struct parm*)malloc(sizeof(*parmp)); 764 bcopy(new, parmp, sizeof(*parmp)); 765 parmp->parm_next = parms; 766 parms = parmp; 767 768 return 0; 769} 770 771 772/* get a network number as a name or a number, with an optional "/xx" 773 * netmask. 774 */ 775int /* 0=bad */ 776getnet(char *name, 777 naddr *netp, /* host byte order */ 778 naddr *maskp) 779{ 780 int i; 781 struct netent *np; 782 naddr mask; 783 struct in_addr in; 784 char hname[MAXHOSTNAMELEN+1]; 785 char *mname, *p; 786 787 788 /* Detect and separate "1.2.3.4/24" 789 */ 790 if (0 != (mname = rindex(name,'/'))) { 791 i = (int)(mname - name); 792 if (i > sizeof(hname)-1) /* name too long */ 793 return 0; 794 bcopy(name, hname, i); 795 hname[i] = '\0'; 796 mname++; 797 name = hname; 798 } 799 800 np = getnetbyname(name); 801 if (np != 0) { 802 in.s_addr = (naddr)np->n_net; 803 } else if (inet_aton(name, &in) == 1) { 804 NTOHL(in.s_addr); 805 } else if (!mname && !strcasecmp(name,"default")) { 806 in.s_addr = RIP_DEFAULT; 807 } else { 808 return 0; 809 } 810 811 if (!mname) { 812 /* we cannot use the interfaces here because we have not 813 * looked at them yet. 814 */ 815 mask = std_mask(in.s_addr); 816 if ((~mask & in.s_addr) != 0) 817 mask = HOST_MASK; 818 } else { 819 mask = (naddr)strtoul(mname, &p, 0); 820 if (*p != '\0' || mask > 32) 821 return 0; 822 mask = HOST_MASK << (32-mask); 823 } 824 825 /* must have mask of 0 with default */ 826 if (mask != 0 && in.s_addr == RIP_DEFAULT) 827 return 0; 828 /* no host bits allowed in a network number */ 829 if ((~mask & in.s_addr) != 0) 830 return 0; 831 /* require non-zero network number */ 832 if ((mask & in.s_addr) == 0 && in.s_addr != RIP_DEFAULT) 833 return 0; 834 if (in.s_addr>>24 == 0 && in.s_addr != RIP_DEFAULT) 835 return 0; 836 if (in.s_addr>>24 == 0xff) 837 return 0; 838 839 *netp = in.s_addr; 840 *maskp = mask; 841 return 1; 842} 843 844 845int /* 0=bad */ 846gethost(char *name, 847 naddr *addrp) 848{ 849 struct hostent *hp; 850 struct in_addr in; 851 852 853 /* Try for a number first, even in IRIX where gethostbyname() 854 * is smart. This avoids hitting the name server which 855 * might be sick because routing is. 856 */ 857 if (inet_aton(name, &in) == 1) { 858 /* get a good number, but check that it it makes some 859 * sense. 860 */ 861 if (ntohl(in.s_addr)>>24 == 0 862 || ntohl(in.s_addr)>>24 == 0xff) 863 return 0; 864 *addrp = in.s_addr; 865 return 1; 866 } 867 868 hp = gethostbyname(name); 869 if (hp) { 870 bcopy(hp->h_addr, addrp, sizeof(*addrp)); 871 return 1; 872 } 873 874 return 0; 875} 876