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