1: /* pathalias -- by steve bellovin, as told to peter honeyman */
   2: #ifndef lint
   3: static char *sccsid = "@(#)printit.c	9.1 87/10/04";
   4: #endif
   5: 
   6: #include "def.h"
   7: 
   8: /*
   9:  * print the routes by traversing the shortest path tree in preorder.
  10:  * use lots of char bufs -- profiling indicates this costs about 5 kbytes
  11:  */
  12: 
  13: /* exports */
  14: extern void printit();
  15: 
  16: /* imports */
  17: extern int Cflag, Vflag, Dflag, Fflag;
  18: extern p_node Home;
  19: #ifndef TMPFILES
  20: #define getnode(x) x
  21: #define getlink(y) y
  22: #else  /*TMPFILES*/
  23: extern node *getnode();
  24: extern link *getlink();
  25: #endif /*TMPFILES*/
  26: extern char *Netchars;
  27: extern void die();
  28: 
  29: /* privates */
  30: static p_link Ancestor; /* for -f option */
  31: STATIC void preorder(), setpath(), printhost(), printdomain();
  32: STATIC char *hostpath();
  33: 
  34: /* in practice, even the longest paths are < 100 bytes */
  35: #ifndef TMPFILES
  36: #define PATHSIZE 512
  37: #else /*TMPFILES*/
  38: #define PATHSIZE 172    /* this saves a stack segment, which we use in heap */
  39: #endif /*TMPFILES*/
  40: 
  41: void
  42: printit()
  43: {   p_link l;
  44:     char pbuf[PATHSIZE];
  45: 
  46:     /* print home */
  47:     if (Cflag)
  48:         printf("%ld\t", (long) getnode(Home)->n_cost);
  49:     printf("%s\t%%s\n", getnode(Home)->n_name);
  50: 
  51:     strcpy(pbuf, "%s");
  52:     for (l = getnode(Home)->n_link; l; l = getlink(l)->l_next) {
  53:         if (getlink(l)->l_flag & LTREE) {
  54:             getlink(l)->l_flag &= ~LTREE;
  55:             Ancestor = l;
  56:             preorder(l, pbuf);
  57:             strcpy(pbuf, "%s");
  58:         }
  59:     }
  60:     fflush(stdout);
  61:     fflush(stderr);
  62: }
  63: 
  64: /*
  65:  * preorder traversal of shortest path tree.
  66:  */
  67: STATIC void
  68: preorder(l, ppath)
  69:     register p_link l;
  70:     char *ppath;
  71: {   register p_node n;
  72:     p_node ncp;     /* circular copy list */
  73:     Cost cost;
  74:     char npath[PATHSIZE];
  75:     short p_dir;        /* DIR bits of parent (for nets) */
  76:     char p_op;      /* net op of parent (for nets) */
  77: 
  78:     setpath(l, ppath, npath);
  79:     n = getlink(l)->l_to;
  80:     if (printable(n)) {
  81:         if (Fflag)
  82:             cost = getnode(getlink(Ancestor)->l_to)->n_cost;
  83:         else
  84:             cost = getnode(n)->n_cost;
  85:         if (ISADOMAIN(getnode(n)))
  86:             printdomain(n, npath, cost);
  87:         else if (!(getnode(n)->n_flag & NNET)) {
  88:             printhost(n, npath, cost);
  89:         }
  90:         getnode(n)->n_flag |= PRINTED;
  91:         for (ncp = getnode(n)->n_copy; ncp != n;
  92:              ncp = getnode(ncp)->n_copy)
  93:             getnode(ncp)->n_flag |= PRINTED;
  94:     }
  95: 
  96:     /* prepare routing bits for domain members */
  97:     p_dir = getlink(l)->l_flag & LDIR;
  98:     p_op = getlink(l)->l_netop;
  99: 
 100:     /* recursion */
 101:     for (l = getnode(n)->n_link; l; l = getlink(l)->l_next) {
 102:         if (!(getlink(l)->l_flag & LTREE))
 103:             continue;
 104:         /* network member inherits the routing syntax of its gateway */
 105:         if (ISANET(getnode(n))) {
 106:             getlink(l)->l_flag = (getlink(l)->l_flag & ~LDIR) | p_dir;
 107:             getlink(l)->l_netop = p_op;
 108:         }
 109:         getlink(l)->l_flag &= ~LTREE;
 110:         preorder(l, npath);
 111:     }
 112: }
 113: 
 114: STATIC int
 115: printable(n)
 116:     register p_node n;
 117: {   p_node ncp;
 118:     p_link l;
 119: 
 120:     if (getnode(n)->n_flag & PRINTED)
 121:         return 0;
 122: 
 123:     /* is there a cheaper copy? */
 124:     for (ncp = getnode(n)->n_copy; n != ncp; ncp = getnode(ncp)->n_copy) {
 125:         if (!(getnode(ncp)->n_flag & MAPPED))
 126:             continue;   /* unmapped copy */
 127: 
 128:         if (getnode(n)->n_cost > getnode(ncp)->n_cost)
 129:             return 0;   /* cheaper copy */
 130: 
 131:         if (getnode(n)->n_cost == getnode(ncp)->n_cost
 132:                       && !(getnode(ncp)->n_flag & NTERMINAL))
 133:             return 0;   /* synthetic copy */
 134:     }
 135: 
 136:     /* will a domain route suffice? */
 137:     if (Dflag && !ISANET(getnode(n)) && ISADOMAIN(getnode(getnode(n)->n_parent))) {
 138:         /*
 139: 		 * are there any interesting links?  a link
 140: 		 * is interesting if it doesn't point back
 141: 		 * to the parent, and is not an alias.
 142: 		 */
 143: 
 144:         /* check n */
 145:         for (l = getnode(n)->n_link; l; l = getlink(l)->l_next) {
 146:             if (getlink(l)->l_to == getnode(n)->n_parent)
 147:                 continue;
 148:             if ((!getlink(l)->l_flag & LALIAS))
 149:                 return 1;
 150:         }
 151: 
 152:         /* check copies of n */
 153:         for (ncp = getnode(n)->n_copy; ncp != n; ncp = getnode(ncp)->n_copy) {
 154:             for (l = getnode(ncp)->n_link; l; l = getlink(l)->l_next) {
 155:                 if (getlink(l)->l_to == getnode(n)->n_parent)
 156:                     continue;
 157:                 if (!(getlink(l)->l_flag & LALIAS))
 158:                     return 1;
 159:             }
 160:         }
 161: 
 162:         /* domain route suffices */
 163:         return 0;
 164:     }
 165:     return 1;
 166: }
 167: 
 168: STATIC void
 169: setpath(l, ppath, npath)
 170:     p_link l;
 171:     register char *ppath, *npath;
 172: {   register p_node next;
 173:     register p_node parent;
 174:     char netchar;
 175: 
 176:     next = getlink(l)->l_to;
 177:     parent = getnode(next)->n_parent;
 178:     netchar = NETCHAR(getlink(l));
 179: 
 180:     /* for magic @->% conversion */
 181:     if (getnode(parent)->n_flag & ATSIGN)
 182:         getnode(next)->n_flag |= ATSIGN;
 183: 
 184:     /*
 185: 	 * i've noticed that distant gateways to domains frequently get
 186: 	 * ...!gateway!user@dom.ain wrong.  ...!gateway!user%dom.ain
 187: 	 * seems to work, so if next is a domain and the parent is
 188: 	 * not the local host, force a magic %->@ conversion.  in this
 189: 	 * context, "parent" is the nearest ancestor that is not a net.
 190: 	 */
 191:     while (ISANET(getnode(parent)))
 192:         parent = getnode(parent)->n_parent;
 193:     if (ISADOMAIN(getnode(next)) && parent != Home)
 194:         getnode(next)->n_flag |= ATSIGN;
 195: 
 196:     /*
 197: 	 * special handling for nets (including domains) and aliases.
 198: 	 * part of the trick is to treat aliases to domains as 0 cost
 199: 	 * links.  (the author believes they should be declared as such
 200: 	 * in the input, but the world disagrees).
 201: 	 */
 202:     if (ISANET(getnode(next)) || ((getlink(l)->l_flag & LALIAS)
 203:         && !ISADOMAIN(getnode(parent)))) {
 204:         strcpy(npath, ppath);
 205:         return;
 206:     }
 207: 
 208:     if (netchar == '@')
 209:         if (getnode(next)->n_flag & ATSIGN)
 210:             netchar = '%';  /* shazam?  shaman? */
 211:         else
 212:             getnode(next)->n_flag |= ATSIGN;
 213: 
 214:     /* remainder should be a sprintf -- foo on '%' as an operator */
 215:     for ( ; *npath = *ppath; ppath++) {
 216:         if (*ppath == '%') {
 217:             switch(ppath[1]) {
 218:             case 's':
 219:                 ppath++;
 220:                 npath = hostpath(npath, l, netchar);
 221:                 break;
 222: 
 223:             case '%':
 224:                 *++npath = *++ppath;
 225:                 npath++;
 226:                 break;
 227: 
 228:             default:
 229:                 die("unknown escape in setpath");
 230:                 break;
 231:             }
 232:         } else
 233:             npath++;
 234:     }
 235: }
 236: 
 237: STATIC char *
 238: hostpath(path, l, netchar)
 239:     register char *path;
 240:     register p_link l;
 241:     char netchar;
 242: {   register p_node prev;
 243: 
 244:     prev = getnode(getlink(l)->l_to)->n_parent;
 245:     if (NETDIR(getlink(l)) == LLEFT) {
 246:         /* host!%s */
 247:         strcpy(path, getnode(getlink(l)->l_to)->n_name);
 248:         path += strlen(path);
 249:         while (ISADOMAIN(getnode(prev))) {
 250:             strcpy(path, getnode(prev)->n_name);
 251:             path += strlen(path);
 252:             prev = getnode(prev)->n_parent;
 253:         }
 254:         *path++ = netchar;
 255:         if (netchar == '%')
 256:             *path++ = '%';
 257:         *path++ = '%';
 258:         *path++ = 's';
 259:     } else {
 260:         /* %s@host */
 261:         *path++ = '%';
 262:         *path++ = 's';
 263:         *path++ = netchar;
 264:         if (netchar == '%')
 265:             *path++ = '%';
 266:         strcpy(path, getnode(getlink(l)->l_to)->n_name);
 267:         path += strlen(path);
 268:         while (ISADOMAIN(getnode(prev))) {
 269:             strcpy(path, getnode(prev)->n_name);
 270:             path += strlen(path);
 271:             prev = getnode(prev)->n_parent;
 272:         }
 273:     }
 274:     return path;
 275: }
 276: 
 277: STATIC void
 278: printhost(n, path, cost)
 279:     register p_node n;
 280:     char *path;
 281:     Cost cost;
 282: {
 283:     if (getnode(n)->n_flag & PRINTED)
 284:         die("printhost called twice");
 285:     getnode(n)->n_flag |= PRINTED;
 286:     /* skip private hosts */
 287:     if ((getnode(n)->n_flag & ISPRIVATE) == 0) {
 288:         if (Cflag)
 289:             printf("%ld\t", (long) cost);
 290:         fputs(getnode(n)->n_name, stdout);
 291:         putchar('\t');
 292:         puts(path);
 293:     }
 294: }
 295: 
 296: STATIC void
 297: printdomain(n, path, cost)
 298:     register p_node n;
 299:     char *path;
 300:     Cost cost;
 301: {   p_node p;
 302: 
 303:     if (getnode(n)->n_flag & PRINTED)
 304:         die("printdomain called twice");
 305:     getnode(n)->n_flag |= PRINTED;
 306: 
 307:     /*
 308: 	 * print a route for dom.ain if it is a top-level domain, unless
 309: 	 * it is private.
 310: 	 *
 311: 	 * print a route for sub.dom.ain only if all its ancestor dom.ains
 312: 	 * are private and sub.dom.ain is not private.
 313: 	 */
 314:     if (!ISADOMAIN(getnode(getnode(n)->n_parent))) {
 315:         /* top-level domain */
 316:         if (getnode(n)->n_flag & ISPRIVATE) {
 317:             vprintf(stderr, "ignoring private top-level domain %s\n", getnode(n)->n_name);
 318:             return;
 319:         }
 320:     } else {
 321:         /* subdomain */
 322:         for (p = getnode(n)->n_parent; ISADOMAIN(getnode(p));
 323:              p = getnode(p)->n_parent)
 324:             if (!(getnode(p)->n_flag & ISPRIVATE))
 325:                 return;
 326:         if (getnode(n)->n_flag & ISPRIVATE)
 327:             return;
 328:     }
 329: 
 330:     /* print it (at last!) */
 331:     if (Cflag)
 332:         printf("%ld\t", (long) cost);
 333:     do {
 334:         fputs(getnode(n)->n_name, stdout);
 335:         n = getnode(n)->n_parent;
 336:     } while (ISADOMAIN(getnode(n)));
 337:     putchar('\t');
 338:     puts(path);
 339: }

Defined functions

hostpath defined in line 237; used 2 times
preorder defined in line 67; used 3 times
printable defined in line 114; used 1 times
  • in line 80
printdomain defined in line 296; used 2 times
printhost defined in line 277; used 2 times
printit defined in line 41; used 4 times
setpath defined in line 168; used 2 times

Defined variables

STATIC defined in line 67; used 7 times
sccsid defined in line 3; never used

Defined macros

PATHSIZE defined in line 38; used 2 times
getlink defined in line 21; used 27 times
getnode defined in line 20; used 70 times
Last modified: 1988-12-24
Generated: 2016-12-26
Generated by src2html V0.67
page hit count: 3881
Valid CSS Valid XHTML 1.0 Strict