/* * Copyright (c) 1985 Regents of the University of California. * All rights reserved. The Berkeley software License Agreement * specifies the terms and conditions for redistribution. * * Includes material written at Cornell University by Bill Nesheim, * by permission of the author. */ #ifndef lint static char sccsid[] = "@(#)startup.c 5.5 (Berkeley) 2/14/86"; #endif not lint /* * Routing Table Management Daemon */ #include "defs.h" #include #include #include #include struct interface *ifnet; int lookforinterfaces = 1; int performnlist = 1; int gateway = 0; int externalinterfaces = 0; /* # of remote and local interfaces */ char ether_broadcast_addr[6] = {0xff, 0xff, 0xff, 0xff, 0xff, 0xff}; /* * Find the network interfaces which have configured themselves. * If the interface is present but not yet up (for example an * ARPANET IMP), set the lookforinterfaces flag so we'll * come back later and look again. */ ifinit() { struct interface ifs, *ifp; int s, n; struct ifconf ifc; char buf[(sizeof (struct ifreq ) * 20)]; struct ifreq ifreq, *ifr; u_long i; if ((s = socket(AF_NS, SOCK_DGRAM, 0)) < 0) { syslog(LOG_ERR, "socket: %m"); exit(1); } ifc.ifc_len = sizeof (buf); ifc.ifc_buf = buf; if (ioctl(s, SIOCGIFCONF, (char *)&ifc) < 0) { syslog(LOG_ERR, "ioctl (get interface configuration)"); close(s); return (0); } ifr = ifc.ifc_req; lookforinterfaces = 0; for (n = ifc.ifc_len / sizeof (struct ifreq); n > 0; n--, ifr++) { bzero((char *)&ifs, sizeof(ifs)); ifs.int_addr = ifr->ifr_addr; ifreq = *ifr; if (ioctl(s, SIOCGIFFLAGS, (char *)&ifreq) < 0) { syslog(LOG_ERR, "ioctl (get interface flags)"); continue; } ifs.int_flags = ifreq.ifr_flags | IFF_INTERFACE; if ((ifs.int_flags & IFF_UP) == 0 || ifr->ifr_addr.sa_family == AF_UNSPEC) { lookforinterfaces = 1; continue; } if (ifs.int_addr.sa_family != AF_NS) continue; if (ifs.int_flags & IFF_POINTOPOINT) { if (ioctl(s, SIOCGIFDSTADDR, (char *)&ifreq) < 0) { syslog(LOG_ERR, "ioctl (get dstaddr): %m"); continue; } ifs.int_dstaddr = ifreq.ifr_dstaddr; } if (ifs.int_flags & IFF_BROADCAST) { if (ioctl(s, SIOCGIFBRDADDR, (char *)&ifreq) < 0) { syslog(LOG_ERR, "ioctl (get broadaddr: %m"); continue; } ifs.int_broadaddr = ifreq.ifr_broadaddr; } /* * already known to us? * what makes a POINTOPOINT if unique is its dst addr, * NOT its source address */ if ( ((ifs.int_flags & IFF_POINTOPOINT) && if_ifwithdstaddr(&ifs.int_dstaddr)) || ( ((ifs.int_flags & IFF_POINTOPOINT) == 0) && if_ifwithaddr(&ifs.int_addr))) continue; /* no one cares about software loopback interfaces */ if (strncmp(ifr->ifr_name,"lo", 2)==0) continue; ifp = (struct interface *)malloc(sizeof (struct interface)); if (ifp == 0) { syslog(LOG_ERR,"XNSrouted: out of memory\n"); break; } *ifp = ifs; /* * Count the # of directly connected networks * and point to point links which aren't looped * back to ourself. This is used below to * decide if we should be a routing ``supplier''. */ if ((ifs.int_flags & IFF_POINTOPOINT) == 0 || if_ifwithaddr(&ifs.int_dstaddr) == 0) externalinterfaces++; /* * If we have a point-to-point link, we want to act * as a supplier even if it's our only interface, * as that's the only way our peer on the other end * can tell that the link is up. */ if ((ifs.int_flags & IFF_POINTOPOINT) && supplier < 0) supplier = 1; ifp->int_name = malloc(strlen(ifr->ifr_name) + 1); if (ifp->int_name == 0) { syslog(LOG_ERR,"XNSrouted: out of memory\n"); goto bad; /* ??? */ } strcpy(ifp->int_name, ifr->ifr_name); ifp->int_metric = 0; ifp->int_next = ifnet; ifnet = ifp; traceinit(ifp); addrouteforif(ifp); } if (externalinterfaces > 1 && supplier < 0) supplier = 1; close(s); return; bad: sleep(60); close(s); sleep(60); execv("/etc/XNSrouted", argv0); _exit(0177); } addrouteforif(ifp) struct interface *ifp; { struct sockaddr_ns net; struct sockaddr *dst; int state, metric; struct rt_entry *rt; if (ifp->int_flags & IFF_POINTOPOINT) { int (*match)(); register struct interface *ifp2 = ifnet; register struct interface *ifprev = ifnet; dst = &ifp->int_dstaddr; /* Search for interfaces with the same net */ ifp->int_sq.n = ifp->int_sq.p = &(ifp->int_sq); match = afswitch[dst->sa_family].af_netmatch; if (match) for (ifp2 = ifnet; ifp2; ifp2 =ifp2->int_next) { if (ifp->int_flags & IFF_POINTOPOINT == 0) continue; if ((*match)(&ifp2->int_dstaddr,&ifp->int_dstaddr)) { insque(&ifp2->int_sq,&ifp->int_sq); break; } } } else { dst = &ifp->int_broadaddr; } rt = rtlookup(dst); if (rt) rtdelete(rt); if (tracing) fprintf(stderr, "Adding route to interface %s\n", ifp->int_name); if (ifp->int_transitions++ > 0) syslog(LOG_ERR, "re-installing interface %s", ifp->int_name); rtadd(dst, &ifp->int_addr, ifp->int_metric, ifp->int_flags & (IFF_INTERFACE|IFF_PASSIVE|IFF_REMOTE)); }