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: #ifndef lint
   8: static char sccsid[] = "@(#)startup.c	5.7 (Berkeley) 6/3/86";
   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("/etc/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:     int state, metric;
 168:     struct rt_entry *rt;
 169: 
 170:     if (ifp->int_flags & IFF_POINTOPOINT)
 171:         dst = &ifp->int_dstaddr;
 172:     else {
 173:         bzero((char *)&net, sizeof (net));
 174:         net.sin_family = AF_INET;
 175:         net.sin_addr = inet_makeaddr(ifp->int_subnet, INADDR_ANY);
 176:         dst = (struct sockaddr *)&net;
 177:     }
 178:     rt = rtfind(dst);
 179:     if (rt &&
 180:         (rt->rt_state & (RTS_INTERFACE | RTS_INTERNAL)) == RTS_INTERFACE)
 181:         return;
 182:     if (rt)
 183:         rtdelete(rt);
 184:     /*
 185: 	 * If interface on subnetted network,
 186: 	 * install route to network as well.
 187: 	 * This is meant for external viewers.
 188: 	 */
 189:     if ((ifp->int_flags & (IFF_SUBNET|IFF_POINTOPOINT)) == IFF_SUBNET) {
 190:         net.sin_addr = inet_makeaddr(ifp->int_net, INADDR_ANY);
 191:         rt = rtfind(dst);
 192:         if (rt == 0)
 193:             rtadd(dst, &ifp->int_addr, ifp->int_metric,
 194:                 ((ifp->int_flags & (IFF_INTERFACE|IFF_REMOTE)) |
 195:                 RTS_PASSIVE | RTS_INTERNAL | RTS_SUBNET));
 196:         net.sin_addr = inet_makeaddr(ifp->int_subnet, INADDR_ANY);
 197:     }
 198:     if (ifp->int_transitions++ > 0)
 199:         syslog(LOG_ERR, "re-installing interface %s", ifp->int_name);
 200:     rtadd(dst, &ifp->int_addr, ifp->int_metric,
 201:         ifp->int_flags & (IFF_INTERFACE|IFF_PASSIVE|IFF_REMOTE|IFF_SUBNET));
 202: 
 203: }
 204: 
 205: /*
 206:  * As a concession to the ARPANET we read a list of gateways
 207:  * from /etc/gateways and add them to our tables.  This file
 208:  * exists at each ARPANET gateway and indicates a set of ``remote''
 209:  * gateways (i.e. a gateway which we can't immediately determine
 210:  * if it's present or not as we can do for those directly connected
 211:  * at the hardware level).  If a gateway is marked ``passive''
 212:  * in the file, then we assume it doesn't have a routing process
 213:  * of our design and simply assume it's always present.  Those
 214:  * not marked passive are treated as if they were directly
 215:  * connected -- they're added into the interface list so we'll
 216:  * send them routing updates.
 217:  */
 218: gwkludge()
 219: {
 220:     struct sockaddr_in dst, gate;
 221:     FILE *fp;
 222:     char *type, *dname, *gname, *qual, buf[BUFSIZ];
 223:     struct interface *ifp;
 224:     int metric, n;
 225:     struct rt_entry route;
 226: 
 227:     fp = fopen("/etc/gateways", "r");
 228:     if (fp == NULL)
 229:         return;
 230:     qual = buf;
 231:     dname = buf + 64;
 232:     gname = buf + ((BUFSIZ - 64) / 3);
 233:     type = buf + (((BUFSIZ - 64) * 2) / 3);
 234:     bzero((char *)&dst, sizeof (dst));
 235:     bzero((char *)&gate, sizeof (gate));
 236:     bzero((char *)&route, sizeof(route));
 237:     /* format: {net | host} XX gateway XX metric DD [passive]\n */
 238: #define readentry(fp) \
 239:     fscanf((fp), "%s %s gateway %s metric %d %s\n", \
 240:         type, dname, gname, &metric, qual)
 241:     for (;;) {
 242:         if ((n = readentry(fp)) == EOF)
 243:             break;
 244:         if (!getnetorhostname(type, dname, &dst))
 245:             continue;
 246:         if (!gethostnameornumber(gname, &gate))
 247:             continue;
 248:         if (strcmp(qual, "passive") == 0) {
 249:             /*
 250: 			 * Passive entries aren't placed in our tables,
 251: 			 * only the kernel's, so we don't copy all of the
 252: 			 * external routing information within a net.
 253: 			 * Internal machines should use the default
 254: 			 * route to a suitable gateway (like us).
 255: 			 */
 256:             route.rt_dst = *(struct sockaddr *) &dst;
 257:             route.rt_router = *(struct sockaddr *) &gate;
 258:             route.rt_flags = RTF_UP;
 259:             if (strcmp(type, "host") == 0)
 260:                 route.rt_flags |= RTF_HOST;
 261:             if (metric)
 262:                 route.rt_flags |= RTF_GATEWAY;
 263:             (void) ioctl(s, SIOCADDRT, (char *)&route.rt_rt);
 264:             continue;
 265:         }
 266:         if (strcmp(qual, "external") == 0) {
 267:             /*
 268: 			 * Entries marked external are handled
 269: 			 * by other means, e.g. EGP,
 270: 			 * and are placed in our tables only
 271: 			 * to prevent overriding them
 272: 			 * with something else.
 273: 			 */
 274:             rtadd(&dst, &gate, metric, RTS_EXTERNAL|RTS_PASSIVE);
 275:             continue;
 276:         }
 277:         /* assume no duplicate entries */
 278:         externalinterfaces++;
 279:         ifp = (struct interface *)malloc(sizeof (*ifp));
 280:         bzero((char *)ifp, sizeof (*ifp));
 281:         ifp->int_flags = IFF_REMOTE;
 282:         /* can't identify broadcast capability */
 283:         ifp->int_net = inet_netof(dst.sin_addr);
 284:         if (strcmp(type, "host") == 0) {
 285:             ifp->int_flags |= IFF_POINTOPOINT;
 286:             ifp->int_dstaddr = *((struct sockaddr *)&dst);
 287:         }
 288:         ifp->int_addr = *((struct sockaddr *)&gate);
 289:         ifp->int_metric = metric;
 290:         ifp->int_next = ifnet;
 291:         ifnet = ifp;
 292:         addrouteforif(ifp);
 293:     }
 294:     fclose(fp);
 295: }
 296: 
 297: getnetorhostname(type, name, sin)
 298:     char *type, *name;
 299:     struct sockaddr_in *sin;
 300: {
 301: 
 302:     if (strcmp(type, "net") == 0) {
 303:         struct netent *np = getnetbyname(name);
 304:         int n;
 305: 
 306:         if (np == 0)
 307:             n = inet_network(name);
 308:         else {
 309:             if (np->n_addrtype != AF_INET)
 310:                 return (0);
 311:             n = np->n_net;
 312:             /*
 313: 			 * getnetbyname returns right-adjusted value.
 314: 			 */
 315:             if (n < 128)
 316:                 n <<= IN_CLASSA_NSHIFT;
 317:             else if (n < 65536)
 318:                 n <<= IN_CLASSB_NSHIFT;
 319:             else
 320:                 n <<= IN_CLASSC_NSHIFT;
 321:         }
 322:         sin->sin_family = AF_INET;
 323:         sin->sin_addr = inet_makeaddr(n, INADDR_ANY);
 324:         return (1);
 325:     }
 326:     if (strcmp(type, "host") == 0) {
 327:         struct hostent *hp = gethostbyname(name);
 328: 
 329:         if (hp == 0)
 330:             sin->sin_addr.s_addr = inet_addr(name);
 331:         else {
 332:             if (hp->h_addrtype != AF_INET)
 333:                 return (0);
 334:             bcopy(hp->h_addr, &sin->sin_addr, hp->h_length);
 335:         }
 336:         sin->sin_family = AF_INET;
 337:         return (1);
 338:     }
 339:     return (0);
 340: }
 341: 
 342: gethostnameornumber(name, sin)
 343:     char *name;
 344:     struct sockaddr_in *sin;
 345: {
 346:     struct hostent *hp;
 347: 
 348:     hp = gethostbyname(name);
 349:     if (hp) {
 350:         bcopy(hp->h_addr, &sin->sin_addr, hp->h_length);
 351:         sin->sin_family = hp->h_addrtype;
 352:         return (1);
 353:     }
 354:     sin->sin_addr.s_addr = inet_addr(name);
 355:     sin->sin_family = AF_INET;
 356:     return (sin->sin_addr.s_addr != -1);
 357: }

Defined functions

addrouteforif defined in line 162; used 4 times
gethostnameornumber defined in line 342; used 1 times
getnetorhostname defined in line 297; used 1 times
gwkludge defined in line 218; 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 238; used 1 times
Last modified: 1986-06-04
Generated: 2016-12-26
Generated by src2html V0.67
page hit count: 1742
Valid CSS Valid XHTML 1.0 Strict