111820Sjulian/* 211820Sjulian * Copyright (c) 1985, 1993 311820Sjulian * The Regents of the University of California. All rights reserved. 411820Sjulian * 511820Sjulian * Copyright (c) 1995 John Hay. All rights reserved. 611820Sjulian * 711820Sjulian * This file includes significant work done at Cornell University by 811820Sjulian * Bill Nesheim. That work included by permission. 911820Sjulian * 1011820Sjulian * Redistribution and use in source and binary forms, with or without 1111820Sjulian * modification, are permitted provided that the following conditions 1211820Sjulian * are met: 1311820Sjulian * 1. Redistributions of source code must retain the above copyright 1411820Sjulian * notice, this list of conditions and the following disclaimer. 1511820Sjulian * 2. Redistributions in binary form must reproduce the above copyright 1611820Sjulian * notice, this list of conditions and the following disclaimer in the 1711820Sjulian * documentation and/or other materials provided with the distribution. 1811820Sjulian * 3. All advertising materials mentioning features or use of this software 1911820Sjulian * must display the following acknowledgement: 2011820Sjulian * This product includes software developed by the University of 2111820Sjulian * California, Berkeley and its contributors. 2211820Sjulian * 4. Neither the name of the University nor the names of its contributors 2311820Sjulian * may be used to endorse or promote products derived from this software 2411820Sjulian * without specific prior written permission. 2511820Sjulian * 2611820Sjulian * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 2711820Sjulian * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 2811820Sjulian * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 2911820Sjulian * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 3011820Sjulian * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 3111820Sjulian * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 3211820Sjulian * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 3311820Sjulian * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 3411820Sjulian * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 3511820Sjulian * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 3611820Sjulian * SUCH DAMAGE. 3711820Sjulian * 3850479Speter * $FreeBSD$ 3911820Sjulian */ 4011820Sjulian 4111820Sjulian#ifndef lint 42122760Strhodesstatic const char sccsid[] = "@(#)startup.c 8.1 (Berkeley) 6/5/93"; 4311820Sjulian#endif /* not lint */ 4411820Sjulian 4511820Sjulian/* 4611820Sjulian * Routing Table Management Daemon 4711820Sjulian */ 4811820Sjulian#include "defs.h" 4911820Sjulian 5011820Sjulian#include <sys/param.h> 5111820Sjulian#include <sys/ioctl.h> 5211820Sjulian#include <sys/sysctl.h> 5320287Swollman#include <sys/time.h> 5411820Sjulian 5511820Sjulian#include <net/if.h> 5611820Sjulian#include <net/if_dl.h> 5711820Sjulian 5859218Simp#include <errno.h> 5911820Sjulian#include <nlist.h> 60122760Strhodes#include <search.h> 6111820Sjulian#include <stdlib.h> 6211820Sjulian 6311820Sjulianstruct interface *ifnet; 6411820Sjulianint lookforinterfaces = 1; 6511820Sjulianint performnlist = 1; 6611820Sjulianint gateway = 0; 6711820Sjulianint externalinterfaces = 0; /* # of remote and local interfaces */ 6811820Sjulian 6911820Sjulianvoid 7011820Sjulianquit(s) 7111820Sjulian char *s; 7211820Sjulian{ 7311820Sjulian int sverrno = errno; 7411820Sjulian 7511820Sjulian (void) fprintf(stderr, "IPXroute: "); 7611820Sjulian if (s) 7711820Sjulian (void) fprintf(stderr, "%s: ", s); 7811820Sjulian (void) fprintf(stderr, "%s\n", strerror(sverrno)); 7911820Sjulian exit(1); 8011820Sjulian /* NOTREACHED */ 8111820Sjulian} 8211820Sjulian 8311820Sjulianstruct rt_addrinfo info; 84128186Sluigi/* XXX Sleazy use of local variables throughout file, warning!!!! */ 8511820Sjulian#define netmask info.rti_info[RTAX_NETMASK] 8611820Sjulian#define ifaaddr info.rti_info[RTAX_IFA] 8711820Sjulian#define brdaddr info.rti_info[RTAX_BRD] 8811820Sjulian 8911820Sjulianvoid 9011820Sjulianrt_xaddrs(cp, cplim, rtinfo) 9111820Sjulian register caddr_t cp, cplim; 9211820Sjulian register struct rt_addrinfo *rtinfo; 9311820Sjulian{ 9411820Sjulian register struct sockaddr *sa; 9511820Sjulian register int i; 9611820Sjulian 9711820Sjulian bzero(rtinfo->rti_info, sizeof(rtinfo->rti_info)); 9811820Sjulian for (i = 0; (i < RTAX_MAX) && (cp < cplim); i++) { 9911820Sjulian if ((rtinfo->rti_addrs & (1 << i)) == 0) 10011820Sjulian continue; 10111820Sjulian rtinfo->rti_info[i] = sa = (struct sockaddr *)cp; 102128186Sluigi cp += SA_SIZE(sa); 10311820Sjulian } 10411820Sjulian} 10511820Sjulian 10611820Sjulian/* 10711820Sjulian * Find the network interfaces which have configured themselves. 10811820Sjulian * If the interface is present but not yet up (for example an 10911820Sjulian * ARPANET IMP), set the lookforinterfaces flag so we'll 11011820Sjulian * come back later and look again. 11111820Sjulian */ 11211820Sjulianvoid 11311820Sjulianifinit(void) 11411820Sjulian{ 11511820Sjulian struct interface ifs, *ifp; 11611820Sjulian size_t needed; 11711820Sjulian int mib[6], no_ipxaddr = 0, flags = 0; 11811820Sjulian char *buf, *cplim, *cp; 11911820Sjulian register struct if_msghdr *ifm; 12011820Sjulian register struct ifa_msghdr *ifam; 12111820Sjulian struct sockaddr_dl *sdl = 0; 12211820Sjulian 12311820Sjulian mib[0] = CTL_NET; 12411820Sjulian mib[1] = PF_ROUTE; 12511820Sjulian mib[2] = 0; 12611820Sjulian mib[3] = AF_IPX; 12711820Sjulian mib[4] = NET_RT_IFLIST; 12811820Sjulian mib[5] = 0; 12911820Sjulian if (sysctl(mib, 6, NULL, &needed, NULL, 0) < 0) 13011820Sjulian quit("route-sysctl-estimate"); 13111820Sjulian if ((buf = malloc(needed)) == NULL) 13211820Sjulian quit("malloc"); 13311820Sjulian if (sysctl(mib, 6, buf, &needed, NULL, 0) < 0) 13411820Sjulian lookforinterfaces = 0; 13511820Sjulian cplim = buf + needed; 13611820Sjulian for (cp = buf; cp < cplim; cp += ifm->ifm_msglen) { 13711820Sjulian ifm = (struct if_msghdr *)cp; 13811820Sjulian if (ifm->ifm_type == RTM_IFINFO) { 13911820Sjulian bzero(&ifs, sizeof(ifs)); 14011820Sjulian ifs.int_flags = flags = ifm->ifm_flags | IFF_INTERFACE; 14111820Sjulian if ((flags & IFF_UP) == 0 || no_ipxaddr) 14211820Sjulian lookforinterfaces = 1; 14311820Sjulian sdl = (struct sockaddr_dl *) (ifm + 1); 14411820Sjulian sdl->sdl_data[sdl->sdl_nlen] = 0; 14511820Sjulian no_ipxaddr = 1; 14611820Sjulian continue; 14711820Sjulian } 14811820Sjulian if (ifm->ifm_type != RTM_NEWADDR) 14911820Sjulian quit("ifinit: out of sync"); 15011820Sjulian if ((flags & IFF_UP) == 0) 15111820Sjulian continue; 15211820Sjulian ifam = (struct ifa_msghdr *)ifm; 15311820Sjulian info.rti_addrs = ifam->ifam_addrs; 15411820Sjulian rt_xaddrs((char *)(ifam + 1), cp + ifam->ifam_msglen, &info); 15511820Sjulian if (ifaaddr == 0) { 15611820Sjulian syslog(LOG_ERR, "%s: (get addr)", sdl->sdl_data); 15711820Sjulian continue; 15811820Sjulian } 15911820Sjulian ifs.int_addr = *ifaaddr; 16011820Sjulian if (ifs.int_addr.sa_family != AF_IPX) 16111820Sjulian continue; 16211820Sjulian no_ipxaddr = 0; 16311820Sjulian if (ifs.int_flags & IFF_POINTOPOINT) { 16411820Sjulian if (brdaddr == 0) { 16511820Sjulian syslog(LOG_ERR, "%s: (get dstaddr)", 16611820Sjulian sdl->sdl_data); 16711820Sjulian continue; 16811820Sjulian } 16911820Sjulian if (brdaddr->sa_family == AF_UNSPEC) { 17011820Sjulian lookforinterfaces = 1; 17111820Sjulian continue; 17211820Sjulian } 17311820Sjulian ifs.int_dstaddr = *brdaddr; 17411820Sjulian } 17511820Sjulian if (ifs.int_flags & IFF_BROADCAST) { 17611820Sjulian if (brdaddr == 0) { 17711820Sjulian syslog(LOG_ERR, "%s: (get broadaddr)", 17811820Sjulian sdl->sdl_data); 17911820Sjulian continue; 18011820Sjulian } 18111820Sjulian ifs.int_dstaddr = *brdaddr; 18211820Sjulian } 18343713Sjhay if (ifs.int_flags & IFF_LOOPBACK) { 18443713Sjhay ifs.int_dstaddr = ifs.int_addr; 18543713Sjhay } 18611820Sjulian /* 18711820Sjulian * already known to us? 18811820Sjulian * what makes a POINTOPOINT if unique is its dst addr, 18911820Sjulian * NOT its source address 19011820Sjulian */ 19111820Sjulian if ( ((ifs.int_flags & IFF_POINTOPOINT) && 19211820Sjulian if_ifwithdstaddr(&ifs.int_dstaddr)) || 19311820Sjulian ( ((ifs.int_flags & IFF_POINTOPOINT) == 0) && 19411820Sjulian if_ifwithaddr(&ifs.int_addr))) 19511820Sjulian continue; 19611820Sjulian ifp = (struct interface *) 19711820Sjulian malloc(sdl->sdl_nlen + 1 + sizeof(ifs)); 19811820Sjulian if (ifp == 0) { 19911820Sjulian syslog(LOG_ERR, "IPXrouted: out of memory\n"); 20011820Sjulian lookforinterfaces = 1; 20111820Sjulian break; 20211820Sjulian } 20311820Sjulian *ifp = ifs; 20411820Sjulian /* 20511820Sjulian * Count the # of directly connected networks 20611820Sjulian * and point to point links which aren't looped 20711820Sjulian * back to ourself. This is used below to 20811820Sjulian * decide if we should be a routing ``supplier''. 20911820Sjulian */ 21011820Sjulian if ((ifs.int_flags & IFF_POINTOPOINT) == 0 || 21111820Sjulian if_ifwithaddr(&ifs.int_dstaddr) == 0) 21211820Sjulian externalinterfaces++; 21311820Sjulian /* 21411820Sjulian * If we have a point-to-point link, we want to act 21511820Sjulian * as a supplier even if it's our only interface, 21611820Sjulian * as that's the only way our peer on the other end 21711820Sjulian * can tell that the link is up. 21811820Sjulian */ 21911820Sjulian if ((ifs.int_flags & IFF_POINTOPOINT) && supplier < 0) 22011820Sjulian supplier = 1; 22111820Sjulian ifp->int_name = (char *)(ifp + 1); 22211820Sjulian strcpy(ifp->int_name, sdl->sdl_data); 22311820Sjulian 22411820Sjulian ifp->int_metric = ifam->ifam_metric; 22511820Sjulian ifp->int_next = ifnet; 22611820Sjulian ifnet = ifp; 22711820Sjulian traceinit(ifp); 22811820Sjulian addrouteforif(ifp); 22911820Sjulian } 23011820Sjulian if (externalinterfaces > 1 && supplier < 0) 23111820Sjulian supplier = 1; 23211820Sjulian free(buf); 23311820Sjulian} 23411820Sjulian 23511820Sjulianvoid 23611820Sjulianaddrouteforif(ifp) 23711820Sjulian struct interface *ifp; 23811820Sjulian{ 23914165Sjulian struct sockaddr_ipx net; 24011820Sjulian struct sockaddr *dst; 24111820Sjulian struct rt_entry *rt; 24211820Sjulian 24311820Sjulian if (ifp->int_flags & IFF_POINTOPOINT) { 24411820Sjulian int (*match)(); 24511820Sjulian register struct interface *ifp2 = ifnet; 24611820Sjulian 24711820Sjulian dst = &ifp->int_dstaddr; 24811820Sjulian 24911820Sjulian /* Search for interfaces with the same net */ 25011820Sjulian ifp->int_sq.n = ifp->int_sq.p = &(ifp->int_sq); 25111820Sjulian match = afswitch[dst->sa_family].af_netmatch; 25211820Sjulian if (match) 25311820Sjulian for (ifp2 = ifnet; ifp2; ifp2 =ifp2->int_next) { 254122760Strhodes if ((ifp->int_flags & IFF_POINTOPOINT) == 0) 25511820Sjulian continue; 25611820Sjulian if ((*match)(&ifp2->int_dstaddr,&ifp->int_dstaddr)) { 25711820Sjulian insque(&ifp2->int_sq,&ifp->int_sq); 25811820Sjulian break; 25911820Sjulian } 26011820Sjulian } 26111820Sjulian } else { 26214165Sjulian bzero(&net, sizeof(net)); 26314165Sjulian net.sipx_family = AF_IPX; 26414165Sjulian net.sipx_len = sizeof (net); 26514165Sjulian net.sipx_addr.x_net = satoipx_addr(ifp->int_broadaddr).x_net; 26614165Sjulian dst = (struct sockaddr *)&net; 26711820Sjulian } 26811820Sjulian rt = rtlookup(dst); 26911820Sjulian if (rt) 27011820Sjulian rtdelete(rt); 27111820Sjulian if (tracing) 27211820Sjulian fprintf(stderr, "Adding route to interface %s\n", ifp->int_name); 27311820Sjulian if (ifp->int_transitions++ > 0) 27411820Sjulian syslog(LOG_ERR, "re-installing interface %s", ifp->int_name); 27511820Sjulian rtadd(dst, &ifp->int_addr, ifp->int_metric, 0, 27611820Sjulian ifp->int_flags & (IFF_INTERFACE|IFF_PASSIVE|IFF_REMOTE)); 27711820Sjulian} 27811820Sjulian 279