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[] =
24 "@(#) $Header: /tcpdump/master/tcpdump/print-decnet.c,v 1.30 2000/09/28 06:42:57 guy Exp $ (LBL)";
31 #include <sys/param.h>
33 #include <sys/socket.h>
39 #include <netdnet/dnetdb.h>
50 #include "interface.h"
51 #include "addrtoname.h"
54 static void print_decnet_ctlmsg(const union routehdr *, u_int);
55 static void print_t_info(int);
56 static void print_l1_routes(const char *, u_int);
57 static void print_l2_routes(const char *, u_int);
58 static void print_i_info(int);
59 static void print_elist(const char *, u_int);
60 static void print_nsp(const u_char *, u_int);
61 static void print_reason(int);
63 static void pdata(u_char *, int);
67 extern char *dnet_htoa(struct dn_naddr *);
71 decnet_print(register const u_char *ap, register u_int length,
72 register u_int caplen)
74 static union routehdr rhcopy;
75 register union routehdr *rhp = &rhcopy;
78 u_int rhlen, nsplen, pktlen;
81 if (length < sizeof(struct shorthdr)) {
82 (void)printf("[|decnet]");
86 pktlen = EXTRACT_LE_16BITS(ap);
88 rhlen = min(length, caplen);
89 rhlen = min(rhlen, sizeof(*rhp));
90 memcpy((char *)rhp, (char *)&(ap[sizeof(short)]), rhlen);
92 mflags = EXTRACT_LE_8BITS(rhp->rh_short.sh_flags);
94 if (mflags & RMF_PAD) {
95 /* pad bytes of some sort in front of message */
96 u_int padlen = mflags & RMF_PADMASK;
98 (void) printf("[pad:%d] ", padlen);
102 rhlen = min(length, caplen);
103 rhlen = min(rhlen, sizeof(*rhp));
104 memcpy((char *)rhp, (char *)&(ap[sizeof(short)]), rhlen);
105 mflags = EXTRACT_LE_8BITS(rhp->rh_short.sh_flags);
108 if (mflags & RMF_FVER) {
109 (void) printf("future-version-decnet");
110 default_print(ap, length);
114 /* is it a control message? */
115 if (mflags & RMF_CTLMSG) {
116 print_decnet_ctlmsg(rhp, min(length, caplen));
120 switch (mflags & RMF_MASK) {
123 EXTRACT_LE_16BITS(rhp->rh_long.lg_dst.dne_remote.dne_nodeaddr);
125 EXTRACT_LE_16BITS(rhp->rh_long.lg_src.dne_remote.dne_nodeaddr);
126 hops = EXTRACT_LE_8BITS(rhp->rh_long.lg_visits);
127 nspp = &(ap[sizeof(short) + sizeof(struct longhdr)]);
128 nsplen = min((length - sizeof(struct longhdr)),
129 (caplen - sizeof(struct longhdr)));
132 dst = EXTRACT_LE_16BITS(rhp->rh_short.sh_dst);
133 src = EXTRACT_LE_16BITS(rhp->rh_short.sh_src);
134 hops = (EXTRACT_LE_8BITS(rhp->rh_short.sh_visits) & VIS_MASK)+1;
135 nspp = &(ap[sizeof(short) + sizeof(struct shorthdr)]);
136 nsplen = min((length - sizeof(struct shorthdr)),
137 (caplen - sizeof(struct shorthdr)));
140 (void) printf("unknown message flags under mask");
141 default_print((u_char *)ap, length);
145 (void)printf("%s > %s %d ",
146 dnaddr_string(src), dnaddr_string(dst), pktlen);
148 if (mflags & RMF_RQR)
149 (void)printf("RQR ");
150 if (mflags & RMF_RTS)
151 (void)printf("RTS ");
154 (void)printf("%d hops ", hops);
157 print_nsp(nspp, nsplen);
161 print_decnet_ctlmsg(register const union routehdr *rhp, u_int length)
163 int mflags = EXTRACT_LE_8BITS(rhp->rh_short.sh_flags);
164 register union controlmsg *cmp = (union controlmsg *)rhp;
165 int src, dst, info, blksize, eco, ueco, hello, other, vers;
166 etheraddr srcea, rtea;
168 char *rhpx = (char *)rhp;
170 switch (mflags & RMF_CTLMASK) {
172 (void)printf("init ");
173 src = EXTRACT_LE_16BITS(cmp->cm_init.in_src);
174 info = EXTRACT_LE_8BITS(cmp->cm_init.in_info);
175 blksize = EXTRACT_LE_16BITS(cmp->cm_init.in_blksize);
176 vers = EXTRACT_LE_8BITS(cmp->cm_init.in_vers);
177 eco = EXTRACT_LE_8BITS(cmp->cm_init.in_eco);
178 ueco = EXTRACT_LE_8BITS(cmp->cm_init.in_ueco);
179 hello = EXTRACT_LE_16BITS(cmp->cm_init.in_hello);
182 "src %sblksize %d vers %d eco %d ueco %d hello %d",
183 dnaddr_string(src), blksize, vers, eco, ueco,
187 (void)printf("verification ");
188 src = EXTRACT_LE_16BITS(cmp->cm_ver.ve_src);
189 other = EXTRACT_LE_8BITS(cmp->cm_ver.ve_fcnval);
190 (void)printf("src %s fcnval %o", dnaddr_string(src), other);
193 (void)printf("test ");
194 src = EXTRACT_LE_16BITS(cmp->cm_test.te_src);
195 other = EXTRACT_LE_8BITS(cmp->cm_test.te_data);
196 (void)printf("src %s data %o", dnaddr_string(src), other);
199 (void)printf("lev-1-routing ");
200 src = EXTRACT_LE_16BITS(cmp->cm_l1rou.r1_src);
201 (void)printf("src %s ", dnaddr_string(src));
202 print_l1_routes(&(rhpx[sizeof(struct l1rout)]),
203 length - sizeof(struct l1rout));
206 (void)printf("lev-2-routing ");
207 src = EXTRACT_LE_16BITS(cmp->cm_l2rout.r2_src);
208 (void)printf("src %s ", dnaddr_string(src));
209 print_l2_routes(&(rhpx[sizeof(struct l2rout)]),
210 length - sizeof(struct l2rout));
213 (void)printf("router-hello ");
214 vers = EXTRACT_LE_8BITS(cmp->cm_rhello.rh_vers);
215 eco = EXTRACT_LE_8BITS(cmp->cm_rhello.rh_eco);
216 ueco = EXTRACT_LE_8BITS(cmp->cm_rhello.rh_ueco);
217 memcpy((char *)&srcea, (char *)&(cmp->cm_rhello.rh_src),
219 src = EXTRACT_LE_16BITS(srcea.dne_remote.dne_nodeaddr);
220 info = EXTRACT_LE_8BITS(cmp->cm_rhello.rh_info);
221 blksize = EXTRACT_LE_16BITS(cmp->cm_rhello.rh_blksize);
222 priority = EXTRACT_LE_8BITS(cmp->cm_rhello.rh_priority);
223 hello = EXTRACT_LE_16BITS(cmp->cm_rhello.rh_hello);
226 "vers %d eco %d ueco %d src %s blksize %d pri %d hello %d",
227 vers, eco, ueco, dnaddr_string(src),
228 blksize, priority, hello);
229 print_elist(&(rhpx[sizeof(struct rhellomsg)]),
230 length - sizeof(struct rhellomsg));
233 (void)printf("endnode-hello ");
234 vers = EXTRACT_LE_8BITS(cmp->cm_ehello.eh_vers);
235 eco = EXTRACT_LE_8BITS(cmp->cm_ehello.eh_eco);
236 ueco = EXTRACT_LE_8BITS(cmp->cm_ehello.eh_ueco);
237 memcpy((char *)&srcea, (char *)&(cmp->cm_ehello.eh_src),
239 src = EXTRACT_LE_16BITS(srcea.dne_remote.dne_nodeaddr);
240 info = EXTRACT_LE_8BITS(cmp->cm_ehello.eh_info);
241 blksize = EXTRACT_LE_16BITS(cmp->cm_ehello.eh_blksize);
243 memcpy((char *)&rtea, (char *)&(cmp->cm_ehello.eh_router),
245 dst = EXTRACT_LE_16BITS(rtea.dne_remote.dne_nodeaddr);
246 hello = EXTRACT_LE_16BITS(cmp->cm_ehello.eh_hello);
247 other = EXTRACT_LE_8BITS(cmp->cm_ehello.eh_data);
250 "vers %d eco %d ueco %d src %s blksize %d rtr %s hello %d data %o",
251 vers, eco, ueco, dnaddr_string(src),
252 blksize, dnaddr_string(dst), hello, other);
256 (void)printf("unknown control message");
257 default_print((u_char *)rhp, length);
263 print_t_info(int info)
265 int ntype = info & 3;
267 case 0: (void)printf("reserved-ntype? "); break;
268 case TI_L2ROUT: (void)printf("l2rout "); break;
269 case TI_L1ROUT: (void)printf("l1rout "); break;
270 case TI_ENDNODE: (void)printf("endnode "); break;
273 (void)printf("verif ");
275 (void)printf("blo ");
279 print_l1_routes(const char *rp, u_int len)
285 /* The last short is a checksum */
286 while (len > (3 * sizeof(short))) {
287 count = EXTRACT_LE_16BITS(rp);
289 return; /* seems to be bogus from here on */
291 len -= sizeof(short);
292 id = EXTRACT_LE_16BITS(rp);
294 len -= sizeof(short);
295 info = EXTRACT_LE_16BITS(rp);
297 len -= sizeof(short);
298 (void)printf("{ids %d-%d cost %d hops %d} ", id, id + count,
299 RI_COST(info), RI_HOPS(info));
304 print_l2_routes(const char *rp, u_int len)
310 /* The last short is a checksum */
311 while (len > (3 * sizeof(short))) {
312 count = EXTRACT_LE_16BITS(rp);
314 return; /* seems to be bogus from here on */
316 len -= sizeof(short);
317 area = EXTRACT_LE_16BITS(rp);
319 len -= sizeof(short);
320 info = EXTRACT_LE_16BITS(rp);
322 len -= sizeof(short);
323 (void)printf("{areas %d-%d cost %d hops %d} ", area, area + count,
324 RI_COST(info), RI_HOPS(info));
329 print_i_info(int info)
331 int ntype = info & II_TYPEMASK;
333 case 0: (void)printf("reserved-ntype? "); break;
334 case II_L2ROUT: (void)printf("l2rout "); break;
335 case II_L1ROUT: (void)printf("l1rout "); break;
336 case II_ENDNODE: (void)printf("endnode "); break;
339 (void)printf("verif ");
340 if (info & II_NOMCAST)
341 (void)printf("nomcast ");
343 (void)printf("blo ");
347 print_elist(const char *elp, u_int len)
349 /* Not enough examples available for me to debug this */
353 print_nsp(const u_char *nspp, u_int nsplen)
355 const struct nsphdr *nsphp = (struct nsphdr *)nspp;
358 flags = EXTRACT_LE_8BITS(nsphp->nh_flags);
359 dst = EXTRACT_LE_16BITS(nsphp->nh_dst);
360 src = EXTRACT_LE_16BITS(nsphp->nh_src);
362 switch (flags & NSP_TYPEMASK) {
364 switch (flags & NSP_SUBMASK) {
368 case MFS_BOM+MFS_EOM:
369 printf("data %d>%d ", src, dst);
371 struct seghdr *shp = (struct seghdr *)nspp;
376 u_int data_off = sizeof(struct minseghdr);
378 ack = EXTRACT_LE_16BITS(shp->sh_seq[0]);
379 if (ack & SGQ_ACK) { /* acknum field */
380 if ((ack & SGQ_NAK) == SGQ_NAK)
381 (void)printf("nak %d ", ack & SGQ_MASK);
383 (void)printf("ack %d ", ack & SGQ_MASK);
384 ack = EXTRACT_LE_16BITS(shp->sh_seq[1]);
385 data_off += sizeof(short);
386 if (ack & SGQ_OACK) { /* ackoth field */
387 if ((ack & SGQ_ONAK) == SGQ_ONAK)
388 (void)printf("onak %d ", ack & SGQ_MASK);
390 (void)printf("oack %d ", ack & SGQ_MASK);
391 ack = EXTRACT_LE_16BITS(shp->sh_seq[2]);
392 data_off += sizeof(short);
395 (void)printf("seg %d ", ack & SGQ_MASK);
397 dp = &(nspp[data_off]);
402 case MFS_ILS+MFS_INT:
405 struct seghdr *shp = (struct seghdr *)nspp;
410 u_int data_off = sizeof(struct minseghdr);
412 ack = EXTRACT_LE_16BITS(shp->sh_seq[0]);
413 if (ack & SGQ_ACK) { /* acknum field */
414 if ((ack & SGQ_NAK) == SGQ_NAK)
415 (void)printf("nak %d ", ack & SGQ_MASK);
417 (void)printf("ack %d ", ack & SGQ_MASK);
418 ack = EXTRACT_LE_16BITS(shp->sh_seq[1]);
419 data_off += sizeof(short);
420 if (ack & SGQ_OACK) { /* ackdat field */
421 if ((ack & SGQ_ONAK) == SGQ_ONAK)
422 (void)printf("nakdat %d ", ack & SGQ_MASK);
424 (void)printf("ackdat %d ", ack & SGQ_MASK);
425 ack = EXTRACT_LE_16BITS(shp->sh_seq[2]);
426 data_off += sizeof(short);
429 (void)printf("seg %d ", ack & SGQ_MASK);
431 dp = &(nspp[data_off]);
437 (void)printf("link-service %d>%d ", src, dst);
439 struct seghdr *shp = (struct seghdr *)nspp;
441 (struct lsmsg *)&(nspp[sizeof(struct seghdr)]);
445 ack = EXTRACT_LE_16BITS(shp->sh_seq[0]);
446 if (ack & SGQ_ACK) { /* acknum field */
447 if ((ack & SGQ_NAK) == SGQ_NAK)
448 (void)printf("nak %d ", ack & SGQ_MASK);
450 (void)printf("ack %d ", ack & SGQ_MASK);
451 ack = EXTRACT_LE_16BITS(shp->sh_seq[1]);
452 if (ack & SGQ_OACK) { /* ackdat field */
453 if ((ack & SGQ_ONAK) == SGQ_ONAK)
454 (void)printf("nakdat %d ", ack & SGQ_MASK);
456 (void)printf("ackdat %d ", ack & SGQ_MASK);
457 ack = EXTRACT_LE_16BITS(shp->sh_seq[2]);
460 (void)printf("seg %d ", ack & SGQ_MASK);
461 lsflags = EXTRACT_LE_8BITS(lsmp->ls_lsflags);
462 fcval = EXTRACT_LE_8BITS(lsmp->ls_fcval);
463 switch (lsflags & LSI_MASK) {
465 (void)printf("dat seg count %d ", fcval);
466 switch (lsflags & LSM_MASK) {
470 (void)printf("donotsend-data ");
473 (void)printf("send-data ");
476 (void)printf("reserved-fcmod? %x", lsflags);
481 (void)printf("intr req count %d ", fcval);
484 (void)printf("reserved-fcval-int? %x", lsflags);
490 (void)printf("reserved-subtype? %x %d > %d", flags, src, dst);
495 switch (flags & NSP_SUBMASK) {
497 (void)printf("data-ack %d>%d ", src, dst);
499 struct ackmsg *amp = (struct ackmsg *)nspp;
502 ack = EXTRACT_LE_16BITS(amp->ak_acknum[0]);
503 if (ack & SGQ_ACK) { /* acknum field */
504 if ((ack & SGQ_NAK) == SGQ_NAK)
505 (void)printf("nak %d ", ack & SGQ_MASK);
507 (void)printf("ack %d ", ack & SGQ_MASK);
508 ack = EXTRACT_LE_16BITS(amp->ak_acknum[1]);
509 if (ack & SGQ_OACK) { /* ackoth field */
510 if ((ack & SGQ_ONAK) == SGQ_ONAK)
511 (void)printf("onak %d ", ack & SGQ_MASK);
513 (void)printf("oack %d ", ack & SGQ_MASK);
519 (void)printf("ils-ack %d>%d ", src, dst);
521 struct ackmsg *amp = (struct ackmsg *)nspp;
524 ack = EXTRACT_LE_16BITS(amp->ak_acknum[0]);
525 if (ack & SGQ_ACK) { /* acknum field */
526 if ((ack & SGQ_NAK) == SGQ_NAK)
527 (void)printf("nak %d ", ack & SGQ_MASK);
529 (void)printf("ack %d ", ack & SGQ_MASK);
530 ack = EXTRACT_LE_16BITS(amp->ak_acknum[1]);
531 if (ack & SGQ_OACK) { /* ackdat field */
532 if ((ack & SGQ_ONAK) == SGQ_ONAK)
533 (void)printf("nakdat %d ", ack & SGQ_MASK);
535 (void)printf("ackdat %d ", ack & SGQ_MASK);
541 (void)printf("conn-ack %d", dst);
544 (void)printf("reserved-acktype? %x %d > %d", flags, src, dst);
549 switch (flags & NSP_SUBMASK) {
552 if ((flags & NSP_SUBMASK) == MFS_CI)
553 (void)printf("conn-initiate ");
555 (void)printf("retrans-conn-initiate ");
556 (void)printf("%d>%d ", src, dst);
558 struct cimsg *cimp = (struct cimsg *)nspp;
559 int services, info, segsize;
564 services = EXTRACT_LE_8BITS(cimp->ci_services);
565 info = EXTRACT_LE_8BITS(cimp->ci_info);
566 segsize = EXTRACT_LE_16BITS(cimp->ci_segsize);
568 switch (services & COS_MASK) {
572 (void)printf("seg ");
575 (void)printf("msg ");
578 (void)printf("crypt ");
581 switch (info & COI_MASK) {
583 (void)printf("ver 3.2 ");
586 (void)printf("ver 3.1 ");
589 (void)printf("ver 4.0 ");
592 (void)printf("ver 4.1 ");
595 (void)printf("segsize %d ", segsize);
597 dp = &(nspp[sizeof(struct cimsg)]);
598 pdata(dp, nsplen - sizeof(struct cimsg));
603 (void)printf("conn-confirm %d>%d ", src, dst);
605 struct ccmsg *ccmp = (struct ccmsg *)nspp;
607 u_int segsize, optlen;
612 services = EXTRACT_LE_8BITS(ccmp->cc_services);
613 info = EXTRACT_LE_8BITS(ccmp->cc_info);
614 segsize = EXTRACT_LE_16BITS(ccmp->cc_segsize);
615 optlen = EXTRACT_LE_8BITS(ccmp->cc_optlen);
617 switch (services & COS_MASK) {
621 (void)printf("seg ");
624 (void)printf("msg ");
627 (void)printf("crypt ");
630 switch (info & COI_MASK) {
632 (void)printf("ver 3.2 ");
635 (void)printf("ver 3.1 ");
638 (void)printf("ver 4.0 ");
641 (void)printf("ver 4.1 ");
644 (void)printf("segsize %d ", segsize);
646 (void)printf("optlen %d ", optlen);
648 optlen = min(optlen, nsplen - sizeof(struct ccmsg));
649 dp = &(nspp[sizeof(struct ccmsg)]);
656 (void)printf("disconn-initiate %d>%d ", src, dst);
658 struct dimsg *dimp = (struct dimsg *)nspp;
665 reason = EXTRACT_LE_16BITS(dimp->di_reason);
666 optlen = EXTRACT_LE_8BITS(dimp->di_optlen);
668 print_reason(reason);
670 (void)printf("optlen %d ", optlen);
672 optlen = min(optlen, nsplen - sizeof(struct dimsg));
673 dp = &(nspp[sizeof(struct dimsg)]);
680 (void)printf("disconn-confirm %d>%d ", src, dst);
682 struct dcmsg *dcmp = (struct dcmsg *)nspp;
685 reason = EXTRACT_LE_16BITS(dcmp->dc_reason);
687 print_reason(reason);
691 (void)printf("reserved-ctltype? %x %d > %d", flags, src, dst);
696 (void)printf("reserved-type? %x %d > %d", flags, src, dst);
701 static struct tok reason2str[] = {
702 { UC_OBJREJECT, "object rejected connect" },
703 { UC_RESOURCES, "insufficient resources" },
704 { UC_NOSUCHNODE, "unrecognized node name" },
705 { DI_SHUT, "node is shutting down" },
706 { UC_NOSUCHOBJ, "unrecognized object" },
707 { UC_INVOBJFORMAT, "invalid object name format" },
708 { UC_OBJTOOBUSY, "object too busy" },
709 { DI_PROTOCOL, "protocol error discovered" },
710 { DI_TPA, "third party abort" },
711 { UC_USERABORT, "user abort" },
712 { UC_INVNODEFORMAT, "invalid node name format" },
713 { UC_LOCALSHUT, "local node shutting down" },
714 { DI_LOCALRESRC, "insufficient local resources" },
715 { DI_REMUSERRESRC, "insufficient remote user resources" },
716 { UC_ACCESSREJECT, "invalid access control information" },
717 { DI_BADACCNT, "bad ACCOUNT information" },
718 { UC_NORESPONSE, "no response from object" },
719 { UC_UNREACHABLE, "node unreachable" },
720 { DC_NOLINK, "no link terminate" },
721 { DC_COMPLETE, "disconnect complete" },
722 { DI_BADIMAGE, "bad image data in connect" },
723 { DI_SERVMISMATCH, "cryptographic service mismatch" },
728 print_reason(register int reason)
730 printf("%s ", tok2str(reason2str, "reason-%d", reason));
734 dnnum_string(u_short dnaddr)
738 int area = (u_short)(dnaddr & AREAMASK) >> AREASHIFT;
739 int node = dnaddr & NODEMASK;
741 str = (char *)malloc(siz = sizeof("00.0000"));
743 error("dnnum_string: malloc");
744 snprintf(str, siz, "%d.%d", area, node);
749 dnname_string(u_short dnaddr)
754 dna.a_len = sizeof(short);
755 memcpy((char *)dna.a_addr, (char *)&dnaddr, sizeof(short));
756 return (savestr(dnet_htoa(&dna)));
758 return(dnnum_string(dnaddr)); /* punt */
764 pdata(u_char *dp, u_int maxlen)
774 printf("\\%o", c & 0xFF);