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