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 * 8*42698Sbostic * %sccs.include.redist.c% 924322Ssklower */ 1024322Ssklower 1124312Ssklower #ifndef lint 12*42698Sbostic static char sccsid[] = "@(#)startup.c 5.9 (Berkeley) 06/01/90"; 1335551Sbostic #endif /* not lint */ 1424312Ssklower 1524312Ssklower /* 1624312Ssklower * Routing Table Management Daemon 1724312Ssklower */ 1824312Ssklower #include "defs.h" 1924312Ssklower #include <sys/ioctl.h> 2024312Ssklower #include <net/if.h> 2124312Ssklower #include <nlist.h> 2224317Ssklower #include <syslog.h> 2324312Ssklower 2424312Ssklower struct interface *ifnet; 2524312Ssklower int lookforinterfaces = 1; 2624312Ssklower int performnlist = 1; 2726170Ssklower int gateway = 0; 2824312Ssklower int externalinterfaces = 0; /* # of remote and local interfaces */ 2924312Ssklower char ether_broadcast_addr[6] = {0xff, 0xff, 0xff, 0xff, 0xff, 0xff}; 3024312Ssklower 3124312Ssklower 3224312Ssklower /* 3324317Ssklower * Find the network interfaces which have configured themselves. 3424317Ssklower * If the interface is present but not yet up (for example an 3524312Ssklower * ARPANET IMP), set the lookforinterfaces flag so we'll 3624312Ssklower * come back later and look again. 3724312Ssklower */ 3824312Ssklower ifinit() 3924312Ssklower { 4024317Ssklower struct interface ifs, *ifp; 4138687Ssklower int s; 4224317Ssklower struct ifconf ifc; 4338687Ssklower char buf[BUFSIZ], *cp, *cplim; 4424317Ssklower struct ifreq ifreq, *ifr; 4524317Ssklower u_long i; 4624312Ssklower 4724317Ssklower if ((s = socket(AF_NS, SOCK_DGRAM, 0)) < 0) { 4824317Ssklower syslog(LOG_ERR, "socket: %m"); 4924317Ssklower exit(1); 5024312Ssklower } 5124317Ssklower ifc.ifc_len = sizeof (buf); 5224317Ssklower ifc.ifc_buf = buf; 5324317Ssklower if (ioctl(s, SIOCGIFCONF, (char *)&ifc) < 0) { 5424317Ssklower syslog(LOG_ERR, "ioctl (get interface configuration)"); 5524317Ssklower close(s); 5636437Skarels exit(1); 5724317Ssklower } 5824317Ssklower ifr = ifc.ifc_req; 5924312Ssklower lookforinterfaces = 0; 6038687Ssklower #ifdef RTM_ADD 6138687Ssklower #define max(a, b) (a > b ? a : b) 6238687Ssklower #define size(p) max((p).sa_len, sizeof(p)) 6338687Ssklower #else 6438687Ssklower #define size(p) (sizeof (p)) 6538687Ssklower #endif 6638687Ssklower cplim = buf + ifc.ifc_len; /*skip over if's with big ifr_addr's */ 6738687Ssklower for (cp = buf; cp < cplim; 6838687Ssklower cp += sizeof (ifr->ifr_name) + size(ifr->ifr_addr)) { 6924317Ssklower bzero((char *)&ifs, sizeof(ifs)); 7024317Ssklower ifs.int_addr = ifr->ifr_addr; 7124317Ssklower ifreq = *ifr; 7224317Ssklower if (ioctl(s, SIOCGIFFLAGS, (char *)&ifreq) < 0) { 7324317Ssklower syslog(LOG_ERR, "ioctl (get interface flags)"); 7424317Ssklower continue; 7524317Ssklower } 7624317Ssklower ifs.int_flags = ifreq.ifr_flags | IFF_INTERFACE; 7724317Ssklower if ((ifs.int_flags & IFF_UP) == 0 || 7824317Ssklower ifr->ifr_addr.sa_family == AF_UNSPEC) { 7924312Ssklower lookforinterfaces = 1; 8024312Ssklower continue; 8124312Ssklower } 8224317Ssklower if (ifs.int_addr.sa_family != AF_NS) 8324317Ssklower continue; 8424317Ssklower if (ifs.int_flags & IFF_POINTOPOINT) { 8524317Ssklower if (ioctl(s, SIOCGIFDSTADDR, (char *)&ifreq) < 0) { 8624874Ssklower syslog(LOG_ERR, "ioctl (get dstaddr): %m"); 8724317Ssklower continue; 8824317Ssklower } 8924317Ssklower ifs.int_dstaddr = ifreq.ifr_dstaddr; 9024312Ssklower } 9124317Ssklower if (ifs.int_flags & IFF_BROADCAST) { 9224317Ssklower if (ioctl(s, SIOCGIFBRDADDR, (char *)&ifreq) < 0) { 9324874Ssklower syslog(LOG_ERR, "ioctl (get broadaddr: %m"); 9424317Ssklower continue; 9524317Ssklower } 9624317Ssklower ifs.int_broadaddr = ifreq.ifr_broadaddr; 9724317Ssklower } 9826170Ssklower /* 9926170Ssklower * already known to us? 10026170Ssklower * what makes a POINTOPOINT if unique is its dst addr, 10126170Ssklower * NOT its source address 10226170Ssklower */ 10326170Ssklower if ( ((ifs.int_flags & IFF_POINTOPOINT) && 10426170Ssklower if_ifwithdstaddr(&ifs.int_dstaddr)) || 10526170Ssklower ( ((ifs.int_flags & IFF_POINTOPOINT) == 0) && 10626170Ssklower if_ifwithaddr(&ifs.int_addr))) 10726170Ssklower continue; 10824317Ssklower /* no one cares about software loopback interfaces */ 10926170Ssklower if (strncmp(ifr->ifr_name,"lo", 2)==0) 11024317Ssklower continue; 11124312Ssklower ifp = (struct interface *)malloc(sizeof (struct interface)); 11224312Ssklower if (ifp == 0) { 11324874Ssklower syslog(LOG_ERR,"XNSrouted: out of memory\n"); 11424312Ssklower break; 11524312Ssklower } 11624317Ssklower *ifp = ifs; 11724312Ssklower /* 11824312Ssklower * Count the # of directly connected networks 11924312Ssklower * and point to point links which aren't looped 12024312Ssklower * back to ourself. This is used below to 12124312Ssklower * decide if we should be a routing ``supplier''. 12224312Ssklower */ 12324317Ssklower if ((ifs.int_flags & IFF_POINTOPOINT) == 0 || 12424317Ssklower if_ifwithaddr(&ifs.int_dstaddr) == 0) 12524312Ssklower externalinterfaces++; 12626170Ssklower /* 12726170Ssklower * If we have a point-to-point link, we want to act 12826170Ssklower * as a supplier even if it's our only interface, 12926170Ssklower * as that's the only way our peer on the other end 13026170Ssklower * can tell that the link is up. 13126170Ssklower */ 13226170Ssklower if ((ifs.int_flags & IFF_POINTOPOINT) && supplier < 0) 13326170Ssklower supplier = 1; 13424317Ssklower ifp->int_name = malloc(strlen(ifr->ifr_name) + 1); 13524312Ssklower if (ifp->int_name == 0) { 13624874Ssklower syslog(LOG_ERR,"XNSrouted: out of memory\n"); 13736437Skarels exit(1); 13824312Ssklower } 13924317Ssklower strcpy(ifp->int_name, ifr->ifr_name); 14024312Ssklower ifp->int_metric = 0; 14124312Ssklower ifp->int_next = ifnet; 14224312Ssklower ifnet = ifp; 14324312Ssklower traceinit(ifp); 14424312Ssklower addrouteforif(ifp); 14524312Ssklower } 14624312Ssklower if (externalinterfaces > 1 && supplier < 0) 14724312Ssklower supplier = 1; 14824317Ssklower close(s); 14924312Ssklower } 15024312Ssklower 15124312Ssklower addrouteforif(ifp) 15224312Ssklower struct interface *ifp; 15324312Ssklower { 15424317Ssklower struct sockaddr_ns net; 15524312Ssklower struct sockaddr *dst; 15624312Ssklower int state, metric; 15724312Ssklower struct rt_entry *rt; 15824312Ssklower 15924322Ssklower if (ifp->int_flags & IFF_POINTOPOINT) { 16024322Ssklower int (*match)(); 16124322Ssklower register struct interface *ifp2 = ifnet; 16224322Ssklower register struct interface *ifprev = ifnet; 16324322Ssklower 16424312Ssklower dst = &ifp->int_dstaddr; 16524322Ssklower 16624322Ssklower /* Search for interfaces with the same net */ 16724322Ssklower ifp->int_sq.n = ifp->int_sq.p = &(ifp->int_sq); 16824322Ssklower match = afswitch[dst->sa_family].af_netmatch; 16924322Ssklower if (match) 17024322Ssklower for (ifp2 = ifnet; ifp2; ifp2 =ifp2->int_next) { 17124322Ssklower if (ifp->int_flags & IFF_POINTOPOINT == 0) 17224322Ssklower continue; 17324322Ssklower if ((*match)(&ifp2->int_dstaddr,&ifp->int_dstaddr)) { 17424322Ssklower insque(&ifp2->int_sq,&ifp->int_sq); 17524322Ssklower break; 17624322Ssklower } 17724322Ssklower } 17824322Ssklower } else { 17924317Ssklower dst = &ifp->int_broadaddr; 18024312Ssklower } 18124312Ssklower rt = rtlookup(dst); 18224317Ssklower if (rt) 18324317Ssklower rtdelete(rt); 18426170Ssklower if (tracing) 18526170Ssklower fprintf(stderr, "Adding route to interface %s\n", ifp->int_name); 18626170Ssklower if (ifp->int_transitions++ > 0) 18726170Ssklower syslog(LOG_ERR, "re-installing interface %s", ifp->int_name); 18824312Ssklower rtadd(dst, &ifp->int_addr, ifp->int_metric, 18924312Ssklower ifp->int_flags & (IFF_INTERFACE|IFF_PASSIVE|IFF_REMOTE)); 19024312Ssklower } 19126170Ssklower 192