121138Sdist /* 234772Sbostic * Copyright (c) 1983, 1988 Regents of the University of California. 333457Skarels * All rights reserved. 433457Skarels * 533457Skarels * Redistribution and use in source and binary forms are permitted 634772Sbostic * provided that the above copyright notice and this paragraph are 734772Sbostic * duplicated in all such forms and that any documentation, 834772Sbostic * advertising materials, and other materials related to such 934772Sbostic * distribution and use acknowledge that the software was developed 1034772Sbostic * by the University of California, Berkeley. The name of the 1134772Sbostic * University may not be used to endorse or promote products derived 1234772Sbostic * from this software without specific prior written permission. 1334772Sbostic * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR 1434772Sbostic * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED 1534772Sbostic * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. 1621138Sdist */ 1721138Sdist 189197Ssam #ifndef lint 1921138Sdist char copyright[] = 2034772Sbostic "@(#) Copyright (c) 1983, 1988 Regents of the University of California.\n\ 2121138Sdist All rights reserved.\n"; 2234772Sbostic #endif /* not lint */ 236478Ssam 2421138Sdist #ifndef lint 25*37278Sbostic static char sccsid[] = "@(#)implog.c 5.11 (Berkeley) 04/02/89"; 2634772Sbostic #endif /* not lint */ 2721138Sdist 28*37278Sbostic #include <sys/param.h> 2913600Ssam #include <sys/time.h> 30*37278Sbostic #include <sys/signal.h> 3134037Skarels #include <sys/file.h> 326478Ssam #include <sys/stat.h> 336478Ssam #include <sys/socket.h> 349195Ssam 3533455Skarels #include <net/if.h> 3633455Skarels 379195Ssam #include <netinet/in.h> 3833455Skarels #define IMPMESSAGES 396478Ssam #define IMPLEADERS 409195Ssam #include <netimp/if_imp.h> 416478Ssam 42*37278Sbostic #include <sgtty.h> 43*37278Sbostic #include <stdio.h> 44*37278Sbostic #include "pathnames.h" 456478Ssam 466478Ssam u_char buf[1024]; 476478Ssam int showdata = 1; 486478Ssam int showcontents = 0; 4927727Skarels int rawheader = 0; 506478Ssam int follow = 0; 5134037Skarels int skip = 0; 526478Ssam int link = -1; 536478Ssam int host = -1; 546478Ssam int imp = -1; 556478Ssam int packettype = -1; 566478Ssam extern int errno; 576478Ssam int log; 586478Ssam 596478Ssam /* 606478Ssam * Socket address, internet style, with 616478Ssam * unused space taken by timestamp and packet 626478Ssam * size. 636478Ssam */ 646478Ssam struct sockstamp { 656478Ssam short sin_family; 666478Ssam u_short sin_port; 676478Ssam struct in_addr sin_addr; 686478Ssam time_t sin_time; 696478Ssam int sin_cc; 706478Ssam }; 716478Ssam struct sockstamp from; 726478Ssam 736478Ssam main(argc, argv) 74*37278Sbostic int argc; 75*37278Sbostic char **argv; 766478Ssam { 77*37278Sbostic extern int errno, optind; 78*37278Sbostic extern char *optarg; 796478Ssam struct stat b; 80*37278Sbostic off_t size, lseek(); 81*37278Sbostic char *logfile, *strerror(); 82*37278Sbostic int ch; 83*37278Sbostic long hostfrom, impfrom; 846478Ssam 85*37278Sbostic while ((ch = getopt(argc, argv, "DFLcfh:i:l:rt:")) != EOF) 86*37278Sbostic switch(ch) { 87*37278Sbostic case 'D': 886478Ssam showdata = 0; 89*37278Sbostic break; 90*37278Sbostic case 'F': 9134037Skarels skip++; 92*37278Sbostic /* FALLTHROUGH */ 93*37278Sbostic case 'f': 9434037Skarels follow++; 95*37278Sbostic break; 96*37278Sbostic case 'L': 97*37278Sbostic link = IMPLINK_IP; 98*37278Sbostic break; 99*37278Sbostic case 'c': 1006478Ssam showcontents++; 101*37278Sbostic break; 102*37278Sbostic case 'h': 103*37278Sbostic host = atoi(optarg); 104*37278Sbostic break; 105*37278Sbostic case 'i': 106*37278Sbostic imp = atoi(optarg); 107*37278Sbostic break; 108*37278Sbostic case 'l': 109*37278Sbostic link = atoi(optarg); 110*37278Sbostic break; 111*37278Sbostic case 'r': 11227727Skarels rawheader++; 113*37278Sbostic break; 114*37278Sbostic case 't': 115*37278Sbostic packettype = atoi(optarg); 116*37278Sbostic break; 117*37278Sbostic case '?': 118*37278Sbostic default: 119*37278Sbostic fprintf(stderr, 120*37278Sbostic "usage: implog [-DFLcfr] [-h host] [-i imp] [-l link] [-t type] [logfile]\n"); 121*37278Sbostic exit(2); 12227727Skarels } 123*37278Sbostic argc -= optind; 124*37278Sbostic argv += optind; 125*37278Sbostic 126*37278Sbostic logfile = argc ? *argv : _PATH_IMPLOG; 127*37278Sbostic log = open(logfile, O_RDONLY, 0); 128*37278Sbostic if (log < 0 || fstat(log, &b)) { 129*37278Sbostic fprintf(stderr, "implog: %s: %s\n", logfile, strerror(errno)); 1306478Ssam exit(1); 1316478Ssam } 1326478Ssam size = b.st_size; 13334037Skarels if (skip) 134*37278Sbostic (void)lseek(log, size, L_SET); 1356478Ssam again: 1366478Ssam while (read(log, (char *)&from, sizeof(from)) == sizeof(from)) { 1376478Ssam if (from.sin_family == 0) { 1386478Ssam printf("restarted: %.24s\n", ctime(&from.sin_time)); 1396478Ssam continue; 1406478Ssam } 14122597Skarels if (host >= 0) { 14222597Skarels long addr = ntohs(from.sin_addr.s_addr); 14322597Skarels 14422597Skarels if (IN_CLASSA(addr)) { 14522597Skarels hostfrom = ((addr>>16) & 0xFF); 14622597Skarels impfrom = addr & 0xFF; 14722597Skarels } else if (IN_CLASSB(addr)) { 14822597Skarels hostfrom = ((addr>>8) & 0xFF); 14922597Skarels impfrom = addr & 0xFF; 15022597Skarels } else { 15122597Skarels hostfrom = ((addr>>4) & 0xF); 15222597Skarels impfrom = addr & 0xF; 15322597Skarels } 15422597Skarels } 15522597Skarels if (host >= 0 && hostfrom != host) { 156*37278Sbostic (void)lseek(log, (long)from.sin_cc, L_INCR); 1576478Ssam continue; 1586478Ssam } 15922597Skarels if (imp >= 0 && impfrom != imp) { 160*37278Sbostic (void)lseek(log, (long)from.sin_cc, L_INCR); 16122597Skarels continue; 1626478Ssam } 1636478Ssam process(log, &from); 1646478Ssam } 1656478Ssam while (follow) { 166*37278Sbostic (void)fflush(stdout); 167*37278Sbostic (void)sleep(5); 168*37278Sbostic (void)fstat(log, &b); 1696478Ssam if (b.st_size > size) { 1706478Ssam size = b.st_size; 1716478Ssam goto again; 1726478Ssam } 1736478Ssam } 1746478Ssam } 1756478Ssam 1766478Ssam int impdata(), impbadleader(), impdown(), impnoop(); 1776478Ssam int imprfnm(), impincomplete(), imphostdead(), imphostunreach(); 1786478Ssam int impbaddata(), impreset(), impretry(), impnotify(), imptrying(); 1796478Ssam int impready(), impundef(); 1806478Ssam 1816478Ssam struct messages { 1826478Ssam u_char m_type; /* type of message */ 1836478Ssam int (*m_func)(); /* routine to process message */ 1846478Ssam } mtypes[] = { 1856478Ssam { IMPTYPE_DATA, impdata }, 1866478Ssam { IMPTYPE_BADLEADER, impbadleader }, 1876478Ssam { IMPTYPE_DOWN, impdown }, 1886478Ssam { IMPTYPE_NOOP, impnoop }, 1896478Ssam { IMPTYPE_RFNM, imprfnm }, 1906478Ssam { IMPTYPE_INCOMPLETE, impincomplete }, 1916478Ssam { IMPTYPE_HOSTDEAD, imphostdead }, 1926478Ssam { IMPTYPE_HOSTUNREACH, imphostunreach }, 1936478Ssam { IMPTYPE_BADDATA, impbaddata }, 1946478Ssam { IMPTYPE_RESET, impreset }, 1956478Ssam { IMPTYPE_RETRY, impretry }, 1966478Ssam { IMPTYPE_NOTIFY, impnotify }, 1976478Ssam { IMPTYPE_TRYING, imptrying }, 1986478Ssam { IMPTYPE_READY, impready }, 1996478Ssam { -1, impundef } 2006478Ssam }; 2016478Ssam 2026478Ssam /* 2036478Ssam * Print a packet. 2046478Ssam */ 2056478Ssam process(l, f) 2066478Ssam int l; 2076478Ssam struct sockstamp *f; 2086478Ssam { 2096478Ssam register struct messages *mp; 2106478Ssam struct imp_leader *ip; 21127727Skarels int (*fn)(); 2126478Ssam 2136478Ssam if (read(l, (char *)buf, f->sin_cc) != f->sin_cc) { 214*37278Sbostic perror("implog: read"); 2156478Ssam return; 2166478Ssam } 2176478Ssam ip = (struct imp_leader *)buf; 21828904Skarels ip->il_imp = ntohs(ip->il_imp); 21927727Skarels if (ip->il_format != IMP_NFF) 22027727Skarels fn = impundef; 22127727Skarels else { 22233085Sbostic for (mp = mtypes; mp->m_type != (u_char)-1; mp++) 22327727Skarels if (mp->m_type == ip->il_mtype) 22427727Skarels break; 22527727Skarels fn = mp->m_func; 22627727Skarels } 22727727Skarels if (ip->il_mtype == IMPTYPE_DATA) { 2286478Ssam if (link >= 0 && ip->il_link != link) 2296478Ssam return; 2306478Ssam if (!showdata) 2316478Ssam return; 2326478Ssam } 23327727Skarels if (packettype >= 0 && ip->il_mtype != packettype) 2346478Ssam return; 2356478Ssam printf("%.24s: ", ctime(&f->sin_time)); 23628904Skarels if (f->sin_cc < sizeof(struct control_leader)) 23728904Skarels printf("(truncated header, %d bytes): ", f->sin_cc); 23827727Skarels (*fn)(ip, f->sin_cc); 23928904Skarels if (rawheader && fn != impundef) { 24028904Skarels putchar('\t'); 24127727Skarels impundef(ip, f->sin_cc); 24228904Skarels } 2436478Ssam } 2446478Ssam 2456478Ssam impdata(ip, cc) 2466478Ssam register struct imp_leader *ip; 247*37278Sbostic int cc; 2486478Ssam { 249*37278Sbostic printf("<DATA, source=%d/%u, link=", ip->il_host, (u_short)ip->il_imp); 2506478Ssam if (ip->il_link == IMPLINK_IP) 2516478Ssam printf("ip,"); 2526478Ssam else 2536478Ssam printf("%d,", ip->il_link); 254*37278Sbostic printf(" len=%u bytes>\n", ntohs((u_short)ip->il_length) >> 3); 2556478Ssam if (showcontents) { 2566478Ssam register u_char *cp = ((u_char *)ip) + sizeof(*ip); 2576478Ssam register int i; 2586478Ssam 2596478Ssam i = (ntohs(ip->il_length) >> 3) - sizeof(struct imp_leader); 260*37278Sbostic cc = MIN(i, cc); 2616478Ssam printf("data: (%d bytes)", cc); 2626478Ssam for (i = 0; i < cc; i++, cp++) { 2636478Ssam if (i % 25 == 0) 2646478Ssam printf("\n"); 2656478Ssam printf("%02x ", *cp); 2666478Ssam } 2676478Ssam putchar('\n'); 2686478Ssam } 2696478Ssam } 2706478Ssam 2716478Ssam char *badleader[] = { 2726478Ssam "error flip-flop set", 2736478Ssam "message < 80 bits", 2746478Ssam "illegal type field", 2756478Ssam "opposite leader type" 2766478Ssam }; 2776478Ssam 278*37278Sbostic /* ARGSUSED */ 279*37278Sbostic impbadleader(ip, cc) 2806478Ssam register struct imp_leader *ip; 281*37278Sbostic int cc; 2826478Ssam { 2836478Ssam printf("bad leader: "); 2846478Ssam if (ip->il_subtype > IMPLEADER_OPPOSITE) 2856478Ssam printf("%x\n", ip->il_subtype); 2866478Ssam else 2876478Ssam printf("%s\n", badleader[ip->il_subtype]); 2886478Ssam } 2896478Ssam 290*37278Sbostic /* ARGSUSED */ 291*37278Sbostic impdown(ip, cc) 2926478Ssam register struct imp_leader *ip; 293*37278Sbostic int cc; 2946478Ssam { 2956478Ssam int tdown, tbackup; 2966478Ssam 29733455Skarels printf("imp going down %s", impmessage[ip->il_link & IMP_DMASK]); 29833455Skarels tdown = ((ip->il_link >> IMPDOWN_WHENSHIFT) & IMPDOWN_WHENMASK) * 29933455Skarels IMPDOWN_WHENUNIT; 30033455Skarels if ((ip->il_link & IMP_DMASK) != IMPDOWN_GOING) 3016478Ssam printf(" in %d minutes", tdown); 30233455Skarels tbackup = ip->il_subtype * IMPDOWN_WHENUNIT; 3036478Ssam printf(": back up "); 3046478Ssam if (tbackup) 3056478Ssam printf("%d minutes\n", tbackup); 3066478Ssam else 3076478Ssam printf("immediately\n"); 3086478Ssam } 3096478Ssam 310*37278Sbostic /* ARGSUSED */ 311*37278Sbostic impnoop(ip, cc) 3126478Ssam register struct imp_leader *ip; 313*37278Sbostic int cc; 3146478Ssam { 315*37278Sbostic printf("noop: host %d, imp %u\n", ip->il_host, ip->il_imp); 3166478Ssam } 3176478Ssam 318*37278Sbostic /* ARGSUSED */ 319*37278Sbostic imprfnm(ip, cc) 3206478Ssam register struct imp_leader *ip; 321*37278Sbostic int cc; 3226478Ssam { 323*37278Sbostic printf("rfnm: htype=%x, source=%d/%u, link=", 3246478Ssam ip->il_htype, ip->il_host, ip->il_imp); 3256478Ssam if (ip->il_link == IMPLINK_IP) 3266478Ssam printf("ip,"); 3276478Ssam else 32827727Skarels printf("%d,", ip->il_link); 3296478Ssam printf(" subtype=%x\n", ip->il_subtype); 3306478Ssam } 3316478Ssam 3326478Ssam char *hostdead[] = { 3339195Ssam "#0", 3346478Ssam "ready-line negated", 3356478Ssam "tardy receiving messages", 3366478Ssam "ncc doesn't know host", 3376478Ssam "imp software won't allow messages", 3386478Ssam "host down for scheduled pm", 3396478Ssam "host down for hardware work", 3406478Ssam "host down for software work", 3416478Ssam "host down for emergency restart", 3426478Ssam "host down because of power outage", 3436478Ssam "host stopped at a breakpoint", 3446478Ssam "host down due to hardware failure", 3456478Ssam "host not scheduled to be up", 3469195Ssam "#13", 3479195Ssam "#14", 3486478Ssam "host in the process of coming up" 3496478Ssam }; 3506478Ssam 351*37278Sbostic /* ARGSUSED */ 352*37278Sbostic imphostdead(ip, cc) 3536478Ssam register struct imp_leader *ip; 354*37278Sbostic int cc; 3556478Ssam { 356*37278Sbostic printf("host %u/%u dead: ", ip->il_host, ip->il_imp); 3576478Ssam if (ip->il_link & IMP_DMASK) 35833455Skarels printf("down %s, ", impmessage[ip->il_link & IMP_DMASK]); 3596478Ssam if (ip->il_subtype <= IMPHOST_COMINGUP) 3606478Ssam printf("%s\n", hostdead[ip->il_subtype]); 3616478Ssam else 3626478Ssam printf("subtype=%x\n", ip->il_subtype); 3636478Ssam } 3646478Ssam 3656478Ssam char *hostunreach[] = { 3666478Ssam "destination imp can't be reached", 3676478Ssam "destination host isn't up", 3686478Ssam "host doesn't support long leader", 3696478Ssam "communication is prohibited" 3706478Ssam }; 3716478Ssam 372*37278Sbostic /* ARGSUSED */ 373*37278Sbostic imphostunreach(ip, cc) 3746478Ssam register struct imp_leader *ip; 375*37278Sbostic int cc; 3766478Ssam { 377*37278Sbostic printf("host %u/%u unreachable: ", ip->il_host, ip->il_imp); 3786478Ssam if (ip->il_subtype <= IMPREACH_PROHIBITED) 3796478Ssam printf("%s\n", hostunreach[ip->il_subtype]); 3806478Ssam else 3816478Ssam printf("subtype=%x\n", ip->il_subtype); 3826478Ssam } 3836478Ssam 384*37278Sbostic /* ARGSUSED */ 385*37278Sbostic impbaddata(ip, cc) 3866478Ssam register struct imp_leader *ip; 387*37278Sbostic int cc; 3886478Ssam { 389*37278Sbostic printf("error in data: htype=%x, source=%u/%u, link=", 3906478Ssam ip->il_htype, ip->il_host, ip->il_imp); 3916478Ssam if (ip->il_link == IMPLINK_IP) 3926478Ssam printf("ip, "); 3936478Ssam else 39427727Skarels printf("%d, ", ip->il_link); 3956478Ssam printf("subtype=%x\n", ip->il_subtype); 3966478Ssam } 3976478Ssam 3986478Ssam char *incomplete[] = { 3996478Ssam "host didn't take data fast enough", 4006478Ssam "message was too long", 4016478Ssam "message transmission time > 15 seconds", 4026478Ssam "imp/circuit failure", 4036478Ssam "no resources within 15 seconds", 4046478Ssam "source imp i/o failure during receipt" 4056478Ssam }; 4066478Ssam 407*37278Sbostic /* ARGSUSED */ 408*37278Sbostic impincomplete(ip, cc) 4096478Ssam register struct imp_leader *ip; 410*37278Sbostic int cc; 4116478Ssam { 412*37278Sbostic printf("incomplete: htype=%x, source=%u/%u, link=", 4136478Ssam ip->il_htype, ip->il_host, ip->il_imp); 4146478Ssam if (ip->il_link == IMPLINK_IP) 4156478Ssam printf("ip,"); 4166478Ssam else 41727727Skarels printf("%d,", ip->il_link); 4186478Ssam if (ip->il_subtype <= IMPCOMPLETE_IMPIO) 4196478Ssam printf(" %s\n", incomplete[ip->il_subtype]); 4206478Ssam else 4216478Ssam printf(" subtype=%x\n", ip->il_subtype); 4226478Ssam } 4236478Ssam 424*37278Sbostic /* ARGSUSED */ 425*37278Sbostic impreset(ip, cc) 426*37278Sbostic struct imp_leader *ip; 427*37278Sbostic int cc; 4286478Ssam { 4296478Ssam printf("reset complete\n"); 4306478Ssam } 4316478Ssam 4326478Ssam char *retry[] = { 4336478Ssam "imp buffer wasn't available", 4346478Ssam "connection block unavailable" 4356478Ssam }; 4366478Ssam 437*37278Sbostic /* ARGSUSED */ 438*37278Sbostic impretry(ip, cc) 4396478Ssam register struct imp_leader *ip; 440*37278Sbostic int cc; 4416478Ssam { 4426478Ssam printf("refused, try again: "); 4436478Ssam if (ip->il_subtype <= IMPRETRY_BLOCK) 4446478Ssam printf("%s\n", retry[ip->il_subtype]); 4456478Ssam else 4466478Ssam printf("subtype=%x\n", ip->il_subtype); 4476478Ssam } 4486478Ssam 4496478Ssam char *notify[] = { 4509195Ssam "#0", 4519195Ssam "#1", 4526478Ssam "connection not available", 4536478Ssam "reassembly space not available at destination", 4546478Ssam "message number not available", 4556478Ssam "transaction block for message not available" 4566478Ssam }; 4576478Ssam 458*37278Sbostic /* ARGSUSED */ 459*37278Sbostic impnotify(ip, cc) 4606478Ssam register struct imp_leader *ip; 461*37278Sbostic int cc; 4626478Ssam { 4636478Ssam printf("refused, will notify: "); 4646478Ssam if (ip->il_subtype <= 5) 4656478Ssam printf("%s\n", notify[ip->il_subtype]); 4666478Ssam else 4676478Ssam printf("subtype=%x\n", ip->il_subtype); 4686478Ssam } 4696478Ssam 470*37278Sbostic /* ARGSUSED */ 471*37278Sbostic imptrying(ip, cc) 472*37278Sbostic struct imp_leader *ip; 473*37278Sbostic int cc; 4746478Ssam { 4756478Ssam printf("refused, still trying\n"); 4766478Ssam } 4776478Ssam 478*37278Sbostic /* ARGSUSED */ 479*37278Sbostic impready(ip, cc) 480*37278Sbostic struct imp_leader *ip; 481*37278Sbostic int cc; 4826478Ssam { 4836478Ssam printf("ready\n"); 4846478Ssam } 4856478Ssam 486*37278Sbostic /* ARGSUSED */ 487*37278Sbostic impundef(ip, cc) 4886478Ssam register struct imp_leader *ip; 489*37278Sbostic int cc; 4906478Ssam { 4916478Ssam printf("<fmt=%x, net=%x, flags=%x, mtype=", ip->il_format, 4926478Ssam ip->il_network, ip->il_flags); 493*37278Sbostic printf("%x, htype=%x,\n\t host=%d(x%x), imp=%u(x%x), link=", 49428904Skarels ip->il_mtype, ip->il_htype, ip->il_host, ip->il_host, 49528904Skarels ip->il_imp, ip->il_imp); 4966478Ssam if (ip->il_link == IMPLINK_IP) 4976478Ssam printf("ip,"); 4986478Ssam else 49928904Skarels printf("%d (x%x),", ip->il_link, ip->il_link); 50028904Skarels printf(" subtype=%x", ip->il_subtype); 501*37278Sbostic if (cc >= sizeof(struct imp_leader) && ip->il_length) 502*37278Sbostic printf(" len=%u bytes", ntohs((u_short)ip->il_length) >> 3); 50328904Skarels printf(">\n"); 5046478Ssam } 505