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