124322Ssklower /* 235551Sbostic * Copyright (c) 1985 The Regents of the University of California. 335551Sbostic * All rights reserved. 424322Ssklower * 535551Sbostic * This file includes significant work done at Cornell University by 635551Sbostic * Bill Nesheim. That work included by permission. 735551Sbostic * 842698Sbostic * %sccs.include.redist.c% 924322Ssklower */ 1024322Ssklower 1124312Ssklower #ifndef lint 12*59578Sbostic static char sccsid[] = "@(#)startup.c 5.14 (Berkeley) 04/30/93"; 1335551Sbostic #endif /* not lint */ 1424312Ssklower 1524312Ssklower /* 1624312Ssklower * Routing Table Management Daemon 1724312Ssklower */ 1824312Ssklower #include "defs.h" 19*59578Sbostic 20*59578Sbostic #include <sys/param.h> 2124312Ssklower #include <sys/ioctl.h> 2258928Smckusick #include <sys/sysctl.h> 23*59578Sbostic 2424312Ssklower #include <net/if.h> 2552623Ssklower #include <net/if_dl.h> 26*59578Sbostic 2724312Ssklower #include <nlist.h> 2846705Sbostic #include <stdlib.h> 2924312Ssklower 3024312Ssklower struct interface *ifnet; 3124312Ssklower int lookforinterfaces = 1; 3224312Ssklower int performnlist = 1; 3326170Ssklower int gateway = 0; 3424312Ssklower int externalinterfaces = 0; /* # of remote and local interfaces */ 3524312Ssklower char ether_broadcast_addr[6] = {0xff, 0xff, 0xff, 0xff, 0xff, 0xff}; 3624312Ssklower 3724312Ssklower 3852623Ssklower void 3952623Ssklower quit(s) 4052623Ssklower char *s; 4152623Ssklower { 4252623Ssklower extern int errno; 4352623Ssklower int sverrno = errno; 4452623Ssklower 4552623Ssklower (void) fprintf(stderr, "route: "); 4652623Ssklower if (s) 4752623Ssklower (void) fprintf(stderr, "%s: ", s); 4852623Ssklower (void) fprintf(stderr, "%s\n", strerror(sverrno)); 4952623Ssklower exit(1); 5052623Ssklower /* NOTREACHED */ 5152623Ssklower } 5252623Ssklower 5352623Ssklower struct rt_addrinfo info; 5452623Ssklower /* Sleazy use of local variables throughout file, warning!!!! */ 5552623Ssklower #define netmask info.rti_info[RTAX_NETMASK] 5652623Ssklower #define ifaaddr info.rti_info[RTAX_IFA] 5752623Ssklower #define brdaddr info.rti_info[RTAX_BRD] 5852623Ssklower 5952623Ssklower #define ROUNDUP(a) \ 6052623Ssklower ((a) > 0 ? (1 + (((a) - 1) | (sizeof(long) - 1))) : sizeof(long)) 6152623Ssklower #define ADVANCE(x, n) (x += ROUNDUP((n)->sa_len)) 6252623Ssklower 6352623Ssklower void 6452623Ssklower rt_xaddrs(cp, cplim, rtinfo) 6552623Ssklower register caddr_t cp, cplim; 6652623Ssklower register struct rt_addrinfo *rtinfo; 6752623Ssklower { 6852623Ssklower register struct sockaddr *sa; 6952623Ssklower register int i; 7052623Ssklower 7152623Ssklower bzero(rtinfo->rti_info, sizeof(rtinfo->rti_info)); 7252623Ssklower for (i = 0; (i < RTAX_MAX) && (cp < cplim); i++) { 7352623Ssklower if ((rtinfo->rti_addrs & (1 << i)) == 0) 7452623Ssklower continue; 7552623Ssklower rtinfo->rti_info[i] = sa = (struct sockaddr *)cp; 7652623Ssklower ADVANCE(cp, sa); 7752623Ssklower } 7852623Ssklower } 7952623Ssklower 8024312Ssklower /* 8124317Ssklower * Find the network interfaces which have configured themselves. 8224317Ssklower * If the interface is present but not yet up (for example an 8324312Ssklower * ARPANET IMP), set the lookforinterfaces flag so we'll 8424312Ssklower * come back later and look again. 8524312Ssklower */ 8624312Ssklower ifinit() 8724312Ssklower { 8824317Ssklower struct interface ifs, *ifp; 8958928Smckusick size_t needed; 9058928Smckusick int mib[6], no_nsaddr = 0, flags = 0; 9152623Ssklower char *buf, *cplim, *cp; 9252623Ssklower register struct if_msghdr *ifm; 9352623Ssklower register struct ifa_msghdr *ifam; 9452623Ssklower struct sockaddr_dl *sdl; 9524317Ssklower u_long i; 9624312Ssklower 9758928Smckusick mib[0] = CTL_NET; 9858928Smckusick mib[1] = PF_ROUTE; 9958928Smckusick mib[2] = 0; 10058928Smckusick mib[3] = AF_NS; 10158928Smckusick mib[4] = NET_RT_IFLIST; 10258928Smckusick mib[5] = 0; 10358928Smckusick if (sysctl(mib, 6, NULL, &needed, NULL, 0) < 0) 10458928Smckusick quit("route-sysctl-estimate"); 10552623Ssklower if ((buf = malloc(needed)) == NULL) 10652623Ssklower quit("malloc"); 10758928Smckusick if (sysctl(mib, 6, buf, &needed, NULL, 0) < 0) 10824312Ssklower lookforinterfaces = 0; 10958928Smckusick cplim = buf + needed; 11052623Ssklower for (cp = buf; cp < cplim; cp += ifm->ifm_msglen) { 11152623Ssklower ifm = (struct if_msghdr *)cp; 11252623Ssklower if (ifm->ifm_type == RTM_IFINFO) { 11352623Ssklower bzero(&ifs, sizeof(ifs)); 11452623Ssklower ifs.int_flags = flags = ifm->ifm_flags | IFF_INTERFACE; 11552623Ssklower if ((flags & IFF_UP) == 0 || no_nsaddr) 11652623Ssklower lookforinterfaces = 1; 11752623Ssklower sdl = (struct sockaddr_dl *) (ifm + 1); 11852623Ssklower sdl->sdl_data[sdl->sdl_nlen] = 0; 11952623Ssklower no_nsaddr = 1; 12024312Ssklower continue; 12124312Ssklower } 12252623Ssklower if (ifm->ifm_type != RTM_NEWADDR) 12352623Ssklower quit("ifinit: out of sync"); 12452623Ssklower if ((flags & IFF_UP) == 0) 12552623Ssklower continue; 12652623Ssklower ifam = (struct ifa_msghdr *)ifm; 12752623Ssklower info.rti_addrs = ifam->ifam_addrs; 12852623Ssklower rt_xaddrs((char *)(ifam + 1), cp + ifam->ifam_msglen, &info); 12952623Ssklower if (ifaaddr == 0) { 13052623Ssklower syslog(LOG_ERR, "%s: (get addr)", sdl->sdl_data); 13152623Ssklower continue; 13252623Ssklower } 13352623Ssklower ifs.int_addr = *ifaaddr; 13424317Ssklower if (ifs.int_addr.sa_family != AF_NS) 13524317Ssklower continue; 13652623Ssklower no_nsaddr = 0; 13752623Ssklower if (ifs.int_flags & IFF_POINTOPOINT) { 13852623Ssklower if (brdaddr == 0) { 13952623Ssklower syslog(LOG_ERR, "%s: (get dstaddr)", 14052623Ssklower sdl->sdl_data); 14152623Ssklower continue; 14224317Ssklower } 14352623Ssklower if (brdaddr->sa_family == AF_UNSPEC) { 14452623Ssklower lookforinterfaces = 1; 14552623Ssklower continue; 14652623Ssklower } 14752623Ssklower ifs.int_dstaddr = *brdaddr; 14824312Ssklower } 14952623Ssklower if (ifs.int_flags & IFF_BROADCAST) { 15052623Ssklower if (brdaddr == 0) { 15152623Ssklower syslog(LOG_ERR, "%s: (get broadaddr)", 15252623Ssklower sdl->sdl_data); 15352623Ssklower continue; 15452623Ssklower } 15552623Ssklower ifs.int_dstaddr = *brdaddr; 15624317Ssklower } 15726170Ssklower /* 15826170Ssklower * already known to us? 15926170Ssklower * what makes a POINTOPOINT if unique is its dst addr, 16026170Ssklower * NOT its source address 16126170Ssklower */ 16226170Ssklower if ( ((ifs.int_flags & IFF_POINTOPOINT) && 16326170Ssklower if_ifwithdstaddr(&ifs.int_dstaddr)) || 16426170Ssklower ( ((ifs.int_flags & IFF_POINTOPOINT) == 0) && 16526170Ssklower if_ifwithaddr(&ifs.int_addr))) 16626170Ssklower continue; 16724317Ssklower /* no one cares about software loopback interfaces */ 16852623Ssklower if (ifs.int_flags & IFF_LOOPBACK) 16924317Ssklower continue; 17052623Ssklower ifp = (struct interface *) 17152623Ssklower malloc(sdl->sdl_nlen + 1 + sizeof(ifs)); 17224312Ssklower if (ifp == 0) { 17352623Ssklower syslog(LOG_ERR, "XNSrouted: out of memory\n"); 17452623Ssklower lookforinterfaces = 1; 17524312Ssklower break; 17624312Ssklower } 17724317Ssklower *ifp = ifs; 17824312Ssklower /* 17924312Ssklower * Count the # of directly connected networks 18024312Ssklower * and point to point links which aren't looped 18124312Ssklower * back to ourself. This is used below to 18224312Ssklower * decide if we should be a routing ``supplier''. 18324312Ssklower */ 18424317Ssklower if ((ifs.int_flags & IFF_POINTOPOINT) == 0 || 18524317Ssklower if_ifwithaddr(&ifs.int_dstaddr) == 0) 18624312Ssklower externalinterfaces++; 18726170Ssklower /* 18826170Ssklower * If we have a point-to-point link, we want to act 18926170Ssklower * as a supplier even if it's our only interface, 19026170Ssklower * as that's the only way our peer on the other end 19126170Ssklower * can tell that the link is up. 19226170Ssklower */ 19326170Ssklower if ((ifs.int_flags & IFF_POINTOPOINT) && supplier < 0) 19426170Ssklower supplier = 1; 19552623Ssklower ifp->int_name = (char *)(ifp + 1); 19652623Ssklower strcpy(ifp->int_name, sdl->sdl_data); 19752623Ssklower ifp->int_metric = ifam->ifam_metric; 19824312Ssklower ifp->int_next = ifnet; 19924312Ssklower ifnet = ifp; 20024312Ssklower traceinit(ifp); 20124312Ssklower addrouteforif(ifp); 20224312Ssklower } 20324312Ssklower if (externalinterfaces > 1 && supplier < 0) 20424312Ssklower supplier = 1; 20552623Ssklower free(buf); 20624312Ssklower } 20724312Ssklower 20824312Ssklower addrouteforif(ifp) 20924312Ssklower struct interface *ifp; 21024312Ssklower { 21124317Ssklower struct sockaddr_ns net; 21224312Ssklower struct sockaddr *dst; 21324312Ssklower int state, metric; 21424312Ssklower struct rt_entry *rt; 21524312Ssklower 21624322Ssklower if (ifp->int_flags & IFF_POINTOPOINT) { 21724322Ssklower int (*match)(); 21824322Ssklower register struct interface *ifp2 = ifnet; 21924322Ssklower register struct interface *ifprev = ifnet; 22024322Ssklower 22124312Ssklower dst = &ifp->int_dstaddr; 22224322Ssklower 22324322Ssklower /* Search for interfaces with the same net */ 22424322Ssklower ifp->int_sq.n = ifp->int_sq.p = &(ifp->int_sq); 22524322Ssklower match = afswitch[dst->sa_family].af_netmatch; 22624322Ssklower if (match) 22724322Ssklower for (ifp2 = ifnet; ifp2; ifp2 =ifp2->int_next) { 22824322Ssklower if (ifp->int_flags & IFF_POINTOPOINT == 0) 22924322Ssklower continue; 23024322Ssklower if ((*match)(&ifp2->int_dstaddr,&ifp->int_dstaddr)) { 23124322Ssklower insque(&ifp2->int_sq,&ifp->int_sq); 23224322Ssklower break; 23324322Ssklower } 23424322Ssklower } 23524322Ssklower } else { 23624317Ssklower dst = &ifp->int_broadaddr; 23724312Ssklower } 23824312Ssklower rt = rtlookup(dst); 23924317Ssklower if (rt) 24024317Ssklower rtdelete(rt); 24126170Ssklower if (tracing) 24226170Ssklower fprintf(stderr, "Adding route to interface %s\n", ifp->int_name); 24326170Ssklower if (ifp->int_transitions++ > 0) 24426170Ssklower syslog(LOG_ERR, "re-installing interface %s", ifp->int_name); 24524312Ssklower rtadd(dst, &ifp->int_addr, ifp->int_metric, 24624312Ssklower ifp->int_flags & (IFF_INTERFACE|IFF_PASSIVE|IFF_REMOTE)); 24724312Ssklower } 24826170Ssklower 249