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.12 (Berkeley) 02/20/92"; 13 #endif /* not lint */ 14 15 /* 16 * Routing Table Management Daemon 17 */ 18 #include "defs.h" 19 #include <sys/ioctl.h> 20 #include <sys/kinfo.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 int needed, rlen, no_nsaddr = 0, flags = 0; 86 char *buf, *cplim, *cp; 87 register struct if_msghdr *ifm; 88 register struct ifa_msghdr *ifam; 89 struct sockaddr_dl *sdl; 90 u_long i; 91 92 if ((needed = getkerninfo(KINFO_RT_IFLIST, 0, 0, 0)) < 0) 93 quit("route-getkerninfo-estimate"); 94 if ((buf = malloc(needed)) == NULL) 95 quit("malloc"); 96 if ((rlen = getkerninfo(KINFO_RT_IFLIST, buf, &needed, 0)) < 0) 97 quit("actual retrieval of interface table"); 98 lookforinterfaces = 0; 99 cplim = buf + rlen; 100 for (cp = buf; cp < cplim; cp += ifm->ifm_msglen) { 101 ifm = (struct if_msghdr *)cp; 102 if (ifm->ifm_type == RTM_IFINFO) { 103 bzero(&ifs, sizeof(ifs)); 104 ifs.int_flags = flags = ifm->ifm_flags | IFF_INTERFACE; 105 if ((flags & IFF_UP) == 0 || no_nsaddr) 106 lookforinterfaces = 1; 107 sdl = (struct sockaddr_dl *) (ifm + 1); 108 sdl->sdl_data[sdl->sdl_nlen] = 0; 109 no_nsaddr = 1; 110 continue; 111 } 112 if (ifm->ifm_type != RTM_NEWADDR) 113 quit("ifinit: out of sync"); 114 if ((flags & IFF_UP) == 0) 115 continue; 116 ifam = (struct ifa_msghdr *)ifm; 117 info.rti_addrs = ifam->ifam_addrs; 118 rt_xaddrs((char *)(ifam + 1), cp + ifam->ifam_msglen, &info); 119 if (ifaaddr == 0) { 120 syslog(LOG_ERR, "%s: (get addr)", sdl->sdl_data); 121 continue; 122 } 123 ifs.int_addr = *ifaaddr; 124 if (ifs.int_addr.sa_family != AF_NS) 125 continue; 126 no_nsaddr = 0; 127 if (ifs.int_flags & IFF_POINTOPOINT) { 128 if (brdaddr == 0) { 129 syslog(LOG_ERR, "%s: (get dstaddr)", 130 sdl->sdl_data); 131 continue; 132 } 133 if (brdaddr->sa_family == AF_UNSPEC) { 134 lookforinterfaces = 1; 135 continue; 136 } 137 ifs.int_dstaddr = *brdaddr; 138 } 139 if (ifs.int_flags & IFF_BROADCAST) { 140 if (brdaddr == 0) { 141 syslog(LOG_ERR, "%s: (get broadaddr)", 142 sdl->sdl_data); 143 continue; 144 } 145 ifs.int_dstaddr = *brdaddr; 146 } 147 /* 148 * already known to us? 149 * what makes a POINTOPOINT if unique is its dst addr, 150 * NOT its source address 151 */ 152 if ( ((ifs.int_flags & IFF_POINTOPOINT) && 153 if_ifwithdstaddr(&ifs.int_dstaddr)) || 154 ( ((ifs.int_flags & IFF_POINTOPOINT) == 0) && 155 if_ifwithaddr(&ifs.int_addr))) 156 continue; 157 /* no one cares about software loopback interfaces */ 158 if (ifs.int_flags & IFF_LOOPBACK) 159 continue; 160 ifp = (struct interface *) 161 malloc(sdl->sdl_nlen + 1 + sizeof(ifs)); 162 if (ifp == 0) { 163 syslog(LOG_ERR, "XNSrouted: out of memory\n"); 164 lookforinterfaces = 1; 165 break; 166 } 167 *ifp = ifs; 168 /* 169 * Count the # of directly connected networks 170 * and point to point links which aren't looped 171 * back to ourself. This is used below to 172 * decide if we should be a routing ``supplier''. 173 */ 174 if ((ifs.int_flags & IFF_POINTOPOINT) == 0 || 175 if_ifwithaddr(&ifs.int_dstaddr) == 0) 176 externalinterfaces++; 177 /* 178 * If we have a point-to-point link, we want to act 179 * as a supplier even if it's our only interface, 180 * as that's the only way our peer on the other end 181 * can tell that the link is up. 182 */ 183 if ((ifs.int_flags & IFF_POINTOPOINT) && supplier < 0) 184 supplier = 1; 185 ifp->int_name = (char *)(ifp + 1); 186 strcpy(ifp->int_name, sdl->sdl_data); 187 ifp->int_metric = ifam->ifam_metric; 188 ifp->int_next = ifnet; 189 ifnet = ifp; 190 traceinit(ifp); 191 addrouteforif(ifp); 192 } 193 if (externalinterfaces > 1 && supplier < 0) 194 supplier = 1; 195 free(buf); 196 } 197 198 addrouteforif(ifp) 199 struct interface *ifp; 200 { 201 struct sockaddr_ns net; 202 struct sockaddr *dst; 203 int state, metric; 204 struct rt_entry *rt; 205 206 if (ifp->int_flags & IFF_POINTOPOINT) { 207 int (*match)(); 208 register struct interface *ifp2 = ifnet; 209 register struct interface *ifprev = ifnet; 210 211 dst = &ifp->int_dstaddr; 212 213 /* Search for interfaces with the same net */ 214 ifp->int_sq.n = ifp->int_sq.p = &(ifp->int_sq); 215 match = afswitch[dst->sa_family].af_netmatch; 216 if (match) 217 for (ifp2 = ifnet; ifp2; ifp2 =ifp2->int_next) { 218 if (ifp->int_flags & IFF_POINTOPOINT == 0) 219 continue; 220 if ((*match)(&ifp2->int_dstaddr,&ifp->int_dstaddr)) { 221 insque(&ifp2->int_sq,&ifp->int_sq); 222 break; 223 } 224 } 225 } else { 226 dst = &ifp->int_broadaddr; 227 } 228 rt = rtlookup(dst); 229 if (rt) 230 rtdelete(rt); 231 if (tracing) 232 fprintf(stderr, "Adding route to interface %s\n", ifp->int_name); 233 if (ifp->int_transitions++ > 0) 234 syslog(LOG_ERR, "re-installing interface %s", ifp->int_name); 235 rtadd(dst, &ifp->int_addr, ifp->int_metric, 236 ifp->int_flags & (IFF_INTERFACE|IFF_PASSIVE|IFF_REMOTE)); 237 } 238 239