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