1: /* 2: * Hyperchannel routing program 3: * 4: * Copyright (c) 1983, Tektronix Inc. 5: * All Rights Reserved 6: * 7: */ 8: 9: static char rcsid[] = "$Header: hyr_main.c,v 2.3 84/05/04 12:15:59 steveg Exp $$Locker: $"; 10: 11: #include <stdio.h> 12: #include <sys/types.h> 13: #include <sys/socket.h> 14: #include <sys/ioctl.h> 15: 16: #include <netinet/in.h> 17: #include <net/if.h> 18: 19: #include <vaxif/if_hy.h> 20: #include <ctype.h> 21: #define MAIN 22: #include "hyr_sym.h" 23: 24: struct hy_route hy_route; 25: struct hy_route ker_hy_route; 26: int comp_flag = 0; 27: int set_flag = 0; 28: int print_flag = 0; 29: int dump_flag = 0; 30: int debug_flag = 0; 31: int lexdebug; 32: int lex_error; 33: int maxgate = 0; 34: char *progname = "hyroute"; 35: char *devname = "hy0"; 36: 37: /* 38: * hash a hyperchannel address into the table 39: * return NULL if table is full or entry not found and adding a new one 40: */ 41: struct hyr_hash * 42: rhash(key, new, r) 43: u_long key; 44: int new; 45: register struct hy_route *r; 46: { 47: register struct hyr_hash *rh; 48: register struct hyr_hash *ret = NULL; 49: int n = HYRHASH(key); 50: 51: if (debug_flag) 52: printf("%s hashing key %6x initial %d ", new? "new": "old", key, n); 53: rh = &r->hyr_hash[n]; 54: n = 0; 55: while (rh->hyr_key != key) { 56: if ((rh->hyr_flags & HYR_INUSE) == 0) { 57: if (new) 58: ret = rh; 59: goto out; 60: } 61: if (n++ > HYRSIZE) { 62: goto out; 63: } 64: if (++rh >= &r->hyr_hash[HYRSIZE]) { 65: rh = &r->hyr_hash[0]; 66: if (debug_flag) printf("|"); 67: } 68: if (debug_flag) printf("."); 69: } 70: ret = rh; 71: out: 72: if (ret == NULL) { 73: if (new) { 74: fprintf(stderr, "%s: %s add_gates, hash table full\n", progname, devname); 75: exit(1); 76: } 77: } 78: if (debug_flag) { 79: if (ret == NULL) 80: printf(" returning NULL\n"); 81: else 82: printf(" returning %d\n", ret - &r->hyr_hash[0]); 83: } 84: return(ret); 85: } 86: 87: /* 88: * add a direct entry to the hash table using the specified key, 89: * destination, control and access fields, and loopback flags. 90: */ 91: add_direct(key, dst, ctl, access, flags, r) 92: u_long key; 93: unsigned dst; 94: unsigned ctl; 95: unsigned access; 96: unsigned flags; 97: register struct hy_route *r; 98: { 99: register struct hyr_hash *kh = rhash(key, 1, r); 100: 101: if ((kh->hyr_flags & HYR_INUSE) == 0) { 102: kh->hyr_flags = (HYR_INUSE | HYR_DIR); 103: kh->hyr_key = key; 104: kh->hyr_dst = dst; 105: kh->hyr_ctl = ctl; 106: kh->hyr_access = access; 107: if (flags & HS_LOOP) 108: kh->hyr_flags |= HYR_LOOP; 109: if (flags & HS_RLOOP) 110: kh->hyr_flags |= HYR_RLOOP; 111: return; 112: } 113: fprintf(stderr, "%s: %s add_direct, hash table full\n", progname, devname); 114: } 115: 116: /* 117: * compare function for the qsort in add_gates, see below 118: */ 119: int 120: compare_gates(a, b) 121: unsigned *a, *b; 122: { 123: if (*a < *b) 124: return(-1); 125: else if (*a > *b) 126: return(1); 127: else 128: return(0); 129: } 130: 131: /* 132: * add a gatewayed entry to the hash table using the sicified array of 133: * gateway keys. reuse space so as to make the gateway table small as 134: * possible. 135: */ 136: add_gates(key, numgates, gates, r) 137: u_long key; 138: unsigned numgates; 139: unsigned gates[256]; 140: register struct hy_route *r; 141: { 142: register struct hyr_hash *kh = rhash(key, 1, r); 143: register struct hyr_hash *rh; 144: int i, j; 145: 146: for (i = 0; i < numgates; i++) { 147: rh = rhash(gates[i], 1, r); 148: gates[i] = rh - &r->hyr_hash[0]; 149: } 150: qsort(gates, numgates, sizeof(unsigned), compare_gates); 151: /* 152: * loop through all existing hash table entries to find one that 153: * matches the currently requested list 154: */ 155: for (rh = &r->hyr_hash[0]; rh < &r->hyr_hash[HYRSIZE]; rh++) { 156: if (rh->hyr_flags & HYR_GATE) { 157: if ((rh->hyr_egate - rh->hyr_pgate + 1) == numgates) { 158: for (i = 0, j = rh->hyr_pgate; i < numgates ; i++, j++) { 159: if (gates[i] != r->hyr_gateway[j]) 160: goto skipit; 161: } 162: /* 163: * found a match, just use it 164: */ 165: kh->hyr_flags = (HYR_INUSE | HYR_GATE); 166: kh->hyr_key = key; 167: kh->hyr_pgate = rh->hyr_pgate; 168: kh->hyr_egate = rh->hyr_egate; 169: kh->hyr_nextgate = rh->hyr_nextgate; 170: return; 171: } 172: } 173: skipit: 174: ; 175: } 176: /* 177: * didn't find anything, if there is room add a new entry 178: */ 179: if (numgates + maxgate > 256) { 180: fprintf(stderr, "%s: %s add_gates, gateway table full\n", progname, devname); 181: exit(1); 182: } 183: kh->hyr_flags = (HYR_INUSE | HYR_GATE); 184: kh->hyr_key = key; 185: kh->hyr_pgate = maxgate; 186: kh->hyr_egate = maxgate + numgates - 1; 187: kh->hyr_nextgate = maxgate; 188: for (i = 0; i < numgates; i++, maxgate++) 189: r->hyr_gateway[maxgate] = gates[i]; 190: } 191: 192: /* 193: * set the kernel table 194: */ 195: settable(r) 196: struct hy_route *r; 197: { 198: int s; 199: struct hyrsetget sg; 200: 201: sg.hyrsg_ptr = r; 202: sg.hyrsg_len = sizeof(*r); 203: strncpy(sg.hyrsg_name, devname, sizeof(sg.hyrsg_name)); 204: 205: if ((s = socket(AF_INET, SOCK_DGRAM, 0)) < 0) { 206: perror("socket create in settable"); 207: exit(1); 208: } 209: if (ioctl(s, HYSETROUTE, (char *)&sg) < 0) { 210: perror("HYSETROUTE ioctl in settable"); 211: exit(1); 212: } 213: if (close(s) < 0) { 214: perror("socket close in settable"); 215: exit(1); 216: } 217: } 218: 219: /* 220: * get the kernel table 221: */ 222: gettable(r) 223: struct hy_route *r; 224: { 225: int s; 226: struct hyrsetget sg; 227: 228: sg.hyrsg_ptr = r; 229: sg.hyrsg_len = sizeof(*r); 230: strncpy(sg.hyrsg_name, devname, sizeof(sg.hyrsg_name)); 231: 232: if ((s = socket(AF_INET, SOCK_DGRAM, 0)) < 0) { 233: perror("socket create in gettable"); 234: exit(1); 235: } 236: if (ioctl(s, HYGETROUTE, (char *)&sg) < 0) { 237: perror("HYGETROUTE ioctl in gettable"); 238: exit(1); 239: } 240: if (close(s) < 0) { 241: perror("socket close in gettable"); 242: exit(1); 243: } 244: } 245: 246: 247: /* 248: * print a somewhat readable version of the routine table 249: * that the kernel uses (mostly for debugging) 250: */ 251: print_table(r) 252: register struct hy_route *r; 253: { 254: register struct hyr_hash *rh; 255: register int i; 256: extern char *ctime(); 257: 258: if (r->hyr_lasttime != 0) 259: printf("table set time: %s", ctime(&r->hyr_lasttime)); 260: else 261: printf("time not set\n"); 262: 263: for (i = 0; i < HYRSIZE; i++) { 264: rh = &r->hyr_hash[i]; 265: if (rh->hyr_flags & HYR_INUSE) { 266: printf("hash %d key %06x flags %x\n", i, rh->hyr_key, rh->hyr_flags); 267: if (rh->hyr_flags & HYR_DIR) 268: printf("\tdst %04x ctl %04x access %04x", 269: ntohs(rh->hyr_dst), 270: ntohs(rh->hyr_ctl), 271: ntohs(rh->hyr_access)); 272: else if (rh->hyr_flags & HYR_GATE) 273: printf("\tpgate %d egate %d nextgate %d", 274: rh->hyr_pgate, 275: rh->hyr_egate, 276: rh->hyr_nextgate); 277: if (rh->hyr_flags & HYR_LOOP) 278: printf(" LOOP"); 279: if (rh->hyr_flags & HYR_RLOOP) 280: printf(" REMLOOP"); 281: printf("\n"); 282: } 283: } 284: 285: for (i = 0; i < 256; i++) { 286: printf("gate[%d] = %d\n", i, r->hyr_gateway[i]); 287: if (r->hyr_gateway[i] == 0 && r->hyr_gateway[i+1] == 0) 288: break; 289: } 290: } 291: 292: /* 293: * comnpare two routing tables tom insure that they are the same 294: */ 295: compare_table(r1, r2) 296: register struct hy_route *r1, *r2; 297: { 298: register struct hyr_hash *rh1, *rh2; 299: register int i; 300: int ndiffs = 0; 301: 302: for (i = 0; i < HYRSIZE; i++) { 303: rh1 = &r1->hyr_hash[i]; 304: rh2 = &r2->hyr_hash[i]; 305: if (rh1->hyr_flags != rh2->hyr_flags) { 306: fprintf(stderr, "%s: hash entry %d - flags differ (%x vs %x)\n", progname, i, rh1->hyr_flags, rh2->hyr_flags); 307: ndiffs++; 308: } 309: if ((rh1->hyr_flags & HYR_INUSE) && (rh1->hyr_flags & HYR_DIR)) { 310: if (rh1->hyr_dst != rh1->hyr_dst || 311: rh1->hyr_ctl != rh1->hyr_ctl || 312: rh1->hyr_access != rh1->hyr_access) { 313: fprintf(stderr, "%s: direct hash entry %d - fields differ\n", progname, i); 314: fprintf(stderr, "\tdst: %04x vs %04x\tctl: %04x vs %04x\taccess: %04x vs %04x\n", 315: ntohs(rh1->hyr_dst), ntohs(rh2->hyr_dst), 316: ntohs(rh1->hyr_ctl), ntohs(rh2->hyr_ctl), 317: ntohs(rh1->hyr_access), ntohs(rh2->hyr_access)); 318: ndiffs++; 319: } 320: } 321: if ((rh1->hyr_flags & HYR_INUSE) && (rh1->hyr_flags & HYR_GATE)) { 322: if (rh1->hyr_pgate != rh1->hyr_pgate || 323: rh1->hyr_egate != rh1->hyr_egate || 324: rh1->hyr_nextgate < rh1->hyr_pgate || 325: rh1->hyr_nextgate > rh1->hyr_egate || 326: rh2->hyr_nextgate < rh2->hyr_pgate || 327: rh2->hyr_nextgate > rh2->hyr_egate) { 328: fprintf(stderr, "%s: direct hash entry %d - fields differ\n", progname, i); 329: fprintf(stderr, "\tpgate: %04x vs %04x\tegate: %04x vs %04x\tnextgate: %04x vs %04x\n", 330: rh1->hyr_pgate, rh2->hyr_pgate, 331: rh1->hyr_egate, rh2->hyr_egate, 332: rh1->hyr_nextgate, rh2->hyr_nextgate); 333: ndiffs++; 334: } 335: } 336: } 337: for (i = 0; i < 256; i++) { 338: if (r1->hyr_gateway[i] != r2->hyr_gateway[i]) { 339: fprintf(stderr, "%s: gate[%d] = %d v2 %d\n", progname, i, 340: r1->hyr_gateway[i], r2->hyr_gateway[i]); 341: } 342: } 343: return(ndiffs); 344: } 345: 346: main(argc, argv) 347: int argc; 348: char *argv[]; 349: { 350: char *filename = NULL; /* input file name (default stdin) */ 351: char *cp; 352: 353: if (argc) 354: progname = argv[0]; 355: else 356: progname = "hyroute"; 357: 358: argc--; argv++; 359: while (argc) { 360: if (argv[0][0] == '-' && argv[0][1] != '\0') { 361: cp = &argv[0][0]; 362: switch(*++cp) { 363: 364: case 's': /* set the kernel table */ 365: set_flag++; 366: break; 367: 368: case 'd': /* print the kernel table */ 369: dump_flag++; 370: break; 371: 372: case 'p': /* print symbol table */ 373: print_flag++; 374: break; 375: 376: case 'c': /* compare with kernel table */ 377: comp_flag++; 378: break; 379: 380: case 'l': /* check the parser */ 381: lexdebug++; 382: break; 383: 384: default: 385: fprintf(stderr, "%s: unrecognized switch -%c\n", progname, *cp); 386: exit(1); 387: } 388: } else if (devname == NULL) { 389: devname = argv[0]; 390: } else if (filename == NULL) { 391: filename = argv[0]; 392: } else { 393: fprintf(stderr, "%s: extra arguments starting with %s\n", progname, argv[0]); 394: exit(1); 395: } 396: argc--; argv++; 397: } 398: 399: if (filename != NULL || set_flag || comp_flag) 400: readin(filename, &hy_route); 401: 402: if (print_flag) 403: symtab_print(); 404: 405: if (set_flag) 406: settable(&hy_route); 407: 408: if (dump_flag) { 409: if (filename == NULL) { 410: gettable(&ker_hy_route); 411: print_table(&ker_hy_route); 412: } else { 413: print_table(&hy_route); 414: } 415: } 416: 417: if (comp_flag) { 418: gettable(&ker_hy_route); 419: compare_table(&hy_route, &ker_hy_route); 420: } 421: } 422: 423: /* 424: * read in the control file named filename into structure r 425: */ 426: readin(filename, r) 427: char *filename; 428: register struct hy_route *r; 429: { 430: register char *cp; 431: register struct sym *s; 432: unsigned gates[256]; 433: char buf[512]; 434: unsigned i; 435: extern FILE *yyin; 436: 437: if (filename == NULL || *filename == '\0' || strcmp(filename, "-") == 0) { 438: yyin = stdin; 439: } else { 440: yyin = fopen(filename, "r"); 441: if (yyin == NULL) { 442: perror(filename); 443: exit(1); 444: } 445: } 446: 447: maxgate = 0; 448: bzero((char *)r, sizeof(*r)); 449: 450: lex_error = 0; 451: yylex(); 452: if (lex_error) { 453: fprintf(stderr, "hyroute: syntax errors, aborting operation\n"); 454: exit(1); 455: } 456: 457: for (s = sym_head; s != NULL; s = s->sym_next) { 458: if (s->sym_flags & HS_DIR) { 459: add_direct(inet_lnaof(s->sym_inaddr), s->sym_dst, s->sym_ctl, s->sym_access, s->sym_flags, r); 460: } else if (s->sym_flags & HS_INDIR) { 461: for (i = 0; i < s->sym_ngate; i++) 462: gates[i] = inet_lnaof(s->sym_gate[i]->sym_inaddr); 463: add_gates(inet_lnaof(s->sym_inaddr), s->sym_ngate, gates, r); 464: } 465: } 466: }