|
|
1.1 ! root 1: #ifndef lint ! 2: static char sccsid[] = "@(#)startup.c 4.4 (Berkeley) 5/25/83"; ! 3: #endif ! 4: ! 5: /* ! 6: * Routing Table Management Daemon ! 7: */ ! 8: #include "defs.h" ! 9: #include <net/if.h> ! 10: #include <nlist.h> ! 11: ! 12: struct interface *ifnet; ! 13: int kmem = -1; ! 14: int lookforinterfaces = 1; ! 15: int performnlist = 1; ! 16: int externalinterfaces = 0; /* # of remote and local interfaces */ ! 17: ! 18: struct nlist nl[] = { ! 19: #define N_IFNET 0 ! 20: { "_ifnet" }, ! 21: { "" }, ! 22: }; ! 23: ! 24: /* ! 25: * Probe the kernel through /dev/kmem to find the network ! 26: * interfaces which have configured themselves. If the ! 27: * interface is present but not yet up (for example an ! 28: * ARPANET IMP), set the lookforinterfaces flag so we'll ! 29: * come back later and look again. ! 30: */ ! 31: ifinit() ! 32: { ! 33: struct interface *ifp; ! 34: struct ifnet ifs, *next; ! 35: char name[32], *cp, *index(); ! 36: ! 37: if (performnlist) { ! 38: nlist("/vmunix", nl); ! 39: if (nl[N_IFNET].n_value == 0) { ! 40: printf("ifnet: not in namelist\n"); ! 41: goto bad; ! 42: } ! 43: performnlist = 0; ! 44: } ! 45: if (kmem < 0) { ! 46: kmem = open("/dev/kmem", 0); ! 47: if (kmem < 0) { ! 48: perror("/dev/kmem"); ! 49: goto bad; ! 50: } ! 51: } ! 52: if (lseek(kmem, (long)nl[N_IFNET].n_value, 0) == -1 || ! 53: read(kmem, (char *)&next, sizeof (next)) != sizeof (next)) { ! 54: printf("ifnet: error reading kmem\n"); ! 55: goto bad; ! 56: } ! 57: lookforinterfaces = 0; ! 58: while (next) { ! 59: if (lseek(kmem, (long)next, 0) == -1 || ! 60: read(kmem, (char *)&ifs, sizeof (ifs)) != sizeof (ifs)) { ! 61: perror("read"); ! 62: goto bad; ! 63: } ! 64: next = ifs.if_next; ! 65: if ((ifs.if_flags & IFF_UP) == 0) { ! 66: lookforinterfaces = 1; ! 67: continue; ! 68: } ! 69: /* already known to us? */ ! 70: if (if_ifwithaddr(&ifs.if_addr)) ! 71: continue; ! 72: /* argh, this'll have to change sometime */ ! 73: if (ifs.if_addr.sa_family != AF_INET) ! 74: continue; ! 75: /* no one cares about software loopback interfaces */ ! 76: if (ifs.if_net == LOOPBACKNET) ! 77: continue; ! 78: ifp = (struct interface *)malloc(sizeof (struct interface)); ! 79: if (ifp == 0) { ! 80: printf("routed: out of memory\n"); ! 81: break; ! 82: } ! 83: /* ! 84: * Count the # of directly connected networks ! 85: * and point to point links which aren't looped ! 86: * back to ourself. This is used below to ! 87: * decide if we should be a routing ``supplier''. ! 88: */ ! 89: if ((ifs.if_flags & IFF_POINTOPOINT) == 0 || ! 90: if_ifwithaddr(&ifs.if_dstaddr) == 0) ! 91: externalinterfaces++; ! 92: lseek(kmem, ifs.if_name, 0); ! 93: read(kmem, name, sizeof (name)); ! 94: name[sizeof (name) - 1] = '\0'; ! 95: cp = index(name, '\0'); ! 96: *cp++ = ifs.if_unit + '0'; ! 97: *cp = '\0'; ! 98: ifp->int_name = malloc(strlen(name) + 1); ! 99: if (ifp->int_name == 0) { ! 100: fprintf(stderr, "routed: ifinit: out of memory\n"); ! 101: goto bad; /* ??? */ ! 102: } ! 103: strcpy(ifp->int_name, name); ! 104: ifp->int_addr = ifs.if_addr; ! 105: ifp->int_flags = ifs.if_flags | IFF_INTERFACE; ! 106: /* this works because broadaddr overlaps dstaddr */ ! 107: ifp->int_broadaddr = ifs.if_broadaddr; ! 108: ifp->int_net = ifs.if_net; ! 109: ifp->int_metric = 0; ! 110: ifp->int_next = ifnet; ! 111: ifnet = ifp; ! 112: traceinit(ifp); ! 113: addrouteforif(ifp); ! 114: } ! 115: if (externalinterfaces > 1 && supplier < 0) ! 116: supplier = 1; ! 117: return; ! 118: bad: ! 119: sleep(60); ! 120: close(kmem), close(s); ! 121: execv("/etc/routed", argv0); ! 122: _exit(0177); ! 123: } ! 124: ! 125: addrouteforif(ifp) ! 126: struct interface *ifp; ! 127: { ! 128: struct sockaddr_in net; ! 129: struct sockaddr *dst; ! 130: int state, metric; ! 131: struct rt_entry *rt; ! 132: ! 133: if (ifp->int_flags & IFF_POINTOPOINT) ! 134: dst = &ifp->int_dstaddr; ! 135: else { ! 136: bzero((char *)&net, sizeof (net)); ! 137: net.sin_family = AF_INET; ! 138: net.sin_addr = inet_makeaddr(ifp->int_net, INADDR_ANY); ! 139: dst = (struct sockaddr *)&net; ! 140: } ! 141: rt = rtlookup(dst); ! 142: rtadd(dst, &ifp->int_addr, ifp->int_metric, ! 143: ifp->int_flags & (IFF_INTERFACE|IFF_PASSIVE|IFF_REMOTE)); ! 144: if (rt) ! 145: rtdelete(rt); ! 146: } ! 147: ! 148: /* ! 149: * As a concession to the ARPANET we read a list of gateways ! 150: * from /etc/gateways and add them to our tables. This file ! 151: * exists at each ARPANET gateway and indicates a set of ``remote'' ! 152: * gateways (i.e. a gateway which we can't immediately determine ! 153: * if it's present or not as we can do for those directly connected ! 154: * at the hardware level). If a gateway is marked ``passive'' ! 155: * in the file, then we assume it doesn't have a routing process ! 156: * of our design and simply assume it's always present. Those ! 157: * not marked passive are treated as if they were directly ! 158: * connected -- they're added into the interface list so we'll ! 159: * send them routing updates. ! 160: */ ! 161: gwkludge() ! 162: { ! 163: struct sockaddr_in dst, gate; ! 164: FILE *fp; ! 165: char *type, *dname, *gname, *qual, buf[BUFSIZ]; ! 166: struct interface *ifp; ! 167: int metric; ! 168: ! 169: fp = fopen("/etc/gateways", "r"); ! 170: if (fp == NULL) ! 171: return; ! 172: qual = buf; ! 173: dname = buf + 64; ! 174: gname = buf + ((BUFSIZ - 64) / 3); ! 175: type = buf + (((BUFSIZ - 64) * 2) / 3); ! 176: bzero((char *)&dst, sizeof (dst)); ! 177: bzero((char *)&gate, sizeof (gate)); ! 178: /* format: {net | host} XX gateway XX metric DD [passive]\n */ ! 179: #define readentry(fp) \ ! 180: fscanf((fp), "%s %s gateway %s metric %d %s\n", \ ! 181: type, dname, gname, &metric, qual) ! 182: for (;;) { ! 183: if (readentry(fp) == EOF) ! 184: break; ! 185: if (!getnetorhostname(type, dname, &dst)) ! 186: continue; ! 187: if (!gethostnameornumber(gname, &gate)) ! 188: continue; ! 189: ifp = (struct interface *)malloc(sizeof (*ifp)); ! 190: bzero((char *)ifp, sizeof (*ifp)); ! 191: ifp->int_flags = IFF_REMOTE; ! 192: /* can't identify broadcast capability */ ! 193: ifp->int_net = inet_netof(dst.sin_addr); ! 194: if (strcmp(type, "host") == 0) { ! 195: ifp->int_flags |= IFF_POINTOPOINT; ! 196: ifp->int_dstaddr = *((struct sockaddr *)&dst); ! 197: } ! 198: if (strcmp(qual, "passive") == 0) ! 199: ifp->int_flags |= IFF_PASSIVE; ! 200: else ! 201: /* assume no duplicate entries */ ! 202: externalinterfaces++; ! 203: ifp->int_addr = *((struct sockaddr *)&gate); ! 204: ifp->int_metric = metric; ! 205: ifp->int_next = ifnet; ! 206: ifnet = ifp; ! 207: addrouteforif(ifp); ! 208: } ! 209: fclose(fp); ! 210: } ! 211: ! 212: getnetorhostname(type, name, sin) ! 213: char *type, *name; ! 214: struct sockaddr_in *sin; ! 215: { ! 216: ! 217: if (strcmp(type, "net") == 0) { ! 218: struct netent *np = getnetbyname(name); ! 219: int n; ! 220: ! 221: if (np == 0) ! 222: n = inet_network(name); ! 223: else { ! 224: if (np->n_addrtype != AF_INET) ! 225: return (0); ! 226: n = np->n_net; ! 227: } ! 228: sin->sin_family = AF_INET; ! 229: sin->sin_addr = inet_makeaddr(n, INADDR_ANY); ! 230: return (1); ! 231: } ! 232: if (strcmp(type, "host") == 0) { ! 233: struct hostent *hp = gethostbyname(name); ! 234: ! 235: if (hp == 0) ! 236: sin->sin_addr.s_addr = inet_addr(name); ! 237: else { ! 238: if (hp->h_addrtype != AF_INET) ! 239: return (0); ! 240: bcopy(hp->h_addr, &sin->sin_addr, hp->h_length); ! 241: } ! 242: sin->sin_family = AF_INET; ! 243: return (1); ! 244: } ! 245: return (0); ! 246: } ! 247: ! 248: gethostnameornumber(name, sin) ! 249: char *name; ! 250: struct sockaddr_in *sin; ! 251: { ! 252: struct hostent *hp; ! 253: ! 254: hp = gethostbyname(name); ! 255: if (hp) { ! 256: bcopy(hp->h_addr, &sin->sin_addr, hp->h_length); ! 257: sin->sin_family = hp->h_addrtype; ! 258: return (1); ! 259: } ! 260: sin->sin_addr.s_addr = inet_addr(name); ! 261: sin->sin_family = AF_INET; ! 262: return (sin->sin_addr.s_addr != -1); ! 263: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.