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