]> The Tcpdump Group git mirrors - tcpdump/blob - print-decnet.c
use safeputchar() instead of cook up on its own.
[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[] =
24 "@(#) $Header: /tcpdump/master/tcpdump/print-decnet.c,v 1.32 2001-01-28 08:06:06 itojun Exp $ (LBL)";
25 #endif
26
27 #ifdef HAVE_CONFIG_H
28 #include "config.h"
29 #endif
30
31 #include <sys/param.h>
32 #include <sys/time.h>
33 #include <sys/socket.h>
34
35 struct mbuf;
36 struct rtentry;
37
38 #ifdef HAVE_LIBDNET
39 #include <netdnet/dnetdb.h>
40 #endif
41
42 #include <ctype.h>
43 #include <stdio.h>
44 #include <stdlib.h>
45 #include <string.h>
46 #include <unistd.h>
47
48 #include "decnet.h"
49 #include "extract.h"
50 #include "interface.h"
51 #include "addrtoname.h"
52
53 /* Forwards */
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);
62 #ifdef PRINT_NSPDATA
63 static void pdata(u_char *, int);
64 #endif
65
66 #ifdef HAVE_LIBDNET
67 extern char *dnet_htoa(struct dn_naddr *);
68 #endif
69
70 void
71 decnet_print(register const u_char *ap, register u_int length,
72 register u_int caplen)
73 {
74 static union routehdr rhcopy;
75 register union routehdr *rhp = &rhcopy;
76 register int mflags;
77 int dst, src, hops;
78 u_int rhlen, nsplen, pktlen;
79 const u_char *nspp;
80
81 if (length < sizeof(struct shorthdr)) {
82 (void)printf("[|decnet]");
83 return;
84 }
85
86 pktlen = EXTRACT_LE_16BITS(ap);
87
88 rhlen = min(length, caplen);
89 rhlen = min(rhlen, sizeof(*rhp));
90 memcpy((char *)rhp, (char *)&(ap[sizeof(short)]), rhlen);
91
92 mflags = EXTRACT_LE_8BITS(rhp->rh_short.sh_flags);
93
94 if (mflags & RMF_PAD) {
95 /* pad bytes of some sort in front of message */
96 u_int padlen = mflags & RMF_PADMASK;
97 if (vflag)
98 (void) printf("[pad:%d] ", padlen);
99 ap += padlen;
100 length -= padlen;
101 caplen -= 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);
106 }
107
108 if (mflags & RMF_FVER) {
109 (void) printf("future-version-decnet");
110 default_print(ap, length);
111 return;
112 }
113
114 /* is it a control message? */
115 if (mflags & RMF_CTLMSG) {
116 print_decnet_ctlmsg(rhp, min(length, caplen));
117 return;
118 }
119
120 switch (mflags & RMF_MASK) {
121 case RMF_LONG:
122 dst =
123 EXTRACT_LE_16BITS(rhp->rh_long.lg_dst.dne_remote.dne_nodeaddr);
124 src =
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)));
130 break;
131 case RMF_SHORT:
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)));
138 break;
139 default:
140 (void) printf("unknown message flags under mask");
141 default_print((u_char *)ap, length);
142 return;
143 }
144
145 (void)printf("%s > %s %d ",
146 dnaddr_string(src), dnaddr_string(dst), pktlen);
147 if (vflag) {
148 if (mflags & RMF_RQR)
149 (void)printf("RQR ");
150 if (mflags & RMF_RTS)
151 (void)printf("RTS ");
152 if (mflags & RMF_IE)
153 (void)printf("IE ");
154 (void)printf("%d hops ", hops);
155 }
156
157 print_nsp(nspp, nsplen);
158 }
159
160 static void
161 print_decnet_ctlmsg(register const union routehdr *rhp, u_int length)
162 {
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;
167 int priority;
168 char *rhpx = (char *)rhp;
169
170 switch (mflags & RMF_CTLMASK) {
171 case RMF_INIT:
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);
180 print_t_info(info);
181 (void)printf(
182 "src %sblksize %d vers %d eco %d ueco %d hello %d",
183 dnaddr_string(src), blksize, vers, eco, ueco,
184 hello);
185 break;
186 case RMF_VER:
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);
191 break;
192 case RMF_TEST:
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);
197 break;
198 case RMF_L1ROUT:
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));
204 break;
205 case RMF_L2ROUT:
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));
211 break;
212 case RMF_RHELLO:
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),
218 sizeof(srcea));
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);
224 print_i_info(info);
225 (void)printf(
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));
231 break;
232 case RMF_EHELLO:
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),
238 sizeof(srcea));
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);
242 /*seed*/
243 memcpy((char *)&rtea, (char *)&(cmp->cm_ehello.eh_router),
244 sizeof(rtea));
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);
248 print_i_info(info);
249 (void)printf(
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);
253 break;
254
255 default:
256 (void)printf("unknown control message");
257 default_print((u_char *)rhp, length);
258 break;
259 }
260 }
261
262 static void
263 print_t_info(int info)
264 {
265 int ntype = info & 3;
266 switch (ntype) {
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;
271 }
272 if (info & TI_VERIF)
273 (void)printf("verif ");
274 if (info & TI_BLOCK)
275 (void)printf("blo ");
276 }
277
278 static void
279 print_l1_routes(const char *rp, u_int len)
280 {
281 int count;
282 int id;
283 int info;
284
285 /* The last short is a checksum */
286 while (len > (3 * sizeof(short))) {
287 count = EXTRACT_LE_16BITS(rp);
288 if (count > 1024)
289 return; /* seems to be bogus from here on */
290 rp += sizeof(short);
291 len -= sizeof(short);
292 id = EXTRACT_LE_16BITS(rp);
293 rp += sizeof(short);
294 len -= sizeof(short);
295 info = EXTRACT_LE_16BITS(rp);
296 rp += sizeof(short);
297 len -= sizeof(short);
298 (void)printf("{ids %d-%d cost %d hops %d} ", id, id + count,
299 RI_COST(info), RI_HOPS(info));
300 }
301 }
302
303 static void
304 print_l2_routes(const char *rp, u_int len)
305 {
306 int count;
307 int area;
308 int info;
309
310 /* The last short is a checksum */
311 while (len > (3 * sizeof(short))) {
312 count = EXTRACT_LE_16BITS(rp);
313 if (count > 1024)
314 return; /* seems to be bogus from here on */
315 rp += sizeof(short);
316 len -= sizeof(short);
317 area = EXTRACT_LE_16BITS(rp);
318 rp += sizeof(short);
319 len -= sizeof(short);
320 info = EXTRACT_LE_16BITS(rp);
321 rp += sizeof(short);
322 len -= sizeof(short);
323 (void)printf("{areas %d-%d cost %d hops %d} ", area, area + count,
324 RI_COST(info), RI_HOPS(info));
325 }
326 }
327
328 static void
329 print_i_info(int info)
330 {
331 int ntype = info & II_TYPEMASK;
332 switch (ntype) {
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;
337 }
338 if (info & II_VERIF)
339 (void)printf("verif ");
340 if (info & II_NOMCAST)
341 (void)printf("nomcast ");
342 if (info & II_BLOCK)
343 (void)printf("blo ");
344 }
345
346 static void
347 print_elist(const char *elp, u_int len)
348 {
349 /* Not enough examples available for me to debug this */
350 }
351
352 static void
353 print_nsp(const u_char *nspp, u_int nsplen)
354 {
355 const struct nsphdr *nsphp = (struct nsphdr *)nspp;
356 int dst, src, flags;
357
358 flags = EXTRACT_LE_8BITS(nsphp->nh_flags);
359 dst = EXTRACT_LE_16BITS(nsphp->nh_dst);
360 src = EXTRACT_LE_16BITS(nsphp->nh_src);
361
362 switch (flags & NSP_TYPEMASK) {
363 case MFT_DATA:
364 switch (flags & NSP_SUBMASK) {
365 case MFS_BOM:
366 case MFS_MOM:
367 case MFS_EOM:
368 case MFS_BOM+MFS_EOM:
369 printf("data %d>%d ", src, dst);
370 {
371 struct seghdr *shp = (struct seghdr *)nspp;
372 int ack;
373 #ifdef PRINT_NSPDATA
374 u_char *dp;
375 #endif
376 u_int data_off = sizeof(struct minseghdr);
377
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);
382 else
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);
389 else
390 (void)printf("oack %d ", ack & SGQ_MASK);
391 ack = EXTRACT_LE_16BITS(shp->sh_seq[2]);
392 data_off += sizeof(short);
393 }
394 }
395 (void)printf("seg %d ", ack & SGQ_MASK);
396 #ifdef PRINT_NSPDATA
397 dp = &(nspp[data_off]);
398 pdata(dp, 10);
399 #endif
400 }
401 break;
402 case MFS_ILS+MFS_INT:
403 printf("intr ");
404 {
405 struct seghdr *shp = (struct seghdr *)nspp;
406 int ack;
407 #ifdef PRINT_NSPDATA
408 u_char *dp;
409 #endif
410 u_int data_off = sizeof(struct minseghdr);
411
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);
416 else
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);
423 else
424 (void)printf("ackdat %d ", ack & SGQ_MASK);
425 ack = EXTRACT_LE_16BITS(shp->sh_seq[2]);
426 data_off += sizeof(short);
427 }
428 }
429 (void)printf("seg %d ", ack & SGQ_MASK);
430 #ifdef PRINT_NSPDATA
431 dp = &(nspp[data_off]);
432 pdata(dp, 10);
433 #endif
434 }
435 break;
436 case MFS_ILS:
437 (void)printf("link-service %d>%d ", src, dst);
438 {
439 struct seghdr *shp = (struct seghdr *)nspp;
440 struct lsmsg *lsmp =
441 (struct lsmsg *)&(nspp[sizeof(struct seghdr)]);
442 int ack;
443 int lsflags, fcval;
444
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);
449 else
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);
455 else
456 (void)printf("ackdat %d ", ack & SGQ_MASK);
457 ack = EXTRACT_LE_16BITS(shp->sh_seq[2]);
458 }
459 }
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) {
464 case LSI_DATA:
465 (void)printf("dat seg count %d ", fcval);
466 switch (lsflags & LSM_MASK) {
467 case LSM_NOCHANGE:
468 break;
469 case LSM_DONOTSEND:
470 (void)printf("donotsend-data ");
471 break;
472 case LSM_SEND:
473 (void)printf("send-data ");
474 break;
475 default:
476 (void)printf("reserved-fcmod? %x", lsflags);
477 break;
478 }
479 break;
480 case LSI_INTR:
481 (void)printf("intr req count %d ", fcval);
482 break;
483 default:
484 (void)printf("reserved-fcval-int? %x", lsflags);
485 break;
486 }
487 }
488 break;
489 default:
490 (void)printf("reserved-subtype? %x %d > %d", flags, src, dst);
491 break;
492 }
493 break;
494 case MFT_ACK:
495 switch (flags & NSP_SUBMASK) {
496 case MFS_DACK:
497 (void)printf("data-ack %d>%d ", src, dst);
498 {
499 struct ackmsg *amp = (struct ackmsg *)nspp;
500 int ack;
501
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);
506 else
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);
512 else
513 (void)printf("oack %d ", ack & SGQ_MASK);
514 }
515 }
516 }
517 break;
518 case MFS_IACK:
519 (void)printf("ils-ack %d>%d ", src, dst);
520 {
521 struct ackmsg *amp = (struct ackmsg *)nspp;
522 int ack;
523
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);
528 else
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);
534 else
535 (void)printf("ackdat %d ", ack & SGQ_MASK);
536 }
537 }
538 }
539 break;
540 case MFS_CACK:
541 (void)printf("conn-ack %d", dst);
542 break;
543 default:
544 (void)printf("reserved-acktype? %x %d > %d", flags, src, dst);
545 break;
546 }
547 break;
548 case MFT_CTL:
549 switch (flags & NSP_SUBMASK) {
550 case MFS_CI:
551 case MFS_RCI:
552 if ((flags & NSP_SUBMASK) == MFS_CI)
553 (void)printf("conn-initiate ");
554 else
555 (void)printf("retrans-conn-initiate ");
556 (void)printf("%d>%d ", src, dst);
557 {
558 struct cimsg *cimp = (struct cimsg *)nspp;
559 int services, info, segsize;
560 #ifdef PRINT_NSPDATA
561 u_char *dp;
562 #endif
563
564 services = EXTRACT_LE_8BITS(cimp->ci_services);
565 info = EXTRACT_LE_8BITS(cimp->ci_info);
566 segsize = EXTRACT_LE_16BITS(cimp->ci_segsize);
567
568 switch (services & COS_MASK) {
569 case COS_NONE:
570 break;
571 case COS_SEGMENT:
572 (void)printf("seg ");
573 break;
574 case COS_MESSAGE:
575 (void)printf("msg ");
576 break;
577 case COS_CRYPTSER:
578 (void)printf("crypt ");
579 break;
580 }
581 switch (info & COI_MASK) {
582 case COI_32:
583 (void)printf("ver 3.2 ");
584 break;
585 case COI_31:
586 (void)printf("ver 3.1 ");
587 break;
588 case COI_40:
589 (void)printf("ver 4.0 ");
590 break;
591 case COI_41:
592 (void)printf("ver 4.1 ");
593 break;
594 }
595 (void)printf("segsize %d ", segsize);
596 #ifdef PRINT_NSPDATA
597 dp = &(nspp[sizeof(struct cimsg)]);
598 pdata(dp, nsplen - sizeof(struct cimsg));
599 #endif
600 }
601 break;
602 case MFS_CC:
603 (void)printf("conn-confirm %d>%d ", src, dst);
604 {
605 struct ccmsg *ccmp = (struct ccmsg *)nspp;
606 int services, info;
607 u_int segsize, optlen;
608 #ifdef PRINT_NSPDATA
609 u_char *dp;
610 #endif
611
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);
616
617 switch (services & COS_MASK) {
618 case COS_NONE:
619 break;
620 case COS_SEGMENT:
621 (void)printf("seg ");
622 break;
623 case COS_MESSAGE:
624 (void)printf("msg ");
625 break;
626 case COS_CRYPTSER:
627 (void)printf("crypt ");
628 break;
629 }
630 switch (info & COI_MASK) {
631 case COI_32:
632 (void)printf("ver 3.2 ");
633 break;
634 case COI_31:
635 (void)printf("ver 3.1 ");
636 break;
637 case COI_40:
638 (void)printf("ver 4.0 ");
639 break;
640 case COI_41:
641 (void)printf("ver 4.1 ");
642 break;
643 }
644 (void)printf("segsize %d ", segsize);
645 if (optlen) {
646 (void)printf("optlen %d ", optlen);
647 #ifdef PRINT_NSPDATA
648 optlen = min(optlen, nsplen - sizeof(struct ccmsg));
649 dp = &(nspp[sizeof(struct ccmsg)]);
650 pdata(dp, optlen);
651 #endif
652 }
653 }
654 break;
655 case MFS_DI:
656 (void)printf("disconn-initiate %d>%d ", src, dst);
657 {
658 struct dimsg *dimp = (struct dimsg *)nspp;
659 int reason;
660 u_int optlen;
661 #ifdef PRINT_NSPDATA
662 u_char *dp;
663 #endif
664
665 reason = EXTRACT_LE_16BITS(dimp->di_reason);
666 optlen = EXTRACT_LE_8BITS(dimp->di_optlen);
667
668 print_reason(reason);
669 if (optlen) {
670 (void)printf("optlen %d ", optlen);
671 #ifdef PRINT_NSPDATA
672 optlen = min(optlen, nsplen - sizeof(struct dimsg));
673 dp = &(nspp[sizeof(struct dimsg)]);
674 pdata(dp, optlen);
675 #endif
676 }
677 }
678 break;
679 case MFS_DC:
680 (void)printf("disconn-confirm %d>%d ", src, dst);
681 {
682 struct dcmsg *dcmp = (struct dcmsg *)nspp;
683 int reason;
684
685 reason = EXTRACT_LE_16BITS(dcmp->dc_reason);
686
687 print_reason(reason);
688 }
689 break;
690 default:
691 (void)printf("reserved-ctltype? %x %d > %d", flags, src, dst);
692 break;
693 }
694 break;
695 default:
696 (void)printf("reserved-type? %x %d > %d", flags, src, dst);
697 break;
698 }
699 }
700
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" },
724 { 0, NULL }
725 };
726
727 static void
728 print_reason(register int reason)
729 {
730 printf("%s ", tok2str(reason2str, "reason-%d", reason));
731 }
732
733 char *
734 dnnum_string(u_short dnaddr)
735 {
736 char *str;
737 size_t siz;
738 int area = (u_short)(dnaddr & AREAMASK) >> AREASHIFT;
739 int node = dnaddr & NODEMASK;
740
741 str = (char *)malloc(siz = sizeof("00.0000"));
742 if (str == NULL)
743 error("dnnum_string: malloc");
744 snprintf(str, siz, "%d.%d", area, node);
745 return(str);
746 }
747
748 char *
749 dnname_string(u_short dnaddr)
750 {
751 #ifdef HAVE_LIBDNET
752 struct dn_naddr dna;
753
754 dna.a_len = sizeof(short);
755 memcpy((char *)dna.a_addr, (char *)&dnaddr, sizeof(short));
756 return (strdup(dnet_htoa(&dna)));
757 #else
758 return(dnnum_string(dnaddr)); /* punt */
759 #endif
760 }
761
762 #ifdef PRINT_NSPDATA
763 static void
764 pdata(u_char *dp, u_int maxlen)
765 {
766 char c;
767 u_int x = maxlen;
768
769 while (x-- > 0) {
770 c = *dp++;
771 safeputchar(c);
772 }
773 }
774 #endif