121998Sdist /*
261540Sbostic * Copyright (c) 1983, 1988, 1993
361540Sbostic * The Regents of the University of California. All rights reserved.
433489Sbostic *
542712Sbostic * %sccs.include.redist.c%
621998Sdist */
721998Sdist
89019Ssam #ifndef lint
9*69003Sbostic static char sccsid[] = "@(#)startup.c 8.2 (Berkeley) 04/28/95";
1033489Sbostic #endif /* not lint */
119019Ssam
129019Ssam /*
139019Ssam * Routing Table Management Daemon
149019Ssam */
1510245Ssam #include "defs.h"
1616327Skarels #include <sys/ioctl.h>
1758927Smckusick #include <sys/sysctl.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
quit(s)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
rt_xaddrs(cp,cplim,rtinfo)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
65*69003Sbostic memset(rtinfo->rti_info, 0, 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 */
ifinit()809019Ssam ifinit()
819019Ssam {
8221842Skarels struct interface ifs, *ifp;
8358927Smckusick size_t needed;
8458927Smckusick int mib[6], no_ipaddr = 0, flags = 0;
8552583Ssklower char *buf, *cplim, *cp;
8652583Ssklower register struct if_msghdr *ifm;
8752583Ssklower register struct ifa_msghdr *ifam;
8852583Ssklower struct sockaddr_dl *sdl;
8921842Skarels struct sockaddr_in *sin;
9021842Skarels u_long i;
919019Ssam
9258927Smckusick mib[0] = CTL_NET;
9358927Smckusick mib[1] = PF_ROUTE;
9458927Smckusick mib[2] = 0;
9558927Smckusick mib[3] = AF_INET;
9658927Smckusick mib[4] = NET_RT_IFLIST;
9758927Smckusick mib[5] = 0;
9858927Smckusick if (sysctl(mib, 6, NULL, &needed, NULL, 0) < 0)
9958927Smckusick quit("route-sysctl-estimate");
10052583Ssklower if ((buf = malloc(needed)) == NULL)
10152583Ssklower quit("malloc");
10258927Smckusick if (sysctl(mib, 6, buf, &needed, NULL, 0) < 0)
10352583Ssklower quit("actual retrieval of interface table");
1049019Ssam lookforinterfaces = 0;
10558927Smckusick cplim = buf + needed;
10652583Ssklower for (cp = buf; cp < cplim; cp += ifm->ifm_msglen) {
10752583Ssklower ifm = (struct if_msghdr *)cp;
10852583Ssklower if (ifm->ifm_type == RTM_IFINFO) {
109*69003Sbostic memset(&ifs, 0, sizeof(ifs));
11055904Ssklower ifs.int_flags = flags = (0xffff & ifm->ifm_flags) | IFF_INTERFACE;
11152583Ssklower if ((flags & IFF_UP) == 0 || no_ipaddr)
11252583Ssklower lookforinterfaces = 1;
11352583Ssklower sdl = (struct sockaddr_dl *) (ifm + 1);
11452583Ssklower sdl->sdl_data[sdl->sdl_nlen] = 0;
11552583Ssklower no_ipaddr = 1;
1169019Ssam continue;
1179019Ssam }
11852583Ssklower if (ifm->ifm_type != RTM_NEWADDR)
11952583Ssklower quit("ifinit: out of sync");
12052583Ssklower if ((flags & IFF_UP) == 0)
12152583Ssklower continue;
12252583Ssklower ifam = (struct ifa_msghdr *)ifm;
12352583Ssklower info.rti_addrs = ifam->ifam_addrs;
12452583Ssklower rt_xaddrs((char *)(ifam + 1), cp + ifam->ifam_msglen, &info);
12552583Ssklower if (ifaaddr == 0) {
12652583Ssklower syslog(LOG_ERR, "%s: (get addr)", sdl->sdl_data);
12752583Ssklower continue;
12852583Ssklower }
12952583Ssklower ifs.int_addr = *ifaaddr;
13036831Skarels if (ifs.int_addr.sa_family != AF_INET)
13136831Skarels continue;
13252583Ssklower no_ipaddr = 0;
13352583Ssklower if (ifs.int_flags & IFF_POINTOPOINT) {
13452583Ssklower if (brdaddr == 0) {
13552583Ssklower syslog(LOG_ERR, "%s: (get dstaddr)",
13652583Ssklower sdl->sdl_data);
13752583Ssklower continue;
13836831Skarels }
13952583Ssklower if (brdaddr->sa_family == AF_UNSPEC) {
14036831Skarels lookforinterfaces = 1;
14136831Skarels continue;
14236831Skarels }
14352583Ssklower ifs.int_dstaddr = *brdaddr;
14436831Skarels }
14534568Skarels /*
14634568Skarels * already known to us?
14734568Skarels * This allows multiple point-to-point links
14834568Skarels * to share a source address (possibly with one
14934568Skarels * other link), but assumes that there will not be
15034568Skarels * multiple links with the same destination address.
15134568Skarels */
15234568Skarels if (ifs.int_flags & IFF_POINTOPOINT) {
15334568Skarels if (if_ifwithdstaddr(&ifs.int_dstaddr))
15434568Skarels continue;
15534568Skarels } else if (if_ifwithaddr(&ifs.int_addr))
1569019Ssam continue;
15731220Skarels if (ifs.int_flags & IFF_LOOPBACK) {
15834568Skarels ifs.int_flags |= IFF_PASSIVE;
15931220Skarels foundloopback = 1;
16031220Skarels loopaddr = ifs.int_addr;
16131220Skarels for (ifp = ifnet; ifp; ifp = ifp->int_next)
16231220Skarels if (ifp->int_flags & IFF_POINTOPOINT)
16331220Skarels add_ptopt_localrt(ifp);
16431220Skarels }
16552583Ssklower if (ifs.int_flags & IFF_BROADCAST) {
16652583Ssklower if (brdaddr == 0) {
16752583Ssklower syslog(LOG_ERR, "%s: (get broadaddr)",
16852583Ssklower sdl->sdl_data);
16952583Ssklower continue;
17052583Ssklower }
17152583Ssklower ifs.int_dstaddr = *brdaddr;
17221842Skarels }
17352621Ssklower /*
17452621Ssklower * Use a minimum metric of one;
17552621Ssklower * treat the interface metric (default 0)
17652621Ssklower * as an increment to the hop count of one.
17752621Ssklower */
17852621Ssklower ifs.int_metric = ifam->ifam_metric + 1;
17952583Ssklower if (netmask == 0) {
18052583Ssklower syslog(LOG_ERR, "%s: (get netmask)",
18152583Ssklower sdl->sdl_data);
18252583Ssklower continue;
18321842Skarels }
18452583Ssklower sin = (struct sockaddr_in *)netmask;
18521842Skarels ifs.int_subnetmask = ntohl(sin->sin_addr.s_addr);
18621842Skarels sin = (struct sockaddr_in *)&ifs.int_addr;
18721842Skarels i = ntohl(sin->sin_addr.s_addr);
18821842Skarels if (IN_CLASSA(i))
18921842Skarels ifs.int_netmask = IN_CLASSA_NET;
19021842Skarels else if (IN_CLASSB(i))
19121842Skarels ifs.int_netmask = IN_CLASSB_NET;
19221842Skarels else
19321842Skarels ifs.int_netmask = IN_CLASSC_NET;
19421842Skarels ifs.int_net = i & ifs.int_netmask;
19521842Skarels ifs.int_subnet = i & ifs.int_subnetmask;
19627231Skarels if (ifs.int_subnetmask != ifs.int_netmask)
19727231Skarels ifs.int_flags |= IFF_SUBNET;
19852583Ssklower ifp = (struct interface *)
19952583Ssklower malloc(sdl->sdl_nlen + 1 + sizeof(ifs));
2009019Ssam if (ifp == 0) {
2019019Ssam printf("routed: out of memory\n");
20252583Ssklower lookforinterfaces = 1;
2039019Ssam break;
2049019Ssam }
20521842Skarels *ifp = ifs;
2069019Ssam /*
2079019Ssam * Count the # of directly connected networks
2089019Ssam * and point to point links which aren't looped
2099019Ssam * back to ourself. This is used below to
2109019Ssam * decide if we should be a routing ``supplier''.
2119019Ssam */
21231220Skarels if ((ifs.int_flags & IFF_LOOPBACK) == 0 &&
21331220Skarels ((ifs.int_flags & IFF_POINTOPOINT) == 0 ||
21431220Skarels if_ifwithaddr(&ifs.int_dstaddr) == 0))
2159019Ssam externalinterfaces++;
21625505Skarels /*
21725505Skarels * If we have a point-to-point link, we want to act
21825505Skarels * as a supplier even if it's our only interface,
21925505Skarels * as that's the only way our peer on the other end
22025505Skarels * can tell that the link is up.
22125505Skarels */
22225505Skarels if ((ifs.int_flags & IFF_POINTOPOINT) && supplier < 0)
22325505Skarels supplier = 1;
22452583Ssklower ifp->int_name = (char *)(ifp + 1);
22552583Ssklower strcpy(ifp->int_name, sdl->sdl_data);
22636831Skarels *ifnext = ifp;
22736831Skarels ifnext = &ifp->int_next;
2289019Ssam traceinit(ifp);
2299019Ssam addrouteforif(ifp);
2309019Ssam }
2319019Ssam if (externalinterfaces > 1 && supplier < 0)
2329019Ssam supplier = 1;
23352583Ssklower free(buf);
2349019Ssam }
2359019Ssam
23627231Skarels /*
23727231Skarels * Add route for interface if not currently installed.
23827231Skarels * Create route to other end if a point-to-point link,
23927231Skarels * otherwise a route to this (sub)network.
24027231Skarels * INTERNET SPECIFIC.
24127231Skarels */
addrouteforif(ifp)2429019Ssam addrouteforif(ifp)
24331220Skarels register struct interface *ifp;
2449019Ssam {
2459019Ssam struct sockaddr_in net;
2469019Ssam struct sockaddr *dst;
24734661Skarels int state;
24831220Skarels register struct rt_entry *rt;
2499019Ssam
2509019Ssam if (ifp->int_flags & IFF_POINTOPOINT)
2519019Ssam dst = &ifp->int_dstaddr;
2529019Ssam else {
253*69003Sbostic memset(&net, 0, sizeof (net));
2549019Ssam net.sin_family = AF_INET;
25521842Skarels net.sin_addr = inet_makeaddr(ifp->int_subnet, INADDR_ANY);
2569019Ssam dst = (struct sockaddr *)&net;
2579019Ssam }
25821842Skarels rt = rtfind(dst);
25929002Skarels if (rt &&
26029002Skarels (rt->rt_state & (RTS_INTERFACE | RTS_INTERNAL)) == RTS_INTERFACE)
26118114Skarels return;
26221842Skarels if (rt)
26321842Skarels rtdelete(rt);
26427231Skarels /*
26527231Skarels * If interface on subnetted network,
26627231Skarels * install route to network as well.
26727231Skarels * This is meant for external viewers.
26827231Skarels */
26927231Skarels if ((ifp->int_flags & (IFF_SUBNET|IFF_POINTOPOINT)) == IFF_SUBNET) {
27031220Skarels struct in_addr subnet;
27131220Skarels
27231220Skarels subnet = net.sin_addr;
27327231Skarels net.sin_addr = inet_makeaddr(ifp->int_net, INADDR_ANY);
27427231Skarels rt = rtfind(dst);
27529002Skarels if (rt == 0)
27629002Skarels rtadd(dst, &ifp->int_addr, ifp->int_metric,
27729002Skarels ((ifp->int_flags & (IFF_INTERFACE|IFF_REMOTE)) |
27831220Skarels RTS_PASSIVE | RTS_INTERNAL | RTS_SUBNET));
27931220Skarels else if ((rt->rt_state & (RTS_INTERNAL|RTS_SUBNET)) ==
28031220Skarels (RTS_INTERNAL|RTS_SUBNET) &&
28131220Skarels ifp->int_metric < rt->rt_metric)
28231220Skarels rtchange(rt, &rt->rt_router, ifp->int_metric);
28331220Skarels net.sin_addr = subnet;
28427231Skarels }
28529002Skarels if (ifp->int_transitions++ > 0)
28629002Skarels syslog(LOG_ERR, "re-installing interface %s", ifp->int_name);
28731220Skarels state = ifp->int_flags &
28831220Skarels (IFF_INTERFACE | IFF_PASSIVE | IFF_REMOTE | IFF_SUBNET);
28931220Skarels if (ifp->int_flags & IFF_POINTOPOINT &&
29031220Skarels (ntohl(((struct sockaddr_in *)&ifp->int_dstaddr)->sin_addr.s_addr) &
29131220Skarels ifp->int_netmask) != ifp->int_net)
29231220Skarels state &= ~RTS_SUBNET;
29331220Skarels if (ifp->int_flags & IFF_LOOPBACK)
29434568Skarels state |= RTS_EXTERNAL;
29531220Skarels rtadd(dst, &ifp->int_addr, ifp->int_metric, state);
29631220Skarels if (ifp->int_flags & IFF_POINTOPOINT && foundloopback)
29731220Skarels add_ptopt_localrt(ifp);
29831220Skarels }
29929002Skarels
30031220Skarels /*
30131220Skarels * Add route to local end of point-to-point using loopback.
30231220Skarels * If a route to this network is being sent to neighbors on other nets,
30331220Skarels * mark this route as subnet so we don't have to propagate it too.
30431220Skarels */
add_ptopt_localrt(ifp)30531220Skarels add_ptopt_localrt(ifp)
30631220Skarels register struct interface *ifp;
30731220Skarels {
30831220Skarels struct rt_entry *rt;
30931220Skarels struct sockaddr *dst;
31031220Skarels struct sockaddr_in net;
31131220Skarels int state;
31231220Skarels
31331220Skarels state = RTS_INTERFACE | RTS_PASSIVE;
31431220Skarels
31531220Skarels /* look for route to logical network */
316*69003Sbostic memset(&net, 0, sizeof (net));
31731220Skarels net.sin_family = AF_INET;
31831220Skarels net.sin_addr = inet_makeaddr(ifp->int_net, INADDR_ANY);
31931220Skarels dst = (struct sockaddr *)&net;
32031220Skarels rt = rtfind(dst);
32131220Skarels if (rt && rt->rt_state & RTS_INTERNAL)
32231220Skarels state |= RTS_SUBNET;
32331220Skarels
32431220Skarels dst = &ifp->int_addr;
32531220Skarels if (rt = rtfind(dst)) {
32631220Skarels if (rt && rt->rt_state & RTS_INTERFACE)
32731220Skarels return;
32831220Skarels rtdelete(rt);
32931220Skarels }
33034661Skarels rtadd(dst, &loopaddr, 1, state);
3319019Ssam }
3329019Ssam
3339019Ssam /*
3349019Ssam * As a concession to the ARPANET we read a list of gateways
3359019Ssam * from /etc/gateways and add them to our tables. This file
3369019Ssam * exists at each ARPANET gateway and indicates a set of ``remote''
3379019Ssam * gateways (i.e. a gateway which we can't immediately determine
3389019Ssam * if it's present or not as we can do for those directly connected
3399019Ssam * at the hardware level). If a gateway is marked ``passive''
3409019Ssam * in the file, then we assume it doesn't have a routing process
3419019Ssam * of our design and simply assume it's always present. Those
3429019Ssam * not marked passive are treated as if they were directly
3439019Ssam * connected -- they're added into the interface list so we'll
3449019Ssam * send them routing updates.
34531220Skarels *
34631220Skarels * PASSIVE ENTRIES AREN'T NEEDED OR USED ON GATEWAYS RUNNING EGP.
3479019Ssam */
gwkludge()3489019Ssam gwkludge()
3499019Ssam {
3509019Ssam struct sockaddr_in dst, gate;
3519019Ssam FILE *fp;
3529019Ssam char *type, *dname, *gname, *qual, buf[BUFSIZ];
3539019Ssam struct interface *ifp;
35428906Skarels int metric, n;
35516327Skarels struct rt_entry route;
3569019Ssam
35737292Sbostic fp = fopen(_PATH_GATEWAYS, "r");
3589019Ssam if (fp == NULL)
3599019Ssam return;
3609019Ssam qual = buf;
3619019Ssam dname = buf + 64;
3629019Ssam gname = buf + ((BUFSIZ - 64) / 3);
3639019Ssam type = buf + (((BUFSIZ - 64) * 2) / 3);
364*69003Sbostic memset(&dst, 0, sizeof (dst));
365*69003Sbostic memset(&gate, 0, sizeof (gate));
366*69003Sbostic memset(&route, 0, sizeof(route));
36730745Skarels /* format: {net | host} XX gateway XX metric DD [passive | external]\n */
3689019Ssam #define readentry(fp) \
3699019Ssam fscanf((fp), "%s %s gateway %s metric %d %s\n", \
3709019Ssam type, dname, gname, &metric, qual)
3719019Ssam for (;;) {
37228906Skarels if ((n = readentry(fp)) == EOF)
3739019Ssam break;
37410245Ssam if (!getnetorhostname(type, dname, &dst))
3759019Ssam continue;
37610245Ssam if (!gethostnameornumber(gname, &gate))
3779019Ssam continue;
37834661Skarels if (metric == 0) /* XXX */
37934661Skarels metric = 1;
38016327Skarels if (strcmp(qual, "passive") == 0) {
38116327Skarels /*
38216327Skarels * Passive entries aren't placed in our tables,
38316327Skarels * only the kernel's, so we don't copy all of the
38416327Skarels * external routing information within a net.
38516327Skarels * Internal machines should use the default
38616327Skarels * route to a suitable gateway (like us).
38716327Skarels */
38816327Skarels route.rt_dst = *(struct sockaddr *) &dst;
38916327Skarels route.rt_router = *(struct sockaddr *) &gate;
39016327Skarels route.rt_flags = RTF_UP;
39116327Skarels if (strcmp(type, "host") == 0)
39216327Skarels route.rt_flags |= RTF_HOST;
39316327Skarels if (metric)
39416327Skarels route.rt_flags |= RTF_GATEWAY;
39552583Ssklower (void) rtioctl(ADD, &route.rt_rt);
39616327Skarels continue;
39716327Skarels }
39827231Skarels if (strcmp(qual, "external") == 0) {
39927231Skarels /*
40027231Skarels * Entries marked external are handled
40127231Skarels * by other means, e.g. EGP,
40227231Skarels * and are placed in our tables only
40327231Skarels * to prevent overriding them
40427231Skarels * with something else.
40527231Skarels */
40627231Skarels rtadd(&dst, &gate, metric, RTS_EXTERNAL|RTS_PASSIVE);
40728906Skarels continue;
40827231Skarels }
40916327Skarels /* assume no duplicate entries */
41016327Skarels externalinterfaces++;
4119019Ssam ifp = (struct interface *)malloc(sizeof (*ifp));
412*69003Sbostic memset(ifp, 0, sizeof (*ifp));
4139019Ssam ifp->int_flags = IFF_REMOTE;
4149019Ssam /* can't identify broadcast capability */
4159019Ssam ifp->int_net = inet_netof(dst.sin_addr);
4169019Ssam if (strcmp(type, "host") == 0) {
4179019Ssam ifp->int_flags |= IFF_POINTOPOINT;
4189019Ssam ifp->int_dstaddr = *((struct sockaddr *)&dst);
4199019Ssam }
4209019Ssam ifp->int_addr = *((struct sockaddr *)&gate);
4219019Ssam ifp->int_metric = metric;
4229019Ssam ifp->int_next = ifnet;
4239019Ssam ifnet = ifp;
4249019Ssam addrouteforif(ifp);
4259019Ssam }
4269019Ssam fclose(fp);
4279019Ssam }
42810245Ssam
getnetorhostname(type,name,sin)42910245Ssam getnetorhostname(type, name, sin)
43010245Ssam char *type, *name;
43110245Ssam struct sockaddr_in *sin;
43210245Ssam {
43310245Ssam
43410245Ssam if (strcmp(type, "net") == 0) {
43510245Ssam struct netent *np = getnetbyname(name);
43610245Ssam int n;
43710245Ssam
43810245Ssam if (np == 0)
43910245Ssam n = inet_network(name);
44011527Ssam else {
44111527Ssam if (np->n_addrtype != AF_INET)
44211527Ssam return (0);
44310245Ssam n = np->n_net;
44421842Skarels /*
44521842Skarels * getnetbyname returns right-adjusted value.
44621842Skarels */
44721842Skarels if (n < 128)
44821842Skarels n <<= IN_CLASSA_NSHIFT;
44921842Skarels else if (n < 65536)
45021842Skarels n <<= IN_CLASSB_NSHIFT;
45121842Skarels else
45221842Skarels n <<= IN_CLASSC_NSHIFT;
45311527Ssam }
45410245Ssam sin->sin_family = AF_INET;
45510245Ssam sin->sin_addr = inet_makeaddr(n, INADDR_ANY);
45610245Ssam return (1);
45710245Ssam }
45810245Ssam if (strcmp(type, "host") == 0) {
45910245Ssam struct hostent *hp = gethostbyname(name);
46010245Ssam
46110245Ssam if (hp == 0)
46210245Ssam sin->sin_addr.s_addr = inet_addr(name);
46311527Ssam else {
46411527Ssam if (hp->h_addrtype != AF_INET)
46511527Ssam return (0);
466*69003Sbostic memmove(&sin->sin_addr, hp->h_addr, hp->h_length);
46711527Ssam }
46810245Ssam sin->sin_family = AF_INET;
46910245Ssam return (1);
47010245Ssam }
47110245Ssam return (0);
47210245Ssam }
47310245Ssam
gethostnameornumber(name,sin)47410245Ssam gethostnameornumber(name, sin)
47510245Ssam char *name;
47610245Ssam struct sockaddr_in *sin;
47710245Ssam {
47810245Ssam struct hostent *hp;
47910245Ssam
48010245Ssam hp = gethostbyname(name);
48110245Ssam if (hp) {
482*69003Sbostic memmove(&sin->sin_addr, hp->h_addr, hp->h_length);
48310245Ssam sin->sin_family = hp->h_addrtype;
48410245Ssam return (1);
48510245Ssam }
48610245Ssam sin->sin_addr.s_addr = inet_addr(name);
48710245Ssam sin->sin_family = AF_INET;
48810245Ssam return (sin->sin_addr.s_addr != -1);
48910245Ssam }
490