2 * Copyright (c) 1992, 1993, 1994, 1995, 1996, 1997
3 * The Regents of the University of California. All rights reserved.
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
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.
23 static const char rcsid[] _U_ =
24 "@(#) $Header: /tcpdump/master/tcpdump/print-decnet.c,v 1.36.2.2 2003/11/16 08:51:16 guy Exp $ (LBL)";
31 #include <tcpdump-stdinc.h>
36 #ifdef HAVE_NETDNET_DNETDB_H
37 #include <netdnet/dnetdb.h>
46 #include "interface.h"
47 #include "addrtoname.h"
50 static void print_decnet_ctlmsg(const union routehdr *, u_int);
51 static void print_t_info(int);
52 static void print_l1_routes(const char *, u_int);
53 static void print_l2_routes(const char *, u_int);
54 static void print_i_info(int);
55 static void print_elist(const char *, u_int);
56 static void print_nsp(const u_char *, u_int);
57 static void print_reason(int);
59 static void pdata(u_char *, int);
62 #ifndef HAVE_NETDNET_DNETDB_H_DNET_HTOA
63 extern char *dnet_htoa(struct dn_naddr *);
67 decnet_print(register const u_char *ap, register u_int length,
68 register u_int caplen)
70 static union routehdr rhcopy;
71 register union routehdr *rhp = &rhcopy;
74 u_int rhlen, nsplen, pktlen;
77 if (length < sizeof(struct shorthdr)) {
78 (void)printf("[|decnet]");
82 pktlen = EXTRACT_LE_16BITS(ap);
84 rhlen = min(length, caplen);
85 rhlen = min(rhlen, sizeof(*rhp));
86 memcpy((char *)rhp, (char *)&(ap[sizeof(short)]), rhlen);
88 mflags = EXTRACT_LE_8BITS(rhp->rh_short.sh_flags);
90 if (mflags & RMF_PAD) {
91 /* pad bytes of some sort in front of message */
92 u_int padlen = mflags & RMF_PADMASK;
94 (void) printf("[pad:%d] ", 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);
104 if (mflags & RMF_FVER) {
105 (void) printf("future-version-decnet");
106 default_print(ap, length);
110 /* is it a control message? */
111 if (mflags & RMF_CTLMSG) {
112 print_decnet_ctlmsg(rhp, min(length, caplen));
116 switch (mflags & RMF_MASK) {
119 EXTRACT_LE_16BITS(rhp->rh_long.lg_dst.dne_remote.dne_nodeaddr);
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)));
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)));
136 (void) printf("unknown message flags under mask");
137 default_print((u_char *)ap, length);
141 (void)printf("%s > %s %d ",
142 dnaddr_string(src), dnaddr_string(dst), pktlen);
144 if (mflags & RMF_RQR)
145 (void)printf("RQR ");
146 if (mflags & RMF_RTS)
147 (void)printf("RTS ");
150 (void)printf("%d hops ", hops);
153 print_nsp(nspp, nsplen);
157 print_decnet_ctlmsg(register const union routehdr *rhp, u_int length)
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;
164 char *rhpx = (char *)rhp;
166 switch (mflags & RMF_CTLMASK) {
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);
178 "src %sblksize %d vers %d eco %d ueco %d hello %d",
179 dnaddr_string(src), blksize, vers, eco, ueco,
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);
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);
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));
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));
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),
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);
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));
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),
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);
239 memcpy((char *)&rtea, (char *)&(cmp->cm_ehello.eh_router),
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);
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);
252 (void)printf("unknown control message");
253 default_print((u_char *)rhp, length);
259 print_t_info(int info)
261 int ntype = info & 3;
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;
269 (void)printf("verif ");
271 (void)printf("blo ");
275 print_l1_routes(const char *rp, u_int len)
281 /* The last short is a checksum */
282 while (len > (3 * sizeof(short))) {
283 count = EXTRACT_LE_16BITS(rp);
285 return; /* seems to be bogus from here on */
287 len -= sizeof(short);
288 id = EXTRACT_LE_16BITS(rp);
290 len -= sizeof(short);
291 info = EXTRACT_LE_16BITS(rp);
293 len -= sizeof(short);
294 (void)printf("{ids %d-%d cost %d hops %d} ", id, id + count,
295 RI_COST(info), RI_HOPS(info));
300 print_l2_routes(const char *rp, u_int len)
306 /* The last short is a checksum */
307 while (len > (3 * sizeof(short))) {
308 count = EXTRACT_LE_16BITS(rp);
310 return; /* seems to be bogus from here on */
312 len -= sizeof(short);
313 area = EXTRACT_LE_16BITS(rp);
315 len -= sizeof(short);
316 info = EXTRACT_LE_16BITS(rp);
318 len -= sizeof(short);
319 (void)printf("{areas %d-%d cost %d hops %d} ", area, area + count,
320 RI_COST(info), RI_HOPS(info));
325 print_i_info(int info)
327 int ntype = info & II_TYPEMASK;
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;
335 (void)printf("verif ");
336 if (info & II_NOMCAST)
337 (void)printf("nomcast ");
339 (void)printf("blo ");
343 print_elist(const char *elp _U_, u_int len _U_)
345 /* Not enough examples available for me to debug this */
349 print_nsp(const u_char *nspp, u_int nsplen _U_)
351 const struct nsphdr *nsphp = (struct nsphdr *)nspp;
354 flags = EXTRACT_LE_8BITS(nsphp->nh_flags);
355 dst = EXTRACT_LE_16BITS(nsphp->nh_dst);
356 src = EXTRACT_LE_16BITS(nsphp->nh_src);
358 switch (flags & NSP_TYPEMASK) {
360 switch (flags & NSP_SUBMASK) {
364 case MFS_BOM+MFS_EOM:
365 printf("data %d>%d ", src, dst);
367 struct seghdr *shp = (struct seghdr *)nspp;
372 u_int data_off = sizeof(struct minseghdr);
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);
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);
386 (void)printf("oack %d ", ack & SGQ_MASK);
387 ack = EXTRACT_LE_16BITS(shp->sh_seq[2]);
388 data_off += sizeof(short);
391 (void)printf("seg %d ", ack & SGQ_MASK);
393 dp = &(nspp[data_off]);
398 case MFS_ILS+MFS_INT:
401 struct seghdr *shp = (struct seghdr *)nspp;
406 u_int data_off = sizeof(struct minseghdr);
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);
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);
420 (void)printf("ackdat %d ", ack & SGQ_MASK);
421 ack = EXTRACT_LE_16BITS(shp->sh_seq[2]);
422 data_off += sizeof(short);
425 (void)printf("seg %d ", ack & SGQ_MASK);
427 dp = &(nspp[data_off]);
433 (void)printf("link-service %d>%d ", src, dst);
435 struct seghdr *shp = (struct seghdr *)nspp;
437 (struct lsmsg *)&(nspp[sizeof(struct seghdr)]);
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);
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);
452 (void)printf("ackdat %d ", ack & SGQ_MASK);
453 ack = EXTRACT_LE_16BITS(shp->sh_seq[2]);
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) {
461 (void)printf("dat seg count %d ", fcval);
462 switch (lsflags & LSM_MASK) {
466 (void)printf("donotsend-data ");
469 (void)printf("send-data ");
472 (void)printf("reserved-fcmod? %x", lsflags);
477 (void)printf("intr req count %d ", fcval);
480 (void)printf("reserved-fcval-int? %x", lsflags);
486 (void)printf("reserved-subtype? %x %d > %d", flags, src, dst);
491 switch (flags & NSP_SUBMASK) {
493 (void)printf("data-ack %d>%d ", src, dst);
495 struct ackmsg *amp = (struct ackmsg *)nspp;
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);
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);
509 (void)printf("oack %d ", ack & SGQ_MASK);
515 (void)printf("ils-ack %d>%d ", src, dst);
517 struct ackmsg *amp = (struct ackmsg *)nspp;
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);
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);
531 (void)printf("ackdat %d ", ack & SGQ_MASK);
537 (void)printf("conn-ack %d", dst);
540 (void)printf("reserved-acktype? %x %d > %d", flags, src, dst);
545 switch (flags & NSP_SUBMASK) {
548 if ((flags & NSP_SUBMASK) == MFS_CI)
549 (void)printf("conn-initiate ");
551 (void)printf("retrans-conn-initiate ");
552 (void)printf("%d>%d ", src, dst);
554 struct cimsg *cimp = (struct cimsg *)nspp;
555 int services, info, segsize;
560 services = EXTRACT_LE_8BITS(cimp->ci_services);
561 info = EXTRACT_LE_8BITS(cimp->ci_info);
562 segsize = EXTRACT_LE_16BITS(cimp->ci_segsize);
564 switch (services & COS_MASK) {
568 (void)printf("seg ");
571 (void)printf("msg ");
574 (void)printf("crypt ");
577 switch (info & COI_MASK) {
579 (void)printf("ver 3.2 ");
582 (void)printf("ver 3.1 ");
585 (void)printf("ver 4.0 ");
588 (void)printf("ver 4.1 ");
591 (void)printf("segsize %d ", segsize);
593 dp = &(nspp[sizeof(struct cimsg)]);
594 pdata(dp, nsplen - sizeof(struct cimsg));
599 (void)printf("conn-confirm %d>%d ", src, dst);
601 struct ccmsg *ccmp = (struct ccmsg *)nspp;
603 u_int segsize, optlen;
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);
613 switch (services & COS_MASK) {
617 (void)printf("seg ");
620 (void)printf("msg ");
623 (void)printf("crypt ");
626 switch (info & COI_MASK) {
628 (void)printf("ver 3.2 ");
631 (void)printf("ver 3.1 ");
634 (void)printf("ver 4.0 ");
637 (void)printf("ver 4.1 ");
640 (void)printf("segsize %d ", segsize);
642 (void)printf("optlen %d ", optlen);
644 optlen = min(optlen, nsplen - sizeof(struct ccmsg));
645 dp = &(nspp[sizeof(struct ccmsg)]);
652 (void)printf("disconn-initiate %d>%d ", src, dst);
654 struct dimsg *dimp = (struct dimsg *)nspp;
661 reason = EXTRACT_LE_16BITS(dimp->di_reason);
662 optlen = EXTRACT_LE_8BITS(dimp->di_optlen);
664 print_reason(reason);
666 (void)printf("optlen %d ", optlen);
668 optlen = min(optlen, nsplen - sizeof(struct dimsg));
669 dp = &(nspp[sizeof(struct dimsg)]);
676 (void)printf("disconn-confirm %d>%d ", src, dst);
678 struct dcmsg *dcmp = (struct dcmsg *)nspp;
681 reason = EXTRACT_LE_16BITS(dcmp->dc_reason);
683 print_reason(reason);
687 (void)printf("reserved-ctltype? %x %d > %d", flags, src, dst);
692 (void)printf("reserved-type? %x %d > %d", flags, src, dst);
697 static 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" },
724 print_reason(register int reason)
726 printf("%s ", tok2str(reason2str, "reason-%d", reason));
730 dnnum_string(u_short dnaddr)
734 int area = (u_short)(dnaddr & AREAMASK) >> AREASHIFT;
735 int node = dnaddr & NODEMASK;
737 str = (char *)malloc(siz = sizeof("00.0000"));
739 error("dnnum_string: malloc");
740 snprintf(str, siz, "%d.%d", area, node);
745 dnname_string(u_short dnaddr)
747 #ifdef HAVE_DNET_HTOA
750 dna.a_len = sizeof(short);
751 memcpy((char *)dna.a_addr, (char *)&dnaddr, sizeof(short));
752 return (strdup(dnet_htoa(&dna)));
754 return(dnnum_string(dnaddr)); /* punt */
760 pdata(u_char *dp, u_int maxlen)