1 /* 2 * Copyright (c) 1983,1988 Regents of the University of California. 3 * All rights reserved. 4 * 5 * Redistribution and use in source and binary forms are permitted 6 * provided that this notice is preserved and that due credit is given 7 * to the University of California at Berkeley. The name of the University 8 * may not be used to endorse or promote products derived from this 9 * software without specific prior written permission. This software 10 * is provided ``as is'' without express or implied warranty. 11 */ 12 13 #ifndef lint 14 char copyright[] = 15 "@(#) Copyright (c) 1983,1988 Regents of the University of California.\n\ 16 All rights reserved.\n"; 17 #endif not lint 18 19 #ifndef lint 20 static char sccsid[] = "@(#)implog.c 5.8 (Berkeley) 02/08/88"; 21 #endif not lint 22 23 #include <stdio.h> 24 #include <signal.h> 25 #include <sgtty.h> 26 27 #include <sys/time.h> 28 #include <sys/types.h> 29 #include <sys/stat.h> 30 #include <sys/socket.h> 31 32 #include <net/if.h> 33 34 #include <netinet/in.h> 35 #define IMPMESSAGES 36 #define IMPLEADERS 37 #include <netimp/if_imp.h> 38 39 #define min(a, b) ((a) < (b) ? (a) : (b)) 40 41 u_char buf[1024]; 42 int showdata = 1; 43 int showcontents = 0; 44 int rawheader = 0; 45 int follow = 0; 46 int link = -1; 47 int host = -1; 48 int imp = -1; 49 int packettype = -1; 50 extern int errno; 51 int log; 52 char *logfile = "/usr/adm/implog"; 53 54 /* 55 * Socket address, internet style, with 56 * unused space taken by timestamp and packet 57 * size. 58 */ 59 struct sockstamp { 60 short sin_family; 61 u_short sin_port; 62 struct in_addr sin_addr; 63 time_t sin_time; 64 int sin_cc; 65 }; 66 struct sockstamp from; 67 68 main(argc, argv) 69 char *argv[]; 70 { 71 struct stat b; 72 int size; 73 char *cp; 74 int hostfrom, impfrom; 75 76 argc--, argv++; 77 while (argc > 0 && argv[0][0] == '-') { 78 if (strcmp(*argv, "-D") == 0) { 79 showdata = 0; 80 argv++, argc--; 81 continue; 82 } 83 if (strcmp(*argv, "-f") == 0) { 84 follow++; 85 argv++, argc--; 86 continue; 87 } 88 if (strcmp(*argv, "-c") == 0) { 89 showcontents++; 90 argv++, argc--; 91 continue; 92 } 93 if (strcmp(*argv, "-r") == 0) { 94 rawheader++; 95 argv++, argc--; 96 continue; 97 } 98 if (strcmp(*argv, "-l") == 0) { 99 argc--, argv++; 100 if (argc > 0) { 101 link = atoi(*argv); 102 argc--, argv++; 103 } else 104 link = IMPLINK_IP; 105 continue; 106 } 107 if (strcmp(*argv, "-h") == 0) { 108 argc--, argv++; 109 if (argc < 1) { 110 printf("-h: missing host #\n"); 111 exit(2); 112 } 113 host = atoi(*argv); 114 argv++, argc--; 115 continue; 116 } 117 if (strcmp(*argv, "-i") == 0) { 118 argc--, argv++; 119 if (argc < 1) { 120 printf("-i: missing imp #\n"); 121 exit(2); 122 } 123 imp = atoi(*argv); 124 argv++, argc--; 125 continue; 126 } 127 if (strcmp(*argv, "-t") == 0) { 128 argc--, argv++;; 129 if (argc < 1) { 130 printf("-t: missing packet type\n"); 131 exit(2); 132 } 133 packettype = atoi(*argv); 134 argv++, argc--;; 135 continue; 136 } 137 printf("usage: implog [ -D ] [ -c ] [ -f ] [ -r ] [-h #] [-i #] [ -t # ] [-l [#]] [logfile]\n"); 138 exit(2); 139 } 140 if (argc > 0) 141 logfile = argv[0]; 142 log = open(logfile, 0); 143 if (log < 0) { 144 perror(logfile); 145 exit(1); 146 } 147 fstat(log, &b); 148 size = b.st_size; 149 again: 150 while (read(log, (char *)&from, sizeof(from)) == sizeof(from)) { 151 if (from.sin_family == 0) { 152 printf("restarted: %.24s\n", ctime(&from.sin_time)); 153 continue; 154 } 155 if (host >= 0) { 156 long addr = ntohs(from.sin_addr.s_addr); 157 158 if (IN_CLASSA(addr)) { 159 hostfrom = ((addr>>16) & 0xFF); 160 impfrom = addr & 0xFF; 161 } else if (IN_CLASSB(addr)) { 162 hostfrom = ((addr>>8) & 0xFF); 163 impfrom = addr & 0xFF; 164 } else { 165 hostfrom = ((addr>>4) & 0xF); 166 impfrom = addr & 0xF; 167 } 168 } 169 if (host >= 0 && hostfrom != host) { 170 lseek(log, from.sin_cc, 1); 171 continue; 172 } 173 if (imp >= 0 && impfrom != imp) { 174 lseek(log, from.sin_cc, 1); 175 continue; 176 } 177 process(log, &from); 178 } 179 while (follow) { 180 fflush(stdout); 181 sleep(5); 182 fstat(log, &b); 183 if (b.st_size > size) { 184 size = b.st_size; 185 goto again; 186 } 187 } 188 } 189 190 int impdata(), impbadleader(), impdown(), impnoop(); 191 int imprfnm(), impincomplete(), imphostdead(), imphostunreach(); 192 int impbaddata(), impreset(), impretry(), impnotify(), imptrying(); 193 int impready(), impundef(); 194 195 struct messages { 196 u_char m_type; /* type of message */ 197 int (*m_func)(); /* routine to process message */ 198 } mtypes[] = { 199 { IMPTYPE_DATA, impdata }, 200 { IMPTYPE_BADLEADER, impbadleader }, 201 { IMPTYPE_DOWN, impdown }, 202 { IMPTYPE_NOOP, impnoop }, 203 { IMPTYPE_RFNM, imprfnm }, 204 { IMPTYPE_INCOMPLETE, impincomplete }, 205 { IMPTYPE_HOSTDEAD, imphostdead }, 206 { IMPTYPE_HOSTUNREACH, imphostunreach }, 207 { IMPTYPE_BADDATA, impbaddata }, 208 { IMPTYPE_RESET, impreset }, 209 { IMPTYPE_RETRY, impretry }, 210 { IMPTYPE_NOTIFY, impnotify }, 211 { IMPTYPE_TRYING, imptrying }, 212 { IMPTYPE_READY, impready }, 213 { -1, impundef } 214 }; 215 216 /* 217 * Print a packet. 218 */ 219 process(l, f) 220 int l; 221 struct sockstamp *f; 222 { 223 register struct messages *mp; 224 struct imp_leader *ip; 225 int (*fn)(); 226 227 if (read(l, (char *)buf, f->sin_cc) != f->sin_cc) { 228 perror("read"); 229 return; 230 } 231 ip = (struct imp_leader *)buf; 232 ip->il_imp = ntohs(ip->il_imp); 233 if (ip->il_format != IMP_NFF) 234 fn = impundef; 235 else { 236 for (mp = mtypes; mp->m_type != (u_char)-1; mp++) 237 if (mp->m_type == ip->il_mtype) 238 break; 239 fn = mp->m_func; 240 } 241 if (ip->il_mtype == IMPTYPE_DATA) { 242 if (link >= 0 && ip->il_link != link) 243 return; 244 if (!showdata) 245 return; 246 } 247 if (packettype >= 0 && ip->il_mtype != packettype) 248 return; 249 printf("%.24s: ", ctime(&f->sin_time)); 250 if (f->sin_cc < sizeof(struct control_leader)) 251 printf("(truncated header, %d bytes): ", f->sin_cc); 252 (*fn)(ip, f->sin_cc); 253 if (rawheader && fn != impundef) { 254 putchar('\t'); 255 impundef(ip, f->sin_cc); 256 } 257 } 258 259 impdata(ip, cc) 260 register struct imp_leader *ip; 261 { 262 printf("<DATA, source=%d/%d, link=", ip->il_host, (u_short)ip->il_imp); 263 if (ip->il_link == IMPLINK_IP) 264 printf("ip,"); 265 else 266 printf("%d,", ip->il_link); 267 printf(" len=%d bytes>\n", ntohs((u_short)ip->il_length) >> 3); 268 if (showcontents) { 269 register u_char *cp = ((u_char *)ip) + sizeof(*ip); 270 register int i; 271 272 i = (ntohs(ip->il_length) >> 3) - sizeof(struct imp_leader); 273 cc = min(i, cc); 274 printf("data: (%d bytes)", cc); 275 for (i = 0; i < cc; i++, cp++) { 276 if (i % 25 == 0) 277 printf("\n"); 278 printf("%02x ", *cp); 279 } 280 putchar('\n'); 281 } 282 } 283 284 char *badleader[] = { 285 "error flip-flop set", 286 "message < 80 bits", 287 "illegal type field", 288 "opposite leader type" 289 }; 290 291 impbadleader(ip) 292 register struct imp_leader *ip; 293 { 294 printf("bad leader: "); 295 if (ip->il_subtype > IMPLEADER_OPPOSITE) 296 printf("%x\n", ip->il_subtype); 297 else 298 printf("%s\n", badleader[ip->il_subtype]); 299 } 300 301 impdown(ip) 302 register struct imp_leader *ip; 303 { 304 int tdown, tbackup; 305 306 printf("imp going down %s", impmessage[ip->il_link & IMP_DMASK]); 307 tdown = ((ip->il_link >> IMPDOWN_WHENSHIFT) & IMPDOWN_WHENMASK) * 308 IMPDOWN_WHENUNIT; 309 if ((ip->il_link & IMP_DMASK) != IMPDOWN_GOING) 310 printf(" in %d minutes", tdown); 311 tbackup = ip->il_subtype * IMPDOWN_WHENUNIT; 312 printf(": back up "); 313 if (tbackup) 314 printf("%d minutes\n", tbackup); 315 else 316 printf("immediately\n"); 317 } 318 319 impnoop(ip) 320 register struct imp_leader *ip; 321 { 322 printf("noop: host %d, imp %d\n", ip->il_host, 323 (u_short)ip->il_imp); 324 } 325 326 imprfnm(ip) 327 register struct imp_leader *ip; 328 { 329 printf("rfnm: htype=%x, source=%d/%d, link=", 330 ip->il_htype, ip->il_host, ip->il_imp); 331 if (ip->il_link == IMPLINK_IP) 332 printf("ip,"); 333 else 334 printf("%d,", ip->il_link); 335 printf(" subtype=%x\n", ip->il_subtype); 336 } 337 338 char *hostdead[] = { 339 "#0", 340 "ready-line negated", 341 "tardy receiving messages", 342 "ncc doesn't know host", 343 "imp software won't allow messages", 344 "host down for scheduled pm", 345 "host down for hardware work", 346 "host down for software work", 347 "host down for emergency restart", 348 "host down because of power outage", 349 "host stopped at a breakpoint", 350 "host down due to hardware failure", 351 "host not scheduled to be up", 352 "#13", 353 "#14", 354 "host in the process of coming up" 355 }; 356 357 imphostdead(ip) 358 register struct imp_leader *ip; 359 { 360 printf("host %d/%d dead: ", ip->il_host, ip->il_imp); 361 if (ip->il_link & IMP_DMASK) 362 printf("down %s, ", impmessage[ip->il_link & IMP_DMASK]); 363 if (ip->il_subtype <= IMPHOST_COMINGUP) 364 printf("%s\n", hostdead[ip->il_subtype]); 365 else 366 printf("subtype=%x\n", ip->il_subtype); 367 } 368 369 char *hostunreach[] = { 370 "destination imp can't be reached", 371 "destination host isn't up", 372 "host doesn't support long leader", 373 "communication is prohibited" 374 }; 375 376 imphostunreach(ip) 377 register struct imp_leader *ip; 378 { 379 printf("host %d/%d unreachable: ", ip->il_host, ip->il_imp); 380 if (ip->il_subtype <= IMPREACH_PROHIBITED) 381 printf("%s\n", hostunreach[ip->il_subtype]); 382 else 383 printf("subtype=%x\n", ip->il_subtype); 384 } 385 386 impbaddata(ip) 387 register struct imp_leader *ip; 388 { 389 printf("error in data: htype=%x, source=%d/%d, link=", 390 ip->il_htype, ip->il_host, ip->il_imp); 391 if (ip->il_link == IMPLINK_IP) 392 printf("ip, "); 393 else 394 printf("%d, ", ip->il_link); 395 printf("subtype=%x\n", ip->il_subtype); 396 } 397 398 char *incomplete[] = { 399 "host didn't take data fast enough", 400 "message was too long", 401 "message transmission time > 15 seconds", 402 "imp/circuit failure", 403 "no resources within 15 seconds", 404 "source imp i/o failure during receipt" 405 }; 406 407 impincomplete(ip) 408 register struct imp_leader *ip; 409 { 410 printf("incomplete: htype=%x, source=%d/%d, link=", 411 ip->il_htype, ip->il_host, ip->il_imp); 412 if (ip->il_link == IMPLINK_IP) 413 printf("ip,"); 414 else 415 printf("%d,", ip->il_link); 416 if (ip->il_subtype <= IMPCOMPLETE_IMPIO) 417 printf(" %s\n", incomplete[ip->il_subtype]); 418 else 419 printf(" subtype=%x\n", ip->il_subtype); 420 } 421 422 impreset(ip) 423 register struct imp_leader *ip; 424 { 425 printf("reset complete\n"); 426 } 427 428 char *retry[] = { 429 "imp buffer wasn't available", 430 "connection block unavailable" 431 }; 432 433 impretry(ip) 434 register struct imp_leader *ip; 435 { 436 printf("refused, try again: "); 437 if (ip->il_subtype <= IMPRETRY_BLOCK) 438 printf("%s\n", retry[ip->il_subtype]); 439 else 440 printf("subtype=%x\n", ip->il_subtype); 441 } 442 443 char *notify[] = { 444 "#0", 445 "#1", 446 "connection not available", 447 "reassembly space not available at destination", 448 "message number not available", 449 "transaction block for message not available" 450 }; 451 452 impnotify(ip) 453 register struct imp_leader *ip; 454 { 455 printf("refused, will notify: "); 456 if (ip->il_subtype <= 5) 457 printf("%s\n", notify[ip->il_subtype]); 458 else 459 printf("subtype=%x\n", ip->il_subtype); 460 } 461 462 imptrying(ip) 463 register struct imp_leader *ip; 464 { 465 printf("refused, still trying\n"); 466 } 467 468 impready(ip) 469 register struct imp_leader *ip; 470 { 471 printf("ready\n"); 472 } 473 474 impundef(ip, len) 475 register struct imp_leader *ip; 476 { 477 printf("<fmt=%x, net=%x, flags=%x, mtype=", ip->il_format, 478 ip->il_network, ip->il_flags); 479 printf("%x, htype=%x,\n\t host=%d(x%x), imp=%d(x%x), link=", 480 ip->il_mtype, ip->il_htype, ip->il_host, ip->il_host, 481 ip->il_imp, ip->il_imp); 482 if (ip->il_link == IMPLINK_IP) 483 printf("ip,"); 484 else 485 printf("%d (x%x),", ip->il_link, ip->il_link); 486 printf(" subtype=%x", ip->il_subtype); 487 if (len >= sizeof(struct imp_leader) && ip->il_length) 488 printf(" len=%d bytes", ntohs((u_short)ip->il_length) >> 3); 489 printf(">\n"); 490 } 491