1 /* 2 * Copyright (c) 1985 The Regents of the University of California. 3 * All rights reserved. 4 * 5 * This file includes significant work done at Cornell University by 6 * Bill Nesheim. That work included by permission. 7 * 8 * %sccs.include.redist.c% 9 */ 10 11 #ifndef lint 12 static char sccsid[] = "@(#)startup.c 5.11 (Berkeley) 02/26/91"; 13 #endif /* not lint */ 14 15 /* 16 * Routing Table Management Daemon 17 */ 18 #include "defs.h" 19 #include <sys/ioctl.h> 20 #include <net/if.h> 21 #include <nlist.h> 22 #include <stdlib.h> 23 24 struct interface *ifnet; 25 int lookforinterfaces = 1; 26 int performnlist = 1; 27 int gateway = 0; 28 int externalinterfaces = 0; /* # of remote and local interfaces */ 29 char ether_broadcast_addr[6] = {0xff, 0xff, 0xff, 0xff, 0xff, 0xff}; 30 31 32 /* 33 * Find the network interfaces which have configured themselves. 34 * If the interface is present but not yet up (for example an 35 * ARPANET IMP), set the lookforinterfaces flag so we'll 36 * come back later and look again. 37 */ 38 ifinit() 39 { 40 struct interface ifs, *ifp; 41 int s; 42 struct ifconf ifc; 43 char buf[BUFSIZ], *cp, *cplim; 44 struct ifreq ifreq, *ifr; 45 u_long i; 46 47 if ((s = socket(AF_NS, SOCK_DGRAM, 0)) < 0) { 48 syslog(LOG_ERR, "socket: %m"); 49 exit(1); 50 } 51 ifc.ifc_len = sizeof (buf); 52 ifc.ifc_buf = buf; 53 if (ioctl(s, SIOCGIFCONF, (char *)&ifc) < 0) { 54 syslog(LOG_ERR, "ioctl (get interface configuration)"); 55 close(s); 56 exit(1); 57 } 58 ifr = ifc.ifc_req; 59 lookforinterfaces = 0; 60 #ifdef RTM_ADD 61 #define max(a, b) (a > b ? a : b) 62 #define size(p) max((p).sa_len, sizeof(p)) 63 #else 64 #define size(p) (sizeof (p)) 65 #endif 66 cplim = buf + ifc.ifc_len; /*skip over if's with big ifr_addr's */ 67 for (cp = buf; cp < cplim; 68 cp += sizeof (ifr->ifr_name) + size(ifr->ifr_addr)) { 69 ifr = (struct ifreq *)cp; 70 bzero((char *)&ifs, sizeof(ifs)); 71 ifs.int_addr = ifr->ifr_addr; 72 ifreq = *ifr; 73 if (ioctl(s, SIOCGIFFLAGS, (char *)&ifreq) < 0) { 74 syslog(LOG_ERR, "ioctl (get interface flags)"); 75 continue; 76 } 77 ifs.int_flags = ifreq.ifr_flags | IFF_INTERFACE; 78 if ((ifs.int_flags & IFF_UP) == 0 || 79 ifr->ifr_addr.sa_family == AF_UNSPEC) { 80 lookforinterfaces = 1; 81 continue; 82 } 83 if (ifs.int_addr.sa_family != AF_NS) 84 continue; 85 if (ifs.int_flags & IFF_POINTOPOINT) { 86 if (ioctl(s, SIOCGIFDSTADDR, (char *)&ifreq) < 0) { 87 syslog(LOG_ERR, "ioctl (get dstaddr): %m"); 88 continue; 89 } 90 ifs.int_dstaddr = ifreq.ifr_dstaddr; 91 } 92 if (ifs.int_flags & IFF_BROADCAST) { 93 if (ioctl(s, SIOCGIFBRDADDR, (char *)&ifreq) < 0) { 94 syslog(LOG_ERR, "ioctl (get broadaddr: %m"); 95 continue; 96 } 97 ifs.int_broadaddr = ifreq.ifr_broadaddr; 98 } 99 /* 100 * already known to us? 101 * what makes a POINTOPOINT if unique is its dst addr, 102 * NOT its source address 103 */ 104 if ( ((ifs.int_flags & IFF_POINTOPOINT) && 105 if_ifwithdstaddr(&ifs.int_dstaddr)) || 106 ( ((ifs.int_flags & IFF_POINTOPOINT) == 0) && 107 if_ifwithaddr(&ifs.int_addr))) 108 continue; 109 /* no one cares about software loopback interfaces */ 110 if (strncmp(ifr->ifr_name,"lo", 2)==0) 111 continue; 112 ifp = (struct interface *)malloc(sizeof (struct interface)); 113 if (ifp == 0) { 114 syslog(LOG_ERR,"XNSrouted: out of memory\n"); 115 break; 116 } 117 *ifp = ifs; 118 /* 119 * Count the # of directly connected networks 120 * and point to point links which aren't looped 121 * back to ourself. This is used below to 122 * decide if we should be a routing ``supplier''. 123 */ 124 if ((ifs.int_flags & IFF_POINTOPOINT) == 0 || 125 if_ifwithaddr(&ifs.int_dstaddr) == 0) 126 externalinterfaces++; 127 /* 128 * If we have a point-to-point link, we want to act 129 * as a supplier even if it's our only interface, 130 * as that's the only way our peer on the other end 131 * can tell that the link is up. 132 */ 133 if ((ifs.int_flags & IFF_POINTOPOINT) && supplier < 0) 134 supplier = 1; 135 ifp->int_name = malloc(strlen(ifr->ifr_name) + 1); 136 if (ifp->int_name == 0) { 137 syslog(LOG_ERR,"XNSrouted: out of memory\n"); 138 exit(1); 139 } 140 strcpy(ifp->int_name, ifr->ifr_name); 141 ifp->int_metric = 0; 142 ifp->int_next = ifnet; 143 ifnet = ifp; 144 traceinit(ifp); 145 addrouteforif(ifp); 146 } 147 if (externalinterfaces > 1 && supplier < 0) 148 supplier = 1; 149 close(s); 150 } 151 152 addrouteforif(ifp) 153 struct interface *ifp; 154 { 155 struct sockaddr_ns net; 156 struct sockaddr *dst; 157 int state, metric; 158 struct rt_entry *rt; 159 160 if (ifp->int_flags & IFF_POINTOPOINT) { 161 int (*match)(); 162 register struct interface *ifp2 = ifnet; 163 register struct interface *ifprev = ifnet; 164 165 dst = &ifp->int_dstaddr; 166 167 /* Search for interfaces with the same net */ 168 ifp->int_sq.n = ifp->int_sq.p = &(ifp->int_sq); 169 match = afswitch[dst->sa_family].af_netmatch; 170 if (match) 171 for (ifp2 = ifnet; ifp2; ifp2 =ifp2->int_next) { 172 if (ifp->int_flags & IFF_POINTOPOINT == 0) 173 continue; 174 if ((*match)(&ifp2->int_dstaddr,&ifp->int_dstaddr)) { 175 insque(&ifp2->int_sq,&ifp->int_sq); 176 break; 177 } 178 } 179 } else { 180 dst = &ifp->int_broadaddr; 181 } 182 rt = rtlookup(dst); 183 if (rt) 184 rtdelete(rt); 185 if (tracing) 186 fprintf(stderr, "Adding route to interface %s\n", ifp->int_name); 187 if (ifp->int_transitions++ > 0) 188 syslog(LOG_ERR, "re-installing interface %s", ifp->int_name); 189 rtadd(dst, &ifp->int_addr, ifp->int_metric, 190 ifp->int_flags & (IFF_INTERFACE|IFF_PASSIVE|IFF_REMOTE)); 191 } 192 193