xref: /original-bsd/old/implog/implog.c (revision 44811ff2)
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