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