|
|
1.1 ! root 1: /* ! 2: * Copyright (c) 1983 Regents of the University of California. ! 3: * All rights reserved. The Berkeley software License Agreement ! 4: * specifies the terms and conditions for redistribution. ! 5: */ ! 6: ! 7: #ifndef lint ! 8: static char sccsid[] = "@(#)startup.c 5.7 (Berkeley) 6/3/86"; ! 9: #endif not lint ! 10: ! 11: /* ! 12: * Routing Table Management Daemon ! 13: */ ! 14: #include "defs.h" ! 15: #include <sys/ioctl.h> ! 16: #include <net/if.h> ! 17: #include <syslog.h> ! 18: ! 19: struct interface *ifnet; ! 20: int lookforinterfaces = 1; ! 21: int externalinterfaces = 0; /* # of remote and local interfaces */ ! 22: ! 23: /* ! 24: * Find the network interfaces which have configured themselves. ! 25: * If the interface is present but not yet up (for example an ! 26: * ARPANET IMP), set the lookforinterfaces flag so we'll ! 27: * come back later and look again. ! 28: */ ! 29: ifinit() ! 30: { ! 31: struct interface ifs, *ifp; ! 32: int s, n; ! 33: char buf[BUFSIZ]; ! 34: struct ifconf ifc; ! 35: struct ifreq ifreq, *ifr; ! 36: struct sockaddr_in *sin; ! 37: u_long i; ! 38: ! 39: if ((s = socket(AF_INET, SOCK_DGRAM, 0)) < 0) { ! 40: syslog(LOG_ERR, "socket: %m"); ! 41: exit(1); ! 42: } ! 43: ifc.ifc_len = sizeof (buf); ! 44: ifc.ifc_buf = buf; ! 45: if (ioctl(s, SIOCGIFCONF, (char *)&ifc) < 0) { ! 46: syslog(LOG_ERR, "ioctl (get interface configuration)"); ! 47: close(s); ! 48: return (0); ! 49: } ! 50: ifr = ifc.ifc_req; ! 51: lookforinterfaces = 0; ! 52: for (n = ifc.ifc_len / sizeof (struct ifreq); n > 0; n--, ifr++) { ! 53: bzero((char *)&ifs, sizeof(ifs)); ! 54: ifs.int_addr = ifr->ifr_addr; ! 55: ifreq = *ifr; ! 56: if (ioctl(s, SIOCGIFFLAGS, (char *)&ifreq) < 0) { ! 57: syslog(LOG_ERR, "ioctl (get interface flags)"); ! 58: continue; ! 59: } ! 60: ifs.int_flags = ifreq.ifr_flags | IFF_INTERFACE; ! 61: /* no one cares about software loopback interfaces */ ! 62: if (ifs.int_flags & IFF_LOOPBACK) ! 63: continue; ! 64: if ((ifs.int_flags & IFF_UP) == 0 || ! 65: ifr->ifr_addr.sa_family == AF_UNSPEC) { ! 66: lookforinterfaces = 1; ! 67: continue; ! 68: } ! 69: /* already known to us? */ ! 70: if (if_ifwithaddr(&ifs.int_addr)) ! 71: continue; ! 72: /* argh, this'll have to change sometime */ ! 73: if (ifs.int_addr.sa_family != AF_INET) ! 74: continue; ! 75: if (ifs.int_flags & IFF_POINTOPOINT) { ! 76: if (ioctl(s, SIOCGIFDSTADDR, (char *)&ifreq) < 0) { ! 77: syslog(LOG_ERR, "ioctl (get dstaddr)"); ! 78: continue; ! 79: } ! 80: ifs.int_dstaddr = ifreq.ifr_dstaddr; ! 81: } ! 82: if (ifs.int_flags & IFF_BROADCAST) { ! 83: if (ioctl(s, SIOCGIFBRDADDR, (char *)&ifreq) < 0) { ! 84: syslog(LOG_ERR, "ioctl (get broadaddr)"); ! 85: continue; ! 86: } ! 87: ifs.int_broadaddr = ifreq.ifr_broadaddr; ! 88: } ! 89: if (ioctl(s, SIOCGIFMETRIC, (char *)&ifreq) < 0) ! 90: syslog(LOG_ERR, "ioctl (get metric)"); ! 91: else ! 92: ifs.int_metric = ifreq.ifr_metric; ! 93: if (ioctl(s, SIOCGIFNETMASK, (char *)&ifreq) < 0) { ! 94: syslog(LOG_ERR, "ioctl (get netmask)"); ! 95: continue; ! 96: } ! 97: sin = (struct sockaddr_in *)&ifreq.ifr_addr; ! 98: ifs.int_subnetmask = ntohl(sin->sin_addr.s_addr); ! 99: sin = (struct sockaddr_in *)&ifs.int_addr; ! 100: i = ntohl(sin->sin_addr.s_addr); ! 101: if (IN_CLASSA(i)) ! 102: ifs.int_netmask = IN_CLASSA_NET; ! 103: else if (IN_CLASSB(i)) ! 104: ifs.int_netmask = IN_CLASSB_NET; ! 105: else ! 106: ifs.int_netmask = IN_CLASSC_NET; ! 107: ifs.int_net = i & ifs.int_netmask; ! 108: ifs.int_subnet = i & ifs.int_subnetmask; ! 109: if (ifs.int_subnetmask != ifs.int_netmask) ! 110: ifs.int_flags |= IFF_SUBNET; ! 111: ifp = (struct interface *)malloc(sizeof (struct interface)); ! 112: if (ifp == 0) { ! 113: printf("routed: out of memory\n"); ! 114: break; ! 115: } ! 116: *ifp = ifs; ! 117: /* ! 118: * Count the # of directly connected networks ! 119: * and point to point links which aren't looped ! 120: * back to ourself. This is used below to ! 121: * decide if we should be a routing ``supplier''. ! 122: */ ! 123: if ((ifs.int_flags & IFF_POINTOPOINT) == 0 || ! 124: if_ifwithaddr(&ifs.int_dstaddr) == 0) ! 125: externalinterfaces++; ! 126: /* ! 127: * If we have a point-to-point link, we want to act ! 128: * as a supplier even if it's our only interface, ! 129: * as that's the only way our peer on the other end ! 130: * can tell that the link is up. ! 131: */ ! 132: if ((ifs.int_flags & IFF_POINTOPOINT) && supplier < 0) ! 133: supplier = 1; ! 134: ifp->int_name = malloc(strlen(ifr->ifr_name) + 1); ! 135: if (ifp->int_name == 0) { ! 136: fprintf(stderr, "routed: ifinit: out of memory\n"); ! 137: goto bad; /* ??? */ ! 138: } ! 139: strcpy(ifp->int_name, ifr->ifr_name); ! 140: ifp->int_next = ifnet; ! 141: ifnet = ifp; ! 142: traceinit(ifp); ! 143: addrouteforif(ifp); ! 144: } ! 145: if (externalinterfaces > 1 && supplier < 0) ! 146: supplier = 1; ! 147: close(s); ! 148: return; ! 149: bad: ! 150: sleep(60); ! 151: close(kmem), close(s); ! 152: execv("/etc/routed", argv0); ! 153: _exit(0177); ! 154: } ! 155: ! 156: /* ! 157: * Add route for interface if not currently installed. ! 158: * Create route to other end if a point-to-point link, ! 159: * otherwise a route to this (sub)network. ! 160: * INTERNET SPECIFIC. ! 161: */ ! 162: addrouteforif(ifp) ! 163: struct interface *ifp; ! 164: { ! 165: struct sockaddr_in net; ! 166: struct sockaddr *dst; ! 167: int state, metric; ! 168: struct rt_entry *rt; ! 169: ! 170: if (ifp->int_flags & IFF_POINTOPOINT) ! 171: dst = &ifp->int_dstaddr; ! 172: else { ! 173: bzero((char *)&net, sizeof (net)); ! 174: net.sin_family = AF_INET; ! 175: net.sin_addr = inet_makeaddr(ifp->int_subnet, INADDR_ANY); ! 176: dst = (struct sockaddr *)&net; ! 177: } ! 178: rt = rtfind(dst); ! 179: if (rt && ! 180: (rt->rt_state & (RTS_INTERFACE | RTS_INTERNAL)) == RTS_INTERFACE) ! 181: return; ! 182: if (rt) ! 183: rtdelete(rt); ! 184: /* ! 185: * If interface on subnetted network, ! 186: * install route to network as well. ! 187: * This is meant for external viewers. ! 188: */ ! 189: if ((ifp->int_flags & (IFF_SUBNET|IFF_POINTOPOINT)) == IFF_SUBNET) { ! 190: net.sin_addr = inet_makeaddr(ifp->int_net, INADDR_ANY); ! 191: rt = rtfind(dst); ! 192: if (rt == 0) ! 193: rtadd(dst, &ifp->int_addr, ifp->int_metric, ! 194: ((ifp->int_flags & (IFF_INTERFACE|IFF_REMOTE)) | ! 195: RTS_PASSIVE | RTS_INTERNAL | RTS_SUBNET)); ! 196: net.sin_addr = inet_makeaddr(ifp->int_subnet, INADDR_ANY); ! 197: } ! 198: if (ifp->int_transitions++ > 0) ! 199: syslog(LOG_ERR, "re-installing interface %s", ifp->int_name); ! 200: rtadd(dst, &ifp->int_addr, ifp->int_metric, ! 201: ifp->int_flags & (IFF_INTERFACE|IFF_PASSIVE|IFF_REMOTE|IFF_SUBNET)); ! 202: ! 203: } ! 204: ! 205: /* ! 206: * As a concession to the ARPANET we read a list of gateways ! 207: * from /etc/gateways and add them to our tables. This file ! 208: * exists at each ARPANET gateway and indicates a set of ``remote'' ! 209: * gateways (i.e. a gateway which we can't immediately determine ! 210: * if it's present or not as we can do for those directly connected ! 211: * at the hardware level). If a gateway is marked ``passive'' ! 212: * in the file, then we assume it doesn't have a routing process ! 213: * of our design and simply assume it's always present. Those ! 214: * not marked passive are treated as if they were directly ! 215: * connected -- they're added into the interface list so we'll ! 216: * send them routing updates. ! 217: */ ! 218: gwkludge() ! 219: { ! 220: struct sockaddr_in dst, gate; ! 221: FILE *fp; ! 222: char *type, *dname, *gname, *qual, buf[BUFSIZ]; ! 223: struct interface *ifp; ! 224: int metric, n; ! 225: struct rt_entry route; ! 226: ! 227: fp = fopen("/etc/gateways", "r"); ! 228: if (fp == NULL) ! 229: return; ! 230: qual = buf; ! 231: dname = buf + 64; ! 232: gname = buf + ((BUFSIZ - 64) / 3); ! 233: type = buf + (((BUFSIZ - 64) * 2) / 3); ! 234: bzero((char *)&dst, sizeof (dst)); ! 235: bzero((char *)&gate, sizeof (gate)); ! 236: bzero((char *)&route, sizeof(route)); ! 237: /* format: {net | host} XX gateway XX metric DD [passive]\n */ ! 238: #define readentry(fp) \ ! 239: fscanf((fp), "%s %s gateway %s metric %d %s\n", \ ! 240: type, dname, gname, &metric, qual) ! 241: for (;;) { ! 242: if ((n = readentry(fp)) == EOF) ! 243: break; ! 244: if (!getnetorhostname(type, dname, &dst)) ! 245: continue; ! 246: if (!gethostnameornumber(gname, &gate)) ! 247: continue; ! 248: if (strcmp(qual, "passive") == 0) { ! 249: /* ! 250: * Passive entries aren't placed in our tables, ! 251: * only the kernel's, so we don't copy all of the ! 252: * external routing information within a net. ! 253: * Internal machines should use the default ! 254: * route to a suitable gateway (like us). ! 255: */ ! 256: route.rt_dst = *(struct sockaddr *) &dst; ! 257: route.rt_router = *(struct sockaddr *) &gate; ! 258: route.rt_flags = RTF_UP; ! 259: if (strcmp(type, "host") == 0) ! 260: route.rt_flags |= RTF_HOST; ! 261: if (metric) ! 262: route.rt_flags |= RTF_GATEWAY; ! 263: (void) ioctl(s, SIOCADDRT, (char *)&route.rt_rt); ! 264: continue; ! 265: } ! 266: if (strcmp(qual, "external") == 0) { ! 267: /* ! 268: * Entries marked external are handled ! 269: * by other means, e.g. EGP, ! 270: * and are placed in our tables only ! 271: * to prevent overriding them ! 272: * with something else. ! 273: */ ! 274: rtadd(&dst, &gate, metric, RTS_EXTERNAL|RTS_PASSIVE); ! 275: continue; ! 276: } ! 277: /* assume no duplicate entries */ ! 278: externalinterfaces++; ! 279: ifp = (struct interface *)malloc(sizeof (*ifp)); ! 280: bzero((char *)ifp, sizeof (*ifp)); ! 281: ifp->int_flags = IFF_REMOTE; ! 282: /* can't identify broadcast capability */ ! 283: ifp->int_net = inet_netof(dst.sin_addr); ! 284: if (strcmp(type, "host") == 0) { ! 285: ifp->int_flags |= IFF_POINTOPOINT; ! 286: ifp->int_dstaddr = *((struct sockaddr *)&dst); ! 287: } ! 288: ifp->int_addr = *((struct sockaddr *)&gate); ! 289: ifp->int_metric = metric; ! 290: ifp->int_next = ifnet; ! 291: ifnet = ifp; ! 292: addrouteforif(ifp); ! 293: } ! 294: fclose(fp); ! 295: } ! 296: ! 297: getnetorhostname(type, name, sin) ! 298: char *type, *name; ! 299: struct sockaddr_in *sin; ! 300: { ! 301: ! 302: if (strcmp(type, "net") == 0) { ! 303: struct netent *np = getnetbyname(name); ! 304: int n; ! 305: ! 306: if (np == 0) ! 307: n = inet_network(name); ! 308: else { ! 309: if (np->n_addrtype != AF_INET) ! 310: return (0); ! 311: n = np->n_net; ! 312: /* ! 313: * getnetbyname returns right-adjusted value. ! 314: */ ! 315: if (n < 128) ! 316: n <<= IN_CLASSA_NSHIFT; ! 317: else if (n < 65536) ! 318: n <<= IN_CLASSB_NSHIFT; ! 319: else ! 320: n <<= IN_CLASSC_NSHIFT; ! 321: } ! 322: sin->sin_family = AF_INET; ! 323: sin->sin_addr = inet_makeaddr(n, INADDR_ANY); ! 324: return (1); ! 325: } ! 326: if (strcmp(type, "host") == 0) { ! 327: struct hostent *hp = gethostbyname(name); ! 328: ! 329: if (hp == 0) ! 330: sin->sin_addr.s_addr = inet_addr(name); ! 331: else { ! 332: if (hp->h_addrtype != AF_INET) ! 333: return (0); ! 334: bcopy(hp->h_addr, &sin->sin_addr, hp->h_length); ! 335: } ! 336: sin->sin_family = AF_INET; ! 337: return (1); ! 338: } ! 339: return (0); ! 340: } ! 341: ! 342: gethostnameornumber(name, sin) ! 343: char *name; ! 344: struct sockaddr_in *sin; ! 345: { ! 346: struct hostent *hp; ! 347: ! 348: hp = gethostbyname(name); ! 349: if (hp) { ! 350: bcopy(hp->h_addr, &sin->sin_addr, hp->h_length); ! 351: sin->sin_family = hp->h_addrtype; ! 352: return (1); ! 353: } ! 354: sin->sin_addr.s_addr = inet_addr(name); ! 355: sin->sin_family = AF_INET; ! 356: return (sin->sin_addr.s_addr != -1); ! 357: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.