124312Ssklower #ifndef lint 224312Ssklower static char rcsid[] = "$Header$"; 324312Ssklower #endif 424312Ssklower 524312Ssklower /* 624312Ssklower * Routing Table Management Daemon 724312Ssklower */ 824312Ssklower #include "defs.h" 924312Ssklower #include <sys/ioctl.h> 1024312Ssklower #include <net/if.h> 1124312Ssklower #include <nlist.h> 12*24317Ssklower #include <syslog.h> 1324312Ssklower 1424312Ssklower struct interface *ifnet; 1524312Ssklower int lookforinterfaces = 1; 1624312Ssklower int performnlist = 1; 1724312Ssklower int externalinterfaces = 0; /* # of remote and local interfaces */ 1824312Ssklower int gateway = 0; /* 1 if we are a gateway to parts beyond */ 1924312Ssklower char ether_broadcast_addr[6] = {0xff, 0xff, 0xff, 0xff, 0xff, 0xff}; 2024312Ssklower 2124312Ssklower 2224312Ssklower /* 23*24317Ssklower * Find the network interfaces which have configured themselves. 24*24317Ssklower * If the interface is present but not yet up (for example an 2524312Ssklower * ARPANET IMP), set the lookforinterfaces flag so we'll 2624312Ssklower * come back later and look again. 2724312Ssklower */ 2824312Ssklower ifinit() 2924312Ssklower { 30*24317Ssklower struct interface ifs, *ifp; 31*24317Ssklower int s, n; 32*24317Ssklower char buf[BUFSIZ]; 33*24317Ssklower struct ifconf ifc; 34*24317Ssklower struct ifreq ifreq, *ifr; 35*24317Ssklower u_long i; 3624312Ssklower 37*24317Ssklower if ((s = socket(AF_NS, SOCK_DGRAM, 0)) < 0) { 38*24317Ssklower syslog(LOG_ERR, "socket: %m"); 39*24317Ssklower exit(1); 4024312Ssklower } 41*24317Ssklower ifc.ifc_len = sizeof (buf); 42*24317Ssklower ifc.ifc_buf = buf; 43*24317Ssklower if (ioctl(s, SIOCGIFCONF, (char *)&ifc) < 0) { 44*24317Ssklower syslog(LOG_ERR, "ioctl (get interface configuration)"); 45*24317Ssklower close(s); 46*24317Ssklower return (0); 47*24317Ssklower } 48*24317Ssklower ifr = ifc.ifc_req; 4924312Ssklower lookforinterfaces = 0; 50*24317Ssklower for (n = ifc.ifc_len / sizeof (struct ifreq); n > 0; n--, ifr++) { 51*24317Ssklower bzero((char *)&ifs, sizeof(ifs)); 52*24317Ssklower ifs.int_addr = ifr->ifr_addr; 53*24317Ssklower ifreq = *ifr; 54*24317Ssklower if (ioctl(s, SIOCGIFFLAGS, (char *)&ifreq) < 0) { 55*24317Ssklower syslog(LOG_ERR, "ioctl (get interface flags)"); 56*24317Ssklower continue; 57*24317Ssklower } 58*24317Ssklower ifs.int_flags = ifreq.ifr_flags | IFF_INTERFACE; 59*24317Ssklower if ((ifs.int_flags & IFF_UP) == 0 || 60*24317Ssklower ifr->ifr_addr.sa_family == AF_UNSPEC) { 6124312Ssklower lookforinterfaces = 1; 6224312Ssklower continue; 6324312Ssklower } 64*24317Ssklower /* already known to us? */ 65*24317Ssklower if (if_ifwithaddr(&ifs.int_addr)) 66*24317Ssklower continue; 67*24317Ssklower /* argh, this'll have to change sometime */ 68*24317Ssklower if (ifs.int_addr.sa_family != AF_NS) 69*24317Ssklower continue; 70*24317Ssklower if (ifs.int_flags & IFF_POINTOPOINT) { 71*24317Ssklower if (ioctl(s, SIOCGIFDSTADDR, (char *)&ifreq) < 0) { 72*24317Ssklower syslog(LOG_ERR, "ioctl (get dstaddr)"); 73*24317Ssklower continue; 74*24317Ssklower } 75*24317Ssklower ifs.int_dstaddr = ifreq.ifr_dstaddr; 7624312Ssklower } 77*24317Ssklower if (ifs.int_flags & IFF_BROADCAST) { 78*24317Ssklower if (ioctl(s, SIOCGIFBRDADDR, (char *)&ifreq) < 0) { 79*24317Ssklower syslog(LOG_ERR, "ioctl (get broadaddr)"); 80*24317Ssklower continue; 81*24317Ssklower } 82*24317Ssklower ifs.int_broadaddr = ifreq.ifr_broadaddr; 83*24317Ssklower } 84*24317Ssklower /* no one cares about software loopback interfaces */ 85*24317Ssklower if (strcmp(ifr->ifr_name,"lo0")==0) 86*24317Ssklower continue; 8724312Ssklower ifp = (struct interface *)malloc(sizeof (struct interface)); 8824312Ssklower if (ifp == 0) { 8924312Ssklower printf("routed: out of memory\n"); 9024312Ssklower break; 9124312Ssklower } 92*24317Ssklower *ifp = ifs; 9324312Ssklower /* 9424312Ssklower * Count the # of directly connected networks 9524312Ssklower * and point to point links which aren't looped 9624312Ssklower * back to ourself. This is used below to 9724312Ssklower * decide if we should be a routing ``supplier''. 9824312Ssklower */ 99*24317Ssklower if ((ifs.int_flags & IFF_POINTOPOINT) == 0 || 100*24317Ssklower if_ifwithaddr(&ifs.int_dstaddr) == 0) 10124312Ssklower externalinterfaces++; 102*24317Ssklower ifp->int_name = malloc(strlen(ifr->ifr_name) + 1); 10324312Ssklower if (ifp->int_name == 0) { 10424312Ssklower fprintf(stderr, "routed: ifinit: out of memory\n"); 10524312Ssklower goto bad; /* ??? */ 10624312Ssklower } 107*24317Ssklower strcpy(ifp->int_name, ifr->ifr_name); 10824312Ssklower ifp->int_metric = 0; 10924312Ssklower ifp->int_next = ifnet; 11024312Ssklower ifnet = ifp; 11124312Ssklower traceinit(ifp); 11224312Ssklower addrouteforif(ifp); 11324312Ssklower } 11424312Ssklower if (externalinterfaces > 1 && supplier < 0) 11524312Ssklower supplier = 1; 116*24317Ssklower close(s); 11724312Ssklower return; 11824312Ssklower bad: 11924312Ssklower sleep(60); 120*24317Ssklower close(s); 12124312Ssklower execv("/etc/XNSrouted", argv0); 12224312Ssklower _exit(0177); 12324312Ssklower } 12424312Ssklower 12524312Ssklower addrouteforif(ifp) 12624312Ssklower struct interface *ifp; 12724312Ssklower { 128*24317Ssklower struct sockaddr_ns net; 12924312Ssklower struct sockaddr *dst; 13024312Ssklower int state, metric; 13124312Ssklower struct rt_entry *rt; 13224312Ssklower 13324312Ssklower if (ifp->int_flags & IFF_POINTOPOINT) 13424312Ssklower dst = &ifp->int_dstaddr; 13524312Ssklower else { 136*24317Ssklower dst = &ifp->int_broadaddr; 13724312Ssklower } 13824312Ssklower rt = rtlookup(dst); 139*24317Ssklower if (rt) 140*24317Ssklower rtdelete(rt); 14124312Ssklower rtadd(dst, &ifp->int_addr, ifp->int_metric, 14224312Ssklower ifp->int_flags & (IFF_INTERFACE|IFF_PASSIVE|IFF_REMOTE)); 14324312Ssklower } 14424312Ssklower 145