Beispiel #1
0
void ifinit(void)
{
    struct interface ifs, *ifp;
    int s;
    char buf[BUFSIZ], *cp, *cplim;
    struct ifconf ifc;
    struct ifreq ifreq, *ifr;
    struct sockaddr_in *sin;
    u_long i;

    if ((s = socket(AF_INET, SOCK_DGRAM, 0)) < 0) {
        syslog(LOG_ERR, "socket: %m");
        close(s);
        return;
    }
    ifc.ifc_len = sizeof (buf);
    ifc.ifc_buf = buf;
    if (ioctl(s, SIOCGIFCONF, (char *)&ifc) < 0) {
        syslog(LOG_ERR, "ioctl (get interface configuration)");
        close(s);
        return;
    }
    ifr = ifc.ifc_req;
    lookforinterfaces = 0;
    cplim = buf + ifc.ifc_len; /*skip over if's with big ifr_addr's */
    for (cp = buf; cp < cplim;
            cp += sizeof (ifr->ifr_name) + sizeof(ifr->ifr_ifru)) {
        ifr = (struct ifreq *)cp;
        bzero((char *)&ifs, sizeof(ifs));
        ifs.int_addr = ifr->ifr_addr;
        ifreq = *ifr;
        if (ioctl(s, SIOCGIFFLAGS, (char *)&ifreq) < 0) {
            syslog(LOG_ERR, "%s: ioctl (get interface flags)",
                   ifr->ifr_name);
            continue;
        }
        ifs.int_flags =
            ifreq.ifr_flags | IFF_INTERFACE;
        if ((ifs.int_flags & IFF_UP) == 0 ||
                ifr->ifr_addr.sa_family == AF_UNSPEC) {
            lookforinterfaces = 1;
            continue;
        }
        /* argh, this'll have to change sometime */
        if (ifs.int_addr.sa_family != AF_INET)
            continue;
        if (ifs.int_flags & IFF_POINTOPOINT) {
            if (ioctl(s, SIOCGIFDSTADDR, (char *)&ifreq) < 0) {
                syslog(LOG_ERR, "%s: ioctl (get dstaddr)",
                       ifr->ifr_name);
                continue;
            }
            if (ifr->ifr_addr.sa_family == AF_UNSPEC) {
                lookforinterfaces = 1;
                continue;
            }
            ifs.int_dstaddr = ifreq.ifr_dstaddr;
        }
        /*
         * already known to us?
         * This allows multiple point-to-point links
         * to share a source address (possibly with one
         * other link), but assumes that there will not be
         * multiple links with the same destination address.
         */
        if (ifs.int_flags & IFF_POINTOPOINT) {
            if (if_ifwithdstaddr(&ifs.int_dstaddr))
                continue;
        } else if (if_ifwithaddr(&ifs.int_addr))
            continue;
        if (ifs.int_flags & IFF_LOOPBACK) {
            ifs.int_flags |= IFF_PASSIVE;
            foundloopback = 1;
            loopaddr = ifs.int_addr;
            for (ifp = ifnet; ifp; ifp = ifp->int_next)
                if (ifp->int_flags & IFF_POINTOPOINT)
                    add_ptopt_localrt(ifp);
        }
        if (ifs.int_flags & IFF_BROADCAST) {
            if (ioctl(s, SIOCGIFBRDADDR, (char *)&ifreq) < 0) {
                syslog(LOG_ERR, "%s: ioctl (get broadaddr)",
                       ifr->ifr_name);
                continue;
            }
            ifs.int_broadaddr = ifreq.ifr_broadaddr;
        }
#ifdef SIOCGIFMETRIC
        if (ioctl(s, SIOCGIFMETRIC, (char *)&ifreq) < 0) {
            syslog(LOG_ERR, "%s: ioctl (get metric)",
                   ifr->ifr_name);
            ifs.int_metric = 0;
        } else
            ifs.int_metric = ifreq.ifr_metric;
#else
        ifs.int_metric = 0;
#endif
        /*
         * Use a minimum metric of one;
         * treat the interface metric (default 0)
         * as an increment to the hop count of one.
         */
        ifs.int_metric++;
        if (ioctl(s, SIOCGIFNETMASK, (char *)&ifreq) < 0) {
            syslog(LOG_ERR, "%s: ioctl (get netmask)",
                   ifr->ifr_name);
            continue;
        }
        sin = (struct sockaddr_in *)&ifreq.ifr_addr;
        ifs.int_subnetmask = ntohl(sin->sin_addr.s_addr);
        sin = (struct sockaddr_in *)&ifs.int_addr;
        i = ntohl(sin->sin_addr.s_addr);
        if (IN_CLASSA(i))
            ifs.int_netmask = IN_CLASSA_NET;
        else if (IN_CLASSB(i))
            ifs.int_netmask = IN_CLASSB_NET;
        else
            ifs.int_netmask = IN_CLASSC_NET;
        ifs.int_net = i & ifs.int_netmask;
        ifs.int_subnet = i & ifs.int_subnetmask;
        if (ifs.int_subnetmask != ifs.int_netmask)
            ifs.int_flags |= IFF_SUBNET;
        ifp = (struct interface *)malloc(sizeof (struct interface));
        if (ifp == 0) {
            printf("routed: out of memory\n");
            break;
        }
        *ifp = ifs;
        /*
         * Count the # of directly connected networks
         * and point to point links which aren't looped
         * back to ourself.  This is used below to
         * decide if we should be a routing ``supplier''.
         */
        if ((ifs.int_flags & IFF_LOOPBACK) == 0 &&
                ((ifs.int_flags & IFF_POINTOPOINT) == 0 ||
                 if_ifwithaddr(&ifs.int_dstaddr) == 0))
            externalinterfaces++;
        /*
         * If we have a point-to-point link, we want to act
         * as a supplier even if it's our only interface,
         * as that's the only way our peer on the other end
         * can tell that the link is up.
         */
        if ((ifs.int_flags & IFF_POINTOPOINT) && supplier < 0)
            supplier = 1;
        ifp->int_name = malloc(strlen(ifr->ifr_name) + 1);
        if (ifp->int_name == 0) {
            fprintf(stderr, "routed: ifinit: out of memory\n");
            syslog(LOG_ERR, "routed: ifinit: out of memory\n");
            close(s);
            return;
        }
        strcpy(ifp->int_name, ifr->ifr_name);
        *ifnext = ifp;
        ifnext = &ifp->int_next;
        traceinit(ifp);
        addrouteforif(ifp);
    }
    if (externalinterfaces > 1 && supplier < 0)
        supplier = 1;
    close(s);
}
Beispiel #2
0
/*
 * This is called at startup and after that, every CHECK_INTERVAL seconds or
 * when a SIGHUP is received.
 */
