]> The Tcpdump Group git mirrors - tcpdump/blob - print-ip.c
TCP: Add a missing 'truncated' message
[tcpdump] / print-ip.c
1 /*
2 * Copyright (c) 1988, 1989, 1990, 1991, 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 /* \summary: IP printer */
23
24 #ifdef HAVE_CONFIG_H
25 #include <config.h>
26 #endif
27
28 #include "netdissect-stdinc.h"
29
30 #include <string.h>
31
32 #include "netdissect.h"
33 #include "addrtoname.h"
34 #include "extract.h"
35
36 #include "ip.h"
37 #include "ipproto.h"
38
39
40 static const struct tok ip_option_values[] = {
41 { IPOPT_EOL, "EOL" },
42 { IPOPT_NOP, "NOP" },
43 { IPOPT_TS, "timestamp" },
44 { IPOPT_SECURITY, "security" },
45 { IPOPT_RR, "RR" },
46 { IPOPT_SSRR, "SSRR" },
47 { IPOPT_LSRR, "LSRR" },
48 { IPOPT_RA, "RA" },
49 { IPOPT_RFC1393, "traceroute" },
50 { 0, NULL }
51 };
52
53 /*
54 * print the recorded route in an IP RR, LSRR or SSRR option.
55 */
56 static int
57 ip_printroute(netdissect_options *ndo,
58 const u_char *cp, u_int length)
59 {
60 u_int ptr;
61 u_int len;
62
63 if (length < 3) {
64 ND_PRINT(" [bad length %u]", length);
65 return (0);
66 }
67 if ((length + 1) & 3)
68 ND_PRINT(" [bad length %u]", length);
69 ND_TCHECK_1(cp + 2);
70 ptr = EXTRACT_U_1(cp + 2) - 1;
71 if (ptr < 3 || ((ptr + 1) & 3) || ptr > length + 1)
72 ND_PRINT(" [bad ptr %u]", EXTRACT_U_1(cp + 2));
73
74 for (len = 3; len < length; len += 4) {
75 ND_TCHECK_4(cp + len);
76 ND_PRINT(" %s", ipaddr_string(ndo, cp + len));
77 if (ptr > len)
78 ND_PRINT(",");
79 }
80 return (0);
81
82 trunc:
83 return (-1);
84 }
85
86 /*
87 * If source-routing is present and valid, return the final destination.
88 * Otherwise, return IP destination.
89 *
90 * This is used for UDP and TCP pseudo-header in the checksum
91 * calculation.
92 */
93 static uint32_t
94 ip_finddst(netdissect_options *ndo,
95 const struct ip *ip)
96 {
97 u_int length;
98 u_int len;
99 const u_char *cp;
100
101 cp = (const u_char *)(ip + 1);
102 length = (IP_HL(ip) << 2);
103 if (length < sizeof(struct ip))
104 goto trunc;
105 length -= sizeof(struct ip);
106
107 for (; length != 0; cp += len, length -= len) {
108 int tt;
109
110 ND_TCHECK_1(cp);
111 tt = EXTRACT_U_1(cp);
112 if (tt == IPOPT_EOL)
113 break;
114 else if (tt == IPOPT_NOP)
115 len = 1;
116 else {
117 ND_TCHECK_1(cp + 1);
118 len = EXTRACT_U_1(cp + 1);
119 if (len < 2)
120 break;
121 }
122 if (length < len)
123 goto trunc;
124 ND_TCHECK_LEN(cp, len);
125 switch (tt) {
126
127 case IPOPT_SSRR:
128 case IPOPT_LSRR:
129 if (len < 7)
130 break;
131 return (EXTRACT_IPV4_TO_NETWORK_ORDER(cp + len - 4));
132 }
133 }
134 trunc:
135 return (EXTRACT_IPV4_TO_NETWORK_ORDER(ip->ip_dst));
136 }
137
138 /*
139 * Compute a V4-style checksum by building a pseudoheader.
140 */
141 int
142 nextproto4_cksum(netdissect_options *ndo,
143 const struct ip *ip, const uint8_t *data,
144 u_int len, u_int covlen, u_int next_proto)
145 {
146 struct phdr {
147 uint32_t src;
148 uint32_t dst;
149 u_char mbz;
150 u_char proto;
151 uint16_t len;
152 } ph;
153 struct cksum_vec vec[2];
154
155 /* pseudo-header.. */
156 ph.len = htons((uint16_t)len);
157 ph.mbz = 0;
158 ph.proto = next_proto;
159 ph.src = EXTRACT_IPV4_TO_NETWORK_ORDER(ip->ip_src);
160 if (IP_HL(ip) == 5)
161 ph.dst = EXTRACT_IPV4_TO_NETWORK_ORDER(ip->ip_dst);
162 else
163 ph.dst = ip_finddst(ndo, ip);
164
165 vec[0].ptr = (const uint8_t *)(void *)&ph;
166 vec[0].len = sizeof(ph);
167 vec[1].ptr = data;
168 vec[1].len = covlen;
169 return (in_cksum(vec, 2));
170 }
171
172 static int
173 ip_printts(netdissect_options *ndo,
174 const u_char *cp, u_int length)
175 {
176 u_int ptr;
177 u_int len;
178 u_int hoplen;
179 const char *type;
180
181 if (length < 4) {
182 ND_PRINT("[bad length %u]", length);
183 return (0);
184 }
185 ND_PRINT(" TS{");
186 ND_TCHECK_1(cp + 3);
187 hoplen = ((EXTRACT_U_1(cp + 3) & 0xF) != IPOPT_TS_TSONLY) ? 8 : 4;
188 if ((length - 4) & (hoplen-1))
189 ND_PRINT("[bad length %u]", length);
190 ND_TCHECK_1(cp + 2);
191 ptr = EXTRACT_U_1(cp + 2) - 1;
192 len = 0;
193 if (ptr < 4 || ((ptr - 4) & (hoplen-1)) || ptr > length + 1)
194 ND_PRINT("[bad ptr %u]", EXTRACT_U_1(cp + 2));
195 ND_TCHECK_1(cp + 3);
196 switch (EXTRACT_U_1(cp + 3)&0xF) {
197 case IPOPT_TS_TSONLY:
198 ND_PRINT("TSONLY");
199 break;
200 case IPOPT_TS_TSANDADDR:
201 ND_PRINT("TS+ADDR");
202 break;
203 /*
204 * prespecified should really be 3, but some ones might send 2
205 * instead, and the IPOPT_TS_PRESPEC constant can apparently
206 * have both values, so we have to hard-code it here.
207 */
208
209 case 2:
210 ND_PRINT("PRESPEC2.0");
211 break;
212 case 3: /* IPOPT_TS_PRESPEC */
213 ND_PRINT("PRESPEC");
214 break;
215 default:
216 ND_PRINT("[bad ts type %u]", EXTRACT_U_1(cp + 3)&0xF);
217 goto done;
218 }
219
220 type = " ";
221 for (len = 4; len < length; len += hoplen) {
222 if (ptr == len)
223 type = " ^ ";
224 ND_TCHECK_LEN(cp + len, hoplen);
225 ND_PRINT("%s%u@%s", type, EXTRACT_BE_U_4(cp + len + hoplen - 4),
226 hoplen!=8 ? "" : ipaddr_string(ndo, cp + len));
227 type = " ";
228 }
229
230 done:
231 ND_PRINT("%s", ptr == len ? " ^ " : "");
232
233 if (EXTRACT_U_1(cp + 3) >> 4)
234 ND_PRINT(" [%u hops not recorded]} ", EXTRACT_U_1(cp + 3)>>4);
235 else
236 ND_PRINT("}");
237 return (0);
238
239 trunc:
240 return (-1);
241 }
242
243 /*
244 * print IP options.
245 */
246 static void
247 ip_optprint(netdissect_options *ndo,
248 const u_char *cp, u_int length)
249 {
250 u_int option_len;
251 const char *sep = "";
252
253 for (; length > 0; cp += option_len, length -= option_len) {
254 u_int option_code;
255
256 ND_PRINT("%s", sep);
257 sep = ",";
258
259 ND_TCHECK_1(cp);
260 option_code = EXTRACT_U_1(cp);
261
262 ND_PRINT("%s",
263 tok2str(ip_option_values,"unknown %u",option_code));
264
265 if (option_code == IPOPT_NOP ||
266 option_code == IPOPT_EOL)
267 option_len = 1;
268
269 else {
270 ND_TCHECK_1(cp + 1);
271 option_len = EXTRACT_U_1(cp + 1);
272 if (option_len < 2) {
273 ND_PRINT(" [bad length %u]", option_len);
274 return;
275 }
276 }
277
278 if (option_len > length) {
279 ND_PRINT(" [bad length %u]", option_len);
280 return;
281 }
282
283 ND_TCHECK_LEN(cp, option_len);
284
285 switch (option_code) {
286 case IPOPT_EOL:
287 return;
288
289 case IPOPT_TS:
290 if (ip_printts(ndo, cp, option_len) == -1)
291 goto trunc;
292 break;
293
294 case IPOPT_RR: /* fall through */
295 case IPOPT_SSRR:
296 case IPOPT_LSRR:
297 if (ip_printroute(ndo, cp, option_len) == -1)
298 goto trunc;
299 break;
300
301 case IPOPT_RA:
302 if (option_len < 4) {
303 ND_PRINT(" [bad length %u]", option_len);
304 break;
305 }
306 ND_TCHECK_1(cp + 3);
307 if (EXTRACT_BE_U_2(cp + 2) != 0)
308 ND_PRINT(" value %u", EXTRACT_BE_U_2(cp + 2));
309 break;
310
311 case IPOPT_NOP: /* nothing to print - fall through */
312 case IPOPT_SECURITY:
313 default:
314 break;
315 }
316 }
317 return;
318
319 trunc:
320 nd_print_trunc(ndo);
321 }
322
323 #define IP_RES 0x8000
324
325 static const struct tok ip_frag_values[] = {
326 { IP_MF, "+" },
327 { IP_DF, "DF" },
328 { IP_RES, "rsvd" }, /* The RFC3514 evil ;-) bit */
329 { 0, NULL }
330 };
331
332 struct ip_print_demux_state {
333 const struct ip *ip;
334 const u_char *cp;
335 u_int len, off;
336 u_char nh;
337 int advance;
338 };
339
340 static void
341 ip_print_demux(netdissect_options *ndo,
342 struct ip_print_demux_state *ipds)
343 {
344 const char *p_name;
345
346 again:
347 switch (ipds->nh) {
348
349 case IPPROTO_AH:
350 if (!ND_TTEST_1(ipds->cp)) {
351 ND_PRINT("[|AH]");
352 break;
353 }
354 ipds->nh = EXTRACT_U_1(ipds->cp);
355 ipds->advance = ah_print(ndo, ipds->cp);
356 if (ipds->advance <= 0)
357 break;
358 ipds->cp += ipds->advance;
359 ipds->len -= ipds->advance;
360 goto again;
361
362 case IPPROTO_ESP:
363 {
364 u_int enh, padlen;
365 ipds->advance = esp_print(ndo, ipds->cp, ipds->len,
366 (const u_char *)ipds->ip,
367 &enh, &padlen);
368 if (ipds->advance <= 0)
369 break;
370 ipds->cp += ipds->advance;
371 ipds->len -= ipds->advance + padlen;
372 ipds->nh = enh & 0xff;
373 goto again;
374 }
375
376 case IPPROTO_IPCOMP:
377 {
378 ipcomp_print(ndo, ipds->cp);
379 /*
380 * Either this has decompressed the payload and
381 * printed it, in which case there's nothing more
382 * to do, or it hasn't, in which case there's
383 * nothing more to do.
384 */
385 break;
386 }
387
388 case IPPROTO_SCTP:
389 sctp_print(ndo, ipds->cp, (const u_char *)ipds->ip, ipds->len);
390 break;
391
392 case IPPROTO_DCCP:
393 dccp_print(ndo, ipds->cp, (const u_char *)ipds->ip, ipds->len);
394 break;
395
396 case IPPROTO_TCP:
397 /* pass on the MF bit plus the offset to detect fragments */
398 tcp_print(ndo, ipds->cp, ipds->len, (const u_char *)ipds->ip,
399 ipds->off & (IP_MF|IP_OFFMASK));
400 break;
401
402 case IPPROTO_UDP:
403 /* pass on the MF bit plus the offset to detect fragments */
404 udp_print(ndo, ipds->cp, ipds->len, (const u_char *)ipds->ip,
405 ipds->off & (IP_MF|IP_OFFMASK));
406 break;
407
408 case IPPROTO_ICMP:
409 /* pass on the MF bit plus the offset to detect fragments */
410 icmp_print(ndo, ipds->cp, ipds->len, (const u_char *)ipds->ip,
411 ipds->off & (IP_MF|IP_OFFMASK));
412 break;
413
414 case IPPROTO_PIGP:
415 /*
416 * XXX - the current IANA protocol number assignments
417 * page lists 9 as "any private interior gateway
418 * (used by Cisco for their IGRP)" and 88 as
419 * "EIGRP" from Cisco.
420 *
421 * Recent BSD <netinet/in.h> headers define
422 * IP_PROTO_PIGP as 9 and IP_PROTO_IGRP as 88.
423 * We define IP_PROTO_PIGP as 9 and
424 * IP_PROTO_EIGRP as 88; those names better
425 * match was the current protocol number
426 * assignments say.
427 */
428 igrp_print(ndo, ipds->cp, ipds->len);
429 break;
430
431 case IPPROTO_EIGRP:
432 eigrp_print(ndo, ipds->cp, ipds->len);
433 break;
434
435 case IPPROTO_ND:
436 ND_PRINT(" nd %u", ipds->len);
437 break;
438
439 case IPPROTO_EGP:
440 egp_print(ndo, ipds->cp, ipds->len);
441 break;
442
443 case IPPROTO_OSPF:
444 ospf_print(ndo, ipds->cp, ipds->len, (const u_char *)ipds->ip);
445 break;
446
447 case IPPROTO_IGMP:
448 igmp_print(ndo, ipds->cp, ipds->len);
449 break;
450
451 case IPPROTO_IPV4:
452 /* DVMRP multicast tunnel (ip-in-ip encapsulation) */
453 ip_print(ndo, ipds->cp, ipds->len);
454 if (! ndo->ndo_vflag) {
455 ND_PRINT(" (ipip-proto-4)");
456 return;
457 }
458 break;
459
460 case IPPROTO_IPV6:
461 /* ip6-in-ip encapsulation */
462 ip6_print(ndo, ipds->cp, ipds->len);
463 break;
464
465 case IPPROTO_RSVP:
466 rsvp_print(ndo, ipds->cp, ipds->len);
467 break;
468
469 case IPPROTO_GRE:
470 /* do it */
471 gre_print(ndo, ipds->cp, ipds->len);
472 break;
473
474 case IPPROTO_MOBILE:
475 mobile_print(ndo, ipds->cp, ipds->len);
476 break;
477
478 case IPPROTO_PIM:
479 pim_print(ndo, ipds->cp, ipds->len, (const u_char *)ipds->ip);
480 break;
481
482 case IPPROTO_VRRP:
483 if (ndo->ndo_packettype == PT_CARP) {
484 if (ndo->ndo_vflag)
485 ND_PRINT("carp %s > %s: ",
486 ipaddr_string(ndo, ipds->ip->ip_src),
487 ipaddr_string(ndo, ipds->ip->ip_dst));
488 carp_print(ndo, ipds->cp, ipds->len,
489 EXTRACT_U_1(ipds->ip->ip_ttl));
490 } else {
491 if (ndo->ndo_vflag)
492 ND_PRINT("vrrp %s > %s: ",
493 ipaddr_string(ndo, ipds->ip->ip_src),
494 ipaddr_string(ndo, ipds->ip->ip_dst));
495 vrrp_print(ndo, ipds->cp, ipds->len,
496 (const u_char *)ipds->ip,
497 EXTRACT_U_1(ipds->ip->ip_ttl));
498 }
499 break;
500
501 case IPPROTO_PGM:
502 pgm_print(ndo, ipds->cp, ipds->len, (const u_char *)ipds->ip);
503 break;
504
505 default:
506 if (ndo->ndo_nflag==0 && (p_name = netdb_protoname(ipds->nh)) != NULL)
507 ND_PRINT(" %s", p_name);
508 else
509 ND_PRINT(" ip-proto-%u", ipds->nh);
510 ND_PRINT(" %u", ipds->len);
511 break;
512 }
513 }
514
515 void
516 ip_inner_print(netdissect_options *ndo,
517 const u_char *bp,
518 u_int length, u_int nh,
519 const u_char *bp2)
520 {
521 struct ip_print_demux_state ipd;
522
523 ipd.ip = (const struct ip *)bp2;
524 ipd.cp = bp;
525 ipd.len = length;
526 ipd.off = 0;
527 ipd.nh = nh;
528 ipd.advance = 0;
529
530 ip_print_demux(ndo, &ipd);
531 }
532
533
534 /*
535 * print an IP datagram.
536 */
537 void
538 ip_print(netdissect_options *ndo,
539 const u_char *bp,
540 u_int length)
541 {
542 struct ip_print_demux_state ipd;
543 struct ip_print_demux_state *ipds=&ipd;
544 const u_char *ipend;
545 u_int hlen;
546 struct cksum_vec vec[1];
547 uint8_t ip_tos, ip_ttl, ip_proto;
548 uint16_t sum, ip_sum;
549 const char *p_name;
550
551 ndo->ndo_protocol = "ip";
552 ipds->ip = (const struct ip *)bp;
553 ND_TCHECK_1(ipds->ip->ip_vhl);
554 if (IP_V(ipds->ip) != 4) { /* print version and fail if != 4 */
555 if (IP_V(ipds->ip) == 6)
556 ND_PRINT("IP6, wrong link-layer encapsulation");
557 else
558 ND_PRINT("IP%u", IP_V(ipds->ip));
559 return;
560 }
561 if (!ndo->ndo_eflag)
562 ND_PRINT("IP ");
563
564 ND_TCHECK_SIZE(ipds->ip);
565 if (length < sizeof (struct ip)) {
566 ND_PRINT("truncated-ip %u", length);
567 return;
568 }
569 hlen = IP_HL(ipds->ip) * 4;
570 if (hlen < sizeof (struct ip)) {
571 ND_PRINT("bad-hlen %u", hlen);
572 return;
573 }
574
575 ipds->len = EXTRACT_BE_U_2(ipds->ip->ip_len);
576 if (length < ipds->len)
577 ND_PRINT("truncated-ip - %u bytes missing! ",
578 ipds->len - length);
579 if (ipds->len < hlen) {
580 #ifdef GUESS_TSO
581 if (ipds->len) {
582 ND_PRINT("bad-len %u", ipds->len);
583 return;
584 }
585 else {
586 /* we guess that it is a TSO send */
587 ipds->len = length;
588 }
589 #else
590 ND_PRINT("bad-len %u", ipds->len);
591 return;
592 #endif /* GUESS_TSO */
593 }
594
595 /*
596 * Cut off the snapshot length to the end of the IP payload.
597 */
598 ipend = bp + ipds->len;
599 if (ipend < ndo->ndo_snapend)
600 ndo->ndo_snapend = ipend;
601
602 ipds->len -= hlen;
603
604 ipds->off = EXTRACT_BE_U_2(ipds->ip->ip_off);
605
606 ip_proto = EXTRACT_U_1(ipds->ip->ip_p);
607
608 if (ndo->ndo_vflag) {
609 ip_tos = EXTRACT_U_1(ipds->ip->ip_tos);
610 ND_PRINT("(tos 0x%x", ip_tos);
611 /* ECN bits */
612 switch (ip_tos & 0x03) {
613
614 case 0:
615 break;
616
617 case 1:
618 ND_PRINT(",ECT(1)");
619 break;
620
621 case 2:
622 ND_PRINT(",ECT(0)");
623 break;
624
625 case 3:
626 ND_PRINT(",CE");
627 break;
628 }
629
630 ip_ttl = EXTRACT_U_1(ipds->ip->ip_ttl);
631 if (ip_ttl >= 1)
632 ND_PRINT(", ttl %u", ip_ttl);
633
634 /*
635 * for the firewall guys, print id, offset.
636 * On all but the last stick a "+" in the flags portion.
637 * For unfragmented datagrams, note the don't fragment flag.
638 */
639 ND_PRINT(", id %u, offset %u, flags [%s], proto %s (%u)",
640 EXTRACT_BE_U_2(ipds->ip->ip_id),
641 (ipds->off & 0x1fff) * 8,
642 bittok2str(ip_frag_values, "none", ipds->off&0xe000),
643 tok2str(ipproto_values, "unknown", ip_proto),
644 ip_proto);
645
646 ND_PRINT(", length %u", EXTRACT_BE_U_2(ipds->ip->ip_len));
647
648 if ((hlen - sizeof(struct ip)) > 0) {
649 ND_PRINT(", options (");
650 ip_optprint(ndo, (const u_char *)(ipds->ip + 1), hlen - sizeof(struct ip));
651 ND_PRINT(")");
652 }
653
654 if (!ndo->ndo_Kflag && (const u_char *)ipds->ip + hlen <= ndo->ndo_snapend) {
655 vec[0].ptr = (const uint8_t *)(const void *)ipds->ip;
656 vec[0].len = hlen;
657 sum = in_cksum(vec, 1);
658 if (sum != 0) {
659 ip_sum = EXTRACT_BE_U_2(ipds->ip->ip_sum);
660 ND_PRINT(", bad cksum %x (->%x)!", ip_sum,
661 in_cksum_shouldbe(ip_sum, sum));
662 }
663 }
664
665 ND_PRINT(")\n ");
666 }
667
668 /*
669 * If this is fragment zero, hand it to the next higher
670 * level protocol.
671 */
672 if ((ipds->off & 0x1fff) == 0) {
673 ipds->cp = (const u_char *)ipds->ip + hlen;
674 ipds->nh = EXTRACT_U_1(ipds->ip->ip_p);
675
676 if (ipds->nh != IPPROTO_TCP && ipds->nh != IPPROTO_UDP &&
677 ipds->nh != IPPROTO_SCTP && ipds->nh != IPPROTO_DCCP) {
678 ND_PRINT("%s > %s: ",
679 ipaddr_string(ndo, ipds->ip->ip_src),
680 ipaddr_string(ndo, ipds->ip->ip_dst));
681 }
682 ip_print_demux(ndo, ipds);
683 } else {
684 /*
685 * Ultra quiet now means that all this stuff should be
686 * suppressed.
687 */
688 if (ndo->ndo_qflag > 1)
689 return;
690
691 /*
692 * This isn't the first frag, so we're missing the
693 * next level protocol header. print the ip addr
694 * and the protocol.
695 */
696 ND_PRINT("%s > %s:", ipaddr_string(ndo, ipds->ip->ip_src),
697 ipaddr_string(ndo, ipds->ip->ip_dst));
698 if (!ndo->ndo_nflag && (p_name = netdb_protoname(ip_proto)) != NULL)
699 ND_PRINT(" %s", p_name);
700 else
701 ND_PRINT(" ip-proto-%u", ip_proto);
702 }
703 return;
704
705 trunc:
706 nd_print_trunc(ndo);
707 return;
708 }
709
710 void
711 ipN_print(netdissect_options *ndo, const u_char *bp, u_int length)
712 {
713 ndo->ndo_protocol = "ipN";
714 if (length < 1) {
715 ND_PRINT("truncated-ip %u", length);
716 return;
717 }
718
719 ND_TCHECK_1(bp);
720 switch (EXTRACT_U_1(bp) & 0xF0) {
721 case 0x40:
722 ip_print(ndo, bp, length);
723 break;
724 case 0x60:
725 ip6_print(ndo, bp, length);
726 break;
727 default:
728 ND_PRINT("unknown ip %u", (EXTRACT_U_1(bp) & 0xF0) >> 4);
729 break;
730 }
731 return;
732
733 trunc:
734 nd_print_trunc(ndo);
735 return;
736 }