1: /*
   2:  * Copyright (c) 1983 Regents of the University of California.
   3:  * All rights reserved.  The Berkeley software License Agreement
   4:  * specifies the terms and conditions for redistribution.
   5:  */
   6: 
   7: #if !defined(lint) && defined(DOSCCS)
   8: static char sccsid[] = "@(#)startup.c	5.7.1 (2.11BSD) 1996/11/19";
   9: #endif not lint
  10: 
  11: /*
  12:  * Routing Table Management Daemon
  13:  */
  14: #include "defs.h"
  15: #include <sys/ioctl.h>
  16: #include <net/if.h>
  17: #include <syslog.h>
  18: 
  19: struct  interface *ifnet;
  20: int lookforinterfaces = 1;
  21: int externalinterfaces = 0;     /* # of remote and local interfaces */
  22: 
  23: /*
  24:  * Find the network interfaces which have configured themselves.
  25:  * If the interface is present but not yet up (for example an
  26:  * ARPANET IMP), set the lookforinterfaces flag so we'll
  27:  * come back later and look again.
  28:  */
  29: ifinit()
  30: {
  31:     struct interface ifs, *ifp;
  32:     int s, n;
  33:     char buf[BUFSIZ];
  34:         struct ifconf ifc;
  35:         struct ifreq ifreq, *ifr;
  36:         struct sockaddr_in *sin;
  37:     u_long i;
  38: 
  39:     if ((s = socket(AF_INET, SOCK_DGRAM, 0)) < 0) {
  40:         syslog(LOG_ERR, "socket: %m");
  41:         exit(1);
  42:     }
  43:         ifc.ifc_len = sizeof (buf);
  44:         ifc.ifc_buf = buf;
  45:         if (ioctl(s, SIOCGIFCONF, (char *)&ifc) < 0) {
  46:                 syslog(LOG_ERR, "ioctl (get interface configuration)");
  47:         close(s);
  48:                 return (0);
  49:         }
  50:         ifr = ifc.ifc_req;
  51:     lookforinterfaces = 0;
  52:         for (n = ifc.ifc_len / sizeof (struct ifreq); n > 0; n--, ifr++) {
  53:         bzero((char *)&ifs, sizeof(ifs));
  54:         ifs.int_addr = ifr->ifr_addr;
  55:         ifreq = *ifr;
  56:                 if (ioctl(s, SIOCGIFFLAGS, (char *)&ifreq) < 0) {
  57:                         syslog(LOG_ERR, "ioctl (get interface flags)");
  58:                         continue;
  59:                 }
  60:         ifs.int_flags = ifreq.ifr_flags | IFF_INTERFACE;
  61:         /* no one cares about software loopback interfaces */
  62:         if (ifs.int_flags & IFF_LOOPBACK)
  63:             continue;
  64:         if ((ifs.int_flags & IFF_UP) == 0 ||
  65:             ifr->ifr_addr.sa_family == AF_UNSPEC) {
  66:             lookforinterfaces = 1;
  67:             continue;
  68:         }
  69:         /* already known to us? */
  70:         if (if_ifwithaddr(&ifs.int_addr))
  71:             continue;
  72:         /* argh, this'll have to change sometime */
  73:         if (ifs.int_addr.sa_family != AF_INET)
  74:             continue;
  75:                 if (ifs.int_flags & IFF_POINTOPOINT) {
  76:                         if (ioctl(s, SIOCGIFDSTADDR, (char *)&ifreq) < 0) {
  77:                                 syslog(LOG_ERR, "ioctl (get dstaddr)");
  78:                                 continue;
  79:             }
  80:             ifs.int_dstaddr = ifreq.ifr_dstaddr;
  81:         }
  82:                 if (ifs.int_flags & IFF_BROADCAST) {
  83:                         if (ioctl(s, SIOCGIFBRDADDR, (char *)&ifreq) < 0) {
  84:                                 syslog(LOG_ERR, "ioctl (get broadaddr)");
  85:                                 continue;
  86:                         }
  87:             ifs.int_broadaddr = ifreq.ifr_broadaddr;
  88:         }
  89:         if (ioctl(s, SIOCGIFMETRIC, (char *)&ifreq) < 0)
  90:             syslog(LOG_ERR, "ioctl (get metric)");
  91:         else
  92:             ifs.int_metric = ifreq.ifr_metric;
  93:         if (ioctl(s, SIOCGIFNETMASK, (char *)&ifreq) < 0) {
  94:             syslog(LOG_ERR, "ioctl (get netmask)");
  95:             continue;
  96:         }
  97:         sin = (struct sockaddr_in *)&ifreq.ifr_addr;
  98:         ifs.int_subnetmask = ntohl(sin->sin_addr.s_addr);
  99:         sin = (struct sockaddr_in *)&ifs.int_addr;
 100:         i = ntohl(sin->sin_addr.s_addr);
 101:         if (IN_CLASSA(i))
 102:             ifs.int_netmask = IN_CLASSA_NET;
 103:         else if (IN_CLASSB(i))
 104:             ifs.int_netmask = IN_CLASSB_NET;
 105:         else
 106:             ifs.int_netmask = IN_CLASSC_NET;
 107:         ifs.int_net = i & ifs.int_netmask;
 108:         ifs.int_subnet = i & ifs.int_subnetmask;
 109:         if (ifs.int_subnetmask != ifs.int_netmask)
 110:             ifs.int_flags |= IFF_SUBNET;
 111:         ifp = (struct interface *)malloc(sizeof (struct interface));
 112:         if (ifp == 0) {
 113:             printf("routed: out of memory\n");
 114:             break;
 115:         }
 116:         *ifp = ifs;
 117:         /*
 118: 		 * Count the # of directly connected networks
 119: 		 * and point to point links which aren't looped
 120: 		 * back to ourself.  This is used below to
 121: 		 * decide if we should be a routing ``supplier''.
 122: 		 */
 123:         if ((ifs.int_flags & IFF_POINTOPOINT) == 0 ||
 124:             if_ifwithaddr(&ifs.int_dstaddr) == 0)
 125:             externalinterfaces++;
 126:         /*
 127: 		 * If we have a point-to-point link, we want to act
 128: 		 * as a supplier even if it's our only interface,
 129: 		 * as that's the only way our peer on the other end
 130: 		 * can tell that the link is up.
 131: 		 */
 132:         if ((ifs.int_flags & IFF_POINTOPOINT) && supplier < 0)
 133:             supplier = 1;
 134:         ifp->int_name = malloc(strlen(ifr->ifr_name) + 1);
 135:         if (ifp->int_name == 0) {
 136:             fprintf(stderr, "routed: ifinit: out of memory\n");
 137:             goto bad;       /* ??? */
 138:         }
 139:         strcpy(ifp->int_name, ifr->ifr_name);
 140:         ifp->int_next = ifnet;
 141:         ifnet = ifp;
 142:         traceinit(ifp);
 143:         addrouteforif(ifp);
 144:     }
 145:     if (externalinterfaces > 1 && supplier < 0)
 146:         supplier = 1;
 147:     close(s);
 148:     return;
 149: bad:
 150:     sleep(60);
 151:     close(kmem), close(s);
 152:     execv("/sbin/routed", argv0);
 153:     _exit(0177);
 154: }
 155: 
 156: /*
 157:  * Add route for interface if not currently installed.
 158:  * Create route to other end if a point-to-point link,
 159:  * otherwise a route to this (sub)network.
 160:  * INTERNET SPECIFIC.
 161:  */
 162: addrouteforif(ifp)
 163:     struct interface *ifp;
 164: {
 165:     struct sockaddr_in net;
 166:     struct sockaddr *dst;
 167:     struct rt_entry *rt;
 168: 
 169:     if (ifp->int_flags & IFF_POINTOPOINT)
 170:         dst = &ifp->int_dstaddr;
 171:     else {
 172:         bzero((char *)&net, sizeof (net));
 173:         net.sin_family = AF_INET;
 174:         net.sin_addr = inet_makeaddr(ifp->int_subnet, INADDR_ANY);
 175:         dst = (struct sockaddr *)&net;
 176:     }
 177:     rt = rtfind(dst);
 178:     if (rt &&
 179:         (rt->rt_state & (RTS_INTERFACE | RTS_INTERNAL)) == RTS_INTERFACE)
 180:         return;
 181:     if (rt)
 182:         rtdelete(rt);
 183:     /*
 184: 	 * If interface on subnetted network,
 185: 	 * install route to network as well.
 186: 	 * This is meant for external viewers.
 187: 	 */
 188:     if ((ifp->int_flags & (IFF_SUBNET|IFF_POINTOPOINT)) == IFF_SUBNET) {
 189:         net.sin_addr = inet_makeaddr(ifp->int_net, INADDR_ANY);
 190:         rt = rtfind(dst);
 191:         if (rt == 0)
 192:             rtadd(dst, &ifp->int_addr, ifp->int_metric,
 193:                 ((ifp->int_flags & (IFF_INTERFACE|IFF_REMOTE)) |
 194:                 RTS_PASSIVE | RTS_INTERNAL | RTS_SUBNET));
 195:         net.sin_addr = inet_makeaddr(ifp->int_subnet, INADDR_ANY);
 196:     }
 197:     if (ifp->int_transitions++ > 0)
 198:         syslog(LOG_ERR, "re-installing interface %s", ifp->int_name);
 199:     rtadd(dst, &ifp->int_addr, ifp->int_metric,
 200:         ifp->int_flags & (IFF_INTERFACE|IFF_PASSIVE|IFF_REMOTE|IFF_SUBNET));
 201: 
 202: }
 203: 
 204: /*
 205:  * As a concession to the ARPANET we read a list of gateways
 206:  * from /etc/gateways and add them to our tables.  This file
 207:  * exists at each ARPANET gateway and indicates a set of ``remote''
 208:  * gateways (i.e. a gateway which we can't immediately determine
 209:  * if it's present or not as we can do for those directly connected
 210:  * at the hardware level).  If a gateway is marked ``passive''
 211:  * in the file, then we assume it doesn't have a routing process
 212:  * of our design and simply assume it's always present.  Those
 213:  * not marked passive are treated as if they were directly
 214:  * connected -- they're added into the interface list so we'll
 215:  * send them routing updates.
 216:  */
 217: gwkludge()
 218: {
 219:     struct sockaddr_in dst, gate;
 220:     FILE *fp;
 221:     char *type, *dname, *gname, *qual, buf[BUFSIZ];
 222:     struct interface *ifp;
 223:     int metric, n;
 224:     struct rt_entry route;
 225: 
 226:     fp = fopen("/etc/gateways", "r");
 227:     if (fp == NULL)
 228:         return;
 229:     qual = buf;
 230:     dname = buf + 64;
 231:     gname = buf + ((BUFSIZ - 64) / 3);
 232:     type = buf + (((BUFSIZ - 64) * 2) / 3);
 233:     bzero((char *)&dst, sizeof (dst));
 234:     bzero((char *)&gate, sizeof (gate));
 235:     bzero((char *)&route, sizeof(route));
 236:     /* format: {net | host} XX gateway XX metric DD [passive]\n */
 237: #define readentry(fp) \
 238:     fscanf((fp), "%s %s gateway %s metric %d %s\n", \
 239:         type, dname, gname, &metric, qual)
 240:     for (;;) {
 241:         if ((n = readentry(fp)) == EOF)
 242:             break;
 243:         if (!getnetorhostname(type, dname, &dst))
 244:             continue;
 245:         if (!gethostnameornumber(gname, &gate))
 246:             continue;
 247:         if (strcmp(qual, "passive") == 0) {
 248:             /*
 249: 			 * Passive entries aren't placed in our tables,
 250: 			 * only the kernel's, so we don't copy all of the
 251: 			 * external routing information within a net.
 252: 			 * Internal machines should use the default
 253: 			 * route to a suitable gateway (like us).
 254: 			 */
 255:             route.rt_dst = *(struct sockaddr *) &dst;
 256:             route.rt_router = *(struct sockaddr *) &gate;
 257:             route.rt_flags = RTF_UP;
 258:             if (strcmp(type, "host") == 0)
 259:                 route.rt_flags |= RTF_HOST;
 260:             if (metric)
 261:                 route.rt_flags |= RTF_GATEWAY;
 262:             (void) ioctl(s, SIOCADDRT, (char *)&route.rt_rt);
 263:             continue;
 264:         }
 265:         if (strcmp(qual, "external") == 0) {
 266:             /*
 267: 			 * Entries marked external are handled
 268: 			 * by other means, e.g. EGP,
 269: 			 * and are placed in our tables only
 270: 			 * to prevent overriding them
 271: 			 * with something else.
 272: 			 */
 273:             rtadd(&dst, &gate, metric, RTS_EXTERNAL|RTS_PASSIVE);
 274:             continue;
 275:         }
 276:         /* assume no duplicate entries */
 277:         externalinterfaces++;
 278:         ifp = (struct interface *)malloc(sizeof (*ifp));
 279:         bzero((char *)ifp, sizeof (*ifp));
 280:         ifp->int_flags = IFF_REMOTE;
 281:         /* can't identify broadcast capability */
 282:         ifp->int_net = inet_netof(dst.sin_addr);
 283:         if (strcmp(type, "host") == 0) {
 284:             ifp->int_flags |= IFF_POINTOPOINT;
 285:             ifp->int_dstaddr = *((struct sockaddr *)&dst);
 286:         }
 287:         ifp->int_addr = *((struct sockaddr *)&gate);
 288:         ifp->int_metric = metric;
 289:         ifp->int_next = ifnet;
 290:         ifnet = ifp;
 291:         addrouteforif(ifp);
 292:     }
 293:     fclose(fp);
 294: }
 295: 
 296: getnetorhostname(type, name, sin)
 297:     char *type, *name;
 298:     struct sockaddr_in *sin;
 299: {
 300: 
 301:     if (strcmp(type, "net") == 0) {
 302:         struct netent *np = getnetbyname(name);
 303:         u_long n;
 304: 
 305:         if (np == 0)
 306:             n = inet_network(name);
 307:         else {
 308:             if (np->n_addrtype != AF_INET)
 309:                 return (0);
 310:             n = np->n_net;
 311:             /*
 312: 			 * getnetbyname returns right-adjusted value.
 313: 			 */
 314:             if (n < 128)
 315:                 n <<= IN_CLASSA_NSHIFT;
 316:             else if (n < 65536)
 317:                 n <<= IN_CLASSB_NSHIFT;
 318:             else
 319:                 n <<= IN_CLASSC_NSHIFT;
 320:         }
 321:         sin->sin_family = AF_INET;
 322:         sin->sin_addr = inet_makeaddr(n, INADDR_ANY);
 323:         return (1);
 324:     }
 325:     if (strcmp(type, "host") == 0) {
 326:         struct hostent *hp = gethostbyname(name);
 327: 
 328:         if (hp == 0)
 329:             sin->sin_addr.s_addr = inet_addr(name);
 330:         else {
 331:             if (hp->h_addrtype != AF_INET)
 332:                 return (0);
 333:             bcopy(hp->h_addr, &sin->sin_addr, hp->h_length);
 334:         }
 335:         sin->sin_family = AF_INET;
 336:         return (1);
 337:     }
 338:     return (0);
 339: }
 340: 
 341: gethostnameornumber(name, sin)
 342:     char *name;
 343:     struct sockaddr_in *sin;
 344: {
 345:     struct hostent *hp;
 346: 
 347:     hp = gethostbyname(name);
 348:     if (hp) {
 349:         bcopy(hp->h_addr, &sin->sin_addr, hp->h_length);
 350:         sin->sin_family = hp->h_addrtype;
 351:         return (1);
 352:     }
 353:     sin->sin_addr.s_addr = inet_addr(name);
 354:     sin->sin_family = AF_INET;
 355:     return (sin->sin_addr.s_addr != -1);
 356: }

Defined functions

addrouteforif defined in line 162; used 4 times
gethostnameornumber defined in line 341; used 1 times
getnetorhostname defined in line 296; used 1 times
gwkludge defined in line 217; used 1 times
ifinit defined in line 29; used 2 times

Defined variables

externalinterfaces defined in line 21; used 3 times
ifnet defined in line 19; used 12 times
lookforinterfaces defined in line 20; used 2 times
sccsid defined in line 8; never used

Defined macros

readentry defined in line 237; used 1 times
Last modified: 1996-11-20
Generated: 2016-12-26
Generated by src2html V0.67
page hit count: 4390
Valid CSS Valid XHTML 1.0 Strict