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