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