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