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