parms.c revision 1.1.1.2       1 /*
      2  * Copyright (c) 1983, 1993
      3  *	The Regents of the University of California.  All rights reserved.
      4  *
      5  * Redistribution and use in source and binary forms, with or without
      6  * modification, are permitted provided that the following conditions
      7  * are met:
      8  * 1. Redistributions of source code must retain the above copyright
      9  *    notice, this list of conditions and the following disclaimer.
     10  * 2. Redistributions in binary form must reproduce the above copyright
     11  *    notice, this list of conditions and the following disclaimer in the
     12  *    documentation and/or other materials provided with the distribution.
     13  * 3. All advertising materials mentioning features or use of this software
     14  *    must display the following acknowledgement:
     15  *	This product includes software developed by the University of
     16  *	California, Berkeley and its contributors.
     17  * 4. Neither the name of the University nor the names of its contributors
     18  *    may be used to endorse or promote products derived from this software
     19  *    without specific prior written permission.
     20  *
     21  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
     22  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
     23  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
     24  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
     25  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
     26  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
     27  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
     28  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
     29  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
     30  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
     31  * SUCH DAMAGE.
     32  */
     33 
     34 #if !defined(lint) && !defined(sgi) && !defined(__NetBSD__)
     35 static char sccsid[] = "@(#)if.c	8.1 (Berkeley) 6/5/93";
     36 #elif defined(__NetBSD__)
     37 static char rcsid[] = "$NetBSD: parms.c,v 1.1.1.2 1996/09/24 15:11:39 christos Exp $";
     38 #endif
     39 #ident "$Revision: 1.1.1.2 $"
     40 
     41 #include "defs.h"
     42 #include "pathnames.h"
     43 
     44 
     45 struct parm *parms;
     46 struct intnet *intnets;
     47 
     48 
     49 /* use configured parameters
     50  */
     51 void
     52 get_parms(struct interface *ifp)
     53 {
     54 	struct parm *parmp;
     55 
     56 	/* get all relevant parameters
     57 	 */
     58 	for (parmp = parms; parmp != 0; parmp = parmp->parm_next) {
     59 		if ((parmp->parm_name[0] == '\0'
     60 		     && on_net(ifp->int_addr,
     61 			       parmp->parm_addr_h, parmp->parm_mask))
     62 		    || (parmp->parm_name[0] != '\0'
     63 			&& !strcmp(ifp->int_name, parmp->parm_name))) {
     64 			/* this group of parameters is relevant,
     65 			 * so get its settings
     66 			 */
     67 			ifp->int_state |= parmp->parm_int_state;
     68 			if (parmp->parm_passwd[0] != '\0')
     69 				bcopy(parmp->parm_passwd, ifp->int_passwd,
     70 				      sizeof(ifp->int_passwd));
     71 			if (parmp->parm_rdisc_pref != 0)
     72 				ifp->int_rdisc_pref = parmp->parm_rdisc_pref;
     73 			if (parmp->parm_rdisc_int != 0)
     74 				ifp->int_rdisc_int = parmp->parm_rdisc_int;
     75 			if (parmp->parm_d_metric != 0)
     76 				ifp->int_d_metric = parmp->parm_d_metric;
     77 			}
     78 	}
     79 	/* default poor-man's router discovery to a metric that will
     80 	 * be heard by old versions of routed.
     81 	 */
     82 	if ((ifp->int_state & IS_PM_RDISC)
     83 	    && ifp->int_d_metric == 0)
     84 		ifp->int_d_metric = HOPCNT_INFINITY-2;
     85 
     86 	if (IS_RIP_IN_OFF(ifp->int_state))
     87 		ifp->int_state |= IS_NO_RIP_OUT;
     88 
     89 	if (ifp->int_rdisc_int == 0)
     90 		ifp->int_rdisc_int = DefMaxAdvertiseInterval;
     91 
     92 	if (!(ifp->int_if_flags & IFF_MULTICAST)
     93 	    && !(ifp->int_if_flags & IFF_POINTOPOINT))
     94 		ifp->int_state |= IS_NO_RIPV2_OUT;
     95 
     96 	if (!(ifp->int_if_flags & IFF_MULTICAST))
     97 		ifp->int_state |= IS_BCAST_RDISC;
     98 
     99 	if (ifp->int_if_flags & IFF_POINTOPOINT) {
    100 		ifp->int_state |= IS_BCAST_RDISC;
    101 		/* By default, point-to-point links should be passive
    102 		 * about router-discovery for the sake of demand-dialing.
    103 		 */
    104 		if (0 == (ifp->int_state & GROUP_IS_SOL))
    105 			ifp->int_state |= IS_NO_SOL_OUT;
    106 		if (0 == (ifp->int_state & GROUP_IS_ADV))
    107 			ifp->int_state |= IS_NO_ADV_OUT;
    108 	}
    109 
    110 	if (0 != (ifp->int_state & (IS_PASSIVE | IS_REMOTE)))
    111 		ifp->int_state |= IS_NO_RDISC;
    112 	if (ifp->int_state & IS_PASSIVE)
    113 		ifp->int_state |= (IS_NO_RIP | IS_NO_RDISC);
    114 	if ((ifp->int_state & (IS_NO_RIP | IS_NO_RDISC))
    115 	    == (IS_NO_RIP|IS_NO_RDISC))
    116 		ifp->int_state |= IS_PASSIVE;
    117 }
    118 
    119 
    120 /* Read a list of gateways from /etc/gateways and add them to our tables.
    121  *
    122  * This file contains a list of "remote" gateways.  That is usually
    123  * a gateway which we cannot immediately determine if it is present or
    124  * not as we can do for those provided by directly connected hardware.
    125  *
    126  * If a gateway is marked "passive" in the file, then we assume it
    127  * does not understand RIP and assume it is always present.  Those
    128  * not marked passive are treated as if they were directly connected
    129  * and assumed to be broken if they do not send us advertisements.
    130  * All remote interfaces are added to our list, and those not marked
    131  * passive are sent routing updates.
    132  *
    133  * A passive interface can also be local, hardware interface exempt
    134  * from RIP.
    135  */
    136 void
    137 gwkludge(void)
    138 {
    139 	FILE *fp;
    140 	char *p, *lptr;
    141 	char lbuf[200], net_host[5], dname[64+1+64+1], gname[64+1], qual[9];
    142 	struct interface *ifp;
    143 	naddr dst, netmask, gate;
    144 	int metric, n;
    145 	u_int state;
    146 	char *type;
    147 	struct parm *parmp;
    148 
    149 
    150 	fp = fopen(_PATH_GATEWAYS, "r");
    151 	if (fp == 0)
    152 		return;
    153 
    154 	for (;;) {
    155 		if (0 == fgets(lbuf, sizeof(lbuf)-1, fp))
    156 			break;
    157 		lptr = lbuf;
    158 		while (*lptr == ' ')
    159 			lptr++;
    160 		if (*lptr == '\n'	/* ignore null and comment lines */
    161 		    || *lptr == '#')
    162 			continue;
    163 		p = lptr+strlen(lptr)-1;
    164 		while (*p == '\n'
    165 		       || *p == ' ')
    166 			*p-- = '\0';
    167 
    168 		/* notice newfangled parameter lines
    169 		 */
    170 		if (strncasecmp("net", lptr, 3)
    171 		    && strncasecmp("host", lptr, 4)) {
    172 			p = parse_parms(lptr);
    173 			if (p != 0) {
    174 				if (strcmp(p,lptr))
    175 					msglog("bad \"%s\" in "_PATH_GATEWAYS
    176 					       " entry \"%s\"", lptr, p);
    177 				else
    178 					msglog("bad \"%s\" in "_PATH_GATEWAYS,
    179 					       lptr);
    180 			}
    181 			continue;
    182 		}
    183 
    184 /*  {net | host} XX[/M] XX gateway XX metric DD [passive | external]\n */
    185 		n = sscanf(lptr, "%4s %129[^ \t] gateway"
    186 			   " %64[^ / \t] metric %d %8s\n",
    187 			   net_host, dname, gname, &metric, qual);
    188 		if (n != 5) {
    189 			msglog("bad "_PATH_GATEWAYS" entry \"%s\"", lptr);
    190 			continue;
    191 		}
    192 		if (metric < 0 || metric >= HOPCNT_INFINITY) {
    193 			msglog("bad metric in "_PATH_GATEWAYS" entry \"%s\"",
    194 			       lptr);
    195 			continue;
    196 		}
    197 		if (!strcmp(net_host, "host")) {
    198 			if (!gethost(dname, &dst)) {
    199 				msglog("bad host \"%s\" in "_PATH_GATEWAYS
    200 				       " entry \"%s\"", dname, lptr);
    201 				continue;
    202 			}
    203 			netmask = HOST_MASK;
    204 		} else if (!strcmp(net_host, "net")) {
    205 			if (!getnet(dname, &dst, &netmask)) {
    206 				msglog("bad net \"%s\" in "_PATH_GATEWAYS
    207 				       " entry \"%s\"", dname, lptr);
    208 				continue;
    209 			}
    210 		} else {
    211 			msglog("bad \"%s\" in "_PATH_GATEWAYS
    212 			       " entry \"%s\"", lptr);
    213 			continue;
    214 		}
    215 
    216 		if (!gethost(gname, &gate)) {
    217 			msglog("bad gateway \"%s\" in "_PATH_GATEWAYS
    218 			       " entry \"%s\"", gname, lptr);
    219 			continue;
    220 		}
    221 
    222 		if (strcmp(qual, type = "passive") == 0) {
    223 			/* Passive entries are not placed in our tables,
    224 			 * only the kernel's, so we don't copy all of the
    225 			 * external routing information within a net.
    226 			 * Internal machines should use the default
    227 			 * route to a suitable gateway (like us).
    228 			 */
    229 			state = IS_REMOTE | IS_PASSIVE;
    230 			if (metric == 0)
    231 				metric = 1;
    232 
    233 		} else if (strcmp(qual, type = "external") == 0) {
    234 			/* External entries are handled by other means
    235 			 * such as EGP, and are placed only in the daemon
    236 			 * tables to prevent overriding them with something
    237 			 * else.
    238 			 */
    239 			state = IS_REMOTE | IS_PASSIVE | IS_EXTERNAL;
    240 			if (metric == 0)
    241 				metric = 1;
    242 
    243 		} else if (qual[0] == '\0') {
    244 			if (metric != 0) {
    245 				/* Entries that are neither "passive" nor
    246 				 * "external" are "remote" and must behave
    247 				 * like physical interfaces.  If they are not
    248 				 * heard from regularly, they are deleted.
    249 				 */
    250 				state = IS_REMOTE;
    251 				type = "remote";
    252 			} else {
    253 				/* "remote" entries with a metric of 0
    254 				 * are aliases for our own interfaces
    255 				 */
    256 				state = IS_REMOTE | IS_PASSIVE;
    257 				type = "alias";
    258 			}
    259 
    260 		} else {
    261 			msglog("bad "_PATH_GATEWAYS" entry \"%s\"", lptr);
    262 			continue;
    263 		}
    264 
    265 		/* Remember to advertise the corresponding logical network.
    266 		 */
    267 		if (!(state & IS_EXTERNAL)
    268 		    && netmask != std_mask(dst))
    269 			state |= IS_SUBNET;
    270 
    271 		if (0 != (state & (IS_PASSIVE | IS_REMOTE)))
    272 			state |= IS_NO_RDISC;
    273 		if (state & IS_PASSIVE)
    274 			state |= (IS_NO_RIP | IS_NO_RDISC);
    275 		if ((state & (IS_NO_RIP | IS_NO_RDISC))
    276 		    == (IS_NO_RIP|IS_NO_RDISC))
    277 			state |= IS_PASSIVE;
    278 
    279 		parmp = (struct parm*)malloc(sizeof(*parmp));
    280 		bzero(parmp, sizeof(*parmp));
    281 		parmp->parm_next = parms;
    282 		parms = parmp;
    283 		parmp->parm_addr_h = ntohl(dst);
    284 		parmp->parm_mask = -1;
    285 		parmp->parm_d_metric = 0;
    286 		parmp->parm_int_state = state;
    287 
    288 		/* See if this new interface duplicates an existing
    289 		 * interface.
    290 		 */
    291 		for (ifp = ifnet; 0 != ifp; ifp = ifp->int_next) {
    292 			if (ifp->int_mask == netmask
    293 			    && ((ifp->int_addr == dst
    294 				 && netmask != HOST_MASK)
    295 				|| (ifp->int_dstaddr == dst
    296 				    && netmask == HOST_MASK)))
    297 				break;
    298 		}
    299 		if (ifp != 0) {
    300 			/* Let one of our real interfaces be marked passive.
    301 			 */
    302 			if ((state & IS_PASSIVE) && !(state & IS_EXTERNAL)) {
    303 				ifp->int_state |= state;
    304 			} else {
    305 				msglog("%s is duplicated in "_PATH_GATEWAYS
    306 				       " by %s",
    307 				       ifp->int_name, lptr);
    308 			}
    309 			continue;
    310 		}
    311 
    312 		tot_interfaces++;
    313 
    314 		ifp = (struct interface *)malloc(sizeof(*ifp));
    315 		bzero(ifp, sizeof(*ifp));
    316 		if (ifnet != 0) {
    317 			ifp->int_next = ifnet;
    318 			ifnet->int_prev = ifp;
    319 		}
    320 		ifnet = ifp;
    321 
    322 		ifp->int_state = state;
    323 		ifp->int_net = ntohl(dst) & netmask;
    324 		ifp->int_mask = netmask;
    325 		if (netmask == HOST_MASK)
    326 			ifp->int_if_flags |= IFF_POINTOPOINT;
    327 		ifp->int_dstaddr = dst;
    328 		ifp->int_addr = gate;
    329 		ifp->int_metric = metric;
    330 		(void)sprintf(ifp->int_name, "%s-%s", type, naddr_ntoa(dst));
    331 		ifp->int_index = -1;
    332 
    333 		get_parms(ifp);
    334 
    335 		trace_if("Add", ifp);
    336 	}
    337 }
    338 
    339 
    340 /* parse a set of parameters for an interface
    341  */
    342 char *					/* 0 or error message */
    343 parse_parms(char *line)
    344 {
    345 #define PARS(str) (0 == (tgt = str, strcasecmp(tok, tgt)))
    346 #define PARSE(str) (0 == (tgt = str, strncasecmp(tok, str "=", sizeof(str))))
    347 #define CKF(g,b) {if (0 != (parm.parm_int_state & ((g) & ~(b)))) break;	\
    348 	parm.parm_int_state |= (b);}
    349 #define DELIMS " ,\t\n"
    350 	struct parm parm;
    351 	struct intnet *intnetp;
    352 	char *tok, *tgt, *p;
    353 
    354 
    355 	/* "subnet=x.y.z.u/mask" must be alone on the line */
    356 	if (!strncasecmp("subnet=",line,7)) {
    357 		intnetp = (struct intnet*)malloc(sizeof(*intnetp));
    358 		intnetp->intnet_metric = 1;
    359 		if ((p = strrchr(line,','))) {
    360 			*p++ = '\0';
    361 			intnetp->intnet_metric = (int)strtol(p,&p,0);
    362 			if (*p != '\0'
    363 			    || intnetp->intnet_metric <= 0
    364 			    || intnetp->intnet_metric >= HOPCNT_INFINITY)
    365 				return line;
    366 		}
    367 		if (!getnet(&line[7], &intnetp->intnet_addr,
    368 			    &intnetp->intnet_mask)
    369 		    || intnetp->intnet_mask == HOST_MASK
    370 		    || intnetp->intnet_addr == RIP_DEFAULT) {
    371 			free(intnetp);
    372 			return line;
    373 		}
    374 		intnetp->intnet_next = intnets;
    375 		intnets = intnetp;
    376 		return 0;
    377 	}
    378 
    379 	bzero(&parm, sizeof(parm));
    380 
    381 	tgt = "null";
    382 	for (tok = strtok(line, DELIMS);
    383 	     tok != 0 && tok[0] != '\0';
    384 	     tgt = 0, tok = strtok(0,DELIMS)) {
    385 		if (PARSE("if")) {
    386 			if (parm.parm_name[0] != '\0'
    387 			    || tok[3] == '\0'
    388 			    || strlen(tok) > IFNAMSIZ+3)
    389 				break;
    390 			strcpy(parm.parm_name, tok+3);
    391 
    392 		} else if (PARSE("passwd")) {
    393 			if (tok[7] == '\0'
    394 			    || strlen(tok) > RIP_AUTH_PW_LEN+7)
    395 				break;
    396 			strcpy(parm.parm_passwd, tok+7);
    397 
    398 		} else if (PARS("no_ag")) {
    399 			parm.parm_int_state |= (IS_NO_AG | IS_NO_SUPER_AG);
    400 
    401 		} else if (PARS("no_super_ag")) {
    402 			parm.parm_int_state |= IS_NO_SUPER_AG;
    403 
    404 		} else if (PARS("no_ripv1_in")) {
    405 			parm.parm_int_state |= IS_NO_RIPV1_IN;
    406 
    407 		} else if (PARS("no_ripv2_in")) {
    408 			parm.parm_int_state |= IS_NO_RIPV2_IN;
    409 
    410 		} else if (PARS("ripv2_out")) {
    411 			if (parm.parm_int_state & IS_NO_RIPV2_OUT)
    412 				break;
    413 			parm.parm_int_state |= IS_NO_RIPV1_OUT;
    414 
    415 		} else if (PARS("no_rip")) {
    416 			parm.parm_int_state |= IS_NO_RIP;
    417 
    418 		} else if (PARS("no_rdisc")) {
    419 			CKF((GROUP_IS_SOL|GROUP_IS_ADV), IS_NO_RDISC);
    420 
    421 		} else if (PARS("no_solicit")) {
    422 			CKF(GROUP_IS_SOL, IS_NO_SOL_OUT);
    423 
    424 		} else if (PARS("send_solicit")) {
    425 			CKF(GROUP_IS_SOL, IS_SOL_OUT);
    426 
    427 		} else if (PARS("no_rdisc_adv")) {
    428 			CKF(GROUP_IS_ADV, IS_NO_ADV_OUT);
    429 
    430 		} else if (PARS("rdisc_adv")) {
    431 			CKF(GROUP_IS_ADV, IS_ADV_OUT);
    432 
    433 		} else if (PARS("bcast_rdisc")) {
    434 			parm.parm_int_state |= IS_BCAST_RDISC;
    435 
    436 		} else if (PARS("passive")) {
    437 			CKF((GROUP_IS_SOL|GROUP_IS_ADV), IS_NO_RDISC);
    438 			parm.parm_int_state |= IS_NO_RIP;
    439 
    440 		} else if (PARSE("rdisc_pref")) {
    441 			if (parm.parm_rdisc_pref != 0
    442 			    || tok[11] == '\0'
    443 			    || (parm.parm_rdisc_pref = (int)strtol(&tok[11],
    444 								   &p,0),
    445 				*p != '\0'))
    446 				break;
    447 
    448 		} else if (PARS("pm_rdisc")) {
    449 			parm.parm_int_state |= IS_PM_RDISC;
    450 
    451 		} else if (PARSE("rdisc_interval")) {
    452 			if (parm.parm_rdisc_int != 0
    453 			    || tok[15] == '\0'
    454 			    || (parm.parm_rdisc_int = (int)strtol(&tok[15],
    455 								  &p,0),
    456 				*p != '\0')
    457 			    || parm.parm_rdisc_int < MinMaxAdvertiseInterval
    458 			    || parm.parm_rdisc_int > MaxMaxAdvertiseInterval)
    459 				break;
    460 
    461 		} else if (PARSE("fake_default")) {
    462 			if (parm.parm_d_metric != 0
    463 			    || tok[13] == '\0'
    464 			    || (parm.parm_d_metric=(int)strtol(&tok[13],&p,0),
    465 				*p != '\0')
    466 			    || parm.parm_d_metric > HOPCNT_INFINITY-1)
    467 				break;
    468 
    469 		} else {
    470 			tgt = tok;
    471 			break;
    472 		}
    473 	}
    474 	if (tgt != 0)
    475 		return tgt;
    476 
    477 	return check_parms(&parm);
    478 #undef DELIMS
    479 #undef PARS
    480 #undef PARSE
    481 }
    482 
    483 
    484 /* check for duplicate parameter specifications */
    485 char *					/* 0 or error message */
    486 check_parms(struct parm *new)
    487 {
    488 	struct parm *parmp;
    489 
    490 
    491 	/* set implicit values
    492 	 */
    493 	if (!supplier && supplier_set)
    494 		new->parm_int_state |= (IS_NO_RIPV1_OUT
    495 					| IS_NO_RIPV2_OUT
    496 					| IS_NO_ADV_OUT);
    497 	if (new->parm_int_state & IS_NO_ADV_IN)
    498 		new->parm_int_state |= IS_NO_SOL_OUT;
    499 
    500 	if ((new->parm_int_state & (IS_NO_RIP | IS_NO_RDISC))
    501 	    == (IS_NO_RIP | IS_NO_RDISC))
    502 		new->parm_int_state |= IS_PASSIVE;
    503 
    504 	/* compare with existing sets of parameters
    505 	 */
    506 	for (parmp = parms; parmp != 0; parmp = parmp->parm_next) {
    507 		if (strcmp(new->parm_name, parmp->parm_name))
    508 			continue;
    509 		if (!on_net(htonl(parmp->parm_addr_h),
    510 			    new->parm_addr_h, new->parm_mask)
    511 		    && !on_net(htonl(new->parm_addr_h),
    512 			       parmp->parm_addr_h, parmp->parm_mask))
    513 			continue;
    514 
    515 		if (strcmp(parmp->parm_passwd, new->parm_passwd)
    516 		    || (0 != (new->parm_int_state & GROUP_IS_SOL)
    517 			&& 0 != (parmp->parm_int_state & GROUP_IS_SOL)
    518 			&& 0 != ((new->parm_int_state ^ parmp->parm_int_state)
    519 				 && GROUP_IS_SOL))
    520 		    || (0 != (new->parm_int_state & GROUP_IS_ADV)
    521 			&& 0 != (parmp->parm_int_state & GROUP_IS_ADV)
    522 			&& 0 != ((new->parm_int_state ^ parmp->parm_int_state)
    523 				 && GROUP_IS_ADV))
    524 		    || (new->parm_rdisc_pref != 0
    525 			&& parmp->parm_rdisc_pref != 0
    526 			&& new->parm_rdisc_pref != parmp->parm_rdisc_pref)
    527 		    || (new->parm_rdisc_int != 0
    528 			&& parmp->parm_rdisc_int != 0
    529 			&& new->parm_rdisc_int != parmp->parm_rdisc_int)
    530 		    || (new->parm_d_metric != 0
    531 			&& parmp->parm_d_metric != 0
    532 			&& new->parm_d_metric != parmp->parm_d_metric))
    533 			return "duplicate";
    534 	}
    535 
    536 	parmp = (struct parm*)malloc(sizeof(*parmp));
    537 	bcopy(new, parmp, sizeof(*parmp));
    538 	parmp->parm_next = parms;
    539 	parms = parmp;
    540 
    541 	return 0;
    542 }
    543 
    544 
    545 /* get a network number as a name or a number, with an optional "/xx"
    546  * netmask.
    547  */
    548 int					/* 0=bad */
    549 getnet(char *name,
    550        naddr *addrp,			/* host byte order */
    551        naddr *maskp)
    552 {
    553 	int i;
    554 	struct netent *np;
    555 	naddr mask;
    556 	struct in_addr in;
    557 	char hname[MAXHOSTNAMELEN+1];
    558 	char *mname, *p;
    559 
    560 
    561 	/* Detect and separate "1.2.3.4/24"
    562 	 */
    563 	if (0 != (mname = rindex(name,'/'))) {
    564 		i = (int)(mname - name);
    565 		if (i > sizeof(hname)-1)	/* name too long */
    566 			return 0;
    567 		bcopy(name, hname, i);
    568 		hname[i] = '\0';
    569 		mname++;
    570 		name = hname;
    571 	}
    572 
    573 	np = getnetbyname(name);
    574 	if (np != 0) {
    575 		in.s_addr = (naddr)np->n_net;
    576 	} else if (inet_aton(name, &in) == 1) {
    577 		HTONL(in.s_addr);
    578 	} else {
    579 		return 0;
    580 	}
    581 
    582 	if (mname == 0) {
    583 		/* we cannot use the interfaces here because we have not
    584 		 * looked at them yet.
    585 		 */
    586 		mask = std_mask(in.s_addr);
    587 		if ((~mask & ntohl(in.s_addr)) != 0)
    588 			mask = HOST_MASK;
    589 	} else {
    590 		mask = (naddr)strtoul(mname, &p, 0);
    591 		if (*p != '\0' || mask > 32)
    592 			return 0;
    593 		mask = HOST_MASK << (32-mask);
    594 	}
    595 	if (mask != 0 && in.s_addr == RIP_DEFAULT)
    596 		return 0;
    597 	if ((~mask & ntohl(in.s_addr)) != 0)
    598 		return 0;
    599 
    600 	*addrp = in.s_addr;
    601 	*maskp = mask;
    602 	return 1;
    603 }
    604 
    605 
    606 int					/* 0=bad */
    607 gethost(char *name,
    608 	naddr *addrp)
    609 {
    610 	struct hostent *hp;
    611 	struct in_addr in;
    612 
    613 
    614 	/* Try for a number first, even in IRIX where gethostbyname()
    615 	 * is smart.  This avoids hitting the name server which
    616 	 * might be sick because routing is.
    617 	 */
    618 	if (inet_aton(name, &in) == 1) {
    619 		*addrp = in.s_addr;
    620 		return 1;
    621 	}
    622 
    623 	hp = gethostbyname(name);
    624 	if (hp) {
    625 		bcopy(hp->h_addr, addrp, sizeof(*addrp));
    626 		return 1;
    627 	}
    628 
    629 	return 0;
    630 }
    631