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