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