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