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