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