2 * Copyright 2008 Sun Microsystems, Inc. All rights reserved.
3 * Use is subject to license terms.
5 * Copyright (c) 1983, 1993
6 * The Regents of the University of California. All rights reserved.
8 * Redistribution and use in source and binary forms, with or without
9 * modification, are permitted provided that the following conditions
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.
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
36 * $FreeBSD: src/sbin/routed/parms.c,v 1.9 2000/08/11 08:24:38 sheldonh Exp $
40 #include "pathnames.h"
42 #include <arpa/inet.h>
45 #define PARMS_MAXLINELEN 500
46 static struct parm
*parms
;
47 struct intnet
*intnets
;
51 static void addroutefordefault(in_addr_t
, in_addr_t
, in_addr_t
,
54 /* use configured parameters */
56 get_parms(struct interface
*ifp
)
58 static boolean_t warned_auth_in
, warned_auth_out
;
60 int i
, num_passwds
= 0;
65 /* get all relevant parameters */
66 for (parmp
= parms
; parmp
!= NULL
; parmp
= parmp
->parm_next
) {
67 if (parmp
->parm_name
[0] == '\0' ||
68 strcmp(ifp
->int_name
, parmp
->parm_name
) == 0 ||
69 (parmp
->parm_name
[0] == '\n' &&
71 parmp
->parm_net
, parmp
->parm_mask
))) {
74 * This group of parameters is relevant,
77 ifp
->int_state
|= parmp
->parm_int_state
;
78 for (i
= 0; i
< MAX_AUTH_KEYS
; i
++) {
79 if (parmp
->parm_auth
[i
].type
== RIP_AUTH_NONE
||
80 num_passwds
>= MAX_AUTH_KEYS
)
82 ifp
->int_auth
[num_passwds
++] =
85 if (parmp
->parm_rdisc_pref
!= 0)
86 ifp
->int_rdisc_pref
= parmp
->parm_rdisc_pref
;
87 if (parmp
->parm_rdisc_int
!= 0)
88 ifp
->int_rdisc_int
= parmp
->parm_rdisc_int
;
89 if (parmp
->parm_d_metric
!= 0)
90 ifp
->int_d_metric
= parmp
->parm_d_metric
;
91 if (parmp
->parm_ripout_addr
!= 0)
92 ifp
->int_ripout_addr
= parmp
->parm_ripout_addr
;
97 * Set general defaults.
99 * Default poor-man's router discovery to a metric that will
100 * be heard by old versions of `routed`. They ignored received
101 * routes with metric 15.
103 if ((ifp
->int_state
& IS_PM_RDISC
) && ifp
->int_d_metric
== 0)
104 ifp
->int_d_metric
= FAKE_METRIC
;
106 if (ifp
->int_rdisc_int
== 0)
107 ifp
->int_rdisc_int
= DEF_MAXADVERTISEINTERVAL
;
109 if (!(ifp
->int_if_flags
& IFF_MULTICAST
) &&
110 !(ifp
->int_state
& IS_REMOTE
))
111 ifp
->int_state
|= IS_BCAST_RDISC
;
113 if (ifp
->int_if_flags
& IFF_POINTOPOINT
) {
114 ifp
->int_state
|= IS_BCAST_RDISC
;
116 * By default, point-to-point links should be passive
117 * about router-discovery for the sake of demand-dialing.
119 if (!(ifp
->int_state
& GROUP_IS_SOL_OUT
))
120 ifp
->int_state
|= IS_NO_SOL_OUT
;
121 if (!(ifp
->int_state
& GROUP_IS_ADV_OUT
))
122 ifp
->int_state
|= IS_NO_ADV_OUT
;
125 if (0 != (ifp
->int_state
& (IS_PASSIVE
| IS_REMOTE
)))
126 ifp
->int_state
|= IS_NO_RDISC
;
127 if (ifp
->int_state
& IS_PASSIVE
)
128 ifp
->int_state
|= IS_NO_RIP
;
130 if (!IS_RIP_IN_OFF(ifp
->int_state
) &&
131 ifp
->int_auth
[0].type
!= RIP_AUTH_NONE
&&
132 !(ifp
->int_state
& IS_NO_RIPV1_IN
) && !warned_auth_in
) {
133 writelog(LOG_WARNING
, "RIPv1 input via %s"
134 " will be accepted without authentication",
136 warned_auth_in
= _B_TRUE
;
138 if (!IS_RIP_OUT_OFF(ifp
->int_state
) &&
139 ifp
->int_auth
[0].type
!= RIP_AUTH_NONE
&&
140 !(ifp
->int_state
& IS_NO_RIPV1_OUT
)) {
141 if (!warned_auth_out
) {
142 writelog(LOG_WARNING
, "RIPv1 output via %s"
143 " will be sent without authentication",
145 warned_auth_out
= _B_TRUE
;
150 * If not overriden by the rip_neighbor option, set the
151 * default address to which RIP packets will be sent on
154 if (ifp
->int_ripout_addr
== 0) {
155 if (ifp
->int_state
& IS_REMOTE
) {
157 * By definition we always send RIP packets to
158 * the address assigned to a remote interface.
160 ifp
->int_ripout_addr
= ifp
->int_addr
;
161 } else if ((ifp
->int_state
& IS_NO_RIPV1_OUT
) &&
162 (ifp
->int_if_flags
& IFF_MULTICAST
) &&
163 !(ifp
->int_state
& IS_NO_RIP_MCAST
)) {
165 * If the interface is being used for RIPv2
166 * and it supports multicast, and if the user
167 * has not explicitely turned off multicast
168 * RIP output, send to the all RIP routers
171 ifp
->int_ripout_addr
= htonl(INADDR_RIP_GROUP
);
172 } else if (ifp
->int_if_flags
& IFF_POINTOPOINT
) {
174 * For point-to-point interfaces which don't
175 * fall into the two categories above, just
176 * send to the destination address of the
179 ifp
->int_ripout_addr
= ifp
->int_dstaddr
;
181 /* Otherwise, use the broadcast address. */
182 ifp
->int_ripout_addr
= ifp
->int_brdaddr
;
189 * Read a list of gateways from /etc/gateways and add them to our tables.
191 * This file contains a list of "remote" gateways. That is usually
192 * a gateway which we cannot immediately determine if it is present or
193 * not as we can do for those provided by directly connected hardware.
195 * If a gateway is marked "passive" in the file, then we assume it
196 * does not understand RIP and assume it is always present. Those
197 * not marked passive are treated as if they were directly connected
198 * and assumed to be broken if they do not send us advertisements.
199 * All remote interfaces are added to our list, and those not marked
200 * passive are sent routing updates.
202 * A passive interface can also be local, hardware interface exempt
209 #define STR(x) STR2(x)
211 #define NETHOST_LEN 4
212 #define DNAME_LEN MAXHOSTNAMELEN
213 #define GNAME_LEN MAXHOSTNAMELEN
219 char lbuf
[PARMS_MAXLINELEN
], net_host
[NETHOST_LEN
+ 1];
220 char dname
[MAXHOSTNAMELEN
+ 1];
221 char gname
[MAXHOSTNAMELEN
+ 1], qual
[QUAL_LEN
+1];
222 struct interface
*ifp
;
223 uint32_t dst
, netmask
, gate
;
227 uint32_t state
, metric
;
228 boolean_t default_dst
;
231 fp
= fopen(PATH_GATEWAYS
, "r");
235 if (0 > fstat(fileno(fp
), &sb
)) {
236 msglog("fstat() failed: %s for "PATH_GATEWAYS
,
237 rip_strerror(errno
));
242 for (lnum
= 1; ; lnum
++) {
243 if (NULL
== fgets(lbuf
, sizeof (lbuf
), fp
))
246 /* Eliminate the /n character at the end of the lbuf */
247 if (strlen(lbuf
) > 0)
248 lbuf
[strlen(lbuf
) - 1] = '\0';
250 /* Move lptr to the first non-space character */
251 for (lptr
= lbuf
; isspace(*lptr
); lptr
++)
254 if (*lptr
== '#' || *lptr
== '\0')
257 /* Move p to the end of the line */
258 p
= lptr
+ strlen(lptr
) - 1;
260 /* Skip all trailing spaces except escaped space */
261 while (p
> lptr
&& (isspace(*p
) && *(p
-1) != '\\'))
264 /* truncate the line to remove trailing spaces */
267 /* notice newfangled parameter lines */
268 if (strncasecmp("net", lptr
, 3) != 0 &&
269 strncasecmp("host", lptr
, 4) != 0) {
270 cp
= parse_parms(lptr
, (sb
.st_uid
== 0 &&
271 !(sb
.st_mode
&(S_IRWXG
|S_IRWXO
))));
273 msglog("%s in line %u of "PATH_GATEWAYS
,
279 * Processes lines of the follwoing format:
280 * net|host <name>[/mask] gateway <Gname> metric <value>
281 * passive|active|extern
284 n
= sscanf(lptr
, "%"STR(NETHOST_LEN
)"s %"STR(DNAME_LEN
)
285 "[^ \t] gateway %"STR(GNAME_LEN
)"[^ / \t] metric %u %"
286 STR(QUAL_LEN
)"s\n", net_host
, dname
, gname
, &metric
, qual
);
287 if (n
!= 4 && n
!= 5) {
288 msglog("bad "PATH_GATEWAYS
" entry \"%s\"; %d values",
292 if (metric
>= HOPCNT_INFINITY
) {
293 msglog("bad metric in "PATH_GATEWAYS
" entry \"%s\"",
297 default_dst
= _B_FALSE
;
298 if (strcasecmp(net_host
, "host") == 0) {
299 if (!gethost(dname
, &dst
)) {
300 msglog("bad host \"%s\" in "PATH_GATEWAYS
301 " entry \"%s\"", dname
, lptr
);
305 } else if (strcasecmp(net_host
, "net") == 0) {
306 if (!getnet(dname
, &dst
, &netmask
)) {
307 msglog("bad net \"%s\" in "PATH_GATEWAYS
308 " entry \"%s\"", dname
, lptr
);
311 default_dst
= (dst
== RIP_DEFAULT
);
312 dst
= htonl(dst
); /* make network # into IP address */
314 msglog("bad \"%s\" in "PATH_GATEWAYS
315 " entry \"%s\"", net_host
, lptr
);
319 if (!gethost(gname
, &gate
)) {
320 msglog("bad gateway \"%s\" in "PATH_GATEWAYS
321 " entry \"%s\"", gname
, lptr
);
325 if (strcasecmp(qual
, "passive") == 0) {
327 * Passive entries are not placed in our tables,
328 * only the kernel's, so we don't copy all of the
329 * external routing information within a net.
330 * Internal machines should use the default
331 * route to a suitable gateway (like us).
333 state
= IS_REMOTE
| IS_PASSIVE
;
337 } else if (strcasecmp(qual
, "external") == 0) {
339 * External entries are handled by other means
340 * such as EGP, and are placed only in the daemon
341 * tables to prevent overriding them with something
344 (void) strlcpy(qual
, "external", sizeof (qual
));
345 state
= IS_REMOTE
| IS_PASSIVE
| IS_EXTERNAL
;
349 } else if (strcasecmp(qual
, "active") == 0 ||
353 msglog("bad net \"%s\" in "PATH_GATEWAYS
354 " entry \"%s\"-- cannot be default",
361 * Entries that are neither "passive" nor
362 * "external" are "remote" and must behave
363 * like physical interfaces. If they are not
364 * heard from regularly, they are deleted.
369 * "remote" entries with a metric of 0
370 * are aliases for our own interfaces
372 state
= IS_REMOTE
| IS_PASSIVE
| IS_ALIAS
;
376 msglog("bad "PATH_GATEWAYS
" entry \"%s\";"
377 " unknown type %s", lptr
, qual
);
381 if (0 != (state
& (IS_PASSIVE
| IS_REMOTE
)))
382 state
|= IS_NO_RDISC
;
383 if (state
& IS_PASSIVE
)
388 addroutefordefault(dst
, gate
, netmask
, metric
,
389 ((state
& IS_EXTERNAL
)? RTS_EXTERNAL
: 0));
393 ifp
= check_dup(NULL
, gate
, dst
, netmask
, 0, _B_FALSE
);
395 msglog("duplicate "PATH_GATEWAYS
" entry \"%s\"", lptr
);
399 ifp
= rtmalloc(sizeof (*ifp
), "gwkludge()");
400 (void) memset(ifp
, 0, sizeof (*ifp
));
402 ifp
->int_state
= state
;
403 if (netmask
== HOST_MASK
)
404 ifp
->int_if_flags
= IFF_POINTOPOINT
| IFF_UP
;
406 ifp
->int_if_flags
= IFF_UP
;
407 ifp
->int_act_time
= NEVER
;
408 ifp
->int_addr
= gate
;
409 ifp
->int_dstaddr
= dst
;
410 ifp
->int_mask
= netmask
;
411 ifp
->int_ripv1_mask
= netmask
;
412 ifp
->int_std_mask
= std_mask(gate
);
413 ifp
->int_net
= ntohl(dst
);
414 ifp
->int_std_net
= ifp
->int_net
& ifp
->int_std_mask
;
415 ifp
->int_std_addr
= htonl(ifp
->int_std_net
);
416 ifp
->int_metric
= metric
;
417 if (!(state
& IS_EXTERNAL
) &&
418 ifp
->int_mask
!= ifp
->int_std_mask
)
419 ifp
->int_state
|= IS_SUBNET
;
420 (void) snprintf(ifp
->int_name
, sizeof (ifp
->int_name
),
421 "remote(%s)", gname
);
429 * After all of the parameter lines have been read,
430 * apply them to any remote interfaces.
432 for (ifp
= ifnet
; NULL
!= ifp
; ifp
= ifp
->int_next
) {
436 if (!IS_RIP_OFF(ifp
->int_state
))
438 if (!IS_RIP_OUT_OFF(ifp
->int_state
))
441 trace_if("Add", ifp
);
446 /* Parse password timestamp */
457 if (0 > parse_quote(valp
, "| ,", delimp
, buf
, bufsize
) ||
458 buf
[bufsize
-1] != '\0' || buf
[bufsize
-2] != '\0') {
459 (void) snprintf(buf
, bufsize
, "bad timestamp %.25s", val0
);
462 (void) strlcat(buf
, "\n", bufsize
);
463 (void) memset(&tm
, 0, sizeof (tm
));
464 if (5 != sscanf(buf
, "%u/%u/%u@%u:%u\n",
465 (unsigned *)&tm
.tm_year
, (unsigned *)&tm
.tm_mon
,
466 (unsigned *)&tm
.tm_mday
, (unsigned *)&tm
.tm_hour
,
467 (unsigned *)&tm
.tm_min
) ||
468 tm
.tm_mon
< 1 || tm
.tm_mon
> 12 ||
469 tm
.tm_mday
< 1 || tm
.tm_mday
> 31) {
470 (void) snprintf(buf
, bufsize
, "bad timestamp %.25s", val0
);
474 /* assume small years are in the 3rd millenium */
475 if (tm
.tm_year
<= 37)
478 if (tm
.tm_year
>= 1900)
481 if ((*tp
= mktime(&tm
)) == -1) {
482 (void) snprintf(buf
, bufsize
, "bad timestamp %.25s", val0
);
491 * Get a password, key ID, and expiration date in the format
492 * passwd|keyID|year/mon/day@hour:min|year/mon/day@hour:min
493 * returns NULL or error message
496 get_passwd(char *tgt
,
500 boolean_t safe
) /* 1=from secure file */
503 char *val0
, *p
, delim
;
504 struct auth k
, *ap
, *ap2
;
510 return ("ignore unsafe password");
512 for (ap
= parmp
->parm_auth
, i
= 0; ap
->type
!= RIP_AUTH_NONE
;
514 if (i
>= MAX_AUTH_KEYS
)
515 return ("too many passwords");
518 (void) memset(&k
, 0, sizeof (k
));
523 if (0 > parse_quote(&val
, "| ,", &delim
,
524 (char *)k
.key
, sizeof (k
.key
)))
528 if (type
== RIP_AUTH_MD5
)
529 return ("missing Keyid");
532 buf
[sizeof (buf
)-1] = '\0';
533 if (0 > parse_quote(&val
, "| ,", &delim
, buf
,
535 buf
[sizeof (buf
) - 1] != '\0' ||
536 (l
= strtoul(buf
, &p
, 0)) > 255 ||
537 p
== buf
|| *p
!= '\0') {
538 (void) snprintf(buf
, sizeof (buf
),
539 "bad KeyID \"%.20s\"", val0
);
542 for (ap2
= parmp
->parm_auth
; ap2
< ap
; ap2
++) {
543 if (ap2
->keyid
== l
) {
544 (void) snprintf(buf
, sizeof (buf
),
545 "duplicate KeyID \"%.20s\"",
554 if (NULL
!= (p
= parse_ts(&k
.start
, &val
, val0
, &delim
,
558 return ("missing second timestamp");
560 if (NULL
!= (p
= parse_ts(&k
.end
, &val
, val0
, &delim
,
563 if ((ulong_t
)k
.start
> (ulong_t
)k
.end
) {
564 (void) snprintf(buf
, sizeof (buf
),
565 "out of order timestamp %.30s", val0
);
573 (void) memmove(ap
, &k
, sizeof (*ap
));
579 bad_str(const char *estr
)
581 static char buf
[100+8];
583 (void) snprintf(buf
, sizeof (buf
), "bad \"%.100s\"", estr
);
589 * Parse a set of parameters for an interface.
590 * returns NULL or error message
593 parse_parms(char *line
,
594 boolean_t safe
) /* 1=from secure file */
596 #define PARS(str) (strcasecmp(tgt, str) == 0)
597 #define PARSEQ(str) (strncasecmp(tgt, str"=", sizeof (str)) == 0)
599 * This macro checks for conflicting configurations options
600 * For eg one can set either the IS_NO_SOL_OUT flag bit or the IS_SOL_OUT flag
603 #define CKF(g, b) {if (0 != (parm.parm_int_state & ((g) & ~(b)))) break; \
604 parm.parm_int_state |= (b); }
606 struct intnet
*intnetp
;
607 struct r1net
*r1netp
;
610 char delim
, *val0
= 0, *tgt
, *val
, *p
;
612 char buf
[PARMS_MAXLINELEN
], buf2
[PARMS_MAXLINELEN
];
616 /* "subnet=x.y.z.u/mask[,metric]" must be alone on the line */
617 if (strncasecmp(line
, "subnet=", sizeof ("subnet=") - 1) == 0 &&
618 *(val
= &line
[sizeof ("subnet=") -1 ]) != '\0') {
619 if (0 > parse_quote(&val
, ",", &delim
, buf
, sizeof (buf
)))
620 return (bad_str(line
));
621 intnetp
= rtmalloc(sizeof (*intnetp
),
622 "parse_parms subnet");
623 intnetp
->intnet_metric
= 1;
625 intnetp
->intnet_metric
= (int)strtol(val
+1, &p
, 0);
626 if (*p
!= '\0' || intnetp
->intnet_metric
<= 0 ||
628 intnetp
->intnet_metric
>= HOPCNT_INFINITY
) {
630 return (bad_str(line
));
633 if (!getnet(buf
, &intnetp
->intnet_addr
,
634 &intnetp
->intnet_mask
) ||
635 intnetp
->intnet_mask
== HOST_MASK
||
636 intnetp
->intnet_addr
== RIP_DEFAULT
) {
638 return (bad_str(line
));
640 intnetp
->intnet_addr
= htonl(intnetp
->intnet_addr
);
641 intnetp
->intnet_next
= intnets
;
647 * "ripv1_mask=x.y.z.u/mask1,mask2" must be alone on the line.
648 * This requires that x.y.z.u/mask1 be considered a subnet of
649 * x.y.z.u/mask2, as if x.y.z.u/mask2 were a class-full network.
651 if (!strncasecmp(line
, "ripv1_mask=", sizeof ("ripv1_mask=") - 1) &&
652 *(val
= &line
[sizeof ("ripv1_mask=")-1]) != '\0') {
653 if (0 > parse_quote(&val
, ",", &delim
, buf
, sizeof (buf
)) ||
655 return (bad_str(line
));
656 if ((i
= (int)strtol(val
+1, &p
, 0)) <= 0 || i
> 32 ||
658 return (bad_str(line
));
659 r1netp
= rtmalloc(sizeof (*r1netp
), "parse_parms ripv1_mask");
660 r1netp
->r1net_mask
= HOST_MASK
<< (32-i
);
661 if (!getnet(buf
, &r1netp
->r1net_net
, &r1netp
->r1net_match
) ||
662 r1netp
->r1net_net
== RIP_DEFAULT
||
663 r1netp
->r1net_mask
> r1netp
->r1net_match
) {
665 return (bad_str(line
));
667 r1netp
->r1net_next
= r1nets
;
672 (void) memset(&parm
, 0, sizeof (parm
));
674 * Support of the following for Solaris backward compatibility
679 if (strncasecmp("norip", line
, 5) == 0) {
680 char cmd
[64], ifname
[64];
683 n
= sscanf(line
, "%63s %63s\n", cmd
, ifname
);
685 /* Not enough parameters */
686 return (bad_str(line
));
690 * Get the interface name and turn on the appropriate
693 (void) strlcpy(parm
.parm_name
, ifname
, sizeof (parm
.parm_name
));
694 if (strcasecmp("norip", cmd
) == 0) {
695 parm
.parm_int_state
|= IS_NO_RIP
;
696 } else if (strcasecmp("noripin", cmd
) == 0) {
697 parm
.parm_int_state
|= IS_NO_RIP_IN
;
698 } else if (strcasecmp("noripout", cmd
) == 0) {
699 parm
.parm_int_state
|= IS_NO_RIP_OUT
;
702 return (bad_str(line
));
705 * Look for duplication, and if new,
706 * link to the rest of the parm entries.
708 return (insert_parm(&parm
));
712 tgt
= line
+ strspn(line
, " ,\n\r");
713 if (*tgt
== '\0' || *tgt
== '#')
715 line
= tgt
+strcspn(tgt
, "= #,\n\r");
719 if (0 > parse_quote(&line
, " #,", &delim
,
721 return (bad_str(tgt
));
729 if (!isspace(delim
) ||
730 ((delim
= *line
), !isspace(delim
)))
736 if (parm
.parm_name
[0] != '\0' ||
737 strlen(buf
) > IF_NAME_LEN
)
738 return (bad_str(tgt
));
739 (void) strlcpy(parm
.parm_name
, buf
,
740 sizeof (parm
.parm_name
));
742 } else if (PARSEQ("addr")) {
744 * This is a bad idea, because the address based
745 * sets of parameters cannot be checked for
746 * consistency with the interface name parameters.
747 * The parm_net stuff is needed to allow several
750 if (!getnet(val0
, &addr
, &mask
) ||
751 parm
.parm_name
[0] != '\0')
752 return (bad_str(tgt
));
753 parm
.parm_net
= addr
;
754 parm
.parm_mask
= mask
;
755 parm
.parm_name
[0] = '\n';
757 } else if (PARSEQ("passwd")) {
759 * since cleartext passwords are so weak allow
762 msg
= get_passwd(tgt
, val0
, &parm
, RIP_AUTH_PW
, 1);
765 return (bad_str(msg
));
768 } else if (PARSEQ("md5_passwd")) {
769 msg
= get_passwd(tgt
, val0
, &parm
, RIP_AUTH_MD5
, safe
);
772 return (bad_str(msg
));
775 } else if (PARS("no_ag")) {
776 parm
.parm_int_state
|= (IS_NO_AG
| IS_NO_SUPER_AG
);
778 } else if (PARS("no_host")) {
779 parm
.parm_int_state
|= IS_NO_HOST
;
781 } else if (PARS("no_super_ag")) {
782 parm
.parm_int_state
|= IS_NO_SUPER_AG
;
784 } else if (PARS("no_ripv1_in")) {
785 parm
.parm_int_state
|= IS_NO_RIPV1_IN
;
787 } else if (PARS("no_ripv2_in")) {
788 parm
.parm_int_state
|= IS_NO_RIPV2_IN
;
790 } else if (PARS("ripv2_out")) {
791 if (parm
.parm_int_state
& IS_NO_RIPV2_OUT
)
792 return (bad_str(tgt
));
793 parm
.parm_int_state
|= IS_NO_RIPV1_OUT
;
795 } else if (PARS("ripv2")) {
796 if ((parm
.parm_int_state
& IS_NO_RIPV2_OUT
) ||
797 (parm
.parm_int_state
& IS_NO_RIPV2_IN
))
798 return (bad_str(tgt
));
799 parm
.parm_int_state
|= (IS_NO_RIPV1_IN
802 } else if (PARS("no_rip")) {
803 CKF(IS_PM_RDISC
, IS_NO_RIP
);
805 } else if (PARS("no_rip_mcast")) {
806 parm
.parm_int_state
|= IS_NO_RIP_MCAST
;
808 } else if (PARS("no_rdisc")) {
809 CKF((GROUP_IS_SOL_OUT
|GROUP_IS_ADV_OUT
), IS_NO_RDISC
);
811 } else if (PARS("no_solicit")) {
812 CKF(GROUP_IS_SOL_OUT
, IS_NO_SOL_OUT
);
814 } else if (PARS("send_solicit")) {
815 CKF(GROUP_IS_SOL_OUT
, IS_SOL_OUT
);
817 } else if (PARS("no_rdisc_adv")) {
818 CKF(GROUP_IS_ADV_OUT
, IS_NO_ADV_OUT
);
820 } else if (PARS("rdisc_adv")) {
821 CKF(GROUP_IS_ADV_OUT
, IS_ADV_OUT
);
823 } else if (PARS("bcast_rdisc")) {
824 parm
.parm_int_state
|= IS_BCAST_RDISC
;
826 } else if (PARS("passive")) {
827 CKF((GROUP_IS_SOL_OUT
|GROUP_IS_ADV_OUT
), IS_NO_RDISC
);
828 parm
.parm_int_state
|= IS_NO_RIP
| IS_PASSIVE
;
830 } else if (PARSEQ("rdisc_pref")) {
831 if (parm
.parm_rdisc_pref
!= 0 ||
832 (parm
.parm_rdisc_pref
= (int)strtol(buf
, &p
, 0),
833 *p
!= '\0') || (buf
== p
))
834 return (bad_str(tgt
));
836 } else if (PARS("pm_rdisc")) {
837 if (IS_RIP_OUT_OFF(parm
.parm_int_state
))
838 return (bad_str(tgt
));
839 parm
.parm_int_state
|= IS_PM_RDISC
;
841 } else if (PARSEQ("rdisc_interval")) {
842 if (parm
.parm_rdisc_int
!= 0 ||
843 (parm
.parm_rdisc_int
= (int)strtoul(buf
, &p
, 0),
844 *p
!= '\0') || (buf
== p
) ||
845 parm
.parm_rdisc_int
< MIN_MAXADVERTISEINTERVAL
||
846 parm
.parm_rdisc_int
> MAX_MAXADVERTISEINTERVAL
)
847 return (bad_str(tgt
));
849 } else if (PARSEQ("fake_default")) {
850 if (parm
.parm_d_metric
!= 0 ||
851 IS_RIP_OUT_OFF(parm
.parm_int_state
) ||
852 (parm
.parm_d_metric
= (int)strtoul(buf
, &p
, 0),
853 *p
!= '\0') || (buf
== p
) ||
854 parm
.parm_d_metric
> HOPCNT_INFINITY
-1)
855 return (bad_str(tgt
));
857 } else if (PARSEQ("trust_gateway")) {
858 /* look for trust_gateway=x.y.z|net/mask|...) */
860 if (0 > parse_quote(&p
, "|", &delim
, buf2
,
861 sizeof (buf2
)) || !gethost(buf2
, &addr
))
862 return (bad_str(tgt
));
863 tg
= rtmalloc(sizeof (*tg
),
864 "parse_parms trust_gateway");
865 (void) memset(tg
, 0, sizeof (*tg
));
866 tg
->tgate_addr
= addr
;
868 /* The default is to trust all routes. */
869 while (delim
== '|') {
871 if (i
>= MAX_TGATE_NETS
||
872 0 > parse_quote(&p
, "|", &delim
, buf2
,
874 !getnet(buf2
, &tg
->tgate_nets
[i
].net
,
875 &tg
->tgate_nets
[i
].mask
) ||
876 tg
->tgate_nets
[i
].net
== RIP_DEFAULT
||
877 tg
->tgate_nets
[i
].mask
== 0) {
879 return (bad_str(tgt
));
883 tg
->tgate_next
= tgates
;
885 parm
.parm_int_state
|= IS_DISTRUST
;
887 } else if (PARS("redirect_ok")) {
888 parm
.parm_int_state
|= IS_REDIRECT_OK
;
890 } else if (PARSEQ("rip_neighbor")) {
891 if (parm
.parm_name
[0] == '\0' ||
892 gethost(buf
, &parm
.parm_ripout_addr
) != 1)
893 return (bad_str(tgt
));
896 return (bad_str(tgt
)); /* error */
900 return (insert_parm(&parm
));
908 * Insert parameter specifications into the parms list. Returns NULL if
909 * successful, or an error message otherwise.
912 insert_parm(struct parm
*new)
914 struct parm
*parmp
, **parmpp
;
917 /* set implicit values */
918 if (new->parm_int_state
& (IS_NO_ADV_IN
|IS_NO_SOL_OUT
))
919 new->parm_int_state
|= IS_NO_ADV_IN
|IS_NO_SOL_OUT
;
921 for (i
= num_passwds
= 0; i
< MAX_AUTH_KEYS
; i
++) {
922 if (new->parm_auth
[i
].type
!= RIP_AUTH_NONE
)
926 /* compare with existing sets of parameters */
927 for (parmpp
= &parms
; (parmp
= *parmpp
) != 0;
928 parmpp
= &parmp
->parm_next
) {
929 if (strcmp(new->parm_name
, parmp
->parm_name
) != 0)
931 if (!on_net(htonl(parmp
->parm_net
), new->parm_net
,
933 !on_net(htonl(new->parm_net
), parmp
->parm_net
,
937 for (i
= 0; i
< MAX_AUTH_KEYS
; i
++) {
938 if (parmp
->parm_auth
[i
].type
!= RIP_AUTH_NONE
)
941 if (num_passwds
> MAX_AUTH_KEYS
)
942 return ("too many conflicting passwords");
944 if ((0 != (new->parm_int_state
& GROUP_IS_SOL_OUT
) &&
945 0 != (parmp
->parm_int_state
& GROUP_IS_SOL_OUT
) &&
946 0 != ((new->parm_int_state
^ parmp
->parm_int_state
) &&
947 GROUP_IS_SOL_OUT
)) ||
948 (0 != (new->parm_int_state
& GROUP_IS_ADV_OUT
) &&
949 0 != (parmp
->parm_int_state
& GROUP_IS_ADV_OUT
) &&
950 0 != ((new->parm_int_state
^ parmp
->parm_int_state
) &&
951 GROUP_IS_ADV_OUT
)) ||
952 (new->parm_rdisc_pref
!= 0 &&
953 parmp
->parm_rdisc_pref
!= 0 &&
954 new->parm_rdisc_pref
!= parmp
->parm_rdisc_pref
) ||
955 (new->parm_rdisc_int
!= 0 &&
956 parmp
->parm_rdisc_int
!= 0 &&
957 new->parm_rdisc_int
!= parmp
->parm_rdisc_int
)) {
958 return ("conflicting, duplicate router discovery"
963 if (new->parm_d_metric
!= 0 && parmp
->parm_d_metric
!= 0 &&
964 new->parm_d_metric
!= parmp
->parm_d_metric
) {
965 return ("conflicting, duplicate poor man's router"
966 " discovery or fake default metric");
971 * link new entry on the list so that when the entries are scanned,
972 * they affect the result in the order the operator specified.
974 parmp
= rtmalloc(sizeof (*parmp
), "insert_parm");
975 (void) memcpy(parmp
, new, sizeof (*parmp
));
982 gethost(char *name
, in_addr_t
*addrp
)
989 * Try for a number first. This avoids hitting the name
990 * server which might be sick because routing is.
992 if ((in
.s_addr
= inet_addr(name
)) != (in_addr_t
)-1) {
994 * get a good number, but check that it makes some
997 if ((ntohl(in
.s_addr
) >> 24) == 0 ||
998 (ntohl(in
.s_addr
) >> 24) == 0xff)
1004 hp
= gethostbyname(name
);
1006 (void) memcpy(addrp
, hp
->h_addr
, sizeof (*addrp
));
1015 addroutefordefault(in_addr_t dst
, in_addr_t gate
, in_addr_t mask
,
1016 uint32_t metric
, uint16_t rts_flags
)
1018 struct rt_spare
new;
1019 struct interface
*ifp
;
1020 uint16_t rt_newstate
= RS_STATIC
;
1023 ifp
= iflookup(gate
);
1025 msglog("unreachable gateway %s in "PATH_GATEWAYS
,
1030 trace_misc("addroutefordefault: found interface %s", ifp
->int_name
);
1032 (void) memset(&new, 0, sizeof (new));
1034 new.rts_router
= gate
;
1035 new.rts_gate
= gate
;
1036 new.rts_metric
= metric
;
1037 new.rts_time
= now
.tv_sec
;
1038 new.rts_flags
= rts_flags
;
1039 new.rts_origin
= RO_FILE
;
1041 input_route(dst
, mask
, &new, NULL
, rt_newstate
);