X-Git-Url: https://git.tcpdump.org/tcpdump/blobdiff_plain/546558eabd81cfc36a81a4df728fdfea0d83b41a..refs/heads/master:/print-babel.c diff --git a/print-babel.c b/print-babel.c index 9f2ecf10..c7593ce1 100644 --- a/print-babel.c +++ b/print-babel.c @@ -27,10 +27,17 @@ */ /* \summary: Babel Routing Protocol printer */ +/* Specifications: + * + * RFC 6126 + * RFC 7298 + * RFC 7557 + * draft-ietf-babel-rfc6126bis-17 + * draft-ietf-babel-hmac-10 + * draft-ietf-babel-source-specific-0 + */ -#ifdef HAVE_CONFIG_H #include -#endif #include "netdissect-stdinc.h" @@ -41,8 +48,6 @@ #include "addrtoname.h" #include "extract.h" -static const char tstr[] = "[|babel]"; - static void babel_print_v2(netdissect_options *, const u_char *cp, u_int length); void @@ -50,18 +55,18 @@ babel_print(netdissect_options *ndo, const u_char *cp, u_int length) { ndo->ndo_protocol = "babel"; - ND_PRINT("babel"); + nd_print_protocol(ndo); ND_TCHECK_4(cp); - if(EXTRACT_U_1(cp) != 42) { + if(GET_U_1(cp) != 42) { ND_PRINT(" invalid header"); return; } else { - ND_PRINT(" %u", EXTRACT_U_1(cp + 1)); + ND_PRINT(" %u", GET_U_1(cp + 1)); } - switch(EXTRACT_U_1(cp + 1)) { + switch(GET_U_1(cp + 1)) { case 2: babel_print_v2(ndo, cp, length); break; @@ -73,8 +78,7 @@ babel_print(netdissect_options *ndo, return; trunc: - ND_PRINT(" %s", tstr); - return; + nd_print_trunc(ndo); } /* TLVs */ @@ -94,6 +98,10 @@ babel_print(netdissect_options *ndo, #define MESSAGE_UPDATE_SRC_SPECIFIC 13 /* last appearance in draft-boutier-babel-source-specific-01 */ #define MESSAGE_REQUEST_SRC_SPECIFIC 14 /* idem */ #define MESSAGE_MH_REQUEST_SRC_SPECIFIC 15 /* idem */ +#define MESSAGE_MAC 16 +#define MESSAGE_PC 17 +#define MESSAGE_CHALLENGE_REQUEST 18 +#define MESSAGE_CHALLENGE_REPLY 19 /* sub-TLVs */ #define MESSAGE_SUB_PAD1 0 @@ -101,6 +109,12 @@ babel_print(netdissect_options *ndo, #define MESSAGE_SUB_DIVERSITY 2 #define MESSAGE_SUB_TIMESTAMP 3 +/* "Mandatory" bit in sub-TLV types */ +#define MANDATORY_MASK 0x80 + +/* Flags for the Hello TLV */ +#define UNICAST_MASK 0x8000 + /* Diversity sub-TLV channel codes */ static const struct tok diversity_str[] = { { 0, "reserved" }, @@ -109,13 +123,13 @@ static const struct tok diversity_str[] = { }; static const char * -format_id(const u_char *id) +format_id(netdissect_options *ndo, const u_char *id) { static char buf[25]; - nd_snprintf(buf, 25, "%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x", - EXTRACT_U_1(id), EXTRACT_U_1(id + 1), EXTRACT_U_1(id + 2), - EXTRACT_U_1(id + 3), EXTRACT_U_1(id + 4), EXTRACT_U_1(id + 5), - EXTRACT_U_1(id + 6), EXTRACT_U_1(id + 7)); + snprintf(buf, 25, "%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x", + GET_U_1(id), GET_U_1(id + 1), GET_U_1(id + 2), + GET_U_1(id + 3), GET_U_1(id + 4), GET_U_1(id + 5), + GET_U_1(id + 6), GET_U_1(id + 7)); buf[24] = '\0'; return buf; } @@ -127,10 +141,16 @@ static const char * format_prefix(netdissect_options *ndo, const u_char *prefix, unsigned char plen) { static char buf[50]; + + /* + * prefix points to a buffer on the stack into which the prefix has + * been placed, so we can't use GET_IPADDR_STRING() or + * GET_IP6ADDR_STRING() on it. + */ if(plen >= 96 && memcmp(prefix, v4prefix, 12) == 0) - nd_snprintf(buf, 50, "%s/%u", ipaddr_string(ndo, prefix + 12), plen - 96); + snprintf(buf, 50, "%s/%u", ipaddr_string(ndo, prefix + 12), plen - 96); else - nd_snprintf(buf, 50, "%s/%u", ip6addr_string(ndo, prefix), plen); + snprintf(buf, 50, "%s/%u", ip6addr_string(ndo, prefix), plen); buf[49] = '\0'; return buf; } @@ -138,6 +158,11 @@ format_prefix(netdissect_options *ndo, const u_char *prefix, unsigned char plen) static const char * format_address(netdissect_options *ndo, const u_char *prefix) { + /* + * prefix points to a buffer on the stack into which the prefix has + * been placed, so we can't use GET_IPADDR_STRING() or + * GET_IP6ADDR_STRING() on it. + */ if(memcmp(prefix, v4prefix, 12) == 0) return ipaddr_string(ndo, prefix + 12); else @@ -151,7 +176,7 @@ format_interval(const uint16_t i) if (i == 0) return "0.0s (bogus)"; - nd_snprintf(buf, sizeof(buf), "%u.%02us", i / 100, i % 100); + snprintf(buf, sizeof(buf), "%u.%02us", i / 100, i % 100); return buf; } @@ -165,7 +190,7 @@ static const char * format_timestamp(const uint32_t i) { static char buf[sizeof("0000.000000s")]; - nd_snprintf(buf, sizeof(buf), "%u.%06us", i / 1000000, i % 1000000); + snprintf(buf, sizeof(buf), "%u.%06us", i / 1000000, i % 1000000); return buf; } @@ -252,7 +277,7 @@ network_address(int ae, const unsigned char *a, unsigned int len, * o Type 1 stands for PadN sub-TLV with the same encoding as the PadN TLV. * o Type 2 stands for Diversity sub-TLV, which propagates diversity routing * data. Its body is a variable-length sequence of 8-bit unsigned integers, - * each representing per-hop number of interferring radio channel for the + * each representing per-hop number of interfering radio channel for the * prefix. Channel 0 is invalid and must not be used in the sub-TLV, channel * 255 interferes with any other channel. * o Type 3 stands for Timestamp sub-TLV, used to compute RTT between @@ -277,15 +302,17 @@ subtlvs_print(netdissect_options *ndo, uint32_t t1, t2; while (cp < ep) { - subtype = EXTRACT_U_1(cp); + subtype = GET_U_1(cp); cp++; if(subtype == MESSAGE_SUB_PAD1) { ND_PRINT(" sub-pad1"); continue; } + if ((MANDATORY_MASK & subtype) != 0) + ND_PRINT(" (M)"); if(cp == ep) goto invalid; - sublen = EXTRACT_U_1(cp); + sublen = GET_U_1(cp); cp++; if(cp + sublen > ep) goto invalid; @@ -302,10 +329,12 @@ subtlvs_print(netdissect_options *ndo, break; } sep = " "; - while(sublen--) { - ND_PRINT("%s%s", sep, tok2str(diversity_str, "%u", EXTRACT_U_1(cp))); + while (sublen) { + ND_PRINT("%s%s", sep, + tok2str(diversity_str, "%u", GET_U_1(cp))); cp++; sep = "-"; + sublen--; } if(tlv_type != MESSAGE_UPDATE && tlv_type != MESSAGE_UPDATE_SRC_SPECIFIC) @@ -316,14 +345,14 @@ subtlvs_print(netdissect_options *ndo, if(tlv_type == MESSAGE_HELLO) { if(sublen < 4) goto invalid; - t1 = EXTRACT_BE_U_4(cp); + t1 = GET_BE_U_4(cp); ND_PRINT(" %s", format_timestamp(t1)); } else if(tlv_type == MESSAGE_IHU) { if(sublen < 8) goto invalid; - t1 = EXTRACT_BE_U_4(cp); + t1 = GET_BE_U_4(cp); ND_PRINT(" %s", format_timestamp(t1)); - t2 = EXTRACT_BE_U_4(cp + 4); + t2 = GET_BE_U_4(cp + 4); ND_PRINT("|%s", format_timestamp(t2)); } else ND_PRINT(" (bogus)"); @@ -337,49 +366,44 @@ subtlvs_print(netdissect_options *ndo, return; invalid: - ND_PRINT("%s", istr); + nd_print_invalid(ndo); } #define ICHECK(i, l) \ - if ((i) + (l) > bodylen || (i) + (l) > length) goto invalid; + if ((i) + (l) > tlvs_length || (i) + (l) > packet_length_remaining) \ + goto invalid; -static void -babel_print_v2(netdissect_options *ndo, - const u_char *cp, u_int length) +static int +babel_print_v2_tlvs(netdissect_options *ndo, + const u_char *cp, u_int tlvs_length, + u_int packet_length_remaining) { u_int i; - u_short bodylen; u_char v4_prefix[16] = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0xFF, 0xFF, 0, 0, 0, 0 }; u_char v6_prefix[16] = {0}; - ND_TCHECK_4(cp); - if (length < 4) - goto invalid; - bodylen = EXTRACT_BE_U_2(cp + 2); - ND_PRINT(" (%u)", bodylen); - - /* Process the TLVs in the body */ i = 0; - while(i < bodylen) { + while(i < tlvs_length) { const u_char *message; - u_int type, len; + uint8_t type; + u_int len; - message = cp + 4 + i; + message = cp + i; - ND_TCHECK_1(message); - if((type = EXTRACT_U_1(message)) == MESSAGE_PAD1) { + ICHECK(i, 1); + if((type = GET_U_1(message)) == MESSAGE_PAD1) { ND_PRINT(ndo->ndo_vflag ? "\n\tPad 1" : " pad1"); i += 1; continue; } - ND_TCHECK_2(message); ICHECK(i, 2); - len = EXTRACT_U_1(message + 1); + ND_TCHECK_2(message); + len = GET_U_1(message + 1); - ND_TCHECK_LEN(message, 2 + len); ICHECK(i, 2 + len); + ND_TCHECK_LEN(message, 2 + len); switch(type) { case MESSAGE_PADN: { @@ -397,8 +421,8 @@ babel_print_v2(netdissect_options *ndo, else { ND_PRINT("\n\tAcknowledgment Request "); if(len < 6) goto invalid; - nonce = EXTRACT_BE_U_2(message + 4); - interval = EXTRACT_BE_U_2(message + 6); + nonce = GET_BE_U_2(message + 4); + interval = GET_BE_U_2(message + 6); ND_PRINT("%04x %s", nonce, format_interval(interval)); } } @@ -411,22 +435,29 @@ babel_print_v2(netdissect_options *ndo, else { ND_PRINT("\n\tAcknowledgment "); if(len < 2) goto invalid; - nonce = EXTRACT_BE_U_2(message + 2); + nonce = GET_BE_U_2(message + 2); ND_PRINT("%04x", nonce); } } break; case MESSAGE_HELLO: { - u_short seqno, interval; + u_short seqno, interval, unicast; if (!ndo->ndo_vflag) ND_PRINT(" hello"); else { ND_PRINT("\n\tHello "); if(len < 6) goto invalid; - seqno = EXTRACT_BE_U_2(message + 4); - interval = EXTRACT_BE_U_2(message + 6); - ND_PRINT("seqno %u interval %s", seqno, format_interval(interval)); + unicast = (GET_BE_U_2(message + 2) & UNICAST_MASK); + seqno = GET_BE_U_2(message + 4); + interval = GET_BE_U_2(message + 6); + if(unicast) + ND_PRINT("(Unicast) "); + ND_PRINT("seqno %u ", seqno); + if(interval!=0) + ND_PRINT("interval %s", format_interval(interval)); + else + ND_PRINT("unscheduled"); /* Extra data. */ if(len > 6) subtlvs_print(ndo, message + 8, message + 2 + len, type); @@ -444,12 +475,12 @@ babel_print_v2(netdissect_options *ndo, int rc; ND_PRINT("\n\tIHU "); if(len < 6) goto invalid; - rxcost = EXTRACT_BE_U_2(message + 4); - interval = EXTRACT_BE_U_2(message + 6); - ae = EXTRACT_U_1(message + 2); + rxcost = GET_BE_U_2(message + 4); + interval = GET_BE_U_2(message + 6); + ae = GET_U_1(message + 2); rc = network_address(ae, message + 8, len - 6, address); - if(rc < 0) { ND_PRINT("%s", tstr); break; } + if(rc < 0) { nd_print_trunc(ndo); break; } ND_PRINT("%s rxcost %u interval %s", ae == 0 ? "any" : format_address(ndo, address), rxcost, format_interval(interval)); @@ -467,7 +498,7 @@ babel_print_v2(netdissect_options *ndo, else { ND_PRINT("\n\tRouter Id"); if(len < 10) goto invalid; - ND_PRINT(" %s", format_id(message + 4)); + ND_PRINT(" %s", format_id(ndo, message + 4)); } } break; @@ -481,7 +512,7 @@ babel_print_v2(netdissect_options *ndo, u_char nh[16]; ND_PRINT("\n\tNext Hop"); if(len < 2) goto invalid; - ae = EXTRACT_U_1(message + 2); + ae = GET_U_1(message + 2); rc = network_address(ae, message + 4, len - 2, nh); if(rc < 0) goto invalid; @@ -493,13 +524,13 @@ babel_print_v2(netdissect_options *ndo, case MESSAGE_UPDATE: { if (!ndo->ndo_vflag) { ND_PRINT(" update"); - if(len < 1) - ND_PRINT("/truncated"); + if(len < 10) + goto invalid; else ND_PRINT("%s%s%s", - (EXTRACT_U_1(message + 3) & 0x80) ? "/prefix": "", - (EXTRACT_U_1(message + 3) & 0x40) ? "/id" : "", - (EXTRACT_U_1(message + 3) & 0x3f) ? "/unknown" : ""); + (GET_U_1(message + 3) & 0x80) ? "/prefix": "", + (GET_U_1(message + 3) & 0x40) ? "/id" : "", + (GET_U_1(message + 3) & 0x3f) ? "/unknown" : ""); } else { u_short interval, seqno, metric; u_char ae, plen; @@ -507,26 +538,26 @@ babel_print_v2(netdissect_options *ndo, u_char prefix[16]; ND_PRINT("\n\tUpdate"); if(len < 10) goto invalid; - ae = EXTRACT_U_1(message + 2); - plen = EXTRACT_U_1(message + 4) + (EXTRACT_U_1(message + 2) == 1 ? 96 : 0); + ae = GET_U_1(message + 2); + plen = GET_U_1(message + 4) + (GET_U_1(message + 2) == 1 ? 96 : 0); rc = network_prefix(ae, - EXTRACT_U_1(message + 4), - EXTRACT_U_1(message + 5), + GET_U_1(message + 4), + GET_U_1(message + 5), message + 12, - EXTRACT_U_1(message + 2) == 1 ? v4_prefix : v6_prefix, + GET_U_1(message + 2) == 1 ? v4_prefix : v6_prefix, len - 10, prefix); if(rc < 0) goto invalid; - interval = EXTRACT_BE_U_2(message + 6); - seqno = EXTRACT_BE_U_2(message + 8); - metric = EXTRACT_BE_U_2(message + 10); + interval = GET_BE_U_2(message + 6); + seqno = GET_BE_U_2(message + 8); + metric = GET_BE_U_2(message + 10); ND_PRINT("%s%s%s %s metric %u seqno %u interval %s", - (EXTRACT_U_1(message + 3) & 0x80) ? "/prefix": "", - (EXTRACT_U_1(message + 3) & 0x40) ? "/id" : "", - (EXTRACT_U_1(message + 3) & 0x3f) ? "/unknown" : "", + (GET_U_1(message + 3) & 0x80) ? "/prefix": "", + (GET_U_1(message + 3) & 0x40) ? "/id" : "", + (GET_U_1(message + 3) & 0x3f) ? "/unknown" : "", ae == 0 ? "any" : format_prefix(ndo, prefix, plen), metric, seqno, format_interval_update(interval)); - if(EXTRACT_U_1(message + 3) & 0x80) { - if(EXTRACT_U_1(message + 2) == 1) + if(GET_U_1(message + 3) & 0x80) { + if(GET_U_1(message + 2) == 1) memcpy(v4_prefix, prefix, 16); else memcpy(v6_prefix, prefix, 16); @@ -546,10 +577,10 @@ babel_print_v2(netdissect_options *ndo, u_char prefix[16], ae, plen; ND_PRINT("\n\tRoute Request "); if(len < 2) goto invalid; - ae = EXTRACT_U_1(message + 2); - plen = EXTRACT_U_1(message + 3) + (EXTRACT_U_1(message + 2) == 1 ? 96 : 0); + ae = GET_U_1(message + 2); + plen = GET_U_1(message + 3) + (GET_U_1(message + 2) == 1 ? 96 : 0); rc = network_prefix(ae, - EXTRACT_U_1(message + 3), 0, + GET_U_1(message + 3), 0, message + 4, NULL, len - 2, prefix); if(rc < 0) goto invalid; ND_PRINT("for %s", @@ -567,17 +598,17 @@ babel_print_v2(netdissect_options *ndo, u_char prefix[16], ae, plen; ND_PRINT("\n\tSeqno Request "); if(len < 14) goto invalid; - ae = EXTRACT_U_1(message + 2); - seqno = EXTRACT_BE_U_2(message + 4); + ae = GET_U_1(message + 2); + seqno = GET_BE_U_2(message + 4); rc = network_prefix(ae, - EXTRACT_U_1(message + 3), 0, + GET_U_1(message + 3), 0, message + 16, NULL, len - 14, prefix); if(rc < 0) goto invalid; - plen = EXTRACT_U_1(message + 3) + (EXTRACT_U_1(message + 2) == 1 ? 96 : 0); + plen = GET_U_1(message + 3) + (GET_U_1(message + 2) == 1 ? 96 : 0); ND_PRINT("(%u hops) for %s seqno %u id %s", - EXTRACT_U_1(message + 6), + GET_U_1(message + 6), ae == 0 ? "invalid AE 0" : format_prefix(ndo, prefix, plen), - seqno, format_id(message + 8)); + seqno, format_id(ndo, message + 8)); } } break; @@ -587,8 +618,9 @@ babel_print_v2(netdissect_options *ndo, else { ND_PRINT("\n\tTS/PC "); if(len < 6) goto invalid; - ND_PRINT("timestamp %u packetcounter %u", EXTRACT_BE_U_4(message + 4), - EXTRACT_BE_U_2(message + 2)); + ND_PRINT("timestamp %u packetcounter %u", + GET_BE_U_4(message + 4), + GET_BE_U_2(message + 2)); } break; case MESSAGE_HMAC : { @@ -598,9 +630,10 @@ babel_print_v2(netdissect_options *ndo, unsigned j; ND_PRINT("\n\tHMAC "); if(len < 18) goto invalid; - ND_PRINT("key-id %u digest-%u ", EXTRACT_BE_U_2(message + 2), len - 2); + ND_PRINT("key-id %u digest-%u ", GET_BE_U_2(message + 2), + len - 2); for (j = 0; j < len - 2; j++) - ND_PRINT("%02X", EXTRACT_U_1(message + j + 4)); + ND_PRINT("%02X", GET_U_1(message + j + 4)); } } break; @@ -616,13 +649,13 @@ babel_print_v2(netdissect_options *ndo, int parsed_len = 10; ND_PRINT("\n\tSS-Update"); if(len < 10) goto invalid; - ae = EXTRACT_U_1(message + 2); - src_plen = EXTRACT_U_1(message + 3); - plen = EXTRACT_U_1(message + 4); - omitted = EXTRACT_U_1(message + 5); - interval = EXTRACT_BE_U_2(message + 6); - seqno = EXTRACT_BE_U_2(message + 8); - metric = EXTRACT_BE_U_2(message + 10); + ae = GET_U_1(message + 2); + src_plen = GET_U_1(message + 3); + plen = GET_U_1(message + 4); + omitted = GET_U_1(message + 5); + interval = GET_BE_U_2(message + 6); + seqno = GET_BE_U_2(message + 8); + metric = GET_BE_U_2(message + 10); rc = network_prefix(ae, plen, omitted, message + 2 + parsed_len, ae == 1 ? v4_prefix : v6_prefix, len - parsed_len, prefix); @@ -657,9 +690,9 @@ babel_print_v2(netdissect_options *ndo, u_char ae, plen, src_plen, prefix[16], src_prefix[16]; ND_PRINT("\n\tSS-Request "); if(len < 3) goto invalid; - ae = EXTRACT_U_1(message + 2); - plen = EXTRACT_U_1(message + 3); - src_plen = EXTRACT_U_1(message + 4); + ae = GET_U_1(message + 2); + plen = GET_U_1(message + 3); + src_plen = GET_U_1(message + 4); rc = network_prefix(ae, plen, 0, message + 2 + parsed_len, NULL, len - parsed_len, prefix); if(rc < 0) goto invalid; @@ -692,11 +725,11 @@ babel_print_v2(netdissect_options *ndo, const u_char *router_id = NULL; ND_PRINT("\n\tSS-MH-Request "); if(len < 14) goto invalid; - ae = EXTRACT_U_1(message + 2); - plen = EXTRACT_U_1(message + 3); - seqno = EXTRACT_BE_U_2(message + 4); - hopc = EXTRACT_U_1(message + 6); - src_plen = EXTRACT_U_1(message + 7); + ae = GET_U_1(message + 2); + plen = GET_U_1(message + 3); + seqno = GET_BE_U_2(message + 4); + hopc = GET_U_1(message + 6); + src_plen = GET_U_1(message + 7); router_id = message + 8; rc = network_prefix(ae, plen, 0, message + 2 + parsed_len, NULL, len - parsed_len, prefix); @@ -713,7 +746,52 @@ babel_print_v2(netdissect_options *ndo, hopc, format_prefix(ndo, prefix, plen)); ND_PRINT("%s) seqno %u id %s", format_prefix(ndo, src_prefix, src_plen), - seqno, format_id(router_id)); + seqno, format_id(ndo, router_id)); + } + } + break; + + case MESSAGE_MAC: { + if (!ndo->ndo_vflag) + ND_PRINT(" mac"); + else { + ND_PRINT("\n\tMAC "); + ND_PRINT("len %u", len); + } + } + break; + + case MESSAGE_PC: { + if (!ndo->ndo_vflag) + ND_PRINT(" pc"); + else { + ND_PRINT("\n\tPC"); + if(len < 4) goto invalid; + ND_PRINT(" value %u", + GET_BE_U_4(message + 2)); + ND_PRINT(" index len %u", len-4); + } + } + break; + + case MESSAGE_CHALLENGE_REQUEST: { + if (!ndo->ndo_vflag) + ND_PRINT(" challenge_request"); + else { + ND_PRINT("\n\tChallenge Request"); + if(len > 192) goto invalid; + ND_PRINT(" len %u", len); + } + } + break; + + case MESSAGE_CHALLENGE_REPLY: { + if (!ndo->ndo_vflag) + ND_PRINT(" challenge_reply"); + else { + ND_PRINT("\n\tChallenge Reply"); + if (len > 192) goto invalid; + ND_PRINT(" len %u", len); } } break; @@ -726,13 +804,58 @@ babel_print_v2(netdissect_options *ndo, } i += len + 2; } + + return 0; /* OK */ + +trunc: + return -1; /* packet truncated by capture process */ + +invalid: + return -2; /* packet is invalid */ +} + +static void +babel_print_v2(netdissect_options *ndo, + const u_char *cp, u_int length) +{ + u_short bodylen; + int ret; + + ND_TCHECK_4(cp); + if (length < 4) + goto invalid; + bodylen = GET_BE_U_2(cp + 2); + ND_PRINT(" (%u)", bodylen); + length -= 4; + cp += 4; + + /* Process the TLVs in the body */ + if (length < bodylen) + goto invalid; + ret = babel_print_v2_tlvs(ndo, cp, bodylen, length); + if (ret == -1) + goto trunc; + if (ret == -2) + goto invalid; + length -= bodylen; + cp += bodylen; + + /* If there's a trailer, process the TLVs in the trailer */ + if (length != 0) { + if(ndo->ndo_vflag) ND_PRINT("\n\t----"); + else ND_PRINT(" |"); + ret = babel_print_v2_tlvs(ndo, cp, length, length); + if (ret == -1) + goto trunc; + if (ret == -2) + goto invalid; + } return; trunc: - ND_PRINT(" %s", tstr); + nd_print_trunc(ndo); return; invalid: - ND_PRINT("%s", istr); - return; + nd_print_invalid(ndo); }