124322Ssklower /* 224322Ssklower * Copyright (c) 1985 Regents of the University of California. 324322Ssklower * All rights reserved. The Berkeley software License Agreement 424322Ssklower * specifies the terms and conditions for redistribution. 524322Ssklower * 624322Ssklower * Includes material written at Cornell University by Bill Nesheim, 724322Ssklower * by permission of the author. 824322Ssklower */ 924322Ssklower 1024322Ssklower 1124312Ssklower #ifndef lint 12*24874Ssklower static char sccsid[] = "@(#)startup.c 5.4 (Berkeley) 09/17/85"; 1324322Ssklower #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; 2724312Ssklower int externalinterfaces = 0; /* # of remote and local interfaces */ 2824312Ssklower int gateway = 0; /* 1 if we are a gateway to parts beyond */ 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; 4124317Ssklower int s, n; 4224317Ssklower struct ifconf ifc; 43*24874Ssklower char buf[(sizeof (struct ifreq ) * 20)]; 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); 5624317Ssklower return (0); 5724317Ssklower } 5824317Ssklower ifr = ifc.ifc_req; 5924312Ssklower lookforinterfaces = 0; 6024317Ssklower for (n = ifc.ifc_len / sizeof (struct ifreq); n > 0; n--, ifr++) { 6124317Ssklower bzero((char *)&ifs, sizeof(ifs)); 6224317Ssklower ifs.int_addr = ifr->ifr_addr; 6324317Ssklower ifreq = *ifr; 6424317Ssklower if (ioctl(s, SIOCGIFFLAGS, (char *)&ifreq) < 0) { 6524317Ssklower syslog(LOG_ERR, "ioctl (get interface flags)"); 6624317Ssklower continue; 6724317Ssklower } 6824317Ssklower ifs.int_flags = ifreq.ifr_flags | IFF_INTERFACE; 6924317Ssklower if ((ifs.int_flags & IFF_UP) == 0 || 7024317Ssklower ifr->ifr_addr.sa_family == AF_UNSPEC) { 7124312Ssklower lookforinterfaces = 1; 7224312Ssklower continue; 7324312Ssklower } 74*24874Ssklower #ifdef notdef 7524317Ssklower /* already known to us? */ 76*24874Ssklower /* We can have more than one point to point link 77*24874Ssklower with the same local address. 78*24874Ssklower It is not clear what this was guarding against 79*24874Ssklower anyway. 80*24874Ssklower if (if_ifwithaddr(ifr->ifr_addr)) 81*24874Ssklower continue; 82*24874Ssklower */ 83*24874Ssklower #endif 8424317Ssklower if (ifs.int_addr.sa_family != AF_NS) 8524317Ssklower continue; 8624317Ssklower if (ifs.int_flags & IFF_POINTOPOINT) { 8724317Ssklower if (ioctl(s, SIOCGIFDSTADDR, (char *)&ifreq) < 0) { 88*24874Ssklower syslog(LOG_ERR, "ioctl (get dstaddr): %m"); 8924317Ssklower continue; 9024317Ssklower } 9124317Ssklower ifs.int_dstaddr = ifreq.ifr_dstaddr; 9224312Ssklower } 9324317Ssklower if (ifs.int_flags & IFF_BROADCAST) { 9424317Ssklower if (ioctl(s, SIOCGIFBRDADDR, (char *)&ifreq) < 0) { 95*24874Ssklower syslog(LOG_ERR, "ioctl (get broadaddr: %m"); 9624317Ssklower continue; 9724317Ssklower } 9824317Ssklower ifs.int_broadaddr = ifreq.ifr_broadaddr; 9924317Ssklower } 10024317Ssklower /* no one cares about software loopback interfaces */ 10124317Ssklower if (strcmp(ifr->ifr_name,"lo0")==0) 10224317Ssklower continue; 10324312Ssklower ifp = (struct interface *)malloc(sizeof (struct interface)); 10424312Ssklower if (ifp == 0) { 105*24874Ssklower syslog(LOG_ERR,"XNSrouted: out of memory\n"); 10624312Ssklower break; 10724312Ssklower } 10824317Ssklower *ifp = ifs; 10924312Ssklower /* 11024312Ssklower * Count the # of directly connected networks 11124312Ssklower * and point to point links which aren't looped 11224312Ssklower * back to ourself. This is used below to 11324312Ssklower * decide if we should be a routing ``supplier''. 11424312Ssklower */ 11524317Ssklower if ((ifs.int_flags & IFF_POINTOPOINT) == 0 || 11624317Ssklower if_ifwithaddr(&ifs.int_dstaddr) == 0) 11724312Ssklower externalinterfaces++; 11824317Ssklower ifp->int_name = malloc(strlen(ifr->ifr_name) + 1); 11924312Ssklower if (ifp->int_name == 0) { 120*24874Ssklower syslog(LOG_ERR,"XNSrouted: out of memory\n"); 12124312Ssklower goto bad; /* ??? */ 12224312Ssklower } 12324317Ssklower strcpy(ifp->int_name, ifr->ifr_name); 12424312Ssklower ifp->int_metric = 0; 12524312Ssklower ifp->int_next = ifnet; 12624312Ssklower ifnet = ifp; 12724312Ssklower traceinit(ifp); 12824312Ssklower addrouteforif(ifp); 12924312Ssklower } 13024312Ssklower if (externalinterfaces > 1 && supplier < 0) 13124312Ssklower supplier = 1; 13224317Ssklower close(s); 13324312Ssklower return; 13424312Ssklower bad: 13524312Ssklower sleep(60); 13624317Ssklower close(s); 137*24874Ssklower sleep(60); 13824312Ssklower execv("/etc/XNSrouted", argv0); 13924312Ssklower _exit(0177); 14024312Ssklower } 14124312Ssklower 14224312Ssklower addrouteforif(ifp) 14324312Ssklower struct interface *ifp; 14424312Ssklower { 14524317Ssklower struct sockaddr_ns net; 14624312Ssklower struct sockaddr *dst; 14724312Ssklower int state, metric; 14824312Ssklower struct rt_entry *rt; 14924312Ssklower 15024322Ssklower if (ifp->int_flags & IFF_POINTOPOINT) { 15124322Ssklower int (*match)(); 15224322Ssklower register struct interface *ifp2 = ifnet; 15324322Ssklower register struct interface *ifprev = ifnet; 15424322Ssklower 15524312Ssklower dst = &ifp->int_dstaddr; 15624322Ssklower 15724322Ssklower /* Search for interfaces with the same net */ 15824322Ssklower ifp->int_sq.n = ifp->int_sq.p = &(ifp->int_sq); 15924322Ssklower match = afswitch[dst->sa_family].af_netmatch; 16024322Ssklower if (match) 16124322Ssklower for (ifp2 = ifnet; ifp2; ifp2 =ifp2->int_next) { 16224322Ssklower if (ifp->int_flags & IFF_POINTOPOINT == 0) 16324322Ssklower continue; 16424322Ssklower if ((*match)(&ifp2->int_dstaddr,&ifp->int_dstaddr)) { 16524322Ssklower insque(&ifp2->int_sq,&ifp->int_sq); 16624322Ssklower break; 16724322Ssklower } 16824322Ssklower } 16924322Ssklower } else { 17024317Ssklower dst = &ifp->int_broadaddr; 17124312Ssklower } 17224312Ssklower rt = rtlookup(dst); 17324317Ssklower if (rt) 17424317Ssklower rtdelete(rt); 17524312Ssklower rtadd(dst, &ifp->int_addr, ifp->int_metric, 17624312Ssklower ifp->int_flags & (IFF_INTERFACE|IFF_PASSIVE|IFF_REMOTE)); 17724312Ssklower } 178