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