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