GCC Code Coverage Report
Directory: ./ Exec Total Coverage
File: usr.sbin/tcpdump/print-decnet.c Lines: 0 431 0.0 %
Date: 2017-11-13 Branches: 0 359 0.0 %

Line Branch Exec Source
1
/*	$OpenBSD: print-decnet.c,v 1.17 2015/11/16 00:16:39 mmcc Exp $	*/
2
3
/*
4
 * Copyright (c) 1992, 1993, 1994, 1995, 1996, 1997
5
 *	The Regents of the University of California.  All rights reserved.
6
 *
7
 * Redistribution and use in source and binary forms, with or without
8
 * modification, are permitted provided that: (1) source code distributions
9
 * retain the above copyright notice and this paragraph in its entirety, (2)
10
 * distributions including binary code include the above copyright notice and
11
 * this paragraph in its entirety in the documentation or other materials
12
 * provided with the distribution, and (3) all advertising materials mentioning
13
 * features or use of this software display the following acknowledgement:
14
 * ``This product includes software developed by the University of California,
15
 * Lawrence Berkeley Laboratory and its contributors.'' Neither the name of
16
 * the University nor the names of its contributors may be used to endorse
17
 * or promote products derived from this software without specific prior
18
 * written permission.
19
 * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED
20
 * WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
21
 * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
22
 */
23
24
#include <sys/time.h>
25
#include <sys/socket.h>
26
27
struct mbuf;
28
struct rtentry;
29
#include <net/if.h>
30
31
#ifdef	HAVE_LIBDNET
32
#include <netdnet/dnetdb.h>
33
#endif
34
35
#include <ctype.h>
36
#include <stdio.h>
37
#include <stdlib.h>
38
#include <string.h>
39
#include <unistd.h>
40
41
#include "decnet.h"
42
#include "extract.h"
43
#include "interface.h"
44
#include "addrtoname.h"
45
46
/* Forwards */
47
static int print_decnet_ctlmsg(const union routehdr *, u_int, u_int);
48
static void print_t_info(int);
49
static int print_l1_routes(const char *, u_int);
50
static int print_l2_routes(const char *, u_int);
51
static void print_i_info(int);
52
static int print_elist(const char *, u_int);
53
static int print_nsp(const u_char *, u_int);
54
static void print_reason(int);
55
#ifdef	PRINT_NSPDATA
56
static void pdata(u_char *, int);
57
#endif
58
59
#ifdef	HAVE_LIBDNET
60
extern char *dnet_htoa(struct dn_naddr *);
61
#endif
62
63
void
64
decnet_print(const u_char *ap, u_int length, u_int caplen)
65
{
66
	static union routehdr rhcopy;
67
	union routehdr *rhp = &rhcopy;
68
	int mflags;
69
	int dst, src, hops;
70
	u_int rhlen, nsplen, pktlen;
71
	const u_char *nspp;
72
73
	if (length < sizeof(struct shorthdr)) {
74
		(void)printf("[|decnet]");
75
		return;
76
	}
77
78
	TCHECK2(*ap, sizeof(short));
79
	pktlen = EXTRACT_LE_16BITS(ap);
80
	if (pktlen < sizeof(struct shorthdr)) {
81
		(void)printf("[|decnet]");
82
		return;
83
	}
84
	if (pktlen > length) {
85
		(void)printf("[|decnet]");
86
		return;
87
	}
88
	length = pktlen;
89
90
	rhlen = min(length, caplen);
91
	rhlen = min(rhlen, sizeof(*rhp));
92
	memcpy((char *)rhp, (char *)&(ap[sizeof(short)]), rhlen);
93
94
	TCHECK(rhp->rh_short.sh_flags);
95
	mflags = EXTRACT_LE_8BITS(rhp->rh_short.sh_flags);
96
97
	if (mflags & RMF_PAD) {
98
	    /* pad bytes of some sort in front of message */
99
	    u_int padlen = mflags & RMF_PADMASK;
100
	    if (vflag)
101
		(void) printf("[pad:%d] ", padlen);
102
	    if (length < padlen + 2) {
103
		(void)printf("[|decnet]");
104
		return;
105
	    }
106
	    TCHECK2(ap[sizeof(short)], padlen);
107
	    ap += padlen;
108
	    length -= padlen;
109
	    caplen -= padlen;
110
	    rhlen = min(length, caplen);
111
	    rhlen = min(rhlen, sizeof(*rhp));
112
	    memcpy((char *)rhp, (char *)&(ap[sizeof(short)]), rhlen);
113
	    mflags = EXTRACT_LE_8BITS(rhp->rh_short.sh_flags);
114
	}
115
116
	if (mflags & RMF_FVER) {
117
		(void) printf("future-version-decnet");
118
		default_print(ap, min(length, caplen));
119
		return;
120
	}
121
122
	/* is it a control message? */
123
	if (mflags & RMF_CTLMSG) {
124
		if(!print_decnet_ctlmsg(rhp, length, caplen))
125
			goto trunc;
126
		return;
127
	}
128
129
	switch (mflags & RMF_MASK) {
130
	case RMF_LONG:
131
	    if (length < sizeof(struct longhdr)) {
132
		(void)printf("[|decnet]");
133
		return;
134
	    }
135
	    TCHECK(rhp->rh_long);
136
	    dst =
137
		EXTRACT_LE_16BITS(rhp->rh_long.lg_dst.dne_remote.dne_nodeaddr);
138
	    src =
139
		EXTRACT_LE_16BITS(rhp->rh_long.lg_src.dne_remote.dne_nodeaddr);
140
	    hops = EXTRACT_LE_8BITS(rhp->rh_long.lg_visits);
141
	    nspp = &(ap[sizeof(short) + sizeof(struct longhdr)]);
142
	    nsplen = length - sizeof(struct longhdr);
143
	    break;
144
	case RMF_SHORT:
145
	    TCHECK(rhp->rh_short);
146
	    dst = EXTRACT_LE_16BITS(rhp->rh_short.sh_dst);
147
	    src = EXTRACT_LE_16BITS(rhp->rh_short.sh_src);
148
	    hops = (EXTRACT_LE_8BITS(rhp->rh_short.sh_visits) & VIS_MASK)+1;
149
	    nspp = &(ap[sizeof(short) + sizeof(struct shorthdr)]);
150
	    nsplen = length - sizeof(struct shorthdr);
151
	    break;
152
	default:
153
	    (void) printf("unknown message flags under mask");
154
	    default_print((u_char *)ap, min(length, caplen));
155
	    return;
156
	}
157
158
	(void)printf("%s > %s %d ",
159
			dnaddr_string(src), dnaddr_string(dst), pktlen);
160
	if (vflag) {
161
	    if (mflags & RMF_RQR)
162
		(void)printf("RQR ");
163
	    if (mflags & RMF_RTS)
164
		(void)printf("RTS ");
165
	    if (mflags & RMF_IE)
166
		(void)printf("IE ");
167
	    (void)printf("%d hops ", hops);
168
	}
169
170
	if (!print_nsp(nspp, nsplen))
171
		goto trunc;
172
	return;
173
174
trunc:
175
	(void)printf("[|decnet]");
176
	return;
177
}
178
179
static int
180
print_decnet_ctlmsg(const union routehdr *rhp, u_int length,
181
    u_int caplen)
