]> The Tcpdump Group git mirrors - tcpdump/blob - print-decnet.c
add a convenience symlink for README
[tcpdump] / print-decnet.c
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
23 static const char rcsid[] _U_ =
24 "@(#) $Header: /tcpdump/master/tcpdump/print-decnet.c,v 1.39 2005-05-06 02:16:26 guy Exp $ (LBL)";
25 #endif
26
27 #ifdef HAVE_CONFIG_H
28 #include "config.h"
29 #endif
30
31 #include <tcpdump-stdinc.h>
32
33 struct mbuf;
34 struct 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 static const char tstr[] = "[|decnet]";
50
51 /* Forwards */
52 static int print_decnet_ctlmsg(const union routehdr *, u_int, u_int);
53 static void print_t_info(int);
54 static int print_l1_routes(const char *, u_int);
55 static int print_l2_routes(const char *, u_int);
56 static void print_i_info(int);
57 static int print_elist(const char *, u_int);
58 static int print_nsp(const u_char *, u_int);
59 static void print_reason(int);
60 #ifdef PRINT_NSPDATA
61 static void pdata(u_char *, int);
62 #endif
63
64 #ifndef HAVE_NETDNET_DNETDB_H_DNET_HTOA
65 extern char *dnet_htoa(struct dn_naddr *);
66 #endif
67
68 void
69 decnet_print(register const u_char *ap, register u_int length,
70 register u_int caplen)
71 {
72 register const union routehdr *rhp;
73 register int mflags;
74 int dst, src, hops;
75 u_int nsplen, pktlen;
76 const u_char *nspp;
77
78 if (length < sizeof(struct shorthdr)) {
79 (void)printf("%s", tstr);
80 return;
81 }
82
83 TCHECK2(*ap, sizeof(short));
84 pktlen = EXTRACT_LE_16BITS(ap);
85 if (pktlen < sizeof(struct shorthdr)) {
86 (void)printf("%s", tstr);
87 return;
88 }
89 if (pktlen > length) {
90 (void)printf("%s", tstr);
91 return;
92 }
93 length = pktlen;
94
95 rhp = (const union routehdr *)&(ap[sizeof(short)]);
96 TCHECK(rhp->rh_short.sh_flags);
97 mflags = EXTRACT_LE_8BITS(rhp->rh_short.sh_flags);
98
99 if (mflags & RMF_PAD) {
100 /* pad bytes of some sort in front of message */
101 u_int padlen = mflags & RMF_PADMASK;
102 if (vflag)
103 (void) printf("[pad:%d] ", padlen);
104 if (length < padlen + 2) {
105 (void)printf("%s", tstr);
106 return;
107 }
108 TCHECK2(ap[sizeof(short)], padlen);
109 ap += padlen;
110 length -= padlen;
111 caplen -= padlen;
112 rhp = (const union routehdr *)&(ap[sizeof(short)]);
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("%s", tstr);
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("%s", tstr);
176 return;
177 }
178
179 static int
180 print_decnet_ctlmsg(register const union routehdr *rhp, u_int length,
181 u_int caplen)
182 {
183 int mflags = EXTRACT_LE_8BITS(rhp->rh_short.sh_flags);
184 register 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 ret = 1;
210 break;
211 case RMF_VER:
212 (void)printf("verification ");
213 if (length < sizeof(struct verifmsg))
214 goto trunc;
215 TCHECK(cmp->cm_ver);
216 src = EXTRACT_LE_16BITS(cmp->cm_ver.ve_src);
217 other = EXTRACT_LE_8BITS(cmp->cm_ver.ve_fcnval);
218 (void)printf("src %s fcnval %o", dnaddr_string(src), other);
219 ret = 1;
220 break;
221 case RMF_TEST:
222 (void)printf("test ");
223 if (length < sizeof(struct testmsg))
224 goto trunc;
225 TCHECK(cmp->cm_test);
226 src = EXTRACT_LE_16BITS(cmp->cm_test.te_src);
227 other = EXTRACT_LE_8BITS(cmp->cm_test.te_data);
228 (void)printf("src %s data %o", dnaddr_string(src), other);
229 ret = 1;
230 break;
231 case RMF_L1ROUT:
232 (void)printf("lev-1-routing ");
233 if (length < sizeof(struct l1rout))
234 goto trunc;
235 TCHECK(cmp->cm_l1rou);
236 src = EXTRACT_LE_16BITS(cmp->cm_l1rou.r1_src);
237 (void)printf("src %s ", dnaddr_string(src));
238 ret = print_l1_routes(&(rhpx[sizeof(struct l1rout)]),
239 length - sizeof(struct l1rout));
240 break;
241 case RMF_L2ROUT:
242 (void)printf("lev-2-routing ");
243 if (length < sizeof(struct l2rout))
244 goto trunc;
245 TCHECK(cmp->cm_l2rout);
246 src = EXTRACT_LE_16BITS(cmp->cm_l2rout.r2_src);
247 (void)printf("src %s ", dnaddr_string(src));
248 ret = print_l2_routes(&(rhpx[sizeof(struct l2rout)]),
249 length - sizeof(struct l2rout));
250 break;
251 case RMF_RHELLO:
252 (void)printf("router-hello ");
253 if (length < sizeof(struct rhellomsg))
254 goto trunc;
255 TCHECK(cmp->cm_rhello);
256 vers = EXTRACT_LE_8BITS(cmp->cm_rhello.rh_vers);
257 eco = EXTRACT_LE_8BITS(cmp->cm_rhello.rh_eco);
258 ueco = EXTRACT_LE_8BITS(cmp->cm_rhello.rh_ueco);
259 memcpy((char *)&srcea, (char *)&(cmp->cm_rhello.rh_src),
260 sizeof(srcea));
261 src = EXTRACT_LE_16BITS(srcea.dne_remote.dne_nodeaddr);
262 info = EXTRACT_LE_8BITS(cmp->cm_rhello.rh_info);
263 blksize = EXTRACT_LE_16BITS(cmp->cm_rhello.rh_blksize);
264 priority = EXTRACT_LE_8BITS(cmp->cm_rhello.rh_priority);
265 hello = EXTRACT_LE_16BITS(cmp->cm_rhello.rh_hello);
266 print_i_info(info);
267 (void)printf(
268 "vers %d eco %d ueco %d src %s blksize %d pri %d hello %d",
269 vers, eco, ueco, dnaddr_string(src),
270 blksize, priority, hello);
271 ret = print_elist(&(rhpx[sizeof(struct rhellomsg)]),
272 length - sizeof(struct rhellomsg));
273 break;
274 case RMF_EHELLO:
275 (void)printf("endnode-hello ");
276 if (length < sizeof(struct ehellomsg))
277 goto trunc;
278 TCHECK(cmp->cm_ehello);
279 vers = EXTRACT_LE_8BITS(cmp->cm_ehello.eh_vers);
280 eco = EXTRACT_LE_8BITS(cmp->cm_ehello.eh_eco);
281 ueco = EXTRACT_LE_8BITS(cmp->cm_ehello.eh_ueco);
282 memcpy((char *)&srcea, (char *)&(cmp->cm_ehello.eh_src),
283 sizeof(srcea));
284 src = EXTRACT_LE_16BITS(srcea.dne_remote.dne_nodeaddr);
285 info = EXTRACT_LE_8BITS(cmp->cm_ehello.eh_info);
286 blksize = EXTRACT_LE_16BITS(cmp->cm_ehello.eh_blksize);
287 /*seed*/
288 memcpy((char *)&rtea, (char *)&(cmp->cm_ehello.eh_router),
289 sizeof(rtea));
290 dst = EXTRACT_LE_16BITS(rtea.dne_remote.dne_nodeaddr);
291 hello = EXTRACT_LE_16BITS(cmp->cm_ehello.eh_hello);
292 other = EXTRACT_LE_8BITS(cmp->cm_ehello.eh_data);
293 print_i_info(info);
294 (void)printf(
295 "vers %d eco %d ueco %d src %s blksize %d rtr %s hello %d data %o",
296 vers, eco, ueco, dnaddr_string(src),
297 blksize, dnaddr_string(dst), hello, other);
298 ret = 1;
299 break;
300
301 default:
302 (void)printf("unknown control message");
303 default_print((u_char *)rhp, min(length, caplen));
304 ret = 1;
305 break;
306 }
307 return (ret);
308
309 trunc:
310 return (0);
311 }
312
313 static void
314 print_t_info(int info)
315 {
316 int ntype = info & 3;
317 switch (ntype) {
318 case 0: (void)printf("reserved-ntype? "); break;
319 case TI_L2ROUT: (void)printf("l2rout "); break;
320 case TI_L1ROUT: (void)printf("l1rout "); break;
321 case TI_ENDNODE: (void)printf("endnode "); break;
322 }
323 if (info & TI_VERIF)
324 (void)printf("verif ");
325 if (info & TI_BLOCK)
326 (void)printf("blo ");
327 }
328
329 static int
330 print_l1_routes(const char *rp, u_int len)
331 {
332 int count;
333 int id;
334 int info;
335
336 /* The last short is a checksum */
337 while (len > (3 * sizeof(short))) {
338 TCHECK2(*rp, 3 * sizeof(short));
339 count = EXTRACT_LE_16BITS(rp);
340 if (count > 1024)
341 return (1); /* seems to be bogus from here on */
342 rp += sizeof(short);
343 len -= sizeof(short);
344 id = EXTRACT_LE_16BITS(rp);
345 rp += sizeof(short);
346 len -= sizeof(short);
347 info = EXTRACT_LE_16BITS(rp);
348 rp += sizeof(short);
349 len -= sizeof(short);
350 (void)printf("{ids %d-%d cost %d hops %d} ", id, id + count,
351 RI_COST(info), RI_HOPS(info));
352 }
353 return (1);
354
355 trunc:
356 return (0);
357 }
358
359 static int
360 print_l2_routes(const char *rp, u_int len)
361 {
362 int count;
363 int area;
364 int info;
365
366 /* The last short is a checksum */
367 while (len > (3 * sizeof(short))) {
368 TCHECK2(*rp, 3 * sizeof(short));
369 count = EXTRACT_LE_16BITS(rp);
370 if (count > 1024)
371 return (1); /* seems to be bogus from here on */
372 rp += sizeof(short);
373 len -= sizeof(short);
374 area = EXTRACT_LE_16BITS(rp);
375 rp += sizeof(short);
376 len -= sizeof(short);
377 info = EXTRACT_LE_16BITS(rp);
378 rp += sizeof(short);
379 len -= sizeof(short);
380 (void)printf("{areas %d-%d cost %d hops %d} ", area, area + count,
381 RI_COST(info), RI_HOPS(info));
382 }
383 return (1);
384
385 trunc:
386 return (0);
387 }
388
389 static void
390 print_i_info(int info)
391 {
392 int ntype = info & II_TYPEMASK;
393 switch (ntype) {
394 case 0: (void)printf("reserved-ntype? "); break;
395 case II_L2ROUT: (void)printf("l2rout "); break;
396 case II_L1ROUT: (void)printf("l1rout "); break;
397 case II_ENDNODE: (void)printf("endnode "); break;
398 }
399 if (info & II_VERIF)
400 (void)printf("verif ");
401 if (info & II_NOMCAST)
402 (void)printf("nomcast ");
403 if (info & II_BLOCK)
404 (void)printf("blo ");
405 }
406
407 static int
408 print_elist(const char *elp _U_, u_int len _U_)
409 {
410 /* Not enough examples available for me to debug this */
411 return (1);
412 }
413
414 static int
415 print_nsp(const u_char *nspp, u_int nsplen)
416 {
417 const struct nsphdr *nsphp = (struct nsphdr *)nspp;
418 int dst, src, flags;
419
420 if (nsplen < sizeof(struct nsphdr))
421 goto trunc;
422 TCHECK(*nsphp);
423 flags = EXTRACT_LE_8BITS(nsphp->nh_flags);
424 dst = EXTRACT_LE_16BITS(nsphp->nh_dst);
425 src = EXTRACT_LE_16BITS(nsphp->nh_src);
426
427 switch (flags & NSP_TYPEMASK) {
428 case MFT_DATA:
429 switch (flags & NSP_SUBMASK) {
430 case MFS_BOM:
431 case MFS_MOM:
432 case MFS_EOM:
433 case MFS_BOM+MFS_EOM:
434 printf("data %d>%d ", src, dst);
435 {
436 struct seghdr *shp = (struct seghdr *)nspp;
437 int ack;
438 #ifdef PRINT_NSPDATA
439 u_char *dp;
440 #endif
441 u_int data_off = sizeof(struct minseghdr);
442
443 if (nsplen < data_off)
444 goto trunc;
445 TCHECK(shp->sh_seq[0]);
446 ack = EXTRACT_LE_16BITS(shp->sh_seq[0]);
447 if (ack & SGQ_ACK) { /* acknum field */
448 if ((ack & SGQ_NAK) == SGQ_NAK)
449 (void)printf("nak %d ", ack & SGQ_MASK);
450 else
451 (void)printf("ack %d ", ack & SGQ_MASK);
452 data_off += sizeof(short);
453 if (nsplen < data_off)
454 goto trunc;
455 TCHECK(shp->sh_seq[1]);
456 ack = EXTRACT_LE_16BITS(shp->sh_seq[1]);
457 if (ack & SGQ_OACK) { /* ackoth field */
458 if ((ack & SGQ_ONAK) == SGQ_ONAK)
459 (void)printf("onak %d ", ack & SGQ_MASK);
460 else
461 (void)printf("oack %d ", ack & SGQ_MASK);
462 data_off += sizeof(short);
463 if (nsplen < data_off)
464 goto trunc;
465 TCHECK(shp->sh_seq[2]);
466 ack = EXTRACT_LE_16BITS(shp->sh_seq[2]);
467 }
468 }
469 (void)printf("seg %d ", ack & SGQ_MASK);
470 #ifdef PRINT_NSPDATA
471 if (nsplen > data_off) {
472 dp = &(nspp[data_off]);
473 TCHECK2(*dp, nsplen - data_off);
474 pdata(dp, nsplen - data_off);
475 }
476 #endif
477 }
478 break;
479 case MFS_ILS+MFS_INT:
480 printf("intr ");
481 {
482 struct seghdr *shp = (struct seghdr *)nspp;
483 int ack;
484 #ifdef PRINT_NSPDATA
485 u_char *dp;
486 #endif
487 u_int data_off = sizeof(struct minseghdr);
488
489 if (nsplen < data_off)
490 goto trunc;
491 TCHECK(shp->sh_seq[0]);
492 ack = EXTRACT_LE_16BITS(shp->sh_seq[0]);
493 if (ack & SGQ_ACK) { /* acknum field */
494 if ((ack & SGQ_NAK) == SGQ_NAK)
495 (void)printf("nak %d ", ack & SGQ_MASK);
496 else
497 (void)printf("ack %d ", ack & SGQ_MASK);
498 data_off += sizeof(short);
499 if (nsplen < data_off)
500 goto trunc;
501 TCHECK(shp->sh_seq[1]);
502 ack = EXTRACT_LE_16BITS(shp->sh_seq[1]);
503 if (ack & SGQ_OACK) { /* ackdat field */
504 if ((ack & SGQ_ONAK) == SGQ_ONAK)
505 (void)printf("nakdat %d ", ack & SGQ_MASK);
506 else
507 (void)printf("ackdat %d ", ack & SGQ_MASK);
508 data_off += sizeof(short);
509 if (nsplen < data_off)
510 goto trunc;
511 TCHECK(shp->sh_seq[2]);
512 ack = EXTRACT_LE_16BITS(shp->sh_seq[2]);
513 }
514 }
515 (void)printf("seg %d ", ack & SGQ_MASK);
516 #ifdef PRINT_NSPDATA
517 if (nsplen > data_off) {
518 dp = &(nspp[data_off]);
519 TCHECK2(*dp, nsplen - data_off);
520 pdata(dp, nsplen - data_off);
521 }
522 #endif
523 }
524 break;
525 case MFS_ILS:
526 (void)printf("link-service %d>%d ", src, dst);
527 {
528 struct seghdr *shp = (struct seghdr *)nspp;
529 struct lsmsg *lsmp =
530 (struct lsmsg *)&(nspp[sizeof(struct seghdr)]);
531 int ack;
532 int lsflags, fcval;
533
534 if (nsplen < sizeof(struct seghdr) + sizeof(struct lsmsg))
535 goto trunc;
536 TCHECK(shp->sh_seq[0]);
537 ack = EXTRACT_LE_16BITS(shp->sh_seq[0]);
538 if (ack & SGQ_ACK) { /* acknum field */
539 if ((ack & SGQ_NAK) == SGQ_NAK)
540 (void)printf("nak %d ", ack & SGQ_MASK);
541 else
542 (void)printf("ack %d ", ack & SGQ_MASK);
543 TCHECK(shp->sh_seq[1]);
544 ack = EXTRACT_LE_16BITS(shp->sh_seq[1]);
545 if (ack & SGQ_OACK) { /* ackdat field */
546 if ((ack & SGQ_ONAK) == SGQ_ONAK)
547 (void)printf("nakdat %d ", ack & SGQ_MASK);
548 else
549 (void)printf("ackdat %d ", ack & SGQ_MASK);
550 TCHECK(shp->sh_seq[2]);
551 ack = EXTRACT_LE_16BITS(shp->sh_seq[2]);
552 }
553 }
554 (void)printf("seg %d ", ack & SGQ_MASK);
555 TCHECK(*lsmp);
556 lsflags = EXTRACT_LE_8BITS(lsmp->ls_lsflags);
557 fcval = EXTRACT_LE_8BITS(lsmp->ls_fcval);
558 switch (lsflags & LSI_MASK) {
559 case LSI_DATA:
560 (void)printf("dat seg count %d ", fcval);
561 switch (lsflags & LSM_MASK) {
562 case LSM_NOCHANGE:
563 break;
564 case LSM_DONOTSEND:
565 (void)printf("donotsend-data ");
566 break;
567 case LSM_SEND:
568 (void)printf("send-data ");
569 break;
570 default:
571 (void)printf("reserved-fcmod? %x", lsflags);
572 break;
573 }
574 break;
575 case LSI_INTR:
576 (void)printf("intr req count %d ", fcval);
577 break;
578 default:
579 (void)printf("reserved-fcval-int? %x", lsflags);
580 break;
581 }
582 }
583 break;
584 default:
585 (void)printf("reserved-subtype? %x %d > %d", flags, src, dst);
586 break;
587 }
588 break;
589 case MFT_ACK:
590 switch (flags & NSP_SUBMASK) {
591 case MFS_DACK:
592 (void)printf("data-ack %d>%d ", src, dst);
593 {
594 struct ackmsg *amp = (struct ackmsg *)nspp;
595 int ack;
596
597 if (nsplen < sizeof(struct ackmsg))
598 goto trunc;
599 TCHECK(*amp);
600 ack = EXTRACT_LE_16BITS(amp->ak_acknum[0]);
601 if (ack & SGQ_ACK) { /* acknum field */
602 if ((ack & SGQ_NAK) == SGQ_NAK)
603 (void)printf("nak %d ", ack & SGQ_MASK);
604 else
605 (void)printf("ack %d ", ack & SGQ_MASK);
606 ack = EXTRACT_LE_16BITS(amp->ak_acknum[1]);
607 if (ack & SGQ_OACK) { /* ackoth field */
608 if ((ack & SGQ_ONAK) == SGQ_ONAK)
609 (void)printf("onak %d ", ack & SGQ_MASK);
610 else
611 (void)printf("oack %d ", ack & SGQ_MASK);
612 }
613 }
614 }
615 break;
616 case MFS_IACK:
617 (void)printf("ils-ack %d>%d ", src, dst);
618 {
619 struct ackmsg *amp = (struct ackmsg *)nspp;
620 int ack;
621
622 if (nsplen < sizeof(struct ackmsg))
623 goto trunc;
624 TCHECK(*amp);
625 ack = EXTRACT_LE_16BITS(amp->ak_acknum[0]);
626 if (ack & SGQ_ACK) { /* acknum field */
627 if ((ack & SGQ_NAK) == SGQ_NAK)
628 (void)printf("nak %d ", ack & SGQ_MASK);
629 else
630 (void)printf("ack %d ", ack & SGQ_MASK);
631 TCHECK(amp->ak_acknum[1]);
632 ack = EXTRACT_LE_16BITS(amp->ak_acknum[1]);
633 if (ack & SGQ_OACK) { /* ackdat field */
634 if ((ack & SGQ_ONAK) == SGQ_ONAK)
635 (void)printf("nakdat %d ", ack & SGQ_MASK);
636 else
637 (void)printf("ackdat %d ", ack & SGQ_MASK);
638 }
639 }
640 }
641 break;
642 case MFS_CACK:
643 (void)printf("conn-ack %d", dst);
644 break;
645 default:
646 (void)printf("reserved-acktype? %x %d > %d", flags, src, dst);
647 break;
648 }
649 break;
650 case MFT_CTL:
651 switch (flags & NSP_SUBMASK) {
652 case MFS_CI:
653 case MFS_RCI:
654 if ((flags & NSP_SUBMASK) == MFS_CI)
655 (void)printf("conn-initiate ");
656 else
657 (void)printf("retrans-conn-initiate ");
658 (void)printf("%d>%d ", src, dst);
659 {
660 struct cimsg *cimp = (struct cimsg *)nspp;
661 int services, info, segsize;
662 #ifdef PRINT_NSPDATA
663 u_char *dp;
664 #endif
665
666 if (nsplen < sizeof(struct cimsg))
667 goto trunc;
668 TCHECK(*cimp);
669 services = EXTRACT_LE_8BITS(cimp->ci_services);
670 info = EXTRACT_LE_8BITS(cimp->ci_info);
671 segsize = EXTRACT_LE_16BITS(cimp->ci_segsize);
672
673 switch (services & COS_MASK) {
674 case COS_NONE:
675 break;
676 case COS_SEGMENT:
677 (void)printf("seg ");
678 break;
679 case COS_MESSAGE:
680 (void)printf("msg ");
681 break;
682 case COS_CRYPTSER:
683 (void)printf("crypt ");
684 break;
685 }
686 switch (info & COI_MASK) {
687 case COI_32:
688 (void)printf("ver 3.2 ");
689 break;
690 case COI_31:
691 (void)printf("ver 3.1 ");
692 break;
693 case COI_40:
694 (void)printf("ver 4.0 ");
695 break;
696 case COI_41:
697 (void)printf("ver 4.1 ");
698 break;
699 }
700 (void)printf("segsize %d ", segsize);
701 #ifdef PRINT_NSPDATA
702 if (nsplen > sizeof(struct cimsg)) {
703 dp = &(nspp[sizeof(struct cimsg)]);
704 TCHECK2(*dp, nsplen - sizeof(struct cimsg));
705 pdata(dp, nsplen - sizeof(struct cimsg));
706 }
707 #endif
708 }
709 break;
710 case MFS_CC:
711 (void)printf("conn-confirm %d>%d ", src, dst);
712 {
713 struct ccmsg *ccmp = (struct ccmsg *)nspp;
714 int services, info;
715 u_int segsize, optlen;
716 #ifdef PRINT_NSPDATA
717 u_char *dp;
718 #endif
719
720 if (nsplen < sizeof(struct ccmsg))
721 goto trunc;
722 TCHECK(*ccmp);
723 services = EXTRACT_LE_8BITS(ccmp->cc_services);
724 info = EXTRACT_LE_8BITS(ccmp->cc_info);
725 segsize = EXTRACT_LE_16BITS(ccmp->cc_segsize);
726 optlen = EXTRACT_LE_8BITS(ccmp->cc_optlen);
727
728 switch (services & COS_MASK) {
729 case COS_NONE:
730 break;
731 case COS_SEGMENT:
732 (void)printf("seg ");
733 break;
734 case COS_MESSAGE:
735 (void)printf("msg ");
736 break;
737 case COS_CRYPTSER:
738 (void)printf("crypt ");
739 break;
740 }
741 switch (info & COI_MASK) {
742 case COI_32:
743 (void)printf("ver 3.2 ");
744 break;
745 case COI_31:
746 (void)printf("ver 3.1 ");
747 break;
748 case COI_40:
749 (void)printf("ver 4.0 ");
750 break;
751 case COI_41:
752 (void)printf("ver 4.1 ");
753 break;
754 }
755 (void)printf("segsize %d ", segsize);
756 if (optlen) {
757 (void)printf("optlen %d ", optlen);
758 #ifdef PRINT_NSPDATA
759 if (optlen > nsplen - sizeof(struct ccmsg))
760 goto trunc;
761 dp = &(nspp[sizeof(struct ccmsg)]);
762 TCHECK2(*dp, optlen);
763 pdata(dp, optlen);
764 #endif
765 }
766 }
767 break;
768 case MFS_DI:
769 (void)printf("disconn-initiate %d>%d ", src, dst);
770 {
771 struct dimsg *dimp = (struct dimsg *)nspp;
772 int reason;
773 u_int optlen;
774 #ifdef PRINT_NSPDATA
775 u_char *dp;
776 #endif
777
778 if (nsplen < sizeof(struct dimsg))
779 goto trunc;
780 TCHECK(*dimp);
781 reason = EXTRACT_LE_16BITS(dimp->di_reason);
782 optlen = EXTRACT_LE_8BITS(dimp->di_optlen);
783
784 print_reason(reason);
785 if (optlen) {
786 (void)printf("optlen %d ", optlen);
787 #ifdef PRINT_NSPDATA
788 if (optlen > nsplen - sizeof(struct dimsg))
789 goto trunc;
790 dp = &(nspp[sizeof(struct dimsg)]);
791 TCHECK2(*dp, optlen);
792 pdata(dp, optlen);
793 #endif
794 }
795 }
796 break;
797 case MFS_DC:
798 (void)printf("disconn-confirm %d>%d ", src, dst);
799 {
800 struct dcmsg *dcmp = (struct dcmsg *)nspp;
801 int reason;
802
803 TCHECK(*dcmp);
804 reason = EXTRACT_LE_16BITS(dcmp->dc_reason);
805
806 print_reason(reason);
807 }
808 break;
809 default:
810 (void)printf("reserved-ctltype? %x %d > %d", flags, src, dst);
811 break;
812 }
813 break;
814 default:
815 (void)printf("reserved-type? %x %d > %d", flags, src, dst);
816 break;
817 }
818 return (1);
819
820 trunc:
821 return (0);
822 }
823
824 static const struct tok reason2str[] = {
825 { UC_OBJREJECT, "object rejected connect" },
826 { UC_RESOURCES, "insufficient resources" },
827 { UC_NOSUCHNODE, "unrecognized node name" },
828 { DI_SHUT, "node is shutting down" },
829 { UC_NOSUCHOBJ, "unrecognized object" },
830 { UC_INVOBJFORMAT, "invalid object name format" },
831 { UC_OBJTOOBUSY, "object too busy" },
832 { DI_PROTOCOL, "protocol error discovered" },
833 { DI_TPA, "third party abort" },
834 { UC_USERABORT, "user abort" },
835 { UC_INVNODEFORMAT, "invalid node name format" },
836 { UC_LOCALSHUT, "local node shutting down" },
837 { DI_LOCALRESRC, "insufficient local resources" },
838 { DI_REMUSERRESRC, "insufficient remote user resources" },
839 { UC_ACCESSREJECT, "invalid access control information" },
840 { DI_BADACCNT, "bad ACCOUNT information" },
841 { UC_NORESPONSE, "no response from object" },
842 { UC_UNREACHABLE, "node unreachable" },
843 { DC_NOLINK, "no link terminate" },
844 { DC_COMPLETE, "disconnect complete" },
845 { DI_BADIMAGE, "bad image data in connect" },
846 { DI_SERVMISMATCH, "cryptographic service mismatch" },
847 { 0, NULL }
848 };
849
850 static void
851 print_reason(register int reason)
852 {
853 printf("%s ", tok2str(reason2str, "reason-%d", reason));
854 }
855
856 const char *
857 dnnum_string(u_short dnaddr)
858 {
859 char *str;
860 size_t siz;
861 int area = (u_short)(dnaddr & AREAMASK) >> AREASHIFT;
862 int node = dnaddr & NODEMASK;
863
864 str = (char *)malloc(siz = sizeof("00.0000"));
865 if (str == NULL)
866 error("dnnum_string: malloc");
867 snprintf(str, siz, "%d.%d", area, node);
868 return(str);
869 }
870
871 const char *
872 dnname_string(u_short dnaddr)
873 {
874 #ifdef HAVE_DNET_HTOA
875 struct dn_naddr dna;
876
877 dna.a_len = sizeof(short);
878 memcpy((char *)dna.a_addr, (char *)&dnaddr, sizeof(short));
879 return (strdup(dnet_htoa(&dna)));
880 #else
881 return(dnnum_string(dnaddr)); /* punt */
882 #endif
883 }
884
885 #ifdef PRINT_NSPDATA
886 static void
887 pdata(u_char *dp, u_int maxlen)
888 {
889 char c;
890 u_int x = maxlen;
891
892 while (x-- > 0) {
893 c = *dp++;
894 safeputchar(c);
895 }
896 }
897 #endif