void
initifs(void)
{
	static char *buf = NULL;
	static uint_t maxbufsize = 0;
	int bufsize;
	int numifs;
	struct lifnum lifn;
	struct lifconf lifc;
	struct lifreq lifr;
	struct lifreq *lifrp;
	int n;
	struct interface ifs;
	struct interface *ifp;
	int netmaskchange = 0;
	boolean_t changes = _B_FALSE;

	lifn.lifn_family = AF_INET6;
	lifn.lifn_flags = 0;
	if (ioctl(iocsoc, SIOCGLIFNUM, (char *)&lifn) < 0) {
		syslog(LOG_ERR, "initifs: ioctl (get interface numbers): %m");
		return;
	}
	numifs = lifn.lifn_count;
	bufsize = numifs * sizeof (struct lifreq);

	if (buf == NULL || bufsize > maxbufsize) {
		if (buf != NULL)
			free(buf);
		maxbufsize = bufsize;
		buf = (char *)malloc(maxbufsize);
		if (buf == NULL) {
			syslog(LOG_ERR, "initifs: out of memory");
			return;
		}
	}

	lifc.lifc_family = AF_INET6;
	lifc.lifc_flags = 0;
	lifc.lifc_len = bufsize;
	lifc.lifc_buf = buf;
	if (ioctl(iocsoc, SIOCGLIFCONF, (char *)&lifc) < 0) {
		syslog(LOG_ERR,
		    "initifs: ioctl (get interface configuration): %m");
		return;
	}

	/*
	 * Mark all of the currently known interfaces in order to determine
	 * which of the these interfaces no longer exist.
	 */
	for (ifp = ifnet; ifp != NULL; ifp = ifp->int_next)
		ifp->int_flags |= RIP6_IFF_MARKED;
	lifrp = lifc.lifc_req;
	for (n = lifc.lifc_len / sizeof (struct lifreq); n > 0; n--, lifrp++) {
		bzero((char *)&ifs, sizeof (ifs));
		(void) strncpy(lifr.lifr_name, lifrp->lifr_name,
		    sizeof (lifr.lifr_name));
		if (ioctl(iocsoc, SIOCGLIFFLAGS, (char *)&lifr) < 0) {
			syslog(LOG_ERR,
			    "initifs: ioctl (get interface flags): %m");
			continue;
		}
		if (!(lifr.lifr_flags & IFF_IPV6) ||
		    !(lifr.lifr_flags & IFF_MULTICAST) ||
		    (lifr.lifr_flags & IFF_LOOPBACK))
			continue;

		ifp = if_ifwithname(lifr.lifr_name);
		if (ifp != NULL)
			ifp->int_flags &= ~RIP6_IFF_MARKED;
		if (lifr.lifr_flags & IFF_POINTOPOINT)
			ifs.int_flags |= RIP6_IFF_POINTOPOINT;
		if (lifr.lifr_flags & IFF_NORTEXCH)
			ifs.int_flags |= RIP6_IFF_NORTEXCH;
		if (lifr.lifr_flags & IFF_PRIVATE)
			ifs.int_flags |= RIP6_IFF_PRIVATE;
		if (lifr.lifr_flags & IFF_UP) {
			ifs.int_flags |= RIP6_IFF_UP;
		} else {
			if (ifp != NULL) {
				if (ifp->int_flags & RIP6_IFF_UP) {
					/*
					 * If there is an transition from up to
					 * down for an exisiting interface,
					 * increment the counter.
					 */
					ifp->int_transitions++;
					changes = _B_TRUE;
				}
				if_purge(ifp);
			}
			continue;
		}

		if (ifs.int_flags & RIP6_IFF_POINTOPOINT) {
			/*
			 * For point-to-point interfaces, retrieve both the
			 * local and the remote addresses.
			 */
			if (ioctl(iocsoc, SIOCGLIFADDR, (char *)&lifr) < 0) {
				syslog(LOG_ERR,
				    "initifs: ioctl (get interface address): "
				    "%m");
				continue;
			}
			ifs.int_addr =
			    ((struct sockaddr_in6 *)&lifr.lifr_addr)->sin6_addr;
			if (ioctl(iocsoc, SIOCGLIFDSTADDR, (char *)&lifr) < 0) {
				syslog(LOG_ERR,
				    "initifs: ioctl (get destination address): "
				    "%m");
				continue;
			}
			ifs.int_dstaddr = ((struct sockaddr_in6 *)
			    &lifr.lifr_dstaddr)->sin6_addr;
			ifs.int_prefix_length = IPV6_ABITS;
		} else {
			/*
			 * For other interfaces, retreieve the prefix (including
			 * the prefix length.
			 */
			if (ioctl(iocsoc, SIOCGLIFSUBNET, (char *)&lifr) < 0) {
				syslog(LOG_ERR,
				    "initifs: ioctl (get subnet prefix): %m");
				continue;
			}
			/*
			 * This should never happen but check for it in any case
			 * since the kernel stores it as an signed integer.
			 */
			if (lifr.lifr_addrlen < 0 ||
			    lifr.lifr_addrlen > IPV6_ABITS) {
				syslog(LOG_ERR,
				    "initifs: ioctl (get subnet prefix) "
				    "returned invalid prefix length of %d",
				    lifr.lifr_addrlen);
				continue;
			}
			ifs.int_prefix_length = lifr.lifr_addrlen;
			ifs.int_addr = ((struct sockaddr_in6 *)
			    &lifr.lifr_subnet)->sin6_addr;
		}

		if (ioctl(iocsoc, SIOCGLIFMETRIC, (char *)&lifr) < 0 ||
		    lifr.lifr_metric < 0)
			ifs.int_metric = 1;
		else
			ifs.int_metric = lifr.lifr_metric + 1;

		if (ioctl(iocsoc, SIOCGLIFINDEX, (char *)&lifr) < 0) {
			syslog(LOG_ERR, "initifs: ioctl (get index): %m");
			continue;
		}
		ifs.int_ifindex = lifr.lifr_index;

		if (ioctl(iocsoc, SIOCGLIFMTU, (char *)&lifr) < 0) {
			syslog(LOG_ERR, "initifs: ioctl (get mtu): %m");
			continue;
		}

		/*
		 * If the interface's recorded MTU doesn't make sense, use
		 * IPV6_MIN_MTU instead.
		 */
		if (lifr.lifr_mtu < IPV6_MIN_MTU)
			ifs.int_mtu = IPV6_MIN_MTU;
		else
			ifs.int_mtu = lifr.lifr_mtu;

		if (ifp != NULL) {
			/*
			 * RIP6_IFF_NORTEXCH flag change by itself shouldn't
			 * cause an if_purge() call, which also purges all the
			 * routes heard off this interface. So, let's suppress
			 * changes of RIP6_IFF_NORTEXCH	in the following
			 * comparisons.
			 */
			if (ifp->int_prefix_length == ifs.int_prefix_length &&
			    ((ifp->int_flags | RIP6_IFF_NORTEXCH) ==
			    (ifs.int_flags | RIP6_IFF_NORTEXCH)) &&
			    ifp->int_metric == ifs.int_metric &&
			    ifp->int_ifindex == ifs.int_ifindex) {
				/*
				 * Now let's make sure we capture the latest
				 * value of RIP6_IFF_NORTEXCH flag.
				 */
				if (ifs.int_flags & RIP6_IFF_NORTEXCH)
					ifp->int_flags |= RIP6_IFF_NORTEXCH;
				else
					ifp->int_flags &= ~RIP6_IFF_NORTEXCH;

				if (!(ifp->int_flags & RIP6_IFF_POINTOPOINT) &&
				    IN6_ARE_ADDR_EQUAL(&ifp->int_addr,
					&ifs.int_addr))
					continue;
				if ((ifp->int_flags & RIP6_IFF_POINTOPOINT) &&
				    IN6_ARE_ADDR_EQUAL(&ifp->int_dstaddr,
					&ifs.int_dstaddr))
					continue;
			}
			if_purge(ifp);
			if (ifp->int_prefix_length != ifs.int_prefix_length)
				netmaskchange = 1;
			ifp->int_addr = ifs.int_addr;
			ifp->int_dstaddr = ifs.int_dstaddr;
			ifp->int_metric = ifs.int_metric;
			/*
			 * If there is an transition from down to up for an
			 * exisiting interface, increment the counter.
			 */
			if (!(ifp->int_flags & RIP6_IFF_UP) &&
			    (ifs.int_flags & RIP6_IFF_UP))
				ifp->int_transitions++;
			ifp->int_flags |= ifs.int_flags;
			ifp->int_prefix_length = ifs.int_prefix_length;

			/*
			 * If the interface index has changed, we may need to
			 * set up the listen socket again.
			 */
			if (ifp->int_ifindex != ifs.int_ifindex) {
				if (ifp->int_sock != -1) {
					resetup_listen_sock(ifp,
					    ifs.int_ifindex);
				}
				ifp->int_ifindex = ifs.int_ifindex;
			}

			ifp->int_mtu = ifs.int_mtu;
		} else {
			char *cp;
			int log_num;

			ifp = (struct interface *)
			    malloc(sizeof (struct interface));
			if (ifp == NULL) {
				syslog(LOG_ERR, "initifs: out of memory");
				return;
			}
			*ifp = ifs;
			ifp->int_name = ifp->int_ifbase = NULL;
			ifp->int_name =
			    (char *)malloc((size_t)strlen(lifr.lifr_name) + 1);
			if (ifp->int_name == NULL) {
				free(ifp);
				syslog(LOG_ERR, "initifs: out of memory");
				return;
			}
			(void) strcpy(ifp->int_name, lifr.lifr_name);
			ifp->int_ifbase =
			    (char *)malloc((size_t)strlen(lifr.lifr_name) + 1);
			if (ifp->int_ifbase == NULL) {
				free(ifp->int_name);
				free(ifp);
				syslog(LOG_ERR, "initifs: out of memory");
				return;
			}
			(void) strcpy(ifp->int_ifbase, lifr.lifr_name);
			cp = (char *)index(ifp->int_ifbase, IF_SEPARATOR);
			if (cp != NULL) {
				/*
				 * Verify that the value following the separator
				 * is an integer greater than zero (the only
				 * possible value for a logical interface).
				 */
				log_num = atoi((char *)(cp + 1));
				if (log_num <= 0) {
					free(ifp->int_ifbase);
					free(ifp->int_name);
					free(ifp);
					syslog(LOG_ERR,
					    "initifs: interface name %s could "
					    "not be parsed", ifp->int_name);
					return;
				}
				*cp = '\0';
			} else {
				log_num = 0;
			}
			if (log_num == 0) {
				ifp->int_sock =
				    setup_listen_sock(ifp->int_ifindex);
			} else {
				ifp->int_sock = -1;
			}
			ifp->int_next = ifnet;
			ifnet = ifp;
			traceinit(ifp);
		}
		addrouteforif(ifp);
		changes = _B_TRUE;
	}

	/*
	 * Any remaining interfaces that are still marked and which were in an
	 * up state (RIP6_IFF_UP) need to removed from the routing table.
	 */
	for (ifp = ifnet; ifp != NULL; ifp = ifp->int_next) {
		if ((ifp->int_flags & (RIP6_IFF_MARKED | RIP6_IFF_UP)) ==
		    (RIP6_IFF_MARKED | RIP6_IFF_UP)) {
			if_purge(ifp);
			ifp->int_flags &= ~RIP6_IFF_MARKED;
			changes = _B_TRUE;
		}
	}
	if (netmaskchange)
		rtchangeall();
	if (supplier & changes)
		dynamic_update((struct interface *)NULL);
}
Beispiel #3
0
void gwkludge(void)
{
    struct sockaddr_in dst, gate;
    FILE *fp;
    char *type, *dname, *gname, *qual, buf[BUFSIZ];
    struct interface *ifp;
    int metric, n;
    struct rt_entry route;

    fp = fopen(_PATH_GATEWAYS, "r");
    if (fp == NULL)
        return;
    qual = buf;
    dname = buf + 64;
    gname = buf + ((BUFSIZ - 64) / 3);
    type = buf + (((BUFSIZ - 64) * 2) / 3);
    memset(&dst, 0, sizeof (dst));
    memset(&gate, 0, sizeof (gate));
    memset(&route, 0, sizeof(route));
    /* format: {net | host} XX gateway XX metric DD [passive | external]\n */
#define	readentry(fp) \
	fscanf((fp), "%s %s gateway %s metric %d %s\n", \
		type, dname, gname, &metric, qual)
    for (;;) {
        if ((n = readentry(fp)) == EOF)
            break;
        /*
         *	Lusertrap. Vendors should ship the line
         *
         *	CONFIGME CONFIGME gateway CONFIGME metric 1
         *
         */
        if (strcmp(type,"CONFIGME")==0)
        {
            fprintf(stderr,"Not starting gated. Please configure first.\n");
            exit(1);
        }
        if (!getnetorhostname(type, dname, &dst))
            continue;
        if (!gethostnameornumber(gname, &gate))
            continue;
        if (metric == 0)			/* XXX */
            metric = 1;
        if (strcmp(qual, "passive") == 0) {
            /*
             * Passive entries aren't placed in our tables,
             * only the kernel's, so we don't copy all of the
             * external routing information within a net.
             * Internal machines should use the default
             * route to a suitable gateway (like us).
             */
            route.rt_dst = *(struct sockaddr *) &dst;
            route.rt_router = *(struct sockaddr *) &gate;
            route.rt_flags = RTF_UP;
            if (strcmp(type, "host") == 0)
                route.rt_flags |= RTF_HOST;
            if (metric)
                route.rt_flags |= RTF_GATEWAY;
            (void) rtioctl(ADD, &route.rt_rt);
            continue;
        }
        if (strcmp(qual, "external") == 0) {
            /*
             * Entries marked external are handled
             * by other means, e.g. EGP,
             * and are placed in our tables only
             * to prevent overriding them
             * with something else.
             */
            rtadd((struct sockaddr *)&dst,
                  (struct sockaddr *)&gate, metric,
                  RTS_EXTERNAL|RTS_PASSIVE);
            continue;
        }
        /* assume no duplicate entries */
        externalinterfaces++;
        ifp = (struct interface *)malloc(sizeof (*ifp));
        memset(ifp, 0, sizeof (*ifp));
        ifp->int_flags = IFF_REMOTE;
        /* can't identify broadcast capability */
        ifp->int_net = inet_netof_subnet(dst.sin_addr);
        if (strcmp(type, "host") == 0) {
            ifp->int_flags |= IFF_POINTOPOINT;
            ifp->int_dstaddr = *((struct sockaddr *)&dst);
        }
        ifp->int_addr = *((struct sockaddr *)&gate);
        ifp->int_metric = metric;
        ifp->int_next = ifnet;
        ifnet = ifp;
        addrouteforif(ifp);
    }
    fclose(fp);
}
Beispiel #4
0
/*
 * Find the network interfaces which have configured themselves.
 * If the interface is present but not yet up (for example an
 * ARPANET IMP), set the lookforinterfaces flag so we'll
 * come back later and look again.
 */
