124322Ssklower /* 2*35551Sbostic * Copyright (c) 1985 The Regents of the University of California. 3*35551Sbostic * All rights reserved. 424322Ssklower * 5*35551Sbostic * This file includes significant work done at Cornell University by 6*35551Sbostic * Bill Nesheim. That work included by permission. 7*35551Sbostic * 8*35551Sbostic * Redistribution and use in source and binary forms are permitted 9*35551Sbostic * provided that the above copyright notice and this paragraph are 10*35551Sbostic * duplicated in all such forms and that any documentation, 11*35551Sbostic * advertising materials, and other materials related to such 12*35551Sbostic * distribution and use acknowledge that the software was developed 13*35551Sbostic * by the University of California, Berkeley. The name of the 14*35551Sbostic * University may not be used to endorse or promote products derived 15*35551Sbostic * from this software without specific prior written permission. 16*35551Sbostic * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR 17*35551Sbostic * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED 18*35551Sbostic * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. 1924322Ssklower */ 2024322Ssklower 2124312Ssklower #ifndef lint 22*35551Sbostic static char sccsid[] = "@(#)startup.c 5.6 (Berkeley) 09/19/88"; 23*35551Sbostic #endif /* not lint */ 2424312Ssklower 2524312Ssklower /* 2624312Ssklower * Routing Table Management Daemon 2724312Ssklower */ 2824312Ssklower #include "defs.h" 2924312Ssklower #include <sys/ioctl.h> 3024312Ssklower #include <net/if.h> 3124312Ssklower #include <nlist.h> 3224317Ssklower #include <syslog.h> 3324312Ssklower 3424312Ssklower struct interface *ifnet; 3524312Ssklower int lookforinterfaces = 1; 3624312Ssklower int performnlist = 1; 3726170Ssklower int gateway = 0; 3824312Ssklower int externalinterfaces = 0; /* # of remote and local interfaces */ 3924312Ssklower char ether_broadcast_addr[6] = {0xff, 0xff, 0xff, 0xff, 0xff, 0xff}; 4024312Ssklower 4124312Ssklower 4224312Ssklower /* 4324317Ssklower * Find the network interfaces which have configured themselves. 4424317Ssklower * If the interface is present but not yet up (for example an 4524312Ssklower * ARPANET IMP), set the lookforinterfaces flag so we'll 4624312Ssklower * come back later and look again. 4724312Ssklower */ 4824312Ssklower ifinit() 4924312Ssklower { 5024317Ssklower struct interface ifs, *ifp; 5124317Ssklower int s, n; 5224317Ssklower struct ifconf ifc; 5324874Ssklower char buf[(sizeof (struct ifreq ) * 20)]; 5424317Ssklower struct ifreq ifreq, *ifr; 5524317Ssklower u_long i; 5624312Ssklower 5724317Ssklower if ((s = socket(AF_NS, SOCK_DGRAM, 0)) < 0) { 5824317Ssklower syslog(LOG_ERR, "socket: %m"); 5924317Ssklower exit(1); 6024312Ssklower } 6124317Ssklower ifc.ifc_len = sizeof (buf); 6224317Ssklower ifc.ifc_buf = buf; 6324317Ssklower if (ioctl(s, SIOCGIFCONF, (char *)&ifc) < 0) { 6424317Ssklower syslog(LOG_ERR, "ioctl (get interface configuration)"); 6524317Ssklower close(s); 6624317Ssklower return (0); 6724317Ssklower } 6824317Ssklower ifr = ifc.ifc_req; 6924312Ssklower lookforinterfaces = 0; 7024317Ssklower for (n = ifc.ifc_len / sizeof (struct ifreq); n > 0; n--, ifr++) { 7124317Ssklower bzero((char *)&ifs, sizeof(ifs)); 7224317Ssklower ifs.int_addr = ifr->ifr_addr; 7324317Ssklower ifreq = *ifr; 7424317Ssklower if (ioctl(s, SIOCGIFFLAGS, (char *)&ifreq) < 0) { 7524317Ssklower syslog(LOG_ERR, "ioctl (get interface flags)"); 7624317Ssklower continue; 7724317Ssklower } 7824317Ssklower ifs.int_flags = ifreq.ifr_flags | IFF_INTERFACE; 7924317Ssklower if ((ifs.int_flags & IFF_UP) == 0 || 8024317Ssklower ifr->ifr_addr.sa_family == AF_UNSPEC) { 8124312Ssklower lookforinterfaces = 1; 8224312Ssklower continue; 8324312Ssklower } 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) { 8824874Ssklower 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) { 9524874Ssklower syslog(LOG_ERR, "ioctl (get broadaddr: %m"); 9624317Ssklower continue; 9724317Ssklower } 9824317Ssklower ifs.int_broadaddr = ifreq.ifr_broadaddr; 9924317Ssklower } 10026170Ssklower /* 10126170Ssklower * already known to us? 10226170Ssklower * what makes a POINTOPOINT if unique is its dst addr, 10326170Ssklower * NOT its source address 10426170Ssklower */ 10526170Ssklower if ( ((ifs.int_flags & IFF_POINTOPOINT) && 10626170Ssklower if_ifwithdstaddr(&ifs.int_dstaddr)) || 10726170Ssklower ( ((ifs.int_flags & IFF_POINTOPOINT) == 0) && 10826170Ssklower if_ifwithaddr(&ifs.int_addr))) 10926170Ssklower continue; 11024317Ssklower /* no one cares about software loopback interfaces */ 11126170Ssklower if (strncmp(ifr->ifr_name,"lo", 2)==0) 11224317Ssklower continue; 11324312Ssklower ifp = (struct interface *)malloc(sizeof (struct interface)); 11424312Ssklower if (ifp == 0) { 11524874Ssklower syslog(LOG_ERR,"XNSrouted: out of memory\n"); 11624312Ssklower break; 11724312Ssklower } 11824317Ssklower *ifp = ifs; 11924312Ssklower /* 12024312Ssklower * Count the # of directly connected networks 12124312Ssklower * and point to point links which aren't looped 12224312Ssklower * back to ourself. This is used below to 12324312Ssklower * decide if we should be a routing ``supplier''. 12424312Ssklower */ 12524317Ssklower if ((ifs.int_flags & IFF_POINTOPOINT) == 0 || 12624317Ssklower if_ifwithaddr(&ifs.int_dstaddr) == 0) 12724312Ssklower externalinterfaces++; 12826170Ssklower /* 12926170Ssklower * If we have a point-to-point link, we want to act 13026170Ssklower * as a supplier even if it's our only interface, 13126170Ssklower * as that's the only way our peer on the other end 13226170Ssklower * can tell that the link is up. 13326170Ssklower */ 13426170Ssklower if ((ifs.int_flags & IFF_POINTOPOINT) && supplier < 0) 13526170Ssklower supplier = 1; 13624317Ssklower ifp->int_name = malloc(strlen(ifr->ifr_name) + 1); 13724312Ssklower if (ifp->int_name == 0) { 13824874Ssklower syslog(LOG_ERR,"XNSrouted: out of memory\n"); 13924312Ssklower goto bad; /* ??? */ 14024312Ssklower } 14124317Ssklower strcpy(ifp->int_name, ifr->ifr_name); 14224312Ssklower ifp->int_metric = 0; 14324312Ssklower ifp->int_next = ifnet; 14424312Ssklower ifnet = ifp; 14524312Ssklower traceinit(ifp); 14624312Ssklower addrouteforif(ifp); 14724312Ssklower } 14824312Ssklower if (externalinterfaces > 1 && supplier < 0) 14924312Ssklower supplier = 1; 15024317Ssklower close(s); 15124312Ssklower return; 15224312Ssklower bad: 15324312Ssklower sleep(60); 15424317Ssklower close(s); 15524874Ssklower sleep(60); 15624312Ssklower execv("/etc/XNSrouted", argv0); 15724312Ssklower _exit(0177); 15824312Ssklower } 15924312Ssklower 16024312Ssklower addrouteforif(ifp) 16124312Ssklower struct interface *ifp; 16224312Ssklower { 16324317Ssklower struct sockaddr_ns net; 16424312Ssklower struct sockaddr *dst; 16524312Ssklower int state, metric; 16624312Ssklower struct rt_entry *rt; 16724312Ssklower 16824322Ssklower if (ifp->int_flags & IFF_POINTOPOINT) { 16924322Ssklower int (*match)(); 17024322Ssklower register struct interface *ifp2 = ifnet; 17124322Ssklower register struct interface *ifprev = ifnet; 17224322Ssklower 17324312Ssklower dst = &ifp->int_dstaddr; 17424322Ssklower 17524322Ssklower /* Search for interfaces with the same net */ 17624322Ssklower ifp->int_sq.n = ifp->int_sq.p = &(ifp->int_sq); 17724322Ssklower match = afswitch[dst->sa_family].af_netmatch; 17824322Ssklower if (match) 17924322Ssklower for (ifp2 = ifnet; ifp2; ifp2 =ifp2->int_next) { 18024322Ssklower if (ifp->int_flags & IFF_POINTOPOINT == 0) 18124322Ssklower continue; 18224322Ssklower if ((*match)(&ifp2->int_dstaddr,&ifp->int_dstaddr)) { 18324322Ssklower insque(&ifp2->int_sq,&ifp->int_sq); 18424322Ssklower break; 18524322Ssklower } 18624322Ssklower } 18724322Ssklower } else { 18824317Ssklower dst = &ifp->int_broadaddr; 18924312Ssklower } 19024312Ssklower rt = rtlookup(dst); 19124317Ssklower if (rt) 19224317Ssklower rtdelete(rt); 19326170Ssklower if (tracing) 19426170Ssklower fprintf(stderr, "Adding route to interface %s\n", ifp->int_name); 19526170Ssklower if (ifp->int_transitions++ > 0) 19626170Ssklower syslog(LOG_ERR, "re-installing interface %s", ifp->int_name); 19724312Ssklower rtadd(dst, &ifp->int_addr, ifp->int_metric, 19824312Ssklower ifp->int_flags & (IFF_INTERFACE|IFF_PASSIVE|IFF_REMOTE)); 19924312Ssklower } 20026170Ssklower 201