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.13 (Berkeley) 04/01/93"; 13 #endif /* not lint */ 14 15 /* 16 * Routing Table Management Daemon 17 */ 18 #include "defs.h" 19 #include <sys/ioctl.h> 20 #include <sys/sysctl.h> 21 #include <net/if.h> 22 #include <net/if_dl.h> 23 #include <nlist.h> 24 #include <stdlib.h> 25 26 struct interface *ifnet; 27 int lookforinterfaces = 1; 28 int performnlist = 1; 29 int gateway = 0; 30 int externalinterfaces = 0; /* # of remote and local interfaces */ 31 char ether_broadcast_addr[6] = {0xff, 0xff, 0xff, 0xff, 0xff, 0xff}; 32 33 34 void 35 quit(s) 36 char *s; 37 { 38 extern int errno; 39 int sverrno = errno; 40 41 (void) fprintf(stderr, "route: "); 42 if (s) 43 (void) fprintf(stderr, "%s: ", s); 44 (void) fprintf(stderr, "%s\n", strerror(sverrno)); 45 exit(1); 46 /* NOTREACHED */ 47 } 48 49 struct rt_addrinfo info; 50 /* Sleazy use of local variables throughout file, warning!!!! */ 51 #define netmask info.rti_info[RTAX_NETMASK] 52 #define ifaaddr info.rti_info[RTAX_IFA] 53 #define brdaddr info.rti_info[RTAX_BRD] 54 55 #define ROUNDUP(a) \ 56 ((a) > 0 ? (1 + (((a) - 1) | (sizeof(long) - 1))) : sizeof(long)) 57 #define ADVANCE(x, n) (x += ROUNDUP((n)->sa_len)) 58 59 void 60 rt_xaddrs(cp, cplim, rtinfo) 61 register caddr_t cp, cplim; 62 register struct rt_addrinfo *rtinfo; 63 { 64 register struct sockaddr *sa; 65 register int i; 66 67 bzero(rtinfo->rti_info, sizeof(rtinfo->rti_info)); 68 for (i = 0; (i < RTAX_MAX) && (cp < cplim); i++) { 69 if ((rtinfo->rti_addrs & (1 << i)) == 0) 70 continue; 71 rtinfo->rti_info[i] = sa = (struct sockaddr *)cp; 72 ADVANCE(cp, sa); 73 } 74 } 75 76 /* 77 * Find the network interfaces which have configured themselves. 78 * If the interface is present but not yet up (for example an 79 * ARPANET IMP), set the lookforinterfaces flag so we'll 80 * come back later and look again. 81 */ 82 ifinit() 83 { 84 struct interface ifs, *ifp; 85 size_t needed; 86 int mib[6], no_nsaddr = 0, flags = 0; 87 char *buf, *cplim, *cp; 88 register struct if_msghdr *ifm; 89 register struct ifa_msghdr *ifam; 90 struct sockaddr_dl *sdl; 91 u_long i; 92 93 mib[0] = CTL_NET; 94 mib[1] = PF_ROUTE; 95 mib[2] = 0; 96 mib[3] = AF_NS; 97 mib[4] = NET_RT_IFLIST; 98 mib[5] = 0; 99 if (sysctl(mib, 6, NULL, &needed, NULL, 0) < 0) 100 quit("route-sysctl-estimate"); 101 if ((buf = malloc(needed)) == NULL) 102 quit("malloc"); 103 if (sysctl(mib, 6, buf, &needed, NULL, 0) < 0) 104 lookforinterfaces = 0; 105 cplim = buf + needed; 106 for (cp = buf; cp < cplim; cp += ifm->ifm_msglen) { 107 ifm = (struct if_msghdr *)cp; 108 if (ifm->ifm_type == RTM_IFINFO) { 109 bzero(&ifs, sizeof(ifs)); 110 ifs.int_flags = flags = ifm->ifm_flags | IFF_INTERFACE; 111 if ((flags & IFF_UP) == 0 || no_nsaddr) 112 lookforinterfaces = 1; 113 sdl = (struct sockaddr_dl *) (ifm + 1); 114 sdl->sdl_data[sdl->sdl_nlen] = 0; 115 no_nsaddr = 1; 116 continue; 117 } 118 if (ifm->ifm_type != RTM_NEWADDR) 119 quit("ifinit: out of sync"); 120 if ((flags & IFF_UP) == 0) 121 continue; 122 ifam = (struct ifa_msghdr *)ifm; 123 info.rti_addrs = ifam->ifam_addrs; 124 rt_xaddrs((char *)(ifam + 1), cp + ifam->ifam_msglen, &info); 125 if (ifaaddr == 0) { 126 syslog(LOG_ERR, "%s: (get addr)", sdl->sdl_data); 127 continue; 128 } 129 ifs.int_addr = *ifaaddr; 130 if (ifs.int_addr.sa_family != AF_NS) 131 continue; 132 no_nsaddr = 0; 133 if (ifs.int_flags & IFF_POINTOPOINT) { 134 if (brdaddr == 0) { 135 syslog(LOG_ERR, "%s: (get dstaddr)", 136 sdl->sdl_data); 137 continue; 138 } 139 if (brdaddr->sa_family == AF_UNSPEC) { 140 lookforinterfaces = 1; 141 continue; 142 } 143 ifs.int_dstaddr = *brdaddr; 144 } 145 if (ifs.int_flags & IFF_BROADCAST) { 146 if (brdaddr == 0) { 147 syslog(LOG_ERR, "%s: (get broadaddr)", 148 sdl->sdl_data); 149 continue; 150 } 151 ifs.int_dstaddr = *brdaddr; 152 } 153 /* 154 * already known to us? 155 * what makes a POINTOPOINT if unique is its dst addr, 156 * NOT its source address 157 */ 158 if ( ((ifs.int_flags & IFF_POINTOPOINT) && 159 if_ifwithdstaddr(&ifs.int_dstaddr)) || 160 ( ((ifs.int_flags & IFF_POINTOPOINT) == 0) && 161 if_ifwithaddr(&ifs.int_addr))) 162 continue; 163 /* no one cares about software loopback interfaces */ 164 if (ifs.int_flags & IFF_LOOPBACK) 165 continue; 166 ifp = (struct interface *) 167 malloc(sdl->sdl_nlen + 1 + sizeof(ifs)); 168 if (ifp == 0) { 169 syslog(LOG_ERR, "XNSrouted: out of memory\n"); 170 lookforinterfaces = 1; 171 break; 172 } 173 *ifp = ifs; 174 /* 175 * Count the # of directly connected networks 176 * and point to point links which aren't looped 177 * back to ourself. This is used below to 178 * decide if we should be a routing ``supplier''. 179 */ 180 if ((ifs.int_flags & IFF_POINTOPOINT) == 0 || 181 if_ifwithaddr(&ifs.int_dstaddr) == 0) 182 externalinterfaces++; 183 /* 184 * If we have a point-to-point link, we want to act 185 * as a supplier even if it's our only interface, 186 * as that's the only way our peer on the other end 187 * can tell that the link is up. 188 */ 189 if ((ifs.int_flags & IFF_POINTOPOINT) && supplier < 0) 190 supplier = 1; 191 ifp->int_name = (char *)(ifp + 1); 192 strcpy(ifp->int_name, sdl->sdl_data); 193 ifp->int_metric = ifam->ifam_metric; 194 ifp->int_next = ifnet; 195 ifnet = ifp; 196 traceinit(ifp); 197 addrouteforif(ifp); 198 } 199 if (externalinterfaces > 1 && supplier < 0) 200 supplier = 1; 201 free(buf); 202 } 203 204 addrouteforif(ifp) 205 struct interface *ifp; 206 { 207 struct sockaddr_ns net; 208 struct sockaddr *dst; 209 int state, metric; 210 struct rt_entry *rt; 211 212 if (ifp->int_flags & IFF_POINTOPOINT) { 213 int (*match)(); 214 register struct interface *ifp2 = ifnet; 215 register struct interface *ifprev = ifnet; 216 217 dst = &ifp->int_dstaddr; 218 219 /* Search for interfaces with the same net */ 220 ifp->int_sq.n = ifp->int_sq.p = &(ifp->int_sq); 221 match = afswitch[dst->sa_family].af_netmatch; 222 if (match) 223 for (ifp2 = ifnet; ifp2; ifp2 =ifp2->int_next) { 224 if (ifp->int_flags & IFF_POINTOPOINT == 0) 225 continue; 226 if ((*match)(&ifp2->int_dstaddr,&ifp->int_dstaddr)) { 227 insque(&ifp2->int_sq,&ifp->int_sq); 228 break; 229 } 230 } 231 } else { 232 dst = &ifp->int_broadaddr; 233 } 234 rt = rtlookup(dst); 235 if (rt) 236 rtdelete(rt); 237 if (tracing) 238 fprintf(stderr, "Adding route to interface %s\n", ifp->int_name); 239 if (ifp->int_transitions++ > 0) 240 syslog(LOG_ERR, "re-installing interface %s", ifp->int_name); 241 rtadd(dst, &ifp->int_addr, ifp->int_metric, 242 ifp->int_flags & (IFF_INTERFACE|IFF_PASSIVE|IFF_REMOTE)); 243 } 244 245