xref: /csrg-svn/sbin/routed/startup.c (revision 42712)
121998Sdist /*
234568Skarels  * Copyright (c) 1983, 1988 Regents of the University of California.
333489Sbostic  * All rights reserved.
433489Sbostic  *
5*42712Sbostic  * %sccs.include.redist.c%
621998Sdist  */
721998Sdist 
89019Ssam #ifndef lint
9*42712Sbostic static char sccsid[] = "@(#)startup.c	5.18 (Berkeley) 06/01/90";
1033489Sbostic #endif /* not lint */
119019Ssam 
129019Ssam /*
139019Ssam  * Routing Table Management Daemon
149019Ssam  */
1510245Ssam #include "defs.h"
1616327Skarels #include <sys/ioctl.h>
179019Ssam #include <net/if.h>
1817571Skarels #include <syslog.h>
1937292Sbostic #include "pathnames.h"
209019Ssam 
219019Ssam struct	interface *ifnet;
2236831Skarels struct	interface **ifnext = &ifnet;
239019Ssam int	lookforinterfaces = 1;
249019Ssam int	externalinterfaces = 0;		/* # of remote and local interfaces */
2531220Skarels int	foundloopback;			/* valid flag for loopaddr */
2631220Skarels struct	sockaddr loopaddr;		/* our address on loopback */
279019Ssam 
289019Ssam /*
2921842Skarels  * Find the network interfaces which have configured themselves.
3021842Skarels  * If the interface is present but not yet up (for example an
319019Ssam  * ARPANET IMP), set the lookforinterfaces flag so we'll
329019Ssam  * come back later and look again.
339019Ssam  */
349019Ssam ifinit()
359019Ssam {
3621842Skarels 	struct interface ifs, *ifp;
3738685Ssklower 	int s;
3838685Ssklower 	char buf[BUFSIZ], *cp, *cplim;
3921842Skarels         struct ifconf ifc;
4021842Skarels         struct ifreq ifreq, *ifr;
4121842Skarels         struct sockaddr_in *sin;
4221842Skarels 	u_long i;
439019Ssam 
4421842Skarels 	if ((s = socket(AF_INET, SOCK_DGRAM, 0)) < 0) {
4521842Skarels 		syslog(LOG_ERR, "socket: %m");
4636831Skarels 		close(s);
4736831Skarels                 return;
489019Ssam 	}
4921842Skarels         ifc.ifc_len = sizeof (buf);
5021842Skarels         ifc.ifc_buf = buf;
5121842Skarels         if (ioctl(s, SIOCGIFCONF, (char *)&ifc) < 0) {
5221842Skarels                 syslog(LOG_ERR, "ioctl (get interface configuration)");
5321842Skarels 		close(s);
5436831Skarels                 return;
5521842Skarels         }
5621842Skarels         ifr = ifc.ifc_req;
579019Ssam 	lookforinterfaces = 0;
5838685Ssklower #ifdef RTM_ADD
5938685Ssklower #define max(a, b) (a > b ? a : b)
6038685Ssklower #define size(p)	max((p).sa_len, sizeof(p))
6138685Ssklower #else
6238685Ssklower #define size(p) (sizeof (p))
6338685Ssklower #endif
6438685Ssklower 	cplim = buf + ifc.ifc_len; /*skip over if's with big ifr_addr's */
6538685Ssklower 	for (cp = buf; cp < cplim;
6638685Ssklower 			cp += sizeof (ifr->ifr_name) + size(ifr->ifr_addr)) {
6738685Ssklower 		ifr = (struct ifreq *)cp;
6821842Skarels 		bzero((char *)&ifs, sizeof(ifs));
6921842Skarels 		ifs.int_addr = ifr->ifr_addr;
7021842Skarels 		ifreq = *ifr;
7121842Skarels                 if (ioctl(s, SIOCGIFFLAGS, (char *)&ifreq) < 0) {
7236831Skarels                         syslog(LOG_ERR, "%s: ioctl (get interface flags)",
7336831Skarels 			    ifr->ifr_name);
7421842Skarels                         continue;
7521842Skarels                 }
7621842Skarels 		ifs.int_flags = ifreq.ifr_flags | IFF_INTERFACE;
7721842Skarels 		if ((ifs.int_flags & IFF_UP) == 0 ||
7821842Skarels 		    ifr->ifr_addr.sa_family == AF_UNSPEC) {
799019Ssam 			lookforinterfaces = 1;
809019Ssam 			continue;
819019Ssam 		}
8236831Skarels 		/* argh, this'll have to change sometime */
8336831Skarels 		if (ifs.int_addr.sa_family != AF_INET)
8436831Skarels 			continue;
8536831Skarels                 if (ifs.int_flags & IFF_POINTOPOINT) {
8636831Skarels                         if (ioctl(s, SIOCGIFDSTADDR, (char *)&ifreq) < 0) {
8736831Skarels                                 syslog(LOG_ERR, "%s: ioctl (get dstaddr)",
8836831Skarels 				    ifr->ifr_name);
8936831Skarels                                 continue;
9036831Skarels 			}
9136831Skarels 			if (ifr->ifr_addr.sa_family == AF_UNSPEC) {
9236831Skarels 				lookforinterfaces = 1;
9336831Skarels 				continue;
9436831Skarels 			}
9536831Skarels 			ifs.int_dstaddr = ifreq.ifr_dstaddr;
9636831Skarels 		}
9734568Skarels 		/*
9834568Skarels 		 * already known to us?
9934568Skarels 		 * This allows multiple point-to-point links
10034568Skarels 		 * to share a source address (possibly with one
10134568Skarels 		 * other link), but assumes that there will not be
10234568Skarels 		 * multiple links with the same destination address.
10334568Skarels 		 */
10434568Skarels 		if (ifs.int_flags & IFF_POINTOPOINT) {
10534568Skarels 			if (if_ifwithdstaddr(&ifs.int_dstaddr))
10634568Skarels 				continue;
10734568Skarels 		} else if (if_ifwithaddr(&ifs.int_addr))
1089019Ssam 			continue;
10931220Skarels 		if (ifs.int_flags & IFF_LOOPBACK) {
11034568Skarels 			ifs.int_flags |= IFF_PASSIVE;
11131220Skarels 			foundloopback = 1;
11231220Skarels 			loopaddr = ifs.int_addr;
11331220Skarels 			for (ifp = ifnet; ifp; ifp = ifp->int_next)
11431220Skarels 			    if (ifp->int_flags & IFF_POINTOPOINT)
11531220Skarels 				add_ptopt_localrt(ifp);
11631220Skarels 		}
11721842Skarels                 if (ifs.int_flags & IFF_BROADCAST) {
11821842Skarels                         if (ioctl(s, SIOCGIFBRDADDR, (char *)&ifreq) < 0) {
11936831Skarels                                 syslog(LOG_ERR, "%s: ioctl (get broadaddr)",
12036831Skarels 				    ifr->ifr_name);
12121842Skarels                                 continue;
12221842Skarels                         }
12336831Skarels #ifndef sun
12421842Skarels 			ifs.int_broadaddr = ifreq.ifr_broadaddr;
12536831Skarels #else
12636831Skarels 			ifs.int_broadaddr = ifreq.ifr_addr;
12736831Skarels #endif
12821842Skarels 		}
12936831Skarels #ifdef SIOCGIFMETRIC
13036831Skarels 		if (ioctl(s, SIOCGIFMETRIC, (char *)&ifreq) < 0) {
13136831Skarels 			syslog(LOG_ERR, "%s: ioctl (get metric)",
13236831Skarels 			    ifr->ifr_name);
13336831Skarels 			ifs.int_metric = 0;
13436831Skarels 		} else
13526099Skarels 			ifs.int_metric = ifreq.ifr_metric;
13636831Skarels #else
13736831Skarels 		ifs.int_metric = 0;
13836831Skarels #endif
13934568Skarels 		/*
14034568Skarels 		 * Use a minimum metric of one;
14134568Skarels 		 * treat the interface metric (default 0)
14234568Skarels 		 * as an increment to the hop count of one.
14334568Skarels 		 */
14434568Skarels 		ifs.int_metric++;
14521842Skarels 		if (ioctl(s, SIOCGIFNETMASK, (char *)&ifreq) < 0) {
14636831Skarels 			syslog(LOG_ERR, "%s: ioctl (get netmask)",
14736831Skarels 			    ifr->ifr_name);
14821842Skarels 			continue;
14921842Skarels 		}
15021842Skarels 		sin = (struct sockaddr_in *)&ifreq.ifr_addr;
15121842Skarels 		ifs.int_subnetmask = ntohl(sin->sin_addr.s_addr);
15221842Skarels 		sin = (struct sockaddr_in *)&ifs.int_addr;
15321842Skarels 		i = ntohl(sin->sin_addr.s_addr);
15421842Skarels 		if (IN_CLASSA(i))
15521842Skarels 			ifs.int_netmask = IN_CLASSA_NET;
15621842Skarels 		else if (IN_CLASSB(i))
15721842Skarels 			ifs.int_netmask = IN_CLASSB_NET;
15821842Skarels 		else
15921842Skarels 			ifs.int_netmask = IN_CLASSC_NET;
16021842Skarels 		ifs.int_net = i & ifs.int_netmask;
16121842Skarels 		ifs.int_subnet = i & ifs.int_subnetmask;
16227231Skarels 		if (ifs.int_subnetmask != ifs.int_netmask)
16327231Skarels 			ifs.int_flags |= IFF_SUBNET;
1649019Ssam 		ifp = (struct interface *)malloc(sizeof (struct interface));
1659019Ssam 		if (ifp == 0) {
1669019Ssam 			printf("routed: out of memory\n");
1679019Ssam 			break;
1689019Ssam 		}
16921842Skarels 		*ifp = ifs;
1709019Ssam 		/*
1719019Ssam 		 * Count the # of directly connected networks
1729019Ssam 		 * and point to point links which aren't looped
1739019Ssam 		 * back to ourself.  This is used below to
1749019Ssam 		 * decide if we should be a routing ``supplier''.
1759019Ssam 		 */
17631220Skarels 		if ((ifs.int_flags & IFF_LOOPBACK) == 0 &&
17731220Skarels 		    ((ifs.int_flags & IFF_POINTOPOINT) == 0 ||
17831220Skarels 		    if_ifwithaddr(&ifs.int_dstaddr) == 0))
1799019Ssam 			externalinterfaces++;
18025505Skarels 		/*
18125505Skarels 		 * If we have a point-to-point link, we want to act
18225505Skarels 		 * as a supplier even if it's our only interface,
18325505Skarels 		 * as that's the only way our peer on the other end
18425505Skarels 		 * can tell that the link is up.
18525505Skarels 		 */
18625505Skarels 		if ((ifs.int_flags & IFF_POINTOPOINT) && supplier < 0)
18725505Skarels 			supplier = 1;
18821842Skarels 		ifp->int_name = malloc(strlen(ifr->ifr_name) + 1);
1899019Ssam 		if (ifp->int_name == 0) {
1909019Ssam 			fprintf(stderr, "routed: ifinit: out of memory\n");
19131220Skarels 			syslog(LOG_ERR, "routed: ifinit: out of memory\n");
19236831Skarels 			close(s);
19331220Skarels 			return;
1949019Ssam 		}
19521842Skarels 		strcpy(ifp->int_name, ifr->ifr_name);
19636831Skarels 		*ifnext = ifp;
19736831Skarels 		ifnext = &ifp->int_next;
1989019Ssam 		traceinit(ifp);
1999019Ssam 		addrouteforif(ifp);
2009019Ssam 	}
2019019Ssam 	if (externalinterfaces > 1 && supplier < 0)
2029019Ssam 		supplier = 1;
20321842Skarels 	close(s);
2049019Ssam }
2059019Ssam 
20627231Skarels /*
20727231Skarels  * Add route for interface if not currently installed.
20827231Skarels  * Create route to other end if a point-to-point link,
20927231Skarels  * otherwise a route to this (sub)network.
21027231Skarels  * INTERNET SPECIFIC.
21127231Skarels  */
2129019Ssam addrouteforif(ifp)
21331220Skarels 	register struct interface *ifp;
2149019Ssam {
2159019Ssam 	struct sockaddr_in net;
2169019Ssam 	struct sockaddr *dst;
21734661Skarels 	int state;
21831220Skarels 	register struct rt_entry *rt;
2199019Ssam 
2209019Ssam 	if (ifp->int_flags & IFF_POINTOPOINT)
2219019Ssam 		dst = &ifp->int_dstaddr;
2229019Ssam 	else {
2239019Ssam 		bzero((char *)&net, sizeof (net));
2249019Ssam 		net.sin_family = AF_INET;
22521842Skarels 		net.sin_addr = inet_makeaddr(ifp->int_subnet, INADDR_ANY);
2269019Ssam 		dst = (struct sockaddr *)&net;
2279019Ssam 	}
22821842Skarels 	rt = rtfind(dst);
22929002Skarels 	if (rt &&
23029002Skarels 	    (rt->rt_state & (RTS_INTERFACE | RTS_INTERNAL)) == RTS_INTERFACE)
23118114Skarels 		return;
23221842Skarels 	if (rt)
23321842Skarels 		rtdelete(rt);
23427231Skarels 	/*
23527231Skarels 	 * If interface on subnetted network,
23627231Skarels 	 * install route to network as well.
23727231Skarels 	 * This is meant for external viewers.
23827231Skarels 	 */
23927231Skarels 	if ((ifp->int_flags & (IFF_SUBNET|IFF_POINTOPOINT)) == IFF_SUBNET) {
24031220Skarels 		struct in_addr subnet;
24131220Skarels 
24231220Skarels 		subnet = net.sin_addr;
24327231Skarels 		net.sin_addr = inet_makeaddr(ifp->int_net, INADDR_ANY);
24427231Skarels 		rt = rtfind(dst);
24529002Skarels 		if (rt == 0)
24629002Skarels 			rtadd(dst, &ifp->int_addr, ifp->int_metric,
24729002Skarels 			    ((ifp->int_flags & (IFF_INTERFACE|IFF_REMOTE)) |
24831220Skarels 			    RTS_PASSIVE | RTS_INTERNAL | RTS_SUBNET));
24931220Skarels 		else if ((rt->rt_state & (RTS_INTERNAL|RTS_SUBNET)) ==
25031220Skarels 		    (RTS_INTERNAL|RTS_SUBNET) &&
25131220Skarels 		    ifp->int_metric < rt->rt_metric)
25231220Skarels 			rtchange(rt, &rt->rt_router, ifp->int_metric);
25331220Skarels 		net.sin_addr = subnet;
25427231Skarels 	}
25529002Skarels 	if (ifp->int_transitions++ > 0)
25629002Skarels 		syslog(LOG_ERR, "re-installing interface %s", ifp->int_name);
25731220Skarels 	state = ifp->int_flags &
25831220Skarels 	    (IFF_INTERFACE | IFF_PASSIVE | IFF_REMOTE | IFF_SUBNET);
25931220Skarels 	if (ifp->int_flags & IFF_POINTOPOINT &&
26031220Skarels 	    (ntohl(((struct sockaddr_in *)&ifp->int_dstaddr)->sin_addr.s_addr) &
26131220Skarels 	    ifp->int_netmask) != ifp->int_net)
26231220Skarels 		state &= ~RTS_SUBNET;
26331220Skarels 	if (ifp->int_flags & IFF_LOOPBACK)
26434568Skarels 		state |= RTS_EXTERNAL;
26531220Skarels 	rtadd(dst, &ifp->int_addr, ifp->int_metric, state);
26631220Skarels 	if (ifp->int_flags & IFF_POINTOPOINT && foundloopback)
26731220Skarels 		add_ptopt_localrt(ifp);
26831220Skarels }
26929002Skarels 
27031220Skarels /*
27131220Skarels  * Add route to local end of point-to-point using loopback.
27231220Skarels  * If a route to this network is being sent to neighbors on other nets,
27331220Skarels  * mark this route as subnet so we don't have to propagate it too.
27431220Skarels  */
27531220Skarels add_ptopt_localrt(ifp)
27631220Skarels 	register struct interface *ifp;
27731220Skarels {
27831220Skarels 	struct rt_entry *rt;
27931220Skarels 	struct sockaddr *dst;
28031220Skarels 	struct sockaddr_in net;
28131220Skarels 	int state;
28231220Skarels 
28331220Skarels 	state = RTS_INTERFACE | RTS_PASSIVE;
28431220Skarels 
28531220Skarels 	/* look for route to logical network */
28631220Skarels 	bzero((char *)&net, sizeof (net));
28731220Skarels 	net.sin_family = AF_INET;
28831220Skarels 	net.sin_addr = inet_makeaddr(ifp->int_net, INADDR_ANY);
28931220Skarels 	dst = (struct sockaddr *)&net;
29031220Skarels 	rt = rtfind(dst);
29131220Skarels 	if (rt && rt->rt_state & RTS_INTERNAL)
29231220Skarels 		state |= RTS_SUBNET;
29331220Skarels 
29431220Skarels 	dst = &ifp->int_addr;
29531220Skarels 	if (rt = rtfind(dst)) {
29631220Skarels 		if (rt && rt->rt_state & RTS_INTERFACE)
29731220Skarels 			return;
29831220Skarels 		rtdelete(rt);
29931220Skarels 	}
30034661Skarels 	rtadd(dst, &loopaddr, 1, state);
3019019Ssam }
3029019Ssam 
3039019Ssam /*
3049019Ssam  * As a concession to the ARPANET we read a list of gateways
3059019Ssam  * from /etc/gateways and add them to our tables.  This file
3069019Ssam  * exists at each ARPANET gateway and indicates a set of ``remote''
3079019Ssam  * gateways (i.e. a gateway which we can't immediately determine
3089019Ssam  * if it's present or not as we can do for those directly connected
3099019Ssam  * at the hardware level).  If a gateway is marked ``passive''
3109019Ssam  * in the file, then we assume it doesn't have a routing process
3119019Ssam  * of our design and simply assume it's always present.  Those
3129019Ssam  * not marked passive are treated as if they were directly
3139019Ssam  * connected -- they're added into the interface list so we'll
3149019Ssam  * send them routing updates.
31531220Skarels  *
31631220Skarels  * PASSIVE ENTRIES AREN'T NEEDED OR USED ON GATEWAYS RUNNING EGP.
3179019Ssam  */
3189019Ssam gwkludge()
3199019Ssam {
3209019Ssam 	struct sockaddr_in dst, gate;
3219019Ssam 	FILE *fp;
3229019Ssam 	char *type, *dname, *gname, *qual, buf[BUFSIZ];
3239019Ssam 	struct interface *ifp;
32428906Skarels 	int metric, n;
32516327Skarels 	struct rt_entry route;
3269019Ssam 
32737292Sbostic 	fp = fopen(_PATH_GATEWAYS, "r");
3289019Ssam 	if (fp == NULL)
3299019Ssam 		return;
3309019Ssam 	qual = buf;
3319019Ssam 	dname = buf + 64;
3329019Ssam 	gname = buf + ((BUFSIZ - 64) / 3);
3339019Ssam 	type = buf + (((BUFSIZ - 64) * 2) / 3);
3349019Ssam 	bzero((char *)&dst, sizeof (dst));
3359019Ssam 	bzero((char *)&gate, sizeof (gate));
33616327Skarels 	bzero((char *)&route, sizeof(route));
33730745Skarels /* format: {net | host} XX gateway XX metric DD [passive | external]\n */
3389019Ssam #define	readentry(fp) \
3399019Ssam 	fscanf((fp), "%s %s gateway %s metric %d %s\n", \
3409019Ssam 		type, dname, gname, &metric, qual)
3419019Ssam 	for (;;) {
34228906Skarels 		if ((n = readentry(fp)) == EOF)
3439019Ssam 			break;
34410245Ssam 		if (!getnetorhostname(type, dname, &dst))
3459019Ssam 			continue;
34610245Ssam 		if (!gethostnameornumber(gname, &gate))
3479019Ssam 			continue;
34834661Skarels 		if (metric == 0)			/* XXX */
34934661Skarels 			metric = 1;
35016327Skarels 		if (strcmp(qual, "passive") == 0) {
35116327Skarels 			/*
35216327Skarels 			 * Passive entries aren't placed in our tables,
35316327Skarels 			 * only the kernel's, so we don't copy all of the
35416327Skarels 			 * external routing information within a net.
35516327Skarels 			 * Internal machines should use the default
35616327Skarels 			 * route to a suitable gateway (like us).
35716327Skarels 			 */
35816327Skarels 			route.rt_dst = *(struct sockaddr *) &dst;
35916327Skarels 			route.rt_router = *(struct sockaddr *) &gate;
36016327Skarels 			route.rt_flags = RTF_UP;
36116327Skarels 			if (strcmp(type, "host") == 0)
36216327Skarels 				route.rt_flags |= RTF_HOST;
36316327Skarels 			if (metric)
36416327Skarels 				route.rt_flags |= RTF_GATEWAY;
36516327Skarels 			(void) ioctl(s, SIOCADDRT, (char *)&route.rt_rt);
36616327Skarels 			continue;
36716327Skarels 		}
36827231Skarels 		if (strcmp(qual, "external") == 0) {
36927231Skarels 			/*
37027231Skarels 			 * Entries marked external are handled
37127231Skarels 			 * by other means, e.g. EGP,
37227231Skarels 			 * and are placed in our tables only
37327231Skarels 			 * to prevent overriding them
37427231Skarels 			 * with something else.
37527231Skarels 			 */
37627231Skarels 			rtadd(&dst, &gate, metric, RTS_EXTERNAL|RTS_PASSIVE);
37728906Skarels 			continue;
37827231Skarels 		}
37916327Skarels 		/* assume no duplicate entries */
38016327Skarels 		externalinterfaces++;
3819019Ssam 		ifp = (struct interface *)malloc(sizeof (*ifp));
3829019Ssam 		bzero((char *)ifp, sizeof (*ifp));
3839019Ssam 		ifp->int_flags = IFF_REMOTE;
3849019Ssam 		/* can't identify broadcast capability */
3859019Ssam 		ifp->int_net = inet_netof(dst.sin_addr);
3869019Ssam 		if (strcmp(type, "host") == 0) {
3879019Ssam 			ifp->int_flags |= IFF_POINTOPOINT;
3889019Ssam 			ifp->int_dstaddr = *((struct sockaddr *)&dst);
3899019Ssam 		}
3909019Ssam 		ifp->int_addr = *((struct sockaddr *)&gate);
3919019Ssam 		ifp->int_metric = metric;
3929019Ssam 		ifp->int_next = ifnet;
3939019Ssam 		ifnet = ifp;
3949019Ssam 		addrouteforif(ifp);
3959019Ssam 	}
3969019Ssam 	fclose(fp);
3979019Ssam }
39810245Ssam 
39910245Ssam getnetorhostname(type, name, sin)
40010245Ssam 	char *type, *name;
40110245Ssam 	struct sockaddr_in *sin;
40210245Ssam {
40310245Ssam 
40410245Ssam 	if (strcmp(type, "net") == 0) {
40510245Ssam 		struct netent *np = getnetbyname(name);
40610245Ssam 		int n;
40710245Ssam 
40810245Ssam 		if (np == 0)
40910245Ssam 			n = inet_network(name);
41011527Ssam 		else {
41111527Ssam 			if (np->n_addrtype != AF_INET)
41211527Ssam 				return (0);
41310245Ssam 			n = np->n_net;
41421842Skarels 			/*
41521842Skarels 			 * getnetbyname returns right-adjusted value.
41621842Skarels 			 */
41721842Skarels 			if (n < 128)
41821842Skarels 				n <<= IN_CLASSA_NSHIFT;
41921842Skarels 			else if (n < 65536)
42021842Skarels 				n <<= IN_CLASSB_NSHIFT;
42121842Skarels 			else
42221842Skarels 				n <<= IN_CLASSC_NSHIFT;
42311527Ssam 		}
42410245Ssam 		sin->sin_family = AF_INET;
42510245Ssam 		sin->sin_addr = inet_makeaddr(n, INADDR_ANY);
42610245Ssam 		return (1);
42710245Ssam 	}
42810245Ssam 	if (strcmp(type, "host") == 0) {
42910245Ssam 		struct hostent *hp = gethostbyname(name);
43010245Ssam 
43110245Ssam 		if (hp == 0)
43210245Ssam 			sin->sin_addr.s_addr = inet_addr(name);
43311527Ssam 		else {
43411527Ssam 			if (hp->h_addrtype != AF_INET)
43511527Ssam 				return (0);
43610245Ssam 			bcopy(hp->h_addr, &sin->sin_addr, hp->h_length);
43711527Ssam 		}
43810245Ssam 		sin->sin_family = AF_INET;
43910245Ssam 		return (1);
44010245Ssam 	}
44110245Ssam 	return (0);
44210245Ssam }
44310245Ssam 
44410245Ssam gethostnameornumber(name, sin)
44510245Ssam 	char *name;
44610245Ssam 	struct sockaddr_in *sin;
44710245Ssam {
44810245Ssam 	struct hostent *hp;
44910245Ssam 
45010245Ssam 	hp = gethostbyname(name);
45110245Ssam 	if (hp) {
45210245Ssam 		bcopy(hp->h_addr, &sin->sin_addr, hp->h_length);
45310245Ssam 		sin->sin_family = hp->h_addrtype;
45410245Ssam 		return (1);
45510245Ssam 	}
45610245Ssam 	sin->sin_addr.s_addr = inet_addr(name);
45710245Ssam 	sin->sin_family = AF_INET;
45810245Ssam 	return (sin->sin_addr.s_addr != -1);
45910245Ssam }
460