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