182
{
183
	int mflags = EXTRACT_LE_8BITS(rhp->rh_short.sh_flags);
184
	union controlmsg *cmp = (union controlmsg *)rhp;
185
	int src, dst, info, blksize, eco, ueco, hello, other, vers;
186
	etheraddr srcea, rtea;
187
	int priority;
188
	char *rhpx = (char *)rhp;
189
	int ret;
190
191
	switch (mflags & RMF_CTLMASK) {
192
	case RMF_INIT:
193
	    (void)printf("init ");
194
	    if (length < sizeof(struct initmsg))
195
		goto trunc;
196
	    TCHECK(cmp->cm_init);
197
	    src = EXTRACT_LE_16BITS(cmp->cm_init.in_src);
198
	    info = EXTRACT_LE_8BITS(cmp->cm_init.in_info);
199
	    blksize = EXTRACT_LE_16BITS(cmp->cm_init.in_blksize);
200
	    vers = EXTRACT_LE_8BITS(cmp->cm_init.in_vers);
201
	    eco = EXTRACT_LE_8BITS(cmp->cm_init.in_eco);
202
	    ueco = EXTRACT_LE_8BITS(cmp->cm_init.in_ueco);
203
	    hello = EXTRACT_LE_16BITS(cmp->cm_init.in_hello);
204
	    print_t_info(info);
205
	    (void)printf(
206
		"src %sblksize %d vers %d eco %d ueco %d hello %d",
207
			dnaddr_string(src), blksize, vers, eco, ueco,
208
			hello);
209
210
	    ret = 1;
211
	    break;
212
	case RMF_VER:
213
	    (void)printf("verification ");
214
	    if (length < sizeof(struct verifmsg))
215
		goto trunc;
216
	    TCHECK(cmp->cm_ver);
217
	    src = EXTRACT_LE_16BITS(cmp->cm_ver.ve_src);
218
	    other = EXTRACT_LE_8BITS(cmp->cm_ver.ve_fcnval);
219
	    (void)printf("src %s fcnval %o", dnaddr_string(src), other);
220
	    ret = 1;
221
	    break;
222
	case RMF_TEST:
223
	    (void)printf("test ");
224
	    if (length < sizeof(struct testmsg))
225
		goto trunc;
226
	    TCHECK(cmp->cm_test);
227
	    src = EXTRACT_LE_16BITS(cmp->cm_test.te_src);
228
	    other = EXTRACT_LE_8BITS(cmp->cm_test.te_data);
229
	    (void)printf("src %s data %o", dnaddr_string(src), other);
230
	    ret = 1;
231
	    break;
232
	case RMF_L1ROUT:
233
	    (void)printf("lev-1-routing ");
234
	    if (length < sizeof(struct l1rout))
235
		goto trunc;
236
	    TCHECK(cmp->cm_l1rou);
237
	    src = EXTRACT_LE_16BITS(cmp->cm_l1rou.r1_src);
238
	    (void)printf("src %s ", dnaddr_string(src));
239
	    ret = print_l1_routes(&(rhpx[sizeof(struct l1rout)]),
240
				length - sizeof(struct l1rout));
241
	    break;
242
	case RMF_L2ROUT:
243
	    (void)printf("lev-2-routing ");
244
	    if (length < sizeof(struct l2rout))
245
		goto trunc;
246
	    TCHECK(cmp->cm_l2rout);
247
	    src = EXTRACT_LE_16BITS(cmp->cm_l2rout.r2_src);
248
	    (void)printf("src %s ", dnaddr_string(src));
249
	    ret = print_l2_routes(&(rhpx[sizeof(struct l2rout)]),
250
				length - sizeof(struct l2rout));
251
	    break;
252
	case RMF_RHELLO:
253
	    (void)printf("router-hello ");
254
	    if (length < sizeof(struct rhellomsg))
255
		goto trunc;
256
	    TCHECK(cmp->cm_rhello);
257
	    vers = EXTRACT_LE_8BITS(cmp->cm_rhello.rh_vers);
258
	    eco = EXTRACT_LE_8BITS(cmp->cm_rhello.rh_eco);
259
	    ueco = EXTRACT_LE_8BITS(cmp->cm_rhello.rh_ueco);
260
	    memcpy((char *)&srcea, (char *)&(cmp->cm_rhello.rh_src),
261
		sizeof(srcea));
262
	    src = EXTRACT_LE_16BITS(srcea.dne_remote.dne_nodeaddr);
263
	    info = EXTRACT_LE_8BITS(cmp->cm_rhello.rh_info);
264
	    blksize = EXTRACT_LE_16BITS(cmp->cm_rhello.rh_blksize);
265
	    priority = EXTRACT_LE_8BITS(cmp->cm_rhello.rh_priority);
266
	    hello = EXTRACT_LE_16BITS(cmp->cm_rhello.rh_hello);
267
	    print_i_info(info);
268
	    (void)printf(
269
	    "vers %d eco %d ueco %d src %s blksize %d pri %d hello %d",
270
			vers, eco, ueco, dnaddr_string(src),
271
			blksize, priority, hello);
272
	    ret = print_elist(&(rhpx[sizeof(struct rhellomsg)]),
273
				length - sizeof(struct rhellomsg));
274
	    break;
275
	case RMF_EHELLO:
276
	    (void)printf("endnode-hello ");
277
	    if (length < sizeof(struct ehellomsg))
278
		goto trunc;
279
	    TCHECK(cmp->cm_ehello);
280
	    vers = EXTRACT_LE_8BITS(cmp->cm_ehello.eh_vers);
281
	    eco = EXTRACT_LE_8BITS(cmp->cm_ehello.eh_eco);
282
	    ueco = EXTRACT_LE_8BITS(cmp->cm_ehello.eh_ueco);
283
	    memcpy((char *)&srcea, (char *)&(cmp->cm_ehello.eh_src),
284
		sizeof(srcea));
285
	    src = EXTRACT_LE_16BITS(srcea.dne_remote.dne_nodeaddr);
286
	    info = EXTRACT_LE_8BITS(cmp->cm_ehello.eh_info);
287
	    blksize = EXTRACT_LE_16BITS(cmp->cm_ehello.eh_blksize);
288
	    /*seed*/
289
	    memcpy((char *)&rtea, (char *)&(cmp->cm_ehello.eh_router),
290
		sizeof(rtea));
291
	    dst = EXTRACT_LE_16BITS(rtea.dne_remote.dne_nodeaddr);
292
	    hello = EXTRACT_LE_16BITS(cmp->cm_ehello.eh_hello);
293
	    other = EXTRACT_LE_8BITS(cmp->cm_ehello.eh_data);
294
	    print_i_info(info);
295
	    (void)printf(
296
	"vers %d eco %d ueco %d src %s blksize %d rtr %s hello %d data %o",
297
			vers, eco, ueco, dnaddr_string(src),
298
			blksize, dnaddr_string(dst), hello, other);
299
	    ret = 1;
300
	    break;
301
302
	default:
303
	    (void)printf("unknown control message");
304
	    default_print((u_char *)rhp, min(length, caplen));
305
	    ret = 1;
306
	    break;
307
	}
308
	return (ret);
309
310
trunc:
311
	return (0);
312
}
313
314
static void
315
print_t_info(int info)
316
{
317
	int ntype = info & 3;
318
	switch (ntype) {
319
	case 0: (void)printf("reserved-ntype? "); break;
320
	case TI_L2ROUT: (void)printf("l2rout "); break;
321
	case TI_L1ROUT: (void)printf("l1rout "); break;
322
	case TI_ENDNODE: (void)printf("endnode "); break;
323
	}
324
	if (info & TI_VERIF)
325
	    (void)printf("verif ");
326
	if (info & TI_BLOCK)
327
	    (void)printf("blo ");
328
}
329
330
static int
331
print_l1_routes(const char *rp, u_int len)
332
{
333
	int count;
334
	int id;
335
	int info;
336
337
	/* The last short is a checksum */
338
	while (len > (3 * sizeof(short))) {
339
	    TCHECK2(*rp, 3 * sizeof(short));
340
	    count = EXTRACT_LE_16BITS(rp);
341
	    if (count > 1024)
342
		return (1);	/* seems to be bogus from here on */
343
	    rp += sizeof(short);
344
	    len -= sizeof(short);
345
	    id = EXTRACT_LE_16BITS(rp);
346
	    rp += sizeof(short);
347
	    len -= sizeof(short);
348
	    info = EXTRACT_LE_16BITS(rp);
349
	    rp += sizeof(short);
350
	    len -= sizeof(short);
351
	    (void)printf("{ids %d-%d cost %d hops %d} ", id, id + count,
352
			    RI_COST(info), RI_HOPS(info));
353
	}
354
	return (1);
355
356
trunc:
357
	return (0);
358
}
359
360
static int
361
print_l2_routes(const char *rp, u_int len)
362
{
363
	int count;
364
	int area;
365
	int info;
366
367
	/* The last short is a checksum */
368
	while (len > (3 * sizeof(short))) {
369
	    TCHECK2(*rp, 3 * sizeof(short));
370
	    count = EXTRACT_LE_16BITS(rp);
371
	    if (count > 1024)
372
		return (1);	/* seems to be bogus from here on */
373
	    rp += sizeof(short);
374
	    len -= sizeof(short);
375
	    area = EXTRACT_LE_16BITS(rp);
376
	    rp += sizeof(short);
377
	    len -= sizeof(short);
378
	    info = EXTRACT_LE_16BITS(rp);
379
	    rp += sizeof(short);
380
	    len -= sizeof(short);
381
	    (void)printf("{areas %d-%d cost %d hops %d} ", area, area + count,
382
			    RI_COST(info), RI_HOPS(info));
383
	}
384
	return (1);
385
386
trunc:
387
	return (0);
388
}
389
390
static void
391
print_i_info(int info)
392
{
393
	int ntype = info & II_TYPEMASK;
394
	switch (ntype) {
395
	case 0: (void)printf("reserved-ntype? "); break;
396
	case II_L2ROUT: (void)printf("l2rout "); break;
397
	case II_L1ROUT: (void)printf("l1rout "); break;
398
	case II_ENDNODE: (void)printf("endnode "); break;
399
	}
400
	if (info & II_VERIF)
401
	    (void)printf("verif ");
402
	if (info & II_NOMCAST)
403
	    (void)printf("nomcast ");
404
	if (info & II_BLOCK)
405
	    (void)printf("blo ");
406
}
407
408
static int
409
print_elist(const char *elp, u_int len)
410
{
411
	/* Not enough examples available for me to debug this */
412
	return (1);
413
}
414
415
static int
416
print_nsp(const u_char *nspp, u_int nsplen)
417
{
418
	const struct nsphdr *nsphp = (struct nsphdr *)nspp;
419
	int dst, src, flags;
420
421
	if (nsplen < sizeof(struct nsphdr))
422
		goto trunc;
423
	TCHECK(*nsphp);
424
	flags = EXTRACT_LE_8BITS(nsphp->nh_flags);
425
	dst = EXTRACT_LE_16BITS(nsphp->nh_dst);
426
	src = EXTRACT_LE_16BITS(nsphp->nh_src);
427
428
	switch (flags & NSP_TYPEMASK) {
429
	case MFT_DATA:
430
	    switch (flags & NSP_SUBMASK) {
431
	    case MFS_BOM:
432
	    case MFS_MOM:
433
	    case MFS_EOM:
434
	    case MFS_BOM+MFS_EOM:
435
		printf("data %d>%d ", src, dst);
436
		{
437
		    struct seghdr *shp = (struct seghdr *)nspp;
438
		    int ack;
439
#ifdef	PRINT_NSPDATA
440
		    u_char *dp;
441
#endif
442
		    u_int data_off = sizeof(struct minseghdr);
443
444
		    if (nsplen < data_off)
445
			goto trunc;
446
		    TCHECK(shp->sh_seq[0]);
447
		    ack = EXTRACT_LE_16BITS(shp->sh_seq[0]);
448
		    if (ack & SGQ_ACK) {	/* acknum field */
449
			if ((ack & SGQ_NAK) == SGQ_NAK)
450
			    (void)printf("nak %d ", ack & SGQ_MASK);
451
			else
452
			    (void)printf("ack %d ", ack & SGQ_MASK);
453
		        data_off += sizeof(short);
454
			if (nsplen < data_off)
455
			    goto trunc;
456
			TCHECK(shp->sh_seq[1]);
457
			ack = EXTRACT_LE_16BITS(shp->sh_seq[1]);
458
			if (ack & SGQ_OACK) {	/* ackoth field */
459
			    if ((ack & SGQ_ONAK) == SGQ_ONAK)
460
				(void)printf("onak %d ", ack & SGQ_MASK);
461
			    else
462
				(void)printf("oack %d ", ack & SGQ_MASK);
463
			    data_off += sizeof(short);
464
			    if (nsplen < data_off)
465
				goto trunc;
466
			    TCHECK(shp->sh_seq[2]);
467
			    ack = EXTRACT_LE_16BITS(shp->sh_seq[2]);
468
			}
469
		    }
470
		    (void)printf("seg %d ", ack & SGQ_MASK);
471
#ifdef	PRINT_NSPDATA
472
		    if (nsplen > data_off) {
473
			dp = &(nspp[data_off]);
474
			TCHECK2(*dp, nsplen - data_off);
475
			pdata(dp, nsplen - data_off);
476
		    }
477
#endif
478
		}
479
		break;
480
	    case MFS_ILS+MFS_INT:
481
		printf("intr ");
482
		{
483
		    struct seghdr *shp = (struct seghdr *)nspp;
484
		    int ack;
485
#ifdef	PRINT_NSPDATA
486
		    u_char *dp;
487
#endif
488
		    u_int data_off = sizeof(struct minseghdr);
489
490
		    if (nsplen < data_off)
491
			goto trunc;
492
		    TCHECK(shp->sh_seq[0]);
493
		    ack = EXTRACT_LE_16BITS(shp->sh_seq[0]);
494
		    if (ack & SGQ_ACK) {	/* acknum field */
495
			if ((ack & SGQ_NAK) == SGQ_NAK)
496
			    (void)printf("nak %d ", ack & SGQ_MASK);
497
			else
498
			    (void)printf("ack %d ", ack & SGQ_MASK);
499
		        data_off += sizeof(short);
500
			if (nsplen < data_off)
501
			    goto trunc;
502
			TCHECK(shp->sh_seq[1]);
503
			ack = EXTRACT_LE_16BITS(shp->sh_seq[1]);
504
			if (ack & SGQ_OACK) {	/* ackdat field */
505
			    if ((ack & SGQ_ONAK) == SGQ_ONAK)
506
				(void)printf("nakdat %d ", ack & SGQ_MASK);
507
			    else
508
				(void)printf("ackdat %d ", ack & SGQ_MASK);
509
			    data_off += sizeof(short);
510
			    if (nsplen < data_off)
511
				goto trunc;
512
			    TCHECK(shp->sh_seq[2]);
513
			    ack = EXTRACT_LE_16BITS(shp->sh_seq[2]);
514
			}
515
		    }
516
		    (void)printf("seg %d ", ack & SGQ_MASK);
517
#ifdef	PRINT_NSPDATA
518
		    if (nsplen > data_off) {
519
			dp = &(nspp[data_off]);
520
			TCHECK2(*dp, nsplen - data_off);
521
			pdata(dp, nsplen - data_off);
522
		    }
523
#endif
524
		}
525
		break;
526
	    case MFS_ILS:
527
		(void)printf("link-service %d>%d ", src, dst);
528
		{
529
		    struct seghdr *shp = (struct seghdr *)nspp;
530
		    struct lsmsg *lsmp =
531
			(struct lsmsg *)&(nspp[sizeof(struct seghdr)]);
532
		    int ack;
533
		    int lsflags, fcval;
534
535
		    if (nsplen < sizeof(struct seghdr) + sizeof(struct lsmsg))
536
			goto trunc;
537
		    TCHECK(shp->sh_seq[0]);
538
		    ack = EXTRACT_LE_16BITS(shp->sh_seq[0]);
539
		    if (ack & SGQ_ACK) {	/* acknum field */
540
			if ((ack & SGQ_NAK) == SGQ_NAK)
541
			    (void)printf("nak %d ", ack & SGQ_MASK);
542
			else
543
			    (void)printf("ack %d ", ack & SGQ_MASK);
544
			TCHECK(shp->sh_seq[1]);
545
		        ack = EXTRACT_LE_16BITS(shp->sh_seq[1]);
546
			if (ack & SGQ_OACK) {	/* ackdat field */
547
			    if ((ack & SGQ_ONAK) == SGQ_ONAK)
548
				(void)printf("nakdat %d ", ack & SGQ_MASK);
549
			    else
550
				(void)printf("ackdat %d ", ack & SGQ_MASK);
551
			    TCHECK(shp->sh_seq[2]);
552
			    ack = EXTRACT_LE_16BITS(shp->sh_seq[2]);
553
			}
554
		    }
555
		    (void)printf("seg %d ", ack & SGQ_MASK);
556
		    TCHECK(*lsmp);
557
		    lsflags = EXTRACT_LE_8BITS(lsmp->ls_lsflags);
558
		    fcval = EXTRACT_LE_8BITS(lsmp->ls_fcval);
559
		    switch (lsflags & LSI_MASK) {
560
		    case LSI_DATA:
561
			(void)printf("dat seg count %d ", fcval);
562
			switch (lsflags & LSM_MASK) {
563
			case LSM_NOCHANGE:
564
			    break;
565
			case LSM_DONOTSEND:
566
			    (void)printf("donotsend-data ");
567
			    break;
568
			case LSM_SEND:
569
			    (void)printf("send-data ");
570
			    break;
571
			default:
572
			    (void)printf("reserved-fcmod? %x", lsflags);
573
			    break;
574
			}
575
			break;
576
		    case LSI_INTR:
577
			(void)printf("intr req count %d ", fcval);
578
			break;
579
		    default:
580
			(void)printf("reserved-fcval-int? %x", lsflags);
581
			break;
582
		    }
583
		}
584
		break;
585
	    default:
586
		(void)printf("reserved-subtype? %x %d > %d", flags, src, dst);
587
		break;
588
	    }
589
	    break;
590
	case MFT_ACK:
591
	    switch (flags & NSP_SUBMASK) {
592
	    case MFS_DACK:
593
		(void)printf("data-ack %d>%d ", src, dst);
594
		{
595
		    struct ackmsg *amp = (struct ackmsg *)nspp;
596
		    int ack;
597
598
		    if (nsplen < sizeof(struct ackmsg))
599
			goto trunc;
600
		    TCHECK(*amp);
601
		    ack = EXTRACT_LE_16BITS(amp->ak_acknum[0]);
602
		    if (ack & SGQ_ACK) {	/* acknum field */
603
			if ((ack & SGQ_NAK) == SGQ_NAK)
604
			    (void)printf("nak %d ", ack & SGQ_MASK);
605
			else
606
			    (void)printf("ack %d ", ack & SGQ_MASK);
607
		        ack = EXTRACT_LE_16BITS(amp->ak_acknum[1]);
608
			if (ack & SGQ_OACK) {	/* ackoth field */
609
			    if ((ack & SGQ_ONAK) == SGQ_ONAK)
610
				(void)printf("onak %d ", ack & SGQ_MASK);
611
			    else
612
				(void)printf("oack %d ", ack & SGQ_MASK);
613
			}
614
		    }
615
		}
616
		break;
617
	    case MFS_IACK:
618
		(void)printf("ils-ack %d>%d ", src, dst);
619
		{
620
		    struct ackmsg *amp = (struct ackmsg *)nspp;
621
		    int ack;
622
623
		    if (nsplen < sizeof(struct ackmsg))
624
			goto trunc;
625
		    TCHECK(*amp);
626
		    ack = EXTRACT_LE_16BITS(amp->ak_acknum[0]);
627
		    if (ack & SGQ_ACK) {	/* acknum field */
628
			if ((ack & SGQ_NAK) == SGQ_NAK)
629
			    (void)printf("nak %d ", ack & SGQ_MASK);
630
			else
631
			    (void)printf("ack %d ", ack & SGQ_MASK);
632
		        TCHECK(amp->ak_acknum[1]);
633
			ack = EXTRACT_LE_16BITS(amp->ak_acknum[1]);
634
			if (ack & SGQ_OACK) {	/* ackdat field */
635
			    if ((ack & SGQ_ONAK) == SGQ_ONAK)
636
				(void)printf("nakdat %d ", ack & SGQ_MASK);
637
			    else
638
				(void)printf("ackdat %d ", ack & SGQ_MASK);
639
			}
640
		    }
641
		}
642
		break;
643
	    case MFS_CACK:
644
		(void)printf("conn-ack %d", dst);
645
		break;
646
	    default:
647
		(void)printf("reserved-acktype? %x %d > %d", flags, src, dst);
648
		break;
649
	    }
650
	    break;
651
	case MFT_CTL:
652
	    switch (flags & NSP_SUBMASK) {
653
	    case MFS_CI:
654
	    case MFS_RCI:
655
		if ((flags & NSP_SUBMASK) == MFS_CI)
656
		    (void)printf("conn-initiate ");
657
		else
658
		    (void)printf("retrans-conn-initiate ");
659
		(void)printf("%d>%d ", src, dst);
660
		{
661
		    struct cimsg *cimp = (struct cimsg *)nspp;
662
		    int services, info, segsize;
663
#ifdef	PRINT_NSPDATA
664
		    u_char *dp;
665
#endif
666
667
		    if (nsplen < sizeof(struct cimsg))
668
			goto trunc;
669
		    TCHECK(*cimp);
670
		    services = EXTRACT_LE_8BITS(cimp->ci_services);
671
		    info = EXTRACT_LE_8BITS(cimp->ci_info);
672
		    segsize = EXTRACT_LE_16BITS(cimp->ci_segsize);
673
674
		    switch (services & COS_MASK) {
675
		    case COS_NONE:
676
			break;
677
		    case COS_SEGMENT:
678
			(void)printf("seg ");
679
			break;
680
		    case COS_MESSAGE:
681
			(void)printf("msg ");
682
			break;
683
		    case COS_CRYPTSER:
684
			(void)printf("crypt ");
685
			break;
686
		    }
687
		    switch (info & COI_MASK) {
688
		    case COI_32:
689
			(void)printf("ver 3.2 ");
690
			break;
691
		    case COI_31:
692
			(void)printf("ver 3.1 ");
693
			break;
694
		    case COI_40:
695
			(void)printf("ver 4.0 ");
696
			break;
697
		    case COI_41:
698
			(void)printf("ver 4.1 ");
699
			break;
700
		    }
701
		    (void)printf("segsize %d ", segsize);
702
#ifdef	PRINT_NSPDATA
703
		    if (nsplen > sizeof(struct cimsg)) {
704
			dp = &(nspp[sizeof(struct cimsg)]);
705
			TCHECK2(*dp, nsplen - sizeof(struct cimsg));
706
			pdata(dp, nsplen - sizeof(struct cimsg));
707
		    }
708
#endif
709
		}
710
		break;
711
	    case MFS_CC:
712
		(void)printf("conn-confirm %d>%d ", src, dst);
713
		{
714
		    struct ccmsg *ccmp = (struct ccmsg *)nspp;
715
		    int services, info;
716
		    u_int segsize, optlen;
717
#ifdef	PRINT_NSPDATA
718
		    u_char *dp;
719
#endif
720
721
		    if (nsplen < sizeof(struct ccmsg))
722
			goto trunc;
723
		    TCHECK(*ccmp);
724
		    services = EXTRACT_LE_8BITS(ccmp->cc_services);
725
		    info = EXTRACT_LE_8BITS(ccmp->cc_info);
726
		    segsize = EXTRACT_LE_16BITS(ccmp->cc_segsize);
727
		    optlen = EXTRACT_LE_8BITS(ccmp->cc_optlen);
728
729
		    switch (services & COS_MASK) {
730
		    case COS_NONE:
731
			break;
732
		    case COS_SEGMENT:
733
			(void)printf("seg ");
734
			break;
735
		    case COS_MESSAGE:
736
			(void)printf("msg ");
737
			break;
738
		    case COS_CRYPTSER:
739
			(void)printf("crypt ");
740
			break;
741
		    }
742
		    switch (info & COI_MASK) {
743
		    case COI_32:
744
			(void)printf("ver 3.2 ");
745
			break;
746
		    case COI_31:
747
			(void)printf("ver 3.1 ");
748
			break;
749
		    case COI_40:
750
			(void)printf("ver 4.0 ");
751
			break;
752
		    case COI_41:
753
			(void)printf("ver 4.1 ");
754
			break;
755
		    }
756
		    (void)printf("segsize %d ", segsize);
757
		    if (optlen) {
758
			(void)printf("optlen %d ", optlen);
759
#ifdef	PRINT_NSPDATA
760
			if (optlen > nsplen - sizeof(struct ccmsg))
761
			    goto trunc;
762
			dp = &(nspp[sizeof(struct ccmsg)]);
763
			TCHECK2(*dp, optlen);
764
			pdata(dp, optlen);
765
#endif
766
		    }
767
		}
768
		break;
769
	    case MFS_DI:
770
		(void)printf("disconn-initiate %d>%d ", src, dst);
771
		{
772
		    struct dimsg *dimp = (struct dimsg *)nspp;
773
		    int reason;
774
		    u_int optlen;
775
#ifdef	PRINT_NSPDATA
776
		    u_char *dp;
777
#endif
778
779
		    if (nsplen < sizeof(struct dimsg))
780
			goto trunc;
781
		    TCHECK(*dimp);
782
		    reason = EXTRACT_LE_16BITS(dimp->di_reason);
783
		    optlen = EXTRACT_LE_8BITS(dimp->di_optlen);
784
785
		    print_reason(reason);
786
		    if (optlen) {
787
			(void)printf("optlen %d ", optlen);
788
#ifdef	PRINT_NSPDATA
789
			if (optlen > nsplen - sizeof(struct dimsg))
790
			    goto trunc;
791
			dp = &(nspp[sizeof(struct dimsg)]);
792
			TCHECK2(*dp, optlen);
793
			pdata(dp, optlen);
794
#endif
795
		    }
796
		}
797
		break;
798
	    case MFS_DC:
799
		(void)printf("disconn-confirm %d>%d ", src, dst);
800
		{
801
		    struct dcmsg *dcmp = (struct dcmsg *)nspp;
802
		    int reason;
803
804
		    TCHECK(*dcmp);
805
		    reason = EXTRACT_LE_16BITS(dcmp->dc_reason);
806
807
		    print_reason(reason);
808
		}
809
		break;
810
	    default:
811
		(void)printf("reserved-ctltype? %x %d > %d", flags, src, dst);
812
		break;
813
	    }
814
	    break;
815
	default:
816
	    (void)printf("reserved-type? %x %d > %d", flags, src, dst);
817
	    break;
818
	}
819
	return (1);
820
821
trunc:
822
	return (0);
823
}
824
825
static struct tok reason2str[] = {
826
	{ UC_OBJREJECT,		"object rejected connect" },
827
	{ UC_RESOURCES,		"insufficient resources" },
828
	{ UC_NOSUCHNODE,	"unrecognized node name" },
829
	{ DI_SHUT,		"node is shutting down" },
830
	{ UC_NOSUCHOBJ,		"unrecognized object" },
831
	{ UC_INVOBJFORMAT,	"invalid object name format" },
832
	{ UC_OBJTOOBUSY,	"object too busy" },
833
	{ DI_PROTOCOL,		"protocol error discovered" },
834
	{ DI_TPA,		"third party abort" },
835
	{ UC_USERABORT,		"user abort" },
836
	{ UC_INVNODEFORMAT,	"invalid node name format" },
837
	{ UC_LOCALSHUT,		"local node shutting down" },
838
	{ DI_LOCALRESRC,	"insufficient local resources" },
839
	{ DI_REMUSERRESRC,	"insufficient remote user resources" },
840
	{ UC_ACCESSREJECT,	"invalid access control information" },
841
	{ DI_BADACCNT,		"bad ACCOUNT information" },
842
	{ UC_NORESPONSE,	"no response from object" },
843
	{ UC_UNREACHABLE,	"node unreachable" },
844
	{ DC_NOLINK,		"no link terminate" },
845
	{ DC_COMPLETE,		"disconnect complete" },
846
	{ DI_BADIMAGE,		"bad image data in connect" },
847
	{ DI_SERVMISMATCH,	"cryptographic service mismatch" },
848
	{ 0,			NULL }
849
};
850
851
static void
852
print_reason(int reason)
853
{
854
	printf("%s ", tok2str(reason2str, "reason-%d", reason));
855
}
856
857
char *
858
dnnum_string(u_short dnaddr)
859
{
860
	char *str;
861
	int area = (u_short)(dnaddr & AREAMASK) >> AREASHIFT;
862
	int node = dnaddr & NODEMASK;
863
	int len = sizeof("00.0000");
864
865
	str = malloc(len);
866
	if (str == NULL)
867
		error("dnnum_string: malloc");
868
	snprintf(str, len, "%d.%d", area, node);
869
	return(str);
870
}
871
872
char *
873
dnname_string(u_short dnaddr)
874
{
875
#ifdef	HAVE_LIBDNET
876
	struct dn_naddr dna;
877
878
	dna.a_len = sizeof(short);
879
	memcpy((char *)dna.a_addr, (char *)&dnaddr, sizeof(short));
880
	return (savestr(dnet_htoa(&dna)));
881
#else
882
	return(dnnum_string(dnaddr));	/* punt */
883
#endif
884
}
885
886
#ifdef	PRINT_NSPDATA
887
static void
888
pdata(u_char *dp, u_int maxlen)
889
{
890
	int c;
891
	u_int x = maxlen;
892
893
	while (x-- > 0) {
894
	    c = (unsigned char)*dp++;
895
	    if (isprint(c))
896
		putchar(c);
897
	    else
898
		printf("\\%o", c & 0xFF);
899
	}
900
}
901
#endif