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