void
ifinit(void)
{
	struct interface ifs, *ifp;
	size_t needed;
	int mib[6], no_ipxaddr = 0, flags = 0;
	char *buf, *cplim, *cp;
	struct if_msghdr *ifm;
	struct ifa_msghdr *ifam;
	struct sockaddr_dl *sdl = NULL;

        mib[0] = CTL_NET;
        mib[1] = PF_ROUTE;
        mib[2] = 0;
        mib[3] = AF_IPX;
        mib[4] = NET_RT_IFLIST;
        mib[5] = 0;
        if (sysctl(mib, 6, NULL, &needed, NULL, 0) < 0)
                quit("route-sysctl-estimate");
	if ((buf = malloc(needed)) == NULL)
		quit("malloc");
        if (sysctl(mib, 6, buf, &needed, NULL, 0) < 0)
		lookforinterfaces = 0;
	cplim = buf + needed;
	for (cp = buf; cp < cplim; cp += ifm->ifm_msglen) {
		ifm = (struct if_msghdr *)cp;
		if (ifm->ifm_type == RTM_IFINFO) {
			bzero(&ifs, sizeof(ifs));
			ifs.int_flags = flags = ifm->ifm_flags | IFF_INTERFACE;
			if ((flags & IFF_UP) == 0 || no_ipxaddr)
				lookforinterfaces = 1;
			sdl = (struct sockaddr_dl *) (ifm + 1);
			sdl->sdl_data[sdl->sdl_nlen] = 0;
			no_ipxaddr = 1;
			continue;
		}
		if (ifm->ifm_type != RTM_NEWADDR)
			quit("ifinit: out of sync");
		if ((flags & IFF_UP) == 0)
			continue;
		ifam = (struct ifa_msghdr *)ifm;
		info.rti_addrs = ifam->ifam_addrs;
		rt_xaddrs((char *)(ifam + 1), cp + ifam->ifam_msglen, &info);
		if (ifaaddr == 0) {
			syslog(LOG_ERR, "%s: (get addr)", sdl->sdl_data);
			continue;
		}
		ifs.int_addr = *ifaaddr;
		if (ifs.int_addr.sa_family != AF_IPX)
			continue;
		no_ipxaddr = 0;
		if (ifs.int_flags & IFF_POINTOPOINT) {
			if (brdaddr == 0) {
				syslog(LOG_ERR, "%s: (get dstaddr)",
					sdl->sdl_data);
				continue;
			}
			if (brdaddr->sa_family == AF_UNSPEC) {
				lookforinterfaces = 1;
				continue;
			}
			ifs.int_dstaddr = *brdaddr;
		}
		if (ifs.int_flags & IFF_BROADCAST) {
			if (brdaddr == 0) {
				syslog(LOG_ERR, "%s: (get broadaddr)",
					sdl->sdl_data);
				continue;
			}
			ifs.int_dstaddr = *brdaddr;
		}
		if (ifs.int_flags & IFF_LOOPBACK) {
			ifs.int_dstaddr = ifs.int_addr;
		}
		/* 
		 * already known to us? 
		 * what makes a POINTOPOINT if unique is its dst addr,
		 * NOT its source address 
		 */
		if ( ((ifs.int_flags & IFF_POINTOPOINT) &&
			if_ifwithdstaddr(&ifs.int_dstaddr)) ||
			( ((ifs.int_flags & IFF_POINTOPOINT) == 0) &&
			if_ifwithaddr(&ifs.int_addr)))
			continue;
		ifp = (struct interface *)
			malloc(sdl->sdl_nlen + 1 + sizeof(ifs));
		if (ifp == NULL) {
			syslog(LOG_ERR, "IPXrouted: out of memory\n");
			lookforinterfaces = 1;
			break;
		}
		*ifp = ifs;
		/*
		 * Count the # of directly connected networks
		 * and point to point links which aren't looped
		 * back to ourself.  This is used below to
		 * decide if we should be a routing ``supplier''.
		 */
		if ((ifs.int_flags & IFF_POINTOPOINT) == 0 ||
		    if_ifwithaddr(&ifs.int_dstaddr) == 0)
			externalinterfaces++;
		/*
		 * If we have a point-to-point link, we want to act
		 * as a supplier even if it's our only interface,
		 * as that's the only way our peer on the other end
		 * can tell that the link is up.
		 */
		if ((ifs.int_flags & IFF_POINTOPOINT) && supplier < 0)
			supplier = 1;
		ifp->int_name = (char *)(ifp + 1);
		strcpy(ifp->int_name, sdl->sdl_data);

		ifp->int_metric = ifam->ifam_metric;
		ifp->int_next = ifnet;
		ifnet = ifp;
		traceinit(ifp);
		addrouteforif(ifp);
	}
	if (externalinterfaces > 1 && supplier < 0)
		supplier = 1;
	free(buf);
}