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