xref: /csrg-svn/sbin/routed/startup.c (revision 55904)
121998Sdist /*
234568Skarels  * Copyright (c) 1983, 1988 Regents of the University of California.
333489Sbostic  * All rights reserved.
433489Sbostic  *
542712Sbostic  * %sccs.include.redist.c%
621998Sdist  */
721998Sdist 
89019Ssam #ifndef lint
9*55904Ssklower static char sccsid[] = "@(#)startup.c	5.22 (Berkeley) 08/14/92";
1033489Sbostic #endif /* not lint */
119019Ssam 
129019Ssam /*
139019Ssam  * Routing Table Management Daemon
149019Ssam  */
1510245Ssam #include "defs.h"
1616327Skarels #include <sys/ioctl.h>
1752583Ssklower #include <sys/kinfo.h>
189019Ssam #include <net/if.h>
1952583Ssklower #include <net/if_dl.h>
2017571Skarels #include <syslog.h>
2146784Sbostic #include <stdlib.h>
2237292Sbostic #include "pathnames.h"
239019Ssam 
249019Ssam struct	interface *ifnet;
2536831Skarels struct	interface **ifnext = &ifnet;
269019Ssam int	lookforinterfaces = 1;
279019Ssam int	externalinterfaces = 0;		/* # of remote and local interfaces */
2831220Skarels int	foundloopback;			/* valid flag for loopaddr */
2931220Skarels struct	sockaddr loopaddr;		/* our address on loopback */
309019Ssam 
3152583Ssklower 
3252583Ssklower void
3352583Ssklower quit(s)
3452583Ssklower 	char *s;
3552583Ssklower {
3652583Ssklower 	extern int errno;
3752583Ssklower 	int sverrno = errno;
3852583Ssklower 
3952583Ssklower 	(void) fprintf(stderr, "route: ");
4052583Ssklower 	if (s)
4152583Ssklower 		(void) fprintf(stderr, "%s: ", s);
4252583Ssklower 	(void) fprintf(stderr, "%s\n", strerror(sverrno));
4352583Ssklower 	exit(1);
4452583Ssklower 	/* NOTREACHED */
4552583Ssklower }
4652583Ssklower 
4752583Ssklower struct rt_addrinfo info;
4852583Ssklower /* Sleazy use of local variables throughout file, warning!!!! */
4952583Ssklower #define netmask	info.rti_info[RTAX_NETMASK]
5052583Ssklower #define ifaaddr	info.rti_info[RTAX_IFA]
5152583Ssklower #define brdaddr	info.rti_info[RTAX_BRD]
5252583Ssklower 
5352583Ssklower #define ROUNDUP(a) \
5452583Ssklower 	((a) > 0 ? (1 + (((a) - 1) | (sizeof(long) - 1))) : sizeof(long))
5552583Ssklower #define ADVANCE(x, n) (x += ROUNDUP((n)->sa_len))
5652583Ssklower 
5752583Ssklower void
5852583Ssklower rt_xaddrs(cp, cplim, rtinfo)
5952583Ssklower 	register caddr_t cp, cplim;
6052583Ssklower 	register struct rt_addrinfo *rtinfo;
6152583Ssklower {
6252583Ssklower 	register struct sockaddr *sa;
6352583Ssklower 	register int i;
6452583Ssklower 
6552583Ssklower 	bzero(rtinfo->rti_info, sizeof(rtinfo->rti_info));
6652583Ssklower 	for (i = 0; (i < RTAX_MAX) && (cp < cplim); i++) {
6752583Ssklower 		if ((rtinfo->rti_addrs & (1 << i)) == 0)
6852583Ssklower 			continue;
6952583Ssklower 		rtinfo->rti_info[i] = sa = (struct sockaddr *)cp;
7052583Ssklower 		ADVANCE(cp, sa);
7152583Ssklower 	}
7252583Ssklower }
7352583Ssklower 
749019Ssam /*
7521842Skarels  * Find the network interfaces which have configured themselves.
7621842Skarels  * If the interface is present but not yet up (for example an
779019Ssam  * ARPANET IMP), set the lookforinterfaces flag so we'll
789019Ssam  * come back later and look again.
799019Ssam  */
809019Ssam ifinit()
819019Ssam {
8221842Skarels 	struct interface ifs, *ifp;
8352583Ssklower 	int needed, rlen, no_ipaddr = 0, flags = 0;
8452583Ssklower 	char *buf, *cplim, *cp;
8552583Ssklower 	register struct if_msghdr *ifm;
8652583Ssklower 	register struct ifa_msghdr *ifam;
8752583Ssklower 	struct sockaddr_dl *sdl;
8821842Skarels         struct sockaddr_in *sin;
8921842Skarels 	u_long i;
909019Ssam 
9152583Ssklower 	if ((needed = getkerninfo(KINFO_RT_IFLIST, 0, 0, 0)) < 0)
9252583Ssklower 		quit("route-getkerninfo-estimate");
9352583Ssklower 	if ((buf = malloc(needed)) == NULL)
9452583Ssklower 		quit("malloc");
9552583Ssklower 	if ((rlen = getkerninfo(KINFO_RT_IFLIST, buf, &needed, 0)) < 0)
9652583Ssklower 		quit("actual retrieval of interface table");
979019Ssam 	lookforinterfaces = 0;
9852583Ssklower 	cplim = buf + rlen;
9952583Ssklower 	for (cp = buf; cp < cplim; cp += ifm->ifm_msglen) {
10052583Ssklower 		ifm = (struct if_msghdr *)cp;
10152583Ssklower 		if (ifm->ifm_type == RTM_IFINFO) {
10252583Ssklower 			bzero(&ifs, sizeof(ifs));
103*55904Ssklower 			ifs.int_flags = flags = (0xffff & ifm->ifm_flags) | IFF_INTERFACE;
10452583Ssklower 			if ((flags & IFF_UP) == 0 || no_ipaddr)
10552583Ssklower 				lookforinterfaces = 1;
10652583Ssklower 			sdl = (struct sockaddr_dl *) (ifm + 1);
10752583Ssklower 			sdl->sdl_data[sdl->sdl_nlen] = 0;
10852583Ssklower 			no_ipaddr = 1;
1099019Ssam 			continue;
1109019Ssam 		}
11152583Ssklower 		if (ifm->ifm_type != RTM_NEWADDR)
11252583Ssklower 			quit("ifinit: out of sync");
11352583Ssklower 		if ((flags & IFF_UP) == 0)
11452583Ssklower 			continue;
11552583Ssklower 		ifam = (struct ifa_msghdr *)ifm;
11652583Ssklower 		info.rti_addrs = ifam->ifam_addrs;
11752583Ssklower 		rt_xaddrs((char *)(ifam + 1), cp + ifam->ifam_msglen, &info);
11852583Ssklower 		if (ifaaddr == 0) {
11952583Ssklower 			syslog(LOG_ERR, "%s: (get addr)", sdl->sdl_data);
12052583Ssklower 			continue;
12152583Ssklower 		}
12252583Ssklower 		ifs.int_addr = *ifaaddr;
12336831Skarels 		if (ifs.int_addr.sa_family != AF_INET)
12436831Skarels 			continue;
12552583Ssklower 		no_ipaddr = 0;
12652583Ssklower 		if (ifs.int_flags & IFF_POINTOPOINT) {
12752583Ssklower 			if (brdaddr == 0) {
12852583Ssklower 				syslog(LOG_ERR, "%s: (get dstaddr)",
12952583Ssklower 					sdl->sdl_data);
13052583Ssklower 				continue;
13136831Skarels 			}
13252583Ssklower 			if (brdaddr->sa_family == AF_UNSPEC) {
13336831Skarels 				lookforinterfaces = 1;
13436831Skarels 				continue;
13536831Skarels 			}
13652583Ssklower 			ifs.int_dstaddr = *brdaddr;
13736831Skarels 		}
13834568Skarels 		/*
13934568Skarels 		 * already known to us?
14034568Skarels 		 * This allows multiple point-to-point links
14134568Skarels 		 * to share a source address (possibly with one
14234568Skarels 		 * other link), but assumes that there will not be
14334568Skarels 		 * multiple links with the same destination address.
14434568Skarels 		 */
14534568Skarels 		if (ifs.int_flags & IFF_POINTOPOINT) {
14634568Skarels 			if (if_ifwithdstaddr(&ifs.int_dstaddr))
14734568Skarels 				continue;
14834568Skarels 		} else if (if_ifwithaddr(&ifs.int_addr))
1499019Ssam 			continue;
15031220Skarels 		if (ifs.int_flags & IFF_LOOPBACK) {
15134568Skarels 			ifs.int_flags |= IFF_PASSIVE;
15231220Skarels 			foundloopback = 1;
15331220Skarels 			loopaddr = ifs.int_addr;
15431220Skarels 			for (ifp = ifnet; ifp; ifp = ifp->int_next)
15531220Skarels 			    if (ifp->int_flags & IFF_POINTOPOINT)
15631220Skarels 				add_ptopt_localrt(ifp);
15731220Skarels 		}
15852583Ssklower 		if (ifs.int_flags & IFF_BROADCAST) {
15952583Ssklower 			if (brdaddr == 0) {
16052583Ssklower 				syslog(LOG_ERR, "%s: (get broadaddr)",
16152583Ssklower 					sdl->sdl_data);
16252583Ssklower 				continue;
16352583Ssklower 			}
16452583Ssklower 			ifs.int_dstaddr = *brdaddr;
16521842Skarels 		}
16652621Ssklower 		/*
16752621Ssklower 		 * Use a minimum metric of one;
16852621Ssklower 		 * treat the interface metric (default 0)
16952621Ssklower 		 * as an increment to the hop count of one.
17052621Ssklower 		 */
17152621Ssklower 		ifs.int_metric = ifam->ifam_metric + 1;
17252583Ssklower 		if (netmask == 0) {
17352583Ssklower 				syslog(LOG_ERR, "%s: (get netmask)",
17452583Ssklower 					sdl->sdl_data);
17552583Ssklower 				continue;
17621842Skarels 		}
17752583Ssklower 		sin = (struct sockaddr_in *)netmask;
17821842Skarels 		ifs.int_subnetmask = ntohl(sin->sin_addr.s_addr);
17921842Skarels 		sin = (struct sockaddr_in *)&ifs.int_addr;
18021842Skarels 		i = ntohl(sin->sin_addr.s_addr);
18121842Skarels 		if (IN_CLASSA(i))
18221842Skarels 			ifs.int_netmask = IN_CLASSA_NET;
18321842Skarels 		else if (IN_CLASSB(i))
18421842Skarels 			ifs.int_netmask = IN_CLASSB_NET;
18521842Skarels 		else
18621842Skarels 			ifs.int_netmask = IN_CLASSC_NET;
18721842Skarels 		ifs.int_net = i & ifs.int_netmask;
18821842Skarels 		ifs.int_subnet = i & ifs.int_subnetmask;
18927231Skarels 		if (ifs.int_subnetmask != ifs.int_netmask)
19027231Skarels 			ifs.int_flags |= IFF_SUBNET;
19152583Ssklower 		ifp = (struct interface *)
19252583Ssklower 			malloc(sdl->sdl_nlen + 1 + sizeof(ifs));
1939019Ssam 		if (ifp == 0) {
1949019Ssam 			printf("routed: out of memory\n");
19552583Ssklower 			lookforinterfaces = 1;
1969019Ssam 			break;
1979019Ssam 		}
19821842Skarels 		*ifp = ifs;
1999019Ssam 		/*
2009019Ssam 		 * Count the # of directly connected networks
2019019Ssam 		 * and point to point links which aren't looped
2029019Ssam 		 * back to ourself.  This is used below to
2039019Ssam 		 * decide if we should be a routing ``supplier''.
2049019Ssam 		 */
20531220Skarels 		if ((ifs.int_flags & IFF_LOOPBACK) == 0 &&
20631220Skarels 		    ((ifs.int_flags & IFF_POINTOPOINT) == 0 ||
20731220Skarels 		    if_ifwithaddr(&ifs.int_dstaddr) == 0))
2089019Ssam 			externalinterfaces++;
20925505Skarels 		/*
21025505Skarels 		 * If we have a point-to-point link, we want to act
21125505Skarels 		 * as a supplier even if it's our only interface,
21225505Skarels 		 * as that's the only way our peer on the other end
21325505Skarels 		 * can tell that the link is up.
21425505Skarels 		 */
21525505Skarels 		if ((ifs.int_flags & IFF_POINTOPOINT) && supplier < 0)
21625505Skarels 			supplier = 1;
21752583Ssklower 		ifp->int_name = (char *)(ifp + 1);
21852583Ssklower 		strcpy(ifp->int_name, sdl->sdl_data);
21936831Skarels 		*ifnext = ifp;
22036831Skarels 		ifnext = &ifp->int_next;
2219019Ssam 		traceinit(ifp);
2229019Ssam 		addrouteforif(ifp);
2239019Ssam 	}
2249019Ssam 	if (externalinterfaces > 1 && supplier < 0)
2259019Ssam 		supplier = 1;
22652583Ssklower 	free(buf);
2279019Ssam }
2289019Ssam 
22927231Skarels /*
23027231Skarels  * Add route for interface if not currently installed.
23127231Skarels  * Create route to other end if a point-to-point link,
23227231Skarels  * otherwise a route to this (sub)network.
23327231Skarels  * INTERNET SPECIFIC.
23427231Skarels  */
2359019Ssam addrouteforif(ifp)
23631220Skarels 	register struct interface *ifp;
2379019Ssam {
2389019Ssam 	struct sockaddr_in net;
2399019Ssam 	struct sockaddr *dst;
24034661Skarels 	int state;
24131220Skarels 	register struct rt_entry *rt;
2429019Ssam 
2439019Ssam 	if (ifp->int_flags & IFF_POINTOPOINT)
2449019Ssam 		dst = &ifp->int_dstaddr;
2459019Ssam 	else {
2469019Ssam 		bzero((char *)&net, sizeof (net));
2479019Ssam 		net.sin_family = AF_INET;
24821842Skarels 		net.sin_addr = inet_makeaddr(ifp->int_subnet, INADDR_ANY);
2499019Ssam 		dst = (struct sockaddr *)&net;
2509019Ssam 	}
25121842Skarels 	rt = rtfind(dst);
25229002Skarels 	if (rt &&
25329002Skarels 	    (rt->rt_state & (RTS_INTERFACE | RTS_INTERNAL)) == RTS_INTERFACE)
25418114Skarels 		return;
25521842Skarels 	if (rt)
25621842Skarels 		rtdelete(rt);
25727231Skarels 	/*
25827231Skarels 	 * If interface on subnetted network,
25927231Skarels 	 * install route to network as well.
26027231Skarels 	 * This is meant for external viewers.
26127231Skarels 	 */
26227231Skarels 	if ((ifp->int_flags & (IFF_SUBNET|IFF_POINTOPOINT)) == IFF_SUBNET) {
26331220Skarels 		struct in_addr subnet;
26431220Skarels 
26531220Skarels 		subnet = net.sin_addr;
26627231Skarels 		net.sin_addr = inet_makeaddr(ifp->int_net, INADDR_ANY);
26727231Skarels 		rt = rtfind(dst);
26829002Skarels 		if (rt == 0)
26929002Skarels 			rtadd(dst, &ifp->int_addr, ifp->int_metric,
27029002Skarels 			    ((ifp->int_flags & (IFF_INTERFACE|IFF_REMOTE)) |
27131220Skarels 			    RTS_PASSIVE | RTS_INTERNAL | RTS_SUBNET));
27231220Skarels 		else if ((rt->rt_state & (RTS_INTERNAL|RTS_SUBNET)) ==
27331220Skarels 		    (RTS_INTERNAL|RTS_SUBNET) &&
27431220Skarels 		    ifp->int_metric < rt->rt_metric)
27531220Skarels 			rtchange(rt, &rt->rt_router, ifp->int_metric);
27631220Skarels 		net.sin_addr = subnet;
27727231Skarels 	}
27829002Skarels 	if (ifp->int_transitions++ > 0)
27929002Skarels 		syslog(LOG_ERR, "re-installing interface %s", ifp->int_name);
28031220Skarels 	state = ifp->int_flags &
28131220Skarels 	    (IFF_INTERFACE | IFF_PASSIVE | IFF_REMOTE | IFF_SUBNET);
28231220Skarels 	if (ifp->int_flags & IFF_POINTOPOINT &&
28331220Skarels 	    (ntohl(((struct sockaddr_in *)&ifp->int_dstaddr)->sin_addr.s_addr) &
28431220Skarels 	    ifp->int_netmask) != ifp->int_net)
28531220Skarels 		state &= ~RTS_SUBNET;
28631220Skarels 	if (ifp->int_flags & IFF_LOOPBACK)
28734568Skarels 		state |= RTS_EXTERNAL;
28831220Skarels 	rtadd(dst, &ifp->int_addr, ifp->int_metric, state);
28931220Skarels 	if (ifp->int_flags & IFF_POINTOPOINT && foundloopback)
29031220Skarels 		add_ptopt_localrt(ifp);
29131220Skarels }
29229002Skarels 
29331220Skarels /*
29431220Skarels  * Add route to local end of point-to-point using loopback.
29531220Skarels  * If a route to this network is being sent to neighbors on other nets,
29631220Skarels  * mark this route as subnet so we don't have to propagate it too.
29731220Skarels  */
29831220Skarels add_ptopt_localrt(ifp)
29931220Skarels 	register struct interface *ifp;
30031220Skarels {
30131220Skarels 	struct rt_entry *rt;
30231220Skarels 	struct sockaddr *dst;
30331220Skarels 	struct sockaddr_in net;
30431220Skarels 	int state;
30531220Skarels 
30631220Skarels 	state = RTS_INTERFACE | RTS_PASSIVE;
30731220Skarels 
30831220Skarels 	/* look for route to logical network */
30931220Skarels 	bzero((char *)&net, sizeof (net));
31031220Skarels 	net.sin_family = AF_INET;
31131220Skarels 	net.sin_addr = inet_makeaddr(ifp->int_net, INADDR_ANY);
31231220Skarels 	dst = (struct sockaddr *)&net;
31331220Skarels 	rt = rtfind(dst);
31431220Skarels 	if (rt && rt->rt_state & RTS_INTERNAL)
31531220Skarels 		state |= RTS_SUBNET;
31631220Skarels 
31731220Skarels 	dst = &ifp->int_addr;
31831220Skarels 	if (rt = rtfind(dst)) {
31931220Skarels 		if (rt && rt->rt_state & RTS_INTERFACE)
32031220Skarels 			return;
32131220Skarels 		rtdelete(rt);
32231220Skarels 	}
32334661Skarels 	rtadd(dst, &loopaddr, 1, state);
3249019Ssam }
3259019Ssam 
3269019Ssam /*
3279019Ssam  * As a concession to the ARPANET we read a list of gateways
3289019Ssam  * from /etc/gateways and add them to our tables.  This file
3299019Ssam  * exists at each ARPANET gateway and indicates a set of ``remote''
3309019Ssam  * gateways (i.e. a gateway which we can't immediately determine
3319019Ssam  * if it's present or not as we can do for those directly connected
3329019Ssam  * at the hardware level).  If a gateway is marked ``passive''
3339019Ssam  * in the file, then we assume it doesn't have a routing process
3349019Ssam  * of our design and simply assume it's always present.  Those
3359019Ssam  * not marked passive are treated as if they were directly
3369019Ssam  * connected -- they're added into the interface list so we'll
3379019Ssam  * send them routing updates.
33831220Skarels  *
33931220Skarels  * PASSIVE ENTRIES AREN'T NEEDED OR USED ON GATEWAYS RUNNING EGP.
3409019Ssam  */
3419019Ssam gwkludge()
3429019Ssam {
3439019Ssam 	struct sockaddr_in dst, gate;
3449019Ssam 	FILE *fp;
3459019Ssam 	char *type, *dname, *gname, *qual, buf[BUFSIZ];
3469019Ssam 	struct interface *ifp;
34728906Skarels 	int metric, n;
34816327Skarels 	struct rt_entry route;
3499019Ssam 
35037292Sbostic 	fp = fopen(_PATH_GATEWAYS, "r");
3519019Ssam 	if (fp == NULL)
3529019Ssam 		return;
3539019Ssam 	qual = buf;
3549019Ssam 	dname = buf + 64;
3559019Ssam 	gname = buf + ((BUFSIZ - 64) / 3);
3569019Ssam 	type = buf + (((BUFSIZ - 64) * 2) / 3);
3579019Ssam 	bzero((char *)&dst, sizeof (dst));
3589019Ssam 	bzero((char *)&gate, sizeof (gate));
35916327Skarels 	bzero((char *)&route, sizeof(route));
36030745Skarels /* format: {net | host} XX gateway XX metric DD [passive | external]\n */
3619019Ssam #define	readentry(fp) \
3629019Ssam 	fscanf((fp), "%s %s gateway %s metric %d %s\n", \
3639019Ssam 		type, dname, gname, &metric, qual)
3649019Ssam 	for (;;) {
36528906Skarels 		if ((n = readentry(fp)) == EOF)
3669019Ssam 			break;
36710245Ssam 		if (!getnetorhostname(type, dname, &dst))
3689019Ssam 			continue;
36910245Ssam 		if (!gethostnameornumber(gname, &gate))
3709019Ssam 			continue;
37134661Skarels 		if (metric == 0)			/* XXX */
37234661Skarels 			metric = 1;
37316327Skarels 		if (strcmp(qual, "passive") == 0) {
37416327Skarels 			/*
37516327Skarels 			 * Passive entries aren't placed in our tables,
37616327Skarels 			 * only the kernel's, so we don't copy all of the
37716327Skarels 			 * external routing information within a net.
37816327Skarels 			 * Internal machines should use the default
37916327Skarels 			 * route to a suitable gateway (like us).
38016327Skarels 			 */
38116327Skarels 			route.rt_dst = *(struct sockaddr *) &dst;
38216327Skarels 			route.rt_router = *(struct sockaddr *) &gate;
38316327Skarels 			route.rt_flags = RTF_UP;
38416327Skarels 			if (strcmp(type, "host") == 0)
38516327Skarels 				route.rt_flags |= RTF_HOST;
38616327Skarels 			if (metric)
38716327Skarels 				route.rt_flags |= RTF_GATEWAY;
38852583Ssklower 			(void) rtioctl(ADD, &route.rt_rt);
38916327Skarels 			continue;
39016327Skarels 		}
39127231Skarels 		if (strcmp(qual, "external") == 0) {
39227231Skarels 			/*
39327231Skarels 			 * Entries marked external are handled
39427231Skarels 			 * by other means, e.g. EGP,
39527231Skarels 			 * and are placed in our tables only
39627231Skarels 			 * to prevent overriding them
39727231Skarels 			 * with something else.
39827231Skarels 			 */
39927231Skarels 			rtadd(&dst, &gate, metric, RTS_EXTERNAL|RTS_PASSIVE);
40028906Skarels 			continue;
40127231Skarels 		}
40216327Skarels 		/* assume no duplicate entries */
40316327Skarels 		externalinterfaces++;
4049019Ssam 		ifp = (struct interface *)malloc(sizeof (*ifp));
4059019Ssam 		bzero((char *)ifp, sizeof (*ifp));
4069019Ssam 		ifp->int_flags = IFF_REMOTE;
4079019Ssam 		/* can't identify broadcast capability */
4089019Ssam 		ifp->int_net = inet_netof(dst.sin_addr);
4099019Ssam 		if (strcmp(type, "host") == 0) {
4109019Ssam 			ifp->int_flags |= IFF_POINTOPOINT;
4119019Ssam 			ifp->int_dstaddr = *((struct sockaddr *)&dst);
4129019Ssam 		}
4139019Ssam 		ifp->int_addr = *((struct sockaddr *)&gate);
4149019Ssam 		ifp->int_metric = metric;
4159019Ssam 		ifp->int_next = ifnet;
4169019Ssam 		ifnet = ifp;
4179019Ssam 		addrouteforif(ifp);
4189019Ssam 	}
4199019Ssam 	fclose(fp);
4209019Ssam }
42110245Ssam 
42210245Ssam getnetorhostname(type, name, sin)
42310245Ssam 	char *type, *name;
42410245Ssam 	struct sockaddr_in *sin;
42510245Ssam {
42610245Ssam 
42710245Ssam 	if (strcmp(type, "net") == 0) {
42810245Ssam 		struct netent *np = getnetbyname(name);
42910245Ssam 		int n;
43010245Ssam 
43110245Ssam 		if (np == 0)
43210245Ssam 			n = inet_network(name);
43311527Ssam 		else {
43411527Ssam 			if (np->n_addrtype != AF_INET)
43511527Ssam 				return (0);
43610245Ssam 			n = np->n_net;
43721842Skarels 			/*
43821842Skarels 			 * getnetbyname returns right-adjusted value.
43921842Skarels 			 */
44021842Skarels 			if (n < 128)
44121842Skarels 				n <<= IN_CLASSA_NSHIFT;
44221842Skarels 			else if (n < 65536)
44321842Skarels 				n <<= IN_CLASSB_NSHIFT;
44421842Skarels 			else
44521842Skarels 				n <<= IN_CLASSC_NSHIFT;
44611527Ssam 		}
44710245Ssam 		sin->sin_family = AF_INET;
44810245Ssam 		sin->sin_addr = inet_makeaddr(n, INADDR_ANY);
44910245Ssam 		return (1);
45010245Ssam 	}
45110245Ssam 	if (strcmp(type, "host") == 0) {
45210245Ssam 		struct hostent *hp = gethostbyname(name);
45310245Ssam 
45410245Ssam 		if (hp == 0)
45510245Ssam 			sin->sin_addr.s_addr = inet_addr(name);
45611527Ssam 		else {
45711527Ssam 			if (hp->h_addrtype != AF_INET)
45811527Ssam 				return (0);
45910245Ssam 			bcopy(hp->h_addr, &sin->sin_addr, hp->h_length);
46011527Ssam 		}
46110245Ssam 		sin->sin_family = AF_INET;
46210245Ssam 		return (1);
46310245Ssam 	}
46410245Ssam 	return (0);
46510245Ssam }
46610245Ssam 
46710245Ssam gethostnameornumber(name, sin)
46810245Ssam 	char *name;
46910245Ssam 	struct sockaddr_in *sin;
47010245Ssam {
47110245Ssam 	struct hostent *hp;
47210245Ssam 
47310245Ssam 	hp = gethostbyname(name);
47410245Ssam 	if (hp) {
47510245Ssam 		bcopy(hp->h_addr, &sin->sin_addr, hp->h_length);
47610245Ssam 		sin->sin_family = hp->h_addrtype;
47710245Ssam 		return (1);
47810245Ssam 	}
47910245Ssam 	sin->sin_addr.s_addr = inet_addr(name);
48010245Ssam 	sin->sin_family = AF_INET;
48110245Ssam 	return (sin->sin_addr.s_addr != -1);
48210245Ssam }
483