1 #ifndef lint 2 static char sccsid[] = "@(#)startup.c 4.4 (Berkeley) 05/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 } 264