10Sstevel@tonic-gate /*
2*7738SRishi.Srivatsavai@Sun.COM * Copyright 2008 Sun Microsystems, Inc. All rights reserved.
30Sstevel@tonic-gate * Use is subject to license terms.
40Sstevel@tonic-gate *
50Sstevel@tonic-gate * Copyright (c) 1983, 1993
60Sstevel@tonic-gate * The Regents of the University of California. All rights reserved.
70Sstevel@tonic-gate *
80Sstevel@tonic-gate * Redistribution and use in source and binary forms, with or without
90Sstevel@tonic-gate * modification, are permitted provided that the following conditions
100Sstevel@tonic-gate * are met:
110Sstevel@tonic-gate * 1. Redistributions of source code must retain the above copyright
120Sstevel@tonic-gate * notice, this list of conditions and the following disclaimer.
130Sstevel@tonic-gate * 2. Redistributions in binary form must reproduce the above copyright
140Sstevel@tonic-gate * notice, this list of conditions and the following disclaimer in the
150Sstevel@tonic-gate * documentation and/or other materials provided with the distribution.
160Sstevel@tonic-gate * 3. All advertising materials mentioning features or use of this software
170Sstevel@tonic-gate * must display the following acknowledgment:
180Sstevel@tonic-gate * This product includes software developed by the University of
190Sstevel@tonic-gate * California, Berkeley and its contributors.
200Sstevel@tonic-gate * 4. Neither the name of the University nor the names of its contributors
210Sstevel@tonic-gate * may be used to endorse or promote products derived from this software
220Sstevel@tonic-gate * without specific prior written permission.
230Sstevel@tonic-gate *
240Sstevel@tonic-gate * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
250Sstevel@tonic-gate * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
260Sstevel@tonic-gate * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
270Sstevel@tonic-gate * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
280Sstevel@tonic-gate * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
290Sstevel@tonic-gate * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
300Sstevel@tonic-gate * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
310Sstevel@tonic-gate * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
320Sstevel@tonic-gate * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
330Sstevel@tonic-gate * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
340Sstevel@tonic-gate * SUCH DAMAGE.
350Sstevel@tonic-gate *
360Sstevel@tonic-gate * $FreeBSD: src/sbin/routed/parms.c,v 1.9 2000/08/11 08:24:38 sheldonh Exp $
370Sstevel@tonic-gate */
380Sstevel@tonic-gate
390Sstevel@tonic-gate #include "defs.h"
400Sstevel@tonic-gate #include "pathnames.h"
410Sstevel@tonic-gate #include <sys/stat.h>
420Sstevel@tonic-gate #include <arpa/inet.h>
430Sstevel@tonic-gate #include <ctype.h>
440Sstevel@tonic-gate
450Sstevel@tonic-gate #define PARMS_MAXLINELEN 500
460Sstevel@tonic-gate static struct parm *parms;
470Sstevel@tonic-gate struct intnet *intnets;
480Sstevel@tonic-gate struct r1net *r1nets;
490Sstevel@tonic-gate struct tgate *tgates;
500Sstevel@tonic-gate
510Sstevel@tonic-gate static void addroutefordefault(in_addr_t, in_addr_t, in_addr_t,
520Sstevel@tonic-gate uint32_t, uint16_t);
530Sstevel@tonic-gate
540Sstevel@tonic-gate /* use configured parameters */
550Sstevel@tonic-gate void
get_parms(struct interface * ifp)560Sstevel@tonic-gate get_parms(struct interface *ifp)
570Sstevel@tonic-gate {
580Sstevel@tonic-gate static boolean_t warned_auth_in, warned_auth_out;
590Sstevel@tonic-gate struct parm *parmp;
600Sstevel@tonic-gate int i, num_passwds = 0;
610Sstevel@tonic-gate
620Sstevel@tonic-gate if (ifp == NULL)
630Sstevel@tonic-gate return;
640Sstevel@tonic-gate
650Sstevel@tonic-gate /* get all relevant parameters */
660Sstevel@tonic-gate for (parmp = parms; parmp != NULL; parmp = parmp->parm_next) {
670Sstevel@tonic-gate if (parmp->parm_name[0] == '\0' ||
680Sstevel@tonic-gate strcmp(ifp->int_name, parmp->parm_name) == 0 ||
690Sstevel@tonic-gate (parmp->parm_name[0] == '\n' &&
70*7738SRishi.Srivatsavai@Sun.COM on_net(ifp->int_addr,
71*7738SRishi.Srivatsavai@Sun.COM parmp->parm_net, parmp->parm_mask))) {
720Sstevel@tonic-gate
730Sstevel@tonic-gate /*
740Sstevel@tonic-gate * This group of parameters is relevant,
750Sstevel@tonic-gate * so get its settings
760Sstevel@tonic-gate */
770Sstevel@tonic-gate ifp->int_state |= parmp->parm_int_state;
780Sstevel@tonic-gate for (i = 0; i < MAX_AUTH_KEYS; i++) {
790Sstevel@tonic-gate if (parmp->parm_auth[i].type == RIP_AUTH_NONE ||
800Sstevel@tonic-gate num_passwds >= MAX_AUTH_KEYS)
810Sstevel@tonic-gate break;
820Sstevel@tonic-gate ifp->int_auth[num_passwds++] =
830Sstevel@tonic-gate parmp->parm_auth[i];
840Sstevel@tonic-gate }
850Sstevel@tonic-gate if (parmp->parm_rdisc_pref != 0)
860Sstevel@tonic-gate ifp->int_rdisc_pref = parmp->parm_rdisc_pref;
870Sstevel@tonic-gate if (parmp->parm_rdisc_int != 0)
880Sstevel@tonic-gate ifp->int_rdisc_int = parmp->parm_rdisc_int;
890Sstevel@tonic-gate if (parmp->parm_d_metric != 0)
900Sstevel@tonic-gate ifp->int_d_metric = parmp->parm_d_metric;
910Sstevel@tonic-gate if (parmp->parm_ripout_addr != 0)
920Sstevel@tonic-gate ifp->int_ripout_addr = parmp->parm_ripout_addr;
930Sstevel@tonic-gate }
940Sstevel@tonic-gate }
950Sstevel@tonic-gate
960Sstevel@tonic-gate /*
970Sstevel@tonic-gate * Set general defaults.
980Sstevel@tonic-gate *
990Sstevel@tonic-gate * Default poor-man's router discovery to a metric that will
1000Sstevel@tonic-gate * be heard by old versions of `routed`. They ignored received
1010Sstevel@tonic-gate * routes with metric 15.
1020Sstevel@tonic-gate */
1030Sstevel@tonic-gate if ((ifp->int_state & IS_PM_RDISC) && ifp->int_d_metric == 0)
1040Sstevel@tonic-gate ifp->int_d_metric = FAKE_METRIC;
1050Sstevel@tonic-gate
1060Sstevel@tonic-gate if (ifp->int_rdisc_int == 0)
1070Sstevel@tonic-gate ifp->int_rdisc_int = DEF_MAXADVERTISEINTERVAL;
1080Sstevel@tonic-gate
1090Sstevel@tonic-gate if (!(ifp->int_if_flags & IFF_MULTICAST) &&
1100Sstevel@tonic-gate !(ifp->int_state & IS_REMOTE))
1110Sstevel@tonic-gate ifp->int_state |= IS_BCAST_RDISC;
1120Sstevel@tonic-gate
1130Sstevel@tonic-gate if (ifp->int_if_flags & IFF_POINTOPOINT) {
1140Sstevel@tonic-gate ifp->int_state |= IS_BCAST_RDISC;
1150Sstevel@tonic-gate /*
1160Sstevel@tonic-gate * By default, point-to-point links should be passive
1170Sstevel@tonic-gate * about router-discovery for the sake of demand-dialing.
1180Sstevel@tonic-gate */
1190Sstevel@tonic-gate if (!(ifp->int_state & GROUP_IS_SOL_OUT))
1200Sstevel@tonic-gate ifp->int_state |= IS_NO_SOL_OUT;
1210Sstevel@tonic-gate if (!(ifp->int_state & GROUP_IS_ADV_OUT))
1220Sstevel@tonic-gate ifp->int_state |= IS_NO_ADV_OUT;
1230Sstevel@tonic-gate }
1240Sstevel@tonic-gate
1250Sstevel@tonic-gate if (0 != (ifp->int_state & (IS_PASSIVE | IS_REMOTE)))
1260Sstevel@tonic-gate ifp->int_state |= IS_NO_RDISC;
1270Sstevel@tonic-gate if (ifp->int_state & IS_PASSIVE)
1280Sstevel@tonic-gate ifp->int_state |= IS_NO_RIP;
1290Sstevel@tonic-gate
1300Sstevel@tonic-gate if (!IS_RIP_IN_OFF(ifp->int_state) &&
1310Sstevel@tonic-gate ifp->int_auth[0].type != RIP_AUTH_NONE &&
1320Sstevel@tonic-gate !(ifp->int_state & IS_NO_RIPV1_IN) && !warned_auth_in) {
1330Sstevel@tonic-gate writelog(LOG_WARNING, "RIPv1 input via %s"
1340Sstevel@tonic-gate " will be accepted without authentication",
1350Sstevel@tonic-gate ifp->int_name);
1360Sstevel@tonic-gate warned_auth_in = _B_TRUE;
1370Sstevel@tonic-gate }
1380Sstevel@tonic-gate if (!IS_RIP_OUT_OFF(ifp->int_state) &&
1390Sstevel@tonic-gate ifp->int_auth[0].type != RIP_AUTH_NONE &&
1400Sstevel@tonic-gate !(ifp->int_state & IS_NO_RIPV1_OUT)) {
1410Sstevel@tonic-gate if (!warned_auth_out) {
1420Sstevel@tonic-gate writelog(LOG_WARNING, "RIPv1 output via %s"
1430Sstevel@tonic-gate " will be sent without authentication",
1440Sstevel@tonic-gate ifp->int_name);
1450Sstevel@tonic-gate warned_auth_out = _B_TRUE;
1460Sstevel@tonic-gate }
1470Sstevel@tonic-gate }
1480Sstevel@tonic-gate
1490Sstevel@tonic-gate /*
1500Sstevel@tonic-gate * If not overriden by the rip_neighbor option, set the
1510Sstevel@tonic-gate * default address to which RIP packets will be sent on
1520Sstevel@tonic-gate * this interface.
1530Sstevel@tonic-gate */
1540Sstevel@tonic-gate if (ifp->int_ripout_addr == 0) {
1550Sstevel@tonic-gate if (ifp->int_state & IS_REMOTE) {
1560Sstevel@tonic-gate /*
1570Sstevel@tonic-gate * By definition we always send RIP packets to
1580Sstevel@tonic-gate * the address assigned to a remote interface.
1590Sstevel@tonic-gate */
1600Sstevel@tonic-gate ifp->int_ripout_addr = ifp->int_addr;
1610Sstevel@tonic-gate } else if ((ifp->int_state & IS_NO_RIPV1_OUT) &&
1620Sstevel@tonic-gate (ifp->int_if_flags & IFF_MULTICAST) &&
1630Sstevel@tonic-gate !(ifp->int_state & IS_NO_RIP_MCAST)) {
1640Sstevel@tonic-gate /*
1650Sstevel@tonic-gate * If the interface is being used for RIPv2
1660Sstevel@tonic-gate * and it supports multicast, and if the user
1670Sstevel@tonic-gate * has not explicitely turned off multicast
1680Sstevel@tonic-gate * RIP output, send to the all RIP routers
1690Sstevel@tonic-gate * multicast address.
1700Sstevel@tonic-gate */
1710Sstevel@tonic-gate ifp->int_ripout_addr = htonl(INADDR_RIP_GROUP);
1720Sstevel@tonic-gate } else if (ifp->int_if_flags & IFF_POINTOPOINT) {
1730Sstevel@tonic-gate /*
1740Sstevel@tonic-gate * For point-to-point interfaces which don't
1750Sstevel@tonic-gate * fall into the two categories above, just
1760Sstevel@tonic-gate * send to the destination address of the
1770Sstevel@tonic-gate * interface.
1780Sstevel@tonic-gate */
1790Sstevel@tonic-gate ifp->int_ripout_addr = ifp->int_dstaddr;
1800Sstevel@tonic-gate } else {
1810Sstevel@tonic-gate /* Otherwise, use the broadcast address. */
1820Sstevel@tonic-gate ifp->int_ripout_addr = ifp->int_brdaddr;
1830Sstevel@tonic-gate }
1840Sstevel@tonic-gate }
1850Sstevel@tonic-gate }
1860Sstevel@tonic-gate
1870Sstevel@tonic-gate
1880Sstevel@tonic-gate /*
1890Sstevel@tonic-gate * Read a list of gateways from /etc/gateways and add them to our tables.
1900Sstevel@tonic-gate *
1910Sstevel@tonic-gate * This file contains a list of "remote" gateways. That is usually
1920Sstevel@tonic-gate * a gateway which we cannot immediately determine if it is present or
1930Sstevel@tonic-gate * not as we can do for those provided by directly connected hardware.
1940Sstevel@tonic-gate *
1950Sstevel@tonic-gate * If a gateway is marked "passive" in the file, then we assume it
1960Sstevel@tonic-gate * does not understand RIP and assume it is always present. Those
1970Sstevel@tonic-gate * not marked passive are treated as if they were directly connected
1980Sstevel@tonic-gate * and assumed to be broken if they do not send us advertisements.
1990Sstevel@tonic-gate * All remote interfaces are added to our list, and those not marked
2000Sstevel@tonic-gate * passive are sent routing updates.
2010Sstevel@tonic-gate *
2020Sstevel@tonic-gate * A passive interface can also be local, hardware interface exempt
2030Sstevel@tonic-gate * from RIP.
2040Sstevel@tonic-gate */
2050Sstevel@tonic-gate void
gwkludge(void)2060Sstevel@tonic-gate gwkludge(void)
2070Sstevel@tonic-gate {
2080Sstevel@tonic-gate #define STR2(x) #x
2090Sstevel@tonic-gate #define STR(x) STR2(x)
2100Sstevel@tonic-gate
2110Sstevel@tonic-gate #define NETHOST_LEN 4
2120Sstevel@tonic-gate #define DNAME_LEN MAXHOSTNAMELEN
2130Sstevel@tonic-gate #define GNAME_LEN MAXHOSTNAMELEN
2140Sstevel@tonic-gate #define QUAL_LEN 8
2150Sstevel@tonic-gate
2160Sstevel@tonic-gate FILE *fp;
2170Sstevel@tonic-gate char *p, *lptr;
2180Sstevel@tonic-gate const char *cp;
2190Sstevel@tonic-gate char lbuf[PARMS_MAXLINELEN], net_host[NETHOST_LEN + 1];
2200Sstevel@tonic-gate char dname[MAXHOSTNAMELEN + 1];
2210Sstevel@tonic-gate char gname[MAXHOSTNAMELEN + 1], qual[QUAL_LEN +1];
2220Sstevel@tonic-gate struct interface *ifp;
2230Sstevel@tonic-gate uint32_t dst, netmask, gate;
2240Sstevel@tonic-gate int n;
2250Sstevel@tonic-gate uint32_t lnum;
2260Sstevel@tonic-gate struct stat sb;
2270Sstevel@tonic-gate uint32_t state, metric;
2280Sstevel@tonic-gate boolean_t default_dst;
2290Sstevel@tonic-gate
2300Sstevel@tonic-gate
2310Sstevel@tonic-gate fp = fopen(PATH_GATEWAYS, "r");
2320Sstevel@tonic-gate if (fp == NULL)
2330Sstevel@tonic-gate return;
2340Sstevel@tonic-gate
2350Sstevel@tonic-gate if (0 > fstat(fileno(fp), &sb)) {
2360Sstevel@tonic-gate msglog("fstat() failed: %s for "PATH_GATEWAYS,
2370Sstevel@tonic-gate rip_strerror(errno));
2380Sstevel@tonic-gate (void) fclose(fp);
2390Sstevel@tonic-gate return;
2400Sstevel@tonic-gate }
2410Sstevel@tonic-gate
2420Sstevel@tonic-gate for (lnum = 1; ; lnum++) {
2430Sstevel@tonic-gate if (NULL == fgets(lbuf, sizeof (lbuf), fp))
2440Sstevel@tonic-gate break;
2450Sstevel@tonic-gate
2460Sstevel@tonic-gate /* Eliminate the /n character at the end of the lbuf */
2470Sstevel@tonic-gate if (strlen(lbuf) > 0)
2480Sstevel@tonic-gate lbuf[strlen(lbuf) - 1] = '\0';
2490Sstevel@tonic-gate
2500Sstevel@tonic-gate /* Move lptr to the first non-space character */
2510Sstevel@tonic-gate for (lptr = lbuf; isspace(*lptr); lptr++)
2520Sstevel@tonic-gate ;
2530Sstevel@tonic-gate
2540Sstevel@tonic-gate if (*lptr == '#' || *lptr == '\0')
2550Sstevel@tonic-gate continue;
2560Sstevel@tonic-gate
2570Sstevel@tonic-gate /* Move p to the end of the line */
2580Sstevel@tonic-gate p = lptr + strlen(lptr) - 1;
2590Sstevel@tonic-gate
2600Sstevel@tonic-gate /* Skip all trailing spaces except escaped space */
2610Sstevel@tonic-gate while (p > lptr && (isspace(*p) && *(p-1) != '\\'))
2620Sstevel@tonic-gate p--;
2630Sstevel@tonic-gate
2640Sstevel@tonic-gate /* truncate the line to remove trailing spaces */
2650Sstevel@tonic-gate *++p = '\0';
2660Sstevel@tonic-gate
2670Sstevel@tonic-gate /* notice newfangled parameter lines */
2680Sstevel@tonic-gate if (strncasecmp("net", lptr, 3) != 0 &&
2690Sstevel@tonic-gate strncasecmp("host", lptr, 4) != 0) {
2700Sstevel@tonic-gate cp = parse_parms(lptr, (sb.st_uid == 0 &&
2710Sstevel@tonic-gate !(sb.st_mode&(S_IRWXG|S_IRWXO))));
2720Sstevel@tonic-gate if (cp != 0)
2730Sstevel@tonic-gate msglog("%s in line %u of "PATH_GATEWAYS,
2740Sstevel@tonic-gate cp, lnum);
2750Sstevel@tonic-gate continue;
2760Sstevel@tonic-gate }
2770Sstevel@tonic-gate
2780Sstevel@tonic-gate /*
2790Sstevel@tonic-gate * Processes lines of the follwoing format:
2800Sstevel@tonic-gate * net|host <name>[/mask] gateway <Gname> metric <value>
2810Sstevel@tonic-gate * passive|active|extern
2820Sstevel@tonic-gate */
2830Sstevel@tonic-gate qual[0] = '\0';
2840Sstevel@tonic-gate n = sscanf(lptr, "%"STR(NETHOST_LEN)"s %"STR(DNAME_LEN)
2850Sstevel@tonic-gate "[^ \t] gateway %"STR(GNAME_LEN)"[^ / \t] metric %u %"
2860Sstevel@tonic-gate STR(QUAL_LEN)"s\n", net_host, dname, gname, &metric, qual);
2870Sstevel@tonic-gate if (n != 4 && n != 5) {
2880Sstevel@tonic-gate msglog("bad "PATH_GATEWAYS" entry \"%s\"; %d values",
2890Sstevel@tonic-gate lptr, n);
2900Sstevel@tonic-gate continue;
2910Sstevel@tonic-gate }
2920Sstevel@tonic-gate if (metric >= HOPCNT_INFINITY) {
2930Sstevel@tonic-gate msglog("bad metric in "PATH_GATEWAYS" entry \"%s\"",
2940Sstevel@tonic-gate lptr);
2950Sstevel@tonic-gate continue;
2960Sstevel@tonic-gate }
2970Sstevel@tonic-gate default_dst = _B_FALSE;
2980Sstevel@tonic-gate if (strcasecmp(net_host, "host") == 0) {
2990Sstevel@tonic-gate if (!gethost(dname, &dst)) {
3000Sstevel@tonic-gate msglog("bad host \"%s\" in "PATH_GATEWAYS
3010Sstevel@tonic-gate " entry \"%s\"", dname, lptr);
3020Sstevel@tonic-gate continue;
3030Sstevel@tonic-gate }
3040Sstevel@tonic-gate netmask = HOST_MASK;
3050Sstevel@tonic-gate } else if (strcasecmp(net_host, "net") == 0) {
3060Sstevel@tonic-gate if (!getnet(dname, &dst, &netmask)) {
3070Sstevel@tonic-gate msglog("bad net \"%s\" in "PATH_GATEWAYS
3080Sstevel@tonic-gate " entry \"%s\"", dname, lptr);
3090Sstevel@tonic-gate continue;
3100Sstevel@tonic-gate }
3110Sstevel@tonic-gate default_dst = (dst == RIP_DEFAULT);
3120Sstevel@tonic-gate dst = htonl(dst); /* make network # into IP address */
3130Sstevel@tonic-gate } else {
3140Sstevel@tonic-gate msglog("bad \"%s\" in "PATH_GATEWAYS
3150Sstevel@tonic-gate " entry \"%s\"", net_host, lptr);
3160Sstevel@tonic-gate continue;
3170Sstevel@tonic-gate }
3180Sstevel@tonic-gate
3190Sstevel@tonic-gate if (!gethost(gname, &gate)) {
3200Sstevel@tonic-gate msglog("bad gateway \"%s\" in "PATH_GATEWAYS
3210Sstevel@tonic-gate " entry \"%s\"", gname, lptr);
3220Sstevel@tonic-gate continue;
3230Sstevel@tonic-gate }
3240Sstevel@tonic-gate
3250Sstevel@tonic-gate if (strcasecmp(qual, "passive") == 0) {
3260Sstevel@tonic-gate /*
3270Sstevel@tonic-gate * Passive entries are not placed in our tables,
3280Sstevel@tonic-gate * only the kernel's, so we don't copy all of the
3290Sstevel@tonic-gate * external routing information within a net.
3300Sstevel@tonic-gate * Internal machines should use the default
3310Sstevel@tonic-gate * route to a suitable gateway (like us).
3320Sstevel@tonic-gate */
3330Sstevel@tonic-gate state = IS_REMOTE | IS_PASSIVE;
3340Sstevel@tonic-gate if (metric == 0)
3350Sstevel@tonic-gate metric = 1;
3360Sstevel@tonic-gate
3370Sstevel@tonic-gate } else if (strcasecmp(qual, "external") == 0) {
3380Sstevel@tonic-gate /*
3390Sstevel@tonic-gate * External entries are handled by other means
3400Sstevel@tonic-gate * such as EGP, and are placed only in the daemon
3410Sstevel@tonic-gate * tables to prevent overriding them with something
3420Sstevel@tonic-gate * else.
3430Sstevel@tonic-gate */
3440Sstevel@tonic-gate (void) strlcpy(qual, "external", sizeof (qual));
3450Sstevel@tonic-gate state = IS_REMOTE | IS_PASSIVE | IS_EXTERNAL;
3460Sstevel@tonic-gate if (metric == 0)
3470Sstevel@tonic-gate metric = 1;
3480Sstevel@tonic-gate
3490Sstevel@tonic-gate } else if (strcasecmp(qual, "active") == 0 ||
3500Sstevel@tonic-gate qual[0] == '\0') {
3510Sstevel@tonic-gate
3520Sstevel@tonic-gate if (default_dst) {
3530Sstevel@tonic-gate msglog("bad net \"%s\" in "PATH_GATEWAYS
3540Sstevel@tonic-gate " entry \"%s\"-- cannot be default",
3550Sstevel@tonic-gate dname, lptr);
3560Sstevel@tonic-gate continue;
3570Sstevel@tonic-gate }
3580Sstevel@tonic-gate
3590Sstevel@tonic-gate if (metric != 0) {
3600Sstevel@tonic-gate /*
3610Sstevel@tonic-gate * Entries that are neither "passive" nor
3620Sstevel@tonic-gate * "external" are "remote" and must behave
3630Sstevel@tonic-gate * like physical interfaces. If they are not
3640Sstevel@tonic-gate * heard from regularly, they are deleted.
3650Sstevel@tonic-gate */
3660Sstevel@tonic-gate state = IS_REMOTE;
3670Sstevel@tonic-gate } else {
3680Sstevel@tonic-gate /*
3690Sstevel@tonic-gate * "remote" entries with a metric of 0
3700Sstevel@tonic-gate * are aliases for our own interfaces
3710Sstevel@tonic-gate */
3720Sstevel@tonic-gate state = IS_REMOTE | IS_PASSIVE | IS_ALIAS;
3730Sstevel@tonic-gate }
3740Sstevel@tonic-gate
3750Sstevel@tonic-gate } else {
3760Sstevel@tonic-gate msglog("bad "PATH_GATEWAYS" entry \"%s\";"
3770Sstevel@tonic-gate " unknown type %s", lptr, qual);
3780Sstevel@tonic-gate continue;
3790Sstevel@tonic-gate }
3800Sstevel@tonic-gate
3810Sstevel@tonic-gate if (0 != (state & (IS_PASSIVE | IS_REMOTE)))
3820Sstevel@tonic-gate state |= IS_NO_RDISC;
3830Sstevel@tonic-gate if (state & IS_PASSIVE)
3840Sstevel@tonic-gate state |= IS_NO_RIP;
3850Sstevel@tonic-gate
3860Sstevel@tonic-gate
3870Sstevel@tonic-gate if (default_dst) {
3880Sstevel@tonic-gate addroutefordefault(dst, gate, netmask, metric,
3890Sstevel@tonic-gate ((state & IS_EXTERNAL)? RTS_EXTERNAL : 0));
3900Sstevel@tonic-gate continue;
3910Sstevel@tonic-gate }
3920Sstevel@tonic-gate
3930Sstevel@tonic-gate ifp = check_dup(NULL, gate, dst, netmask, 0, _B_FALSE);
3940Sstevel@tonic-gate if (ifp != NULL) {
3950Sstevel@tonic-gate msglog("duplicate "PATH_GATEWAYS" entry \"%s\"", lptr);
3960Sstevel@tonic-gate continue;
3970Sstevel@tonic-gate }
3980Sstevel@tonic-gate
3990Sstevel@tonic-gate ifp = rtmalloc(sizeof (*ifp), "gwkludge()");
4000Sstevel@tonic-gate (void) memset(ifp, 0, sizeof (*ifp));
4010Sstevel@tonic-gate
4020Sstevel@tonic-gate ifp->int_state = state;
4030Sstevel@tonic-gate if (netmask == HOST_MASK)
4040Sstevel@tonic-gate ifp->int_if_flags = IFF_POINTOPOINT | IFF_UP;
4050Sstevel@tonic-gate else
4060Sstevel@tonic-gate ifp->int_if_flags = IFF_UP;
4070Sstevel@tonic-gate ifp->int_act_time = NEVER;
4080Sstevel@tonic-gate ifp->int_addr = gate;
4090Sstevel@tonic-gate ifp->int_dstaddr = dst;
4100Sstevel@tonic-gate ifp->int_mask = netmask;
4110Sstevel@tonic-gate ifp->int_ripv1_mask = netmask;
4120Sstevel@tonic-gate ifp->int_std_mask = std_mask(gate);
4130Sstevel@tonic-gate ifp->int_net = ntohl(dst);
4140Sstevel@tonic-gate ifp->int_std_net = ifp->int_net & ifp->int_std_mask;
4150Sstevel@tonic-gate ifp->int_std_addr = htonl(ifp->int_std_net);
4160Sstevel@tonic-gate ifp->int_metric = metric;
4170Sstevel@tonic-gate if (!(state & IS_EXTERNAL) &&
4180Sstevel@tonic-gate ifp->int_mask != ifp->int_std_mask)
4190Sstevel@tonic-gate ifp->int_state |= IS_SUBNET;
4200Sstevel@tonic-gate (void) snprintf(ifp->int_name, sizeof (ifp->int_name),
4210Sstevel@tonic-gate "remote(%s)", gname);
4220Sstevel@tonic-gate
4230Sstevel@tonic-gate if_link(ifp, 0);
4240Sstevel@tonic-gate }
4250Sstevel@tonic-gate
4260Sstevel@tonic-gate (void) fclose(fp);
4270Sstevel@tonic-gate
4280Sstevel@tonic-gate /*
4290Sstevel@tonic-gate * After all of the parameter lines have been read,
4300Sstevel@tonic-gate * apply them to any remote interfaces.
4310Sstevel@tonic-gate */
4320Sstevel@tonic-gate for (ifp = ifnet; NULL != ifp; ifp = ifp->int_next) {
4330Sstevel@tonic-gate get_parms(ifp);
4340Sstevel@tonic-gate
4350Sstevel@tonic-gate tot_interfaces++;
4360Sstevel@tonic-gate if (!IS_RIP_OFF(ifp->int_state))
4370Sstevel@tonic-gate rip_interfaces++;
4380Sstevel@tonic-gate if (!IS_RIP_OUT_OFF(ifp->int_state))
4390Sstevel@tonic-gate ripout_interfaces++;
4400Sstevel@tonic-gate
4410Sstevel@tonic-gate trace_if("Add", ifp);
4420Sstevel@tonic-gate }
4430Sstevel@tonic-gate
4440Sstevel@tonic-gate }
4450Sstevel@tonic-gate
4460Sstevel@tonic-gate /* Parse password timestamp */
4470Sstevel@tonic-gate static char *
parse_ts(time_t * tp,char ** valp,char * val0,char * delimp,char * buf,uint_t bufsize)4480Sstevel@tonic-gate parse_ts(time_t *tp,
4490Sstevel@tonic-gate char **valp,
4500Sstevel@tonic-gate char *val0,
4510Sstevel@tonic-gate char *delimp,
4520Sstevel@tonic-gate char *buf,
4530Sstevel@tonic-gate uint_t bufsize)
4540Sstevel@tonic-gate {
4550Sstevel@tonic-gate struct tm tm;
4560Sstevel@tonic-gate
4570Sstevel@tonic-gate if (0 > parse_quote(valp, "| ,", delimp, buf, bufsize) ||
4580Sstevel@tonic-gate buf[bufsize-1] != '\0' || buf[bufsize-2] != '\0') {
4590Sstevel@tonic-gate (void) snprintf(buf, bufsize, "bad timestamp %.25s", val0);
4600Sstevel@tonic-gate return (buf);
4610Sstevel@tonic-gate }
4620Sstevel@tonic-gate (void) strlcat(buf, "\n", bufsize);
4630Sstevel@tonic-gate (void) memset(&tm, 0, sizeof (tm));
4640Sstevel@tonic-gate if (5 != sscanf(buf, "%u/%u/%u@%u:%u\n",
4650Sstevel@tonic-gate (unsigned *)&tm.tm_year, (unsigned *)&tm.tm_mon,
4660Sstevel@tonic-gate (unsigned *)&tm.tm_mday, (unsigned *)&tm.tm_hour,
4670Sstevel@tonic-gate (unsigned *)&tm.tm_min) ||
4680Sstevel@tonic-gate tm.tm_mon < 1 || tm.tm_mon > 12 ||
4690Sstevel@tonic-gate tm.tm_mday < 1 || tm.tm_mday > 31) {
4700Sstevel@tonic-gate (void) snprintf(buf, bufsize, "bad timestamp %.25s", val0);
4710Sstevel@tonic-gate return (buf);
4720Sstevel@tonic-gate }
4730Sstevel@tonic-gate tm.tm_mon--;
4740Sstevel@tonic-gate /* assume small years are in the 3rd millenium */
4750Sstevel@tonic-gate if (tm.tm_year <= 37)
4760Sstevel@tonic-gate tm.tm_year += 100;
4770Sstevel@tonic-gate
4780Sstevel@tonic-gate if (tm.tm_year >= 1900)
4790Sstevel@tonic-gate tm.tm_year -= 1900;
4800Sstevel@tonic-gate
4810Sstevel@tonic-gate if ((*tp = mktime(&tm)) == -1) {
4820Sstevel@tonic-gate (void) snprintf(buf, bufsize, "bad timestamp %.25s", val0);
4830Sstevel@tonic-gate return (buf);
4840Sstevel@tonic-gate }
4850Sstevel@tonic-gate
4860Sstevel@tonic-gate return (NULL);
4870Sstevel@tonic-gate }
4880Sstevel@tonic-gate
4890Sstevel@tonic-gate
4900Sstevel@tonic-gate /*
4910Sstevel@tonic-gate * Get a password, key ID, and expiration date in the format
4920Sstevel@tonic-gate * passwd|keyID|year/mon/day@hour:min|year/mon/day@hour:min
4930Sstevel@tonic-gate * returns NULL or error message
4940Sstevel@tonic-gate */
4950Sstevel@tonic-gate static const char *
get_passwd(char * tgt,char * val,struct parm * parmp,uint16_t type,boolean_t safe)4960Sstevel@tonic-gate get_passwd(char *tgt,
4970Sstevel@tonic-gate char *val,
4980Sstevel@tonic-gate struct parm *parmp,
4990Sstevel@tonic-gate uint16_t type,
5000Sstevel@tonic-gate boolean_t safe) /* 1=from secure file */
5010Sstevel@tonic-gate {
5020Sstevel@tonic-gate static char buf[80];
5030Sstevel@tonic-gate char *val0, *p, delim;
5040Sstevel@tonic-gate struct auth k, *ap, *ap2;
5050Sstevel@tonic-gate int i;
5060Sstevel@tonic-gate ulong_t l;
5070Sstevel@tonic-gate
5080Sstevel@tonic-gate
5090Sstevel@tonic-gate if (!safe)
5100Sstevel@tonic-gate return ("ignore unsafe password");
5110Sstevel@tonic-gate
5120Sstevel@tonic-gate for (ap = parmp->parm_auth, i = 0; ap->type != RIP_AUTH_NONE;
5130Sstevel@tonic-gate i++, ap++) {
5140Sstevel@tonic-gate if (i >= MAX_AUTH_KEYS)
5150Sstevel@tonic-gate return ("too many passwords");
5160Sstevel@tonic-gate }
5170Sstevel@tonic-gate
5180Sstevel@tonic-gate (void) memset(&k, 0, sizeof (k));
5190Sstevel@tonic-gate k.type = type;
5200Sstevel@tonic-gate k.end = -1-DAY;
5210Sstevel@tonic-gate
5220Sstevel@tonic-gate val0 = val;
5230Sstevel@tonic-gate if (0 > parse_quote(&val, "| ,", &delim,
5240Sstevel@tonic-gate (char *)k.key, sizeof (k.key)))
5250Sstevel@tonic-gate return (tgt);
5260Sstevel@tonic-gate
5270Sstevel@tonic-gate if (delim != '|') {
5280Sstevel@tonic-gate if (type == RIP_AUTH_MD5)
5290Sstevel@tonic-gate return ("missing Keyid");
5300Sstevel@tonic-gate } else {
5310Sstevel@tonic-gate val0 = ++val;
5320Sstevel@tonic-gate buf[sizeof (buf)-1] = '\0';
5330Sstevel@tonic-gate if (0 > parse_quote(&val, "| ,", &delim, buf,
5340Sstevel@tonic-gate sizeof (buf)) ||
5350Sstevel@tonic-gate buf[sizeof (buf) - 1] != '\0' ||
5360Sstevel@tonic-gate (l = strtoul(buf, &p, 0)) > 255 ||
5370Sstevel@tonic-gate p == buf || *p != '\0') {
5380Sstevel@tonic-gate (void) snprintf(buf, sizeof (buf),
5390Sstevel@tonic-gate "bad KeyID \"%.20s\"", val0);
5400Sstevel@tonic-gate return (buf);
5410Sstevel@tonic-gate }
5420Sstevel@tonic-gate for (ap2 = parmp->parm_auth; ap2 < ap; ap2++) {
5430Sstevel@tonic-gate if (ap2->keyid == l) {
5440Sstevel@tonic-gate (void) snprintf(buf, sizeof (buf),
5450Sstevel@tonic-gate "duplicate KeyID \"%.20s\"",
5460Sstevel@tonic-gate val0);
5470Sstevel@tonic-gate return (buf);
5480Sstevel@tonic-gate }
5490Sstevel@tonic-gate }
5500Sstevel@tonic-gate k.keyid = (int)l;
5510Sstevel@tonic-gate
5520Sstevel@tonic-gate if (delim == '|') {
5530Sstevel@tonic-gate val0 = ++val;
5540Sstevel@tonic-gate if (NULL != (p = parse_ts(&k.start, &val, val0, &delim,
5550Sstevel@tonic-gate buf, sizeof (buf))))
5560Sstevel@tonic-gate return (p);
5570Sstevel@tonic-gate if (delim != '|')
5580Sstevel@tonic-gate return ("missing second timestamp");
5590Sstevel@tonic-gate val0 = ++val;
5600Sstevel@tonic-gate if (NULL != (p = parse_ts(&k.end, &val, val0, &delim,
5610Sstevel@tonic-gate buf, sizeof (buf))))
5620Sstevel@tonic-gate return (p);
5630Sstevel@tonic-gate if ((ulong_t)k.start > (ulong_t)k.end) {
5640Sstevel@tonic-gate (void) snprintf(buf, sizeof (buf),
5650Sstevel@tonic-gate "out of order timestamp %.30s", val0);
5660Sstevel@tonic-gate return (buf);
5670Sstevel@tonic-gate }
5680Sstevel@tonic-gate }
5690Sstevel@tonic-gate }
5700Sstevel@tonic-gate if (delim != '\0')
5710Sstevel@tonic-gate return (tgt);
5720Sstevel@tonic-gate
5730Sstevel@tonic-gate (void) memmove(ap, &k, sizeof (*ap));
5740Sstevel@tonic-gate return (NULL);
5750Sstevel@tonic-gate }
5760Sstevel@tonic-gate
5770Sstevel@tonic-gate
5780Sstevel@tonic-gate static const char *
bad_str(const char * estr)5790Sstevel@tonic-gate bad_str(const char *estr)
5800Sstevel@tonic-gate {
5810Sstevel@tonic-gate static char buf[100+8];
5820Sstevel@tonic-gate
5830Sstevel@tonic-gate (void) snprintf(buf, sizeof (buf), "bad \"%.100s\"", estr);
5840Sstevel@tonic-gate return (buf);
5850Sstevel@tonic-gate }
5860Sstevel@tonic-gate
5870Sstevel@tonic-gate
5880Sstevel@tonic-gate /*
5890Sstevel@tonic-gate * Parse a set of parameters for an interface.
5900Sstevel@tonic-gate * returns NULL or error message
5910Sstevel@tonic-gate */
5920Sstevel@tonic-gate const char *
parse_parms(char * line,boolean_t safe)5930Sstevel@tonic-gate parse_parms(char *line,
5940Sstevel@tonic-gate boolean_t safe) /* 1=from secure file */
5950Sstevel@tonic-gate {
5960Sstevel@tonic-gate #define PARS(str) (strcasecmp(tgt, str) == 0)
5970Sstevel@tonic-gate #define PARSEQ(str) (strncasecmp(tgt, str"=", sizeof (str)) == 0)
5980Sstevel@tonic-gate /*
5990Sstevel@tonic-gate * This macro checks for conflicting configurations options
6000Sstevel@tonic-gate * For eg one can set either the IS_NO_SOL_OUT flag bit or the IS_SOL_OUT flag
6010Sstevel@tonic-gate * bit, but not both.
6020Sstevel@tonic-gate */
6030Sstevel@tonic-gate #define CKF(g, b) {if (0 != (parm.parm_int_state & ((g) & ~(b)))) break; \
6040Sstevel@tonic-gate parm.parm_int_state |= (b); }
6050Sstevel@tonic-gate struct parm parm;
6060Sstevel@tonic-gate struct intnet *intnetp;
6070Sstevel@tonic-gate struct r1net *r1netp;
6080Sstevel@tonic-gate struct tgate *tg;
6090Sstevel@tonic-gate uint32_t addr, mask;
6100Sstevel@tonic-gate char delim, *val0 = 0, *tgt, *val, *p;
6110Sstevel@tonic-gate const char *msg;
6120Sstevel@tonic-gate char buf[PARMS_MAXLINELEN], buf2[PARMS_MAXLINELEN];
6130Sstevel@tonic-gate int i;
6140Sstevel@tonic-gate
6150Sstevel@tonic-gate
6160Sstevel@tonic-gate /* "subnet=x.y.z.u/mask[,metric]" must be alone on the line */
6170Sstevel@tonic-gate if (strncasecmp(line, "subnet=", sizeof ("subnet=") - 1) == 0 &&
6180Sstevel@tonic-gate *(val = &line[sizeof ("subnet=") -1 ]) != '\0') {
6190Sstevel@tonic-gate if (0 > parse_quote(&val, ",", &delim, buf, sizeof (buf)))
6200Sstevel@tonic-gate return (bad_str(line));
6210Sstevel@tonic-gate intnetp = rtmalloc(sizeof (*intnetp),
6220Sstevel@tonic-gate "parse_parms subnet");
6230Sstevel@tonic-gate intnetp->intnet_metric = 1;
6240Sstevel@tonic-gate if (delim == ',') {
6250Sstevel@tonic-gate intnetp->intnet_metric = (int)strtol(val+1, &p, 0);
6260Sstevel@tonic-gate if (*p != '\0' || intnetp->intnet_metric <= 0 ||
6270Sstevel@tonic-gate val+1 == p ||
6280Sstevel@tonic-gate intnetp->intnet_metric >= HOPCNT_INFINITY) {
6290Sstevel@tonic-gate free(intnetp);
6300Sstevel@tonic-gate return (bad_str(line));
6310Sstevel@tonic-gate }
6320Sstevel@tonic-gate }
6330Sstevel@tonic-gate if (!getnet(buf, &intnetp->intnet_addr,
6340Sstevel@tonic-gate &intnetp->intnet_mask) ||
6350Sstevel@tonic-gate intnetp->intnet_mask == HOST_MASK ||
6360Sstevel@tonic-gate intnetp->intnet_addr == RIP_DEFAULT) {
6370Sstevel@tonic-gate free(intnetp);
6380Sstevel@tonic-gate return (bad_str(line));
6390Sstevel@tonic-gate }
6400Sstevel@tonic-gate intnetp->intnet_addr = htonl(intnetp->intnet_addr);
6410Sstevel@tonic-gate intnetp->intnet_next = intnets;
6420Sstevel@tonic-gate intnets = intnetp;
6430Sstevel@tonic-gate return (NULL);
6440Sstevel@tonic-gate }
6450Sstevel@tonic-gate
6460Sstevel@tonic-gate /*
6470Sstevel@tonic-gate * "ripv1_mask=x.y.z.u/mask1,mask2" must be alone on the line.
6480Sstevel@tonic-gate * This requires that x.y.z.u/mask1 be considered a subnet of
6490Sstevel@tonic-gate * x.y.z.u/mask2, as if x.y.z.u/mask2 were a class-full network.
6500Sstevel@tonic-gate */
6510Sstevel@tonic-gate if (!strncasecmp(line, "ripv1_mask=", sizeof ("ripv1_mask=") - 1) &&
6520Sstevel@tonic-gate *(val = &line[sizeof ("ripv1_mask=")-1]) != '\0') {
6530Sstevel@tonic-gate if (0 > parse_quote(&val, ",", &delim, buf, sizeof (buf)) ||
6540Sstevel@tonic-gate delim == '\0')
6550Sstevel@tonic-gate return (bad_str(line));
6560Sstevel@tonic-gate if ((i = (int)strtol(val+1, &p, 0)) <= 0 || i > 32 ||
6570Sstevel@tonic-gate *p != '\0')
6580Sstevel@tonic-gate return (bad_str(line));
6590Sstevel@tonic-gate r1netp = rtmalloc(sizeof (*r1netp), "parse_parms ripv1_mask");
6600Sstevel@tonic-gate r1netp->r1net_mask = HOST_MASK << (32-i);
6610Sstevel@tonic-gate if (!getnet(buf, &r1netp->r1net_net, &r1netp->r1net_match) ||
6620Sstevel@tonic-gate r1netp->r1net_net == RIP_DEFAULT ||
6630Sstevel@tonic-gate r1netp->r1net_mask > r1netp->r1net_match) {
6640Sstevel@tonic-gate free(r1netp);
6650Sstevel@tonic-gate return (bad_str(line));
6660Sstevel@tonic-gate }
6670Sstevel@tonic-gate r1netp->r1net_next = r1nets;
6680Sstevel@tonic-gate r1nets = r1netp;
6690Sstevel@tonic-gate return (NULL);
6700Sstevel@tonic-gate }
6710Sstevel@tonic-gate
6720Sstevel@tonic-gate (void) memset(&parm, 0, sizeof (parm));
6730Sstevel@tonic-gate /*
6740Sstevel@tonic-gate * Support of the following for Solaris backward compatibility
6750Sstevel@tonic-gate * norip <ifname>
6760Sstevel@tonic-gate * noripin <ifname>
6770Sstevel@tonic-gate * noripout <ifname>
6780Sstevel@tonic-gate */
6790Sstevel@tonic-gate if (strncasecmp("norip", line, 5) == 0) {
6800Sstevel@tonic-gate char cmd[64], ifname[64];
6810Sstevel@tonic-gate int n;
6820Sstevel@tonic-gate
6830Sstevel@tonic-gate n = sscanf(line, "%63s %63s\n", cmd, ifname);
6840Sstevel@tonic-gate if (n != 2) {
6850Sstevel@tonic-gate /* Not enough parameters */
6860Sstevel@tonic-gate return (bad_str(line));
6870Sstevel@tonic-gate }
6880Sstevel@tonic-gate
6890Sstevel@tonic-gate /*
6900Sstevel@tonic-gate * Get the interface name and turn on the appropriate
6910Sstevel@tonic-gate * interface flags
6920Sstevel@tonic-gate */
6930Sstevel@tonic-gate (void) strlcpy(parm.parm_name, ifname, sizeof (parm.parm_name));
6940Sstevel@tonic-gate if (strcasecmp("norip", cmd) == 0) {
6950Sstevel@tonic-gate parm.parm_int_state |= IS_NO_RIP;
6960Sstevel@tonic-gate } else if (strcasecmp("noripin", cmd) == 0) {
6970Sstevel@tonic-gate parm.parm_int_state |= IS_NO_RIP_IN;
6980Sstevel@tonic-gate } else if (strcasecmp("noripout", cmd) == 0) {
6990Sstevel@tonic-gate parm.parm_int_state |= IS_NO_RIP_OUT;
7000Sstevel@tonic-gate } else {
7010Sstevel@tonic-gate /* Bad command */
7020Sstevel@tonic-gate return (bad_str(line));
7030Sstevel@tonic-gate }
7040Sstevel@tonic-gate /*
7050Sstevel@tonic-gate * Look for duplication, and if new,
7060Sstevel@tonic-gate * link to the rest of the parm entries.
7070Sstevel@tonic-gate */
7080Sstevel@tonic-gate return (insert_parm(&parm));
7090Sstevel@tonic-gate }
7100Sstevel@tonic-gate
7110Sstevel@tonic-gate for (;;) {
7120Sstevel@tonic-gate tgt = line + strspn(line, " ,\n\r");
7130Sstevel@tonic-gate if (*tgt == '\0' || *tgt == '#')
7140Sstevel@tonic-gate break;
7150Sstevel@tonic-gate line = tgt+strcspn(tgt, "= #,\n\r");
7160Sstevel@tonic-gate delim = *line;
7170Sstevel@tonic-gate if (delim == '=') {
7180Sstevel@tonic-gate val0 = ++line;
7190Sstevel@tonic-gate if (0 > parse_quote(&line, " #,", &delim,
7200Sstevel@tonic-gate buf, sizeof (buf)))
7210Sstevel@tonic-gate return (bad_str(tgt));
7220Sstevel@tonic-gate }
7230Sstevel@tonic-gate if (delim != '\0') {
7240Sstevel@tonic-gate for (;;) {
7250Sstevel@tonic-gate *line = '\0';
7260Sstevel@tonic-gate if (delim == '#')
7270Sstevel@tonic-gate break;
7280Sstevel@tonic-gate ++line;
7290Sstevel@tonic-gate if (!isspace(delim) ||
7300Sstevel@tonic-gate ((delim = *line), !isspace(delim)))
7310Sstevel@tonic-gate break;
7320Sstevel@tonic-gate }
7330Sstevel@tonic-gate }
7340Sstevel@tonic-gate
7350Sstevel@tonic-gate if (PARSEQ("if")) {
7360Sstevel@tonic-gate if (parm.parm_name[0] != '\0' ||
7370Sstevel@tonic-gate strlen(buf) > IF_NAME_LEN)
7380Sstevel@tonic-gate return (bad_str(tgt));
7390Sstevel@tonic-gate (void) strlcpy(parm.parm_name, buf,
7400Sstevel@tonic-gate sizeof (parm.parm_name));
7410Sstevel@tonic-gate
7420Sstevel@tonic-gate } else if (PARSEQ("addr")) {
7430Sstevel@tonic-gate /*
7440Sstevel@tonic-gate * This is a bad idea, because the address based
7450Sstevel@tonic-gate * sets of parameters cannot be checked for
7460Sstevel@tonic-gate * consistency with the interface name parameters.
7470Sstevel@tonic-gate * The parm_net stuff is needed to allow several
7480Sstevel@tonic-gate * -F settings.
7490Sstevel@tonic-gate */
7500Sstevel@tonic-gate if (!getnet(val0, &addr, &mask) ||
7510Sstevel@tonic-gate parm.parm_name[0] != '\0')
7520Sstevel@tonic-gate return (bad_str(tgt));
7530Sstevel@tonic-gate parm.parm_net = addr;
7540Sstevel@tonic-gate parm.parm_mask = mask;
7550Sstevel@tonic-gate parm.parm_name[0] = '\n';
7560Sstevel@tonic-gate
7570Sstevel@tonic-gate } else if (PARSEQ("passwd")) {
7580Sstevel@tonic-gate /*
7590Sstevel@tonic-gate * since cleartext passwords are so weak allow
7600Sstevel@tonic-gate * them anywhere
7610Sstevel@tonic-gate */
7620Sstevel@tonic-gate msg = get_passwd(tgt, val0, &parm, RIP_AUTH_PW, 1);
7630Sstevel@tonic-gate if (msg) {
7640Sstevel@tonic-gate *val0 = '\0';
7650Sstevel@tonic-gate return (bad_str(msg));
7660Sstevel@tonic-gate }
7670Sstevel@tonic-gate
7680Sstevel@tonic-gate } else if (PARSEQ("md5_passwd")) {
7690Sstevel@tonic-gate msg = get_passwd(tgt, val0, &parm, RIP_AUTH_MD5, safe);
7700Sstevel@tonic-gate if (msg) {
7710Sstevel@tonic-gate *val0 = '\0';
7720Sstevel@tonic-gate return (bad_str(msg));
7730Sstevel@tonic-gate }
7740Sstevel@tonic-gate
7750Sstevel@tonic-gate } else if (PARS("no_ag")) {
7760Sstevel@tonic-gate parm.parm_int_state |= (IS_NO_AG | IS_NO_SUPER_AG);
7770Sstevel@tonic-gate
7780Sstevel@tonic-gate } else if (PARS("no_host")) {
7790Sstevel@tonic-gate parm.parm_int_state |= IS_NO_HOST;
7800Sstevel@tonic-gate
7810Sstevel@tonic-gate } else if (PARS("no_super_ag")) {
7820Sstevel@tonic-gate parm.parm_int_state |= IS_NO_SUPER_AG;
7830Sstevel@tonic-gate
7840Sstevel@tonic-gate } else if (PARS("no_ripv1_in")) {
7850Sstevel@tonic-gate parm.parm_int_state |= IS_NO_RIPV1_IN;
7860Sstevel@tonic-gate
7870Sstevel@tonic-gate } else if (PARS("no_ripv2_in")) {
7880Sstevel@tonic-gate parm.parm_int_state |= IS_NO_RIPV2_IN;
7890Sstevel@tonic-gate
7900Sstevel@tonic-gate } else if (PARS("ripv2_out")) {
7910Sstevel@tonic-gate if (parm.parm_int_state & IS_NO_RIPV2_OUT)
7920Sstevel@tonic-gate return (bad_str(tgt));
7930Sstevel@tonic-gate parm.parm_int_state |= IS_NO_RIPV1_OUT;
7940Sstevel@tonic-gate
7950Sstevel@tonic-gate } else if (PARS("ripv2")) {
7960Sstevel@tonic-gate if ((parm.parm_int_state & IS_NO_RIPV2_OUT) ||
7970Sstevel@tonic-gate (parm.parm_int_state & IS_NO_RIPV2_IN))
7980Sstevel@tonic-gate return (bad_str(tgt));
7990Sstevel@tonic-gate parm.parm_int_state |= (IS_NO_RIPV1_IN
8000Sstevel@tonic-gate | IS_NO_RIPV1_OUT);
8010Sstevel@tonic-gate
8020Sstevel@tonic-gate } else if (PARS("no_rip")) {
8030Sstevel@tonic-gate CKF(IS_PM_RDISC, IS_NO_RIP);
8040Sstevel@tonic-gate
8050Sstevel@tonic-gate } else if (PARS("no_rip_mcast")) {
8060Sstevel@tonic-gate parm.parm_int_state |= IS_NO_RIP_MCAST;
8070Sstevel@tonic-gate
8080Sstevel@tonic-gate } else if (PARS("no_rdisc")) {
8090Sstevel@tonic-gate CKF((GROUP_IS_SOL_OUT|GROUP_IS_ADV_OUT), IS_NO_RDISC);
8100Sstevel@tonic-gate
8110Sstevel@tonic-gate } else if (PARS("no_solicit")) {
8120Sstevel@tonic-gate CKF(GROUP_IS_SOL_OUT, IS_NO_SOL_OUT);
8130Sstevel@tonic-gate
8140Sstevel@tonic-gate } else if (PARS("send_solicit")) {
8150Sstevel@tonic-gate CKF(GROUP_IS_SOL_OUT, IS_SOL_OUT);
8160Sstevel@tonic-gate
8170Sstevel@tonic-gate } else if (PARS("no_rdisc_adv")) {
8180Sstevel@tonic-gate CKF(GROUP_IS_ADV_OUT, IS_NO_ADV_OUT);
8190Sstevel@tonic-gate
8200Sstevel@tonic-gate } else if (PARS("rdisc_adv")) {
8210Sstevel@tonic-gate CKF(GROUP_IS_ADV_OUT, IS_ADV_OUT);
8220Sstevel@tonic-gate
8230Sstevel@tonic-gate } else if (PARS("bcast_rdisc")) {
8240Sstevel@tonic-gate parm.parm_int_state |= IS_BCAST_RDISC;
8250Sstevel@tonic-gate
8260Sstevel@tonic-gate } else if (PARS("passive")) {
8270Sstevel@tonic-gate CKF((GROUP_IS_SOL_OUT|GROUP_IS_ADV_OUT), IS_NO_RDISC);
8280Sstevel@tonic-gate parm.parm_int_state |= IS_NO_RIP | IS_PASSIVE;
8290Sstevel@tonic-gate
8300Sstevel@tonic-gate } else if (PARSEQ("rdisc_pref")) {
8310Sstevel@tonic-gate if (parm.parm_rdisc_pref != 0 ||
8320Sstevel@tonic-gate (parm.parm_rdisc_pref = (int)strtol(buf, &p, 0),
8330Sstevel@tonic-gate *p != '\0') || (buf == p))
8340Sstevel@tonic-gate return (bad_str(tgt));
8350Sstevel@tonic-gate
8360Sstevel@tonic-gate } else if (PARS("pm_rdisc")) {
8370Sstevel@tonic-gate if (IS_RIP_OUT_OFF(parm.parm_int_state))
8380Sstevel@tonic-gate return (bad_str(tgt));
8390Sstevel@tonic-gate parm.parm_int_state |= IS_PM_RDISC;
8400Sstevel@tonic-gate
8410Sstevel@tonic-gate } else if (PARSEQ("rdisc_interval")) {
8420Sstevel@tonic-gate if (parm.parm_rdisc_int != 0 ||
8430Sstevel@tonic-gate (parm.parm_rdisc_int = (int)strtoul(buf, &p, 0),
844*7738SRishi.Srivatsavai@Sun.COM *p != '\0') || (buf == p) ||
8450Sstevel@tonic-gate parm.parm_rdisc_int < MIN_MAXADVERTISEINTERVAL ||
8460Sstevel@tonic-gate parm.parm_rdisc_int > MAX_MAXADVERTISEINTERVAL)
8470Sstevel@tonic-gate return (bad_str(tgt));
8480Sstevel@tonic-gate
8490Sstevel@tonic-gate } else if (PARSEQ("fake_default")) {
8500Sstevel@tonic-gate if (parm.parm_d_metric != 0 ||
8510Sstevel@tonic-gate IS_RIP_OUT_OFF(parm.parm_int_state) ||
8520Sstevel@tonic-gate (parm.parm_d_metric = (int)strtoul(buf, &p, 0),
853*7738SRishi.Srivatsavai@Sun.COM *p != '\0') || (buf == p) ||
8540Sstevel@tonic-gate parm.parm_d_metric > HOPCNT_INFINITY-1)
8550Sstevel@tonic-gate return (bad_str(tgt));
8560Sstevel@tonic-gate
8570Sstevel@tonic-gate } else if (PARSEQ("trust_gateway")) {
8580Sstevel@tonic-gate /* look for trust_gateway=x.y.z|net/mask|...) */
8590Sstevel@tonic-gate p = buf;
8600Sstevel@tonic-gate if (0 > parse_quote(&p, "|", &delim, buf2,
8610Sstevel@tonic-gate sizeof (buf2)) || !gethost(buf2, &addr))
8620Sstevel@tonic-gate return (bad_str(tgt));
8630Sstevel@tonic-gate tg = rtmalloc(sizeof (*tg),
8640Sstevel@tonic-gate "parse_parms trust_gateway");
8650Sstevel@tonic-gate (void) memset(tg, 0, sizeof (*tg));
8660Sstevel@tonic-gate tg->tgate_addr = addr;
8670Sstevel@tonic-gate i = 0;
8680Sstevel@tonic-gate /* The default is to trust all routes. */
8690Sstevel@tonic-gate while (delim == '|') {
8700Sstevel@tonic-gate p++;
8710Sstevel@tonic-gate if (i >= MAX_TGATE_NETS ||
8720Sstevel@tonic-gate 0 > parse_quote(&p, "|", &delim, buf2,
873*7738SRishi.Srivatsavai@Sun.COM sizeof (buf2)) ||
8740Sstevel@tonic-gate !getnet(buf2, &tg->tgate_nets[i].net,
875*7738SRishi.Srivatsavai@Sun.COM &tg->tgate_nets[i].mask) ||
8760Sstevel@tonic-gate tg->tgate_nets[i].net == RIP_DEFAULT ||
8770Sstevel@tonic-gate tg->tgate_nets[i].mask == 0) {
8780Sstevel@tonic-gate free(tg);
8790Sstevel@tonic-gate return (bad_str(tgt));
8800Sstevel@tonic-gate }
8810Sstevel@tonic-gate i++;
8820Sstevel@tonic-gate }
8830Sstevel@tonic-gate tg->tgate_next = tgates;
8840Sstevel@tonic-gate tgates = tg;
8850Sstevel@tonic-gate parm.parm_int_state |= IS_DISTRUST;
8860Sstevel@tonic-gate
8870Sstevel@tonic-gate } else if (PARS("redirect_ok")) {
8880Sstevel@tonic-gate parm.parm_int_state |= IS_REDIRECT_OK;
8890Sstevel@tonic-gate
8900Sstevel@tonic-gate } else if (PARSEQ("rip_neighbor")) {
8910Sstevel@tonic-gate if (parm.parm_name[0] == '\0' ||
8920Sstevel@tonic-gate gethost(buf, &parm.parm_ripout_addr) != 1)
8930Sstevel@tonic-gate return (bad_str(tgt));
8940Sstevel@tonic-gate
8950Sstevel@tonic-gate } else {
8960Sstevel@tonic-gate return (bad_str(tgt)); /* error */
8970Sstevel@tonic-gate }
8980Sstevel@tonic-gate }
8990Sstevel@tonic-gate
9000Sstevel@tonic-gate return (insert_parm(&parm));
9010Sstevel@tonic-gate #undef PARS
9020Sstevel@tonic-gate #undef PARSEQ
9030Sstevel@tonic-gate #undef CKF
9040Sstevel@tonic-gate }
9050Sstevel@tonic-gate
9060Sstevel@tonic-gate
9070Sstevel@tonic-gate /*
9080Sstevel@tonic-gate * Insert parameter specifications into the parms list. Returns NULL if
9090Sstevel@tonic-gate * successful, or an error message otherwise.
9100Sstevel@tonic-gate */
9110Sstevel@tonic-gate const char *
insert_parm(struct parm * new)9120Sstevel@tonic-gate insert_parm(struct parm *new)
9130Sstevel@tonic-gate {
9140Sstevel@tonic-gate struct parm *parmp, **parmpp;
9150Sstevel@tonic-gate int i, num_passwds;
9160Sstevel@tonic-gate
9170Sstevel@tonic-gate /* set implicit values */
9180Sstevel@tonic-gate if (new->parm_int_state & (IS_NO_ADV_IN|IS_NO_SOL_OUT))
9190Sstevel@tonic-gate new->parm_int_state |= IS_NO_ADV_IN|IS_NO_SOL_OUT;
9200Sstevel@tonic-gate
9210Sstevel@tonic-gate for (i = num_passwds = 0; i < MAX_AUTH_KEYS; i++) {
9220Sstevel@tonic-gate if (new->parm_auth[i].type != RIP_AUTH_NONE)
9230Sstevel@tonic-gate num_passwds++;
9240Sstevel@tonic-gate }
9250Sstevel@tonic-gate
9260Sstevel@tonic-gate /* compare with existing sets of parameters */
9270Sstevel@tonic-gate for (parmpp = &parms; (parmp = *parmpp) != 0;
9280Sstevel@tonic-gate parmpp = &parmp->parm_next) {
9290Sstevel@tonic-gate if (strcmp(new->parm_name, parmp->parm_name) != 0)
9300Sstevel@tonic-gate continue;
9310Sstevel@tonic-gate if (!on_net(htonl(parmp->parm_net), new->parm_net,
9320Sstevel@tonic-gate new->parm_mask) &&
9330Sstevel@tonic-gate !on_net(htonl(new->parm_net), parmp->parm_net,
934*7738SRishi.Srivatsavai@Sun.COM parmp->parm_mask))
9350Sstevel@tonic-gate continue;
9360Sstevel@tonic-gate
9370Sstevel@tonic-gate for (i = 0; i < MAX_AUTH_KEYS; i++) {
9380Sstevel@tonic-gate if (parmp->parm_auth[i].type != RIP_AUTH_NONE)
9390Sstevel@tonic-gate num_passwds++;
9400Sstevel@tonic-gate }
9410Sstevel@tonic-gate if (num_passwds > MAX_AUTH_KEYS)
9420Sstevel@tonic-gate return ("too many conflicting passwords");
9430Sstevel@tonic-gate
9440Sstevel@tonic-gate if ((0 != (new->parm_int_state & GROUP_IS_SOL_OUT) &&
9450Sstevel@tonic-gate 0 != (parmp->parm_int_state & GROUP_IS_SOL_OUT) &&
9460Sstevel@tonic-gate 0 != ((new->parm_int_state ^ parmp->parm_int_state) &&
947*7738SRishi.Srivatsavai@Sun.COM GROUP_IS_SOL_OUT)) ||
9480Sstevel@tonic-gate (0 != (new->parm_int_state & GROUP_IS_ADV_OUT) &&
949*7738SRishi.Srivatsavai@Sun.COM 0 != (parmp->parm_int_state & GROUP_IS_ADV_OUT) &&
950*7738SRishi.Srivatsavai@Sun.COM 0 != ((new->parm_int_state ^ parmp->parm_int_state) &&
951*7738SRishi.Srivatsavai@Sun.COM GROUP_IS_ADV_OUT)) ||
9520Sstevel@tonic-gate (new->parm_rdisc_pref != 0 &&
953*7738SRishi.Srivatsavai@Sun.COM parmp->parm_rdisc_pref != 0 &&
954*7738SRishi.Srivatsavai@Sun.COM new->parm_rdisc_pref != parmp->parm_rdisc_pref) ||
9550Sstevel@tonic-gate (new->parm_rdisc_int != 0 &&
956*7738SRishi.Srivatsavai@Sun.COM parmp->parm_rdisc_int != 0 &&
957*7738SRishi.Srivatsavai@Sun.COM new->parm_rdisc_int != parmp->parm_rdisc_int)) {
9580Sstevel@tonic-gate return ("conflicting, duplicate router discovery"
959*7738SRishi.Srivatsavai@Sun.COM " parameters");
9600Sstevel@tonic-gate
9610Sstevel@tonic-gate }
9620Sstevel@tonic-gate
9630Sstevel@tonic-gate if (new->parm_d_metric != 0 && parmp->parm_d_metric != 0 &&
9640Sstevel@tonic-gate new->parm_d_metric != parmp->parm_d_metric) {
9650Sstevel@tonic-gate return ("conflicting, duplicate poor man's router"
966*7738SRishi.Srivatsavai@Sun.COM " discovery or fake default metric");
9670Sstevel@tonic-gate }
9680Sstevel@tonic-gate }
9690Sstevel@tonic-gate
9700Sstevel@tonic-gate /*
9710Sstevel@tonic-gate * link new entry on the list so that when the entries are scanned,
9720Sstevel@tonic-gate * they affect the result in the order the operator specified.
9730Sstevel@tonic-gate */
9740Sstevel@tonic-gate parmp = rtmalloc(sizeof (*parmp), "insert_parm");
9750Sstevel@tonic-gate (void) memcpy(parmp, new, sizeof (*parmp));
9760Sstevel@tonic-gate *parmpp = parmp;
9770Sstevel@tonic-gate
9780Sstevel@tonic-gate return (NULL);
9790Sstevel@tonic-gate }
9800Sstevel@tonic-gate
9810Sstevel@tonic-gate int /* 0=bad */
gethost(char * name,in_addr_t * addrp)9820Sstevel@tonic-gate gethost(char *name, in_addr_t *addrp)
9830Sstevel@tonic-gate {
9840Sstevel@tonic-gate struct hostent *hp;
9850Sstevel@tonic-gate struct in_addr in;
9860Sstevel@tonic-gate
9870Sstevel@tonic-gate
9880Sstevel@tonic-gate /*
9890Sstevel@tonic-gate * Try for a number first. This avoids hitting the name
9900Sstevel@tonic-gate * server which might be sick because routing is.
9910Sstevel@tonic-gate */
9920Sstevel@tonic-gate if ((in.s_addr = inet_addr(name)) != (in_addr_t)-1) {
9930Sstevel@tonic-gate /*
9940Sstevel@tonic-gate * get a good number, but check that it makes some
9950Sstevel@tonic-gate * sense.
9960Sstevel@tonic-gate */
9970Sstevel@tonic-gate if ((ntohl(in.s_addr) >> 24) == 0 ||
9980Sstevel@tonic-gate (ntohl(in.s_addr) >> 24) == 0xff)
9990Sstevel@tonic-gate return (0);
10000Sstevel@tonic-gate *addrp = in.s_addr;
10010Sstevel@tonic-gate return (1);
10020Sstevel@tonic-gate }
10030Sstevel@tonic-gate
10040Sstevel@tonic-gate hp = gethostbyname(name);
10050Sstevel@tonic-gate if (hp != NULL) {
10060Sstevel@tonic-gate (void) memcpy(addrp, hp->h_addr, sizeof (*addrp));
10070Sstevel@tonic-gate return (1);
10080Sstevel@tonic-gate }
10090Sstevel@tonic-gate
10100Sstevel@tonic-gate return (0);
10110Sstevel@tonic-gate }
10120Sstevel@tonic-gate
10130Sstevel@tonic-gate
10140Sstevel@tonic-gate static void
addroutefordefault(in_addr_t dst,in_addr_t gate,in_addr_t mask,uint32_t metric,uint16_t rts_flags)10150Sstevel@tonic-gate addroutefordefault(in_addr_t dst, in_addr_t gate, in_addr_t mask,
10160Sstevel@tonic-gate uint32_t metric, uint16_t rts_flags)
10170Sstevel@tonic-gate {
10180Sstevel@tonic-gate struct rt_spare new;
10190Sstevel@tonic-gate struct interface *ifp;
10200Sstevel@tonic-gate uint16_t rt_newstate = RS_STATIC;
10210Sstevel@tonic-gate
10220Sstevel@tonic-gate
10230Sstevel@tonic-gate ifp = iflookup(gate);
10240Sstevel@tonic-gate if (ifp == NULL) {
10250Sstevel@tonic-gate msglog("unreachable gateway %s in "PATH_GATEWAYS,
10260Sstevel@tonic-gate naddr_ntoa(gate));
10270Sstevel@tonic-gate return;
10280Sstevel@tonic-gate }
10290Sstevel@tonic-gate
10300Sstevel@tonic-gate trace_misc("addroutefordefault: found interface %s", ifp->int_name);
10310Sstevel@tonic-gate
10320Sstevel@tonic-gate (void) memset(&new, 0, sizeof (new));
10330Sstevel@tonic-gate new.rts_ifp = ifp;
10340Sstevel@tonic-gate new.rts_router = gate;
10350Sstevel@tonic-gate new.rts_gate = gate;
10360Sstevel@tonic-gate new.rts_metric = metric;
10370Sstevel@tonic-gate new.rts_time = now.tv_sec;
10380Sstevel@tonic-gate new.rts_flags = rts_flags;
10390Sstevel@tonic-gate new.rts_origin = RO_FILE;
10400Sstevel@tonic-gate
10410Sstevel@tonic-gate input_route(dst, mask, &new, NULL, rt_newstate);
10420Sstevel@tonic-gate }
1043