source: rtems-libbsd/freebsd/contrib/tcpdump/print-hncp.c @ 18fa92c

55-freebsd-126-freebsd-12
Last change on this file since 18fa92c was 18fa92c, checked in by Sebastian Huber <sebastian.huber@…>, on 08/20/18 at 13:53:03

Update to FreeBSD head 2018-02-01

Git mirror commit d079ae0442af8fa3cfd6d7ede190d04e64a2c0d4.

Update #3472.

  • Property mode set to 100644
File size: 26.4 KB
Line 
1#include <machine/rtems-bsd-user-space.h>
2
3#ifdef __rtems__
4#include <machine/rtems-bsd-program.h>
5#include "rtems-bsd-tcpdump-namespace.h"
6#endif /* __rtems__ */
7/*
8 * Copyright (c) 2016 Antonin Décimo, Jean-Raphaël Gaglione
9 *
10 * Redistribution and use in source and binary forms, with or without
11 * modification, are permitted provided that the following conditions
12 * are met:
13 * 1. Redistributions of source code must retain the above copyright
14 *    notice, this list of conditions and the following disclaimer.
15 * 2. Redistributions in binary form must reproduce the above copyright
16 *    notice, this list of conditions and the following disclaimer in the
17 *    documentation and/or other materials provided with the distribution.
18 * 3. Neither the name of the project nor the names of its contributors
19 *    may be used to endorse or promote products derived from this software
20 *    without specific prior written permission.
21 *
22 * THIS SOFTWARE IS PROVIDED BY THE PROJECT AND CONTRIBUTORS ``AS IS'' AND
23 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
24 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
25 * ARE DISCLAIMED.  IN NO EVENT SHALL THE PROJECT OR CONTRIBUTORS BE LIABLE
26 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
27 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
28 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
29 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
30 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
31 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
32 * SUCH DAMAGE.
33 */
34
35/* \summary: Home Networking Control Protocol (HNCP) printer */
36
37#ifdef HAVE_CONFIG_H
38#include "config.h"
39#endif
40
41#include <netdissect-stdinc.h>
42
43#include <stdlib.h>
44#include <string.h>
45
46#include "netdissect.h"
47#include "addrtoname.h"
48#include "extract.h"
49
50static void
51hncp_print_rec(netdissect_options *ndo,
52               const u_char *cp, u_int length, int indent);
53
54void
55hncp_print(netdissect_options *ndo,
56           const u_char *cp, u_int length)
57{
58    ND_PRINT((ndo, "hncp (%d)", length));
59    hncp_print_rec(ndo, cp, length, 1);
60}
61
62/* RFC7787 */
63#define DNCP_REQUEST_NETWORK_STATE  1
64#define DNCP_REQUEST_NODE_STATE     2
65#define DNCP_NODE_ENDPOINT          3
66#define DNCP_NETWORK_STATE          4
67#define DNCP_NODE_STATE             5
68#define DNCP_PEER                   8
69#define DNCP_KEEP_ALIVE_INTERVAL    9
70#define DNCP_TRUST_VERDICT         10
71
72/* RFC7788 */
73#define HNCP_HNCP_VERSION          32
74#define HNCP_EXTERNAL_CONNECTION   33
75#define HNCP_DELEGATED_PREFIX      34
76#define HNCP_PREFIX_POLICY         43
77#define HNCP_DHCPV4_DATA           37
78#define HNCP_DHCPV6_DATA           38
79#define HNCP_ASSIGNED_PREFIX       35
80#define HNCP_NODE_ADDRESS          36
81#define HNCP_DNS_DELEGATED_ZONE    39
82#define HNCP_DOMAIN_NAME           40
83#define HNCP_NODE_NAME             41
84#define HNCP_MANAGED_PSK           42
85
86/* See type_mask in hncp_print_rec below */
87#define RANGE_DNCP_RESERVED    0x10000
88#define RANGE_HNCP_UNASSIGNED  0x10001
89#define RANGE_DNCP_PRIVATE_USE 0x10002
90#define RANGE_DNCP_FUTURE_USE  0x10003
91
92static const struct tok type_values[] = {
93    { DNCP_REQUEST_NETWORK_STATE, "Request network state" },
94    { DNCP_REQUEST_NODE_STATE,    "Request node state" },
95    { DNCP_NODE_ENDPOINT,         "Node endpoint" },
96    { DNCP_NETWORK_STATE,         "Network state" },
97    { DNCP_NODE_STATE,            "Node state" },
98    { DNCP_PEER,                  "Peer" },
99    { DNCP_KEEP_ALIVE_INTERVAL,   "Keep-alive interval" },
100    { DNCP_TRUST_VERDICT,         "Trust-Verdict" },
101
102    { HNCP_HNCP_VERSION,        "HNCP-Version" },
103    { HNCP_EXTERNAL_CONNECTION, "External-Connection" },
104    { HNCP_DELEGATED_PREFIX,    "Delegated-Prefix" },
105    { HNCP_PREFIX_POLICY,       "Prefix-Policy" },
106    { HNCP_DHCPV4_DATA,         "DHCPv4-Data" },
107    { HNCP_DHCPV6_DATA,         "DHCPv6-Data" },
108    { HNCP_ASSIGNED_PREFIX,     "Assigned-Prefix" },
109    { HNCP_NODE_ADDRESS,        "Node-Address" },
110    { HNCP_DNS_DELEGATED_ZONE,  "DNS-Delegated-Zone" },
111    { HNCP_DOMAIN_NAME,         "Domain-Name" },
112    { HNCP_NODE_NAME,           "Node-Name" },
113    { HNCP_MANAGED_PSK,         "Managed-PSK" },
114
115    { RANGE_DNCP_RESERVED,    "Reserved" },
116    { RANGE_HNCP_UNASSIGNED,  "Unassigned" },
117    { RANGE_DNCP_PRIVATE_USE, "Private use" },
118    { RANGE_DNCP_FUTURE_USE,  "Future use" },
119
120    { 0, NULL}
121};
122
123#define DH4OPT_DNS_SERVERS 6     /* RFC2132 */
124#define DH4OPT_NTP_SERVERS 42    /* RFC2132 */
125#define DH4OPT_DOMAIN_SEARCH 119 /* RFC3397 */
126
127static const struct tok dh4opt_str[] = {
128    { DH4OPT_DNS_SERVERS, "DNS-server" },
129    { DH4OPT_NTP_SERVERS, "NTP-server"},
130    { DH4OPT_DOMAIN_SEARCH, "DNS-search" },
131    { 0, NULL }
132};
133
134#define DH6OPT_DNS_SERVERS 23   /* RFC3646 */
135#define DH6OPT_DOMAIN_LIST 24   /* RFC3646 */
136#define DH6OPT_SNTP_SERVERS 31  /* RFC4075 */
137
138static const struct tok dh6opt_str[] = {
139    { DH6OPT_DNS_SERVERS,  "DNS-server" },
140    { DH6OPT_DOMAIN_LIST,  "DNS-search-list" },
141    { DH6OPT_SNTP_SERVERS, "SNTP-servers" },
142    { 0, NULL }
143};
144
145/*
146 * For IPv4-mapped IPv6 addresses, length of the prefix that precedes
147 * the 4 bytes of IPv4 address at the end of the IPv6 address.
148 */
149#define IPV4_MAPPED_HEADING_LEN    12
150
151/*
152 * Is an IPv6 address an IPv4-mapped address?
153 */
154static inline int
155is_ipv4_mapped_address(const u_char *addr)
156{
157    /* The value of the prefix */
158    static const u_char ipv4_mapped_heading[IPV4_MAPPED_HEADING_LEN] =
159        { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0xFF, 0xFF };
160
161    return memcmp(addr, ipv4_mapped_heading, IPV4_MAPPED_HEADING_LEN) == 0;
162}
163
164static const char *
165format_nid(const u_char *data)
166{
167    static char buf[4][11+5];
168    static int i = 0;
169    i = (i + 1) % 4;
170    snprintf(buf[i], 16, "%02x:%02x:%02x:%02x",
171             data[0], data[1], data[2], data[3]);
172    return buf[i];
173}
174
175static const char *
176format_256(const u_char *data)
177{
178    static char buf[4][64+5];
179    static int i = 0;
180    i = (i + 1) % 4;
181    snprintf(buf[i], 28, "%016" PRIx64 "%016" PRIx64 "%016" PRIx64 "%016" PRIx64,
182         EXTRACT_64BITS(data),
183         EXTRACT_64BITS(data + 8),
184         EXTRACT_64BITS(data + 16),
185         EXTRACT_64BITS(data + 24)
186    );
187    return buf[i];
188}
189
190static const char *
191format_interval(const uint32_t n)
192{
193    static char buf[4][sizeof("0000000.000s")];
194    static int i = 0;
195    i = (i + 1) % 4;
196    snprintf(buf[i], sizeof(buf[i]), "%u.%03us", n / 1000, n % 1000);
197    return buf[i];
198}
199
200static const char *
201format_ip6addr(netdissect_options *ndo, const u_char *cp)
202{
203    if (is_ipv4_mapped_address(cp))
204        return ipaddr_string(ndo, cp + IPV4_MAPPED_HEADING_LEN);
205    else
206        return ip6addr_string(ndo, cp);
207}
208
209static int
210print_prefix(netdissect_options *ndo, const u_char *prefix, u_int max_length)
211{
212    int plenbytes;
213    char buf[sizeof("xxxx:xxxx:xxxx:xxxx:xxxx:xxxx:xxxx:xxxx::/128")];
214
215    if (prefix[0] >= 96 && max_length >= IPV4_MAPPED_HEADING_LEN + 1 &&
216        is_ipv4_mapped_address(&prefix[1])) {
217        struct in_addr addr;
218        u_int plen;
219
220        plen = prefix[0]-96;
221        if (32 < plen)
222            return -1;
223        max_length -= 1;
224
225        memset(&addr, 0, sizeof(addr));
226        plenbytes = (plen + 7) / 8;
227        if (max_length < (u_int)plenbytes + IPV4_MAPPED_HEADING_LEN)
228            return -3;
229        memcpy(&addr, &prefix[1 + IPV4_MAPPED_HEADING_LEN], plenbytes);
230        if (plen % 8) {
231                ((u_char *)&addr)[plenbytes - 1] &=
232                        ((0xff00 >> (plen % 8)) & 0xff);
233        }
234        snprintf(buf, sizeof(buf), "%s/%d", ipaddr_string(ndo, &addr), plen);
235        plenbytes += 1 + IPV4_MAPPED_HEADING_LEN;
236    } else {
237        plenbytes = decode_prefix6(ndo, prefix, max_length, buf, sizeof(buf));
238    }
239
240    ND_PRINT((ndo, "%s", buf));
241    return plenbytes;
242}
243
244static int
245print_dns_label(netdissect_options *ndo,
246                const u_char *cp, u_int max_length, int print)
247{
248    u_int length = 0;
249    while (length < max_length) {
250        u_int lab_length = cp[length++];
251        if (lab_length == 0)
252            return (int)length;
253        if (length > 1 && print)
254            safeputchar(ndo, '.');
255        if (length+lab_length > max_length) {
256            if (print)
257                safeputs(ndo, cp+length, max_length-length);
258            break;
259        }
260        if (print)
261            safeputs(ndo, cp+length, lab_length);
262        length += lab_length;
263    }
264    if (print)
265        ND_PRINT((ndo, "[|DNS]"));
266    return -1;
267}
268
269static int
270dhcpv4_print(netdissect_options *ndo,
271             const u_char *cp, u_int length, int indent)
272{
273    u_int i, t;
274    const u_char *tlv, *value;
275    uint8_t type, optlen;
276
277    i = 0;
278    while (i < length) {
279        if (i + 2 > length)
280            return -1;
281        tlv = cp + i;
282        type = (uint8_t)tlv[0];
283        optlen = (uint8_t)tlv[1];
284        value = tlv + 2;
285
286        ND_PRINT((ndo, "\n"));
287        for (t = indent; t > 0; t--)
288            ND_PRINT((ndo, "\t"));
289
290        ND_PRINT((ndo, "%s", tok2str(dh4opt_str, "Unknown", type)));
291        ND_PRINT((ndo," (%u)", optlen + 2 ));
292        if (i + 2 + optlen > length)
293            return -1;
294
295        switch (type) {
296        case DH4OPT_DNS_SERVERS:
297        case DH4OPT_NTP_SERVERS: {
298            if (optlen < 4 || optlen % 4 != 0) {
299                return -1;
300            }
301            for (t = 0; t < optlen; t += 4)
302                ND_PRINT((ndo, " %s", ipaddr_string(ndo, value + t)));
303        }
304            break;
305        case DH4OPT_DOMAIN_SEARCH: {
306            const u_char *tp = value;
307            while (tp < value + optlen) {
308                ND_PRINT((ndo, " "));
309                if ((tp = ns_nprint(ndo, tp, value + optlen)) == NULL)
310                    return -1;
311            }
312        }
313            break;
314        }
315
316        i += 2 + optlen;
317    }
318    return 0;
319}
320
321static int
322dhcpv6_print(netdissect_options *ndo,
323             const u_char *cp, u_int length, int indent)
324{
325    u_int i, t;
326    const u_char *tlv, *value;
327    uint16_t type, optlen;
328
329    i = 0;
330    while (i < length) {
331        if (i + 4 > length)
332            return -1;
333        tlv = cp + i;
334        type = EXTRACT_16BITS(tlv);
335        optlen = EXTRACT_16BITS(tlv + 2);
336        value = tlv + 4;
337
338        ND_PRINT((ndo, "\n"));
339        for (t = indent; t > 0; t--)
340            ND_PRINT((ndo, "\t"));
341
342        ND_PRINT((ndo, "%s", tok2str(dh6opt_str, "Unknown", type)));
343        ND_PRINT((ndo," (%u)", optlen + 4 ));
344        if (i + 4 + optlen > length)
345            return -1;
346
347        switch (type) {
348            case DH6OPT_DNS_SERVERS:
349            case DH6OPT_SNTP_SERVERS: {
350                if (optlen % 16 != 0) {
351                    ND_PRINT((ndo, " %s", istr));
352                    return -1;
353                }
354                for (t = 0; t < optlen; t += 16)
355                    ND_PRINT((ndo, " %s", ip6addr_string(ndo, value + t)));
356            }
357                break;
358            case DH6OPT_DOMAIN_LIST: {
359                const u_char *tp = value;
360                while (tp < value + optlen) {
361                    ND_PRINT((ndo, " "));
362                    if ((tp = ns_nprint(ndo, tp, value + optlen)) == NULL)
363                        return -1;
364                }
365            }
366                break;
367        }
368
369        i += 4 + optlen;
370    }
371    return 0;
372}
373
374/* Determine in-line mode */
375static int
376is_in_line(netdissect_options *ndo, int indent)
377{
378    return indent - 1 >= ndo->ndo_vflag && ndo->ndo_vflag < 3;
379}
380
381static void
382print_type_in_line(netdissect_options *ndo,
383                   uint32_t type, int count, int indent, int *first_one)
384{
385    if (count > 0) {
386        if (*first_one) {
387            *first_one = 0;
388            if (indent > 1) {
389                u_int t;
390                ND_PRINT((ndo, "\n"));
391                for (t = indent; t > 0; t--)
392                    ND_PRINT((ndo, "\t"));
393            } else {
394                ND_PRINT((ndo, " "));
395            }
396        } else {
397            ND_PRINT((ndo, ", "));
398        }
399        ND_PRINT((ndo, "%s", tok2str(type_values, "Easter Egg", type)));
400        if (count > 1)
401            ND_PRINT((ndo, " (x%d)", count));
402    }
403}
404
405void
406hncp_print_rec(netdissect_options *ndo,
407               const u_char *cp, u_int length, int indent)
408{
409    const int in_line = is_in_line(ndo, indent);
410    int first_one = 1;
411
412    u_int i, t;
413
414    uint32_t last_type_mask = 0xffffffffU;
415    int last_type_count = -1;
416
417    const u_char *tlv, *value;
418    uint16_t type, bodylen;
419    uint32_t type_mask;
420
421    i = 0;
422    while (i < length) {
423        tlv = cp + i;
424
425        if (!in_line) {
426            ND_PRINT((ndo, "\n"));
427            for (t = indent; t > 0; t--)
428                ND_PRINT((ndo, "\t"));
429        }
430
431        ND_TCHECK2(*tlv, 4);
432        if (i + 4 > length)
433            goto invalid;
434
435        type = EXTRACT_16BITS(tlv);
436        bodylen = EXTRACT_16BITS(tlv + 2);
437        value = tlv + 4;
438        ND_TCHECK2(*value, bodylen);
439        if (i + bodylen + 4 > length)
440            goto invalid;
441
442        type_mask =
443            (type == 0)                   ? RANGE_DNCP_RESERVED:
444            (44 <= type && type <= 511)   ? RANGE_HNCP_UNASSIGNED:
445            (768 <= type && type <= 1023) ? RANGE_DNCP_PRIVATE_USE:
446                                            RANGE_DNCP_FUTURE_USE;
447        if (type == 6 || type == 7)
448            type_mask = RANGE_DNCP_FUTURE_USE;
449
450        /* defined types */
451        {
452            t = 0;
453            while (1) {
454                u_int key = type_values[t++].v;
455                if (key > 0xffff)
456                    break;
457                if (key == type) {
458                    type_mask = type;
459                    break;
460                }
461            }
462        }
463
464        if (in_line) {
465            if (last_type_mask == type_mask) {
466                last_type_count++;
467            } else {
468                print_type_in_line(ndo, last_type_mask, last_type_count, indent, &first_one);
469                last_type_mask = type_mask;
470                last_type_count = 1;
471            }
472
473            goto skip_multiline;
474        }
475
476        ND_PRINT((ndo,"%s", tok2str(type_values, "Easter Egg (42)", type_mask) ));
477        if (type_mask > 0xffff)
478            ND_PRINT((ndo,": type=%u", type ));
479        ND_PRINT((ndo," (%u)", bodylen + 4 ));
480
481        switch (type_mask) {
482
483        case DNCP_REQUEST_NETWORK_STATE: {
484            if (bodylen != 0)
485                ND_PRINT((ndo, " %s", istr));
486        }
487            break;
488
489        case DNCP_REQUEST_NODE_STATE: {
490            const char *node_identifier;
491            if (bodylen != 4) {
492                ND_PRINT((ndo, " %s", istr));
493                break;
494            }
495            node_identifier = format_nid(value);
496            ND_PRINT((ndo, " NID: %s", node_identifier));
497        }
498            break;
499
500        case DNCP_NODE_ENDPOINT: {
501            const char *node_identifier;
502            uint32_t endpoint_identifier;
503            if (bodylen != 8) {
504                ND_PRINT((ndo, " %s", istr));
505                break;
506            }
507            node_identifier = format_nid(value);
508            endpoint_identifier = EXTRACT_32BITS(value + 4);
509            ND_PRINT((ndo, " NID: %s EPID: %08x",
510                node_identifier,
511                endpoint_identifier
512            ));
513        }
514            break;
515
516        case DNCP_NETWORK_STATE: {
517            uint64_t hash;
518            if (bodylen != 8) {
519                ND_PRINT((ndo, " %s", istr));
520                break;
521            }
522            hash = EXTRACT_64BITS(value);
523            ND_PRINT((ndo, " hash: %016" PRIx64, hash));
524        }
525            break;
526
527        case DNCP_NODE_STATE: {
528            const char *node_identifier, *interval;
529            uint32_t sequence_number;
530            uint64_t hash;
531            if (bodylen < 20) {
532                ND_PRINT((ndo, " %s", istr));
533                break;
534            }
535            node_identifier = format_nid(value);
536            sequence_number = EXTRACT_32BITS(value + 4);
537            interval = format_interval(EXTRACT_32BITS(value + 8));
538            hash = EXTRACT_64BITS(value + 12);
539            ND_PRINT((ndo, " NID: %s seqno: %u %s hash: %016" PRIx64,
540                node_identifier,
541                sequence_number,
542                interval,
543                hash
544            ));
545            hncp_print_rec(ndo, value+20, bodylen-20, indent+1);
546        }
547            break;
548
549        case DNCP_PEER: {
550            const char *peer_node_identifier;
551            uint32_t peer_endpoint_identifier, endpoint_identifier;
552            if (bodylen != 12) {
553                ND_PRINT((ndo, " %s", istr));
554                break;
555            }
556            peer_node_identifier = format_nid(value);
557            peer_endpoint_identifier = EXTRACT_32BITS(value + 4);
558            endpoint_identifier = EXTRACT_32BITS(value + 8);
559            ND_PRINT((ndo, " Peer-NID: %s Peer-EPID: %08x Local-EPID: %08x",
560                peer_node_identifier,
561                peer_endpoint_identifier,
562                endpoint_identifier
563            ));
564        }
565            break;
566
567        case DNCP_KEEP_ALIVE_INTERVAL: {
568            uint32_t endpoint_identifier;
569            const char *interval;
570            if (bodylen < 8) {
571                ND_PRINT((ndo, " %s", istr));
572                break;
573            }
574            endpoint_identifier = EXTRACT_32BITS(value);
575            interval = format_interval(EXTRACT_32BITS(value + 4));
576            ND_PRINT((ndo, " EPID: %08x Interval: %s",
577                endpoint_identifier,
578                interval
579            ));
580        }
581            break;
582
583        case DNCP_TRUST_VERDICT: {
584            if (bodylen <= 36) {
585                ND_PRINT((ndo, " %s", istr));
586                break;
587            }
588            ND_PRINT((ndo, " Verdict: %u Fingerprint: %s Common Name: ",
589                *value,
590                format_256(value + 4)));
591            safeputs(ndo, value + 36, bodylen - 36);
592        }
593            break;
594
595        case HNCP_HNCP_VERSION: {
596            uint16_t capabilities;
597            uint8_t M, P, H, L;
598            if (bodylen < 5) {
599                ND_PRINT((ndo, " %s", istr));
600                break;
601            }
602            capabilities = EXTRACT_16BITS(value + 2);
603            M = (uint8_t)((capabilities >> 12) & 0xf);
604            P = (uint8_t)((capabilities >> 8) & 0xf);
605            H = (uint8_t)((capabilities >> 4) & 0xf);
606            L = (uint8_t)(capabilities & 0xf);
607            ND_PRINT((ndo, " M: %u P: %u H: %u L: %u User-agent: ",
608                M, P, H, L
609            ));
610            safeputs(ndo, value + 4, bodylen - 4);
611        }
612            break;
613
614        case HNCP_EXTERNAL_CONNECTION: {
615            /* Container TLV */
616            hncp_print_rec(ndo, value, bodylen, indent+1);
617        }
618            break;
619
620        case HNCP_DELEGATED_PREFIX: {
621            int l;
622            if (bodylen < 9 || bodylen < 9 + (value[8] + 7) / 8) {
623                ND_PRINT((ndo, " %s", istr));
624                break;
625            }
626            ND_PRINT((ndo, " VLSO: %s PLSO: %s Prefix: ",
627                format_interval(EXTRACT_32BITS(value)),
628                format_interval(EXTRACT_32BITS(value + 4))
629            ));
630            l = print_prefix(ndo, value + 8, bodylen - 8);
631            if (l == -1) {
632                ND_PRINT((ndo, "(length is invalid)"));
633                break;
634            }
635            if (l < 0) {
636                /*
637                 * We've already checked that we've captured the
638                 * entire TLV, based on its length, so this will
639                 * either be -1, meaning "the prefix length is
640                 * greater than the longest possible address of
641                 * that type" (i.e., > 32 for IPv4 or > 128 for
642                 * IPv6", or -3, meaning "the prefix runs past
643                 * the end of the TLV".
644                 */
645                ND_PRINT((ndo, " %s", istr));
646                break;
647            }
648            l += 8 + (-l & 3);
649
650            if (bodylen >= l)
651                hncp_print_rec(ndo, value + l, bodylen - l, indent+1);
652        }
653            break;
654
655        case HNCP_PREFIX_POLICY: {
656            uint8_t policy;
657            int l;
658            if (bodylen < 1) {
659                ND_PRINT((ndo, " %s", istr));
660                break;
661            }
662            policy = value[0];
663            ND_PRINT((ndo, " type: "));
664            if (policy == 0) {
665                if (bodylen != 1) {
666                    ND_PRINT((ndo, " %s", istr));
667                    break;
668                }
669                ND_PRINT((ndo, "Internet connectivity"));
670            } else if (policy >= 1 && policy <= 128) {
671                ND_PRINT((ndo, "Dest-Prefix: "));
672                l = print_prefix(ndo, value, bodylen);
673                if (l == -1) {
674                    ND_PRINT((ndo, "(length is invalid)"));
675                    break;
676                }
677                if (l < 0) {
678                    /*
679                     * We've already checked that we've captured the
680                     * entire TLV, based on its length, so this will
681                     * either be -1, meaning "the prefix length is
682                     * greater than the longest possible address of
683                     * that type" (i.e., > 32 for IPv4 or > 128 for
684                     * IPv6", or -3, meaning "the prefix runs past
685                     * the end of the TLV".
686                     */
687                    ND_PRINT((ndo, " %s", istr));
688                    break;
689                }
690            } else if (policy == 129) {
691                ND_PRINT((ndo, "DNS domain: "));
692                print_dns_label(ndo, value+1, bodylen-1, 1);
693            } else if (policy == 130) {
694                ND_PRINT((ndo, "Opaque UTF-8: "));
695                safeputs(ndo, value + 1, bodylen - 1);
696            } else if (policy == 131) {
697                if (bodylen != 1) {
698                    ND_PRINT((ndo, " %s", istr));
699                    break;
700                }
701                ND_PRINT((ndo, "Restrictive assignment"));
702            } else if (policy >= 132) {
703                ND_PRINT((ndo, "Unknown (%u)", policy)); /* Reserved for future additions */
704            }
705        }
706            break;
707
708        case HNCP_DHCPV4_DATA: {
709            if (bodylen == 0) {
710                ND_PRINT((ndo, " %s", istr));
711                break;
712            }
713            if (dhcpv4_print(ndo, value, bodylen, indent+1) != 0)
714                goto invalid;
715        }
716            break;
717
718        case HNCP_DHCPV6_DATA: {
719            if (bodylen == 0) {
720                ND_PRINT((ndo, " %s", istr));
721                break;
722            }
723            if (dhcpv6_print(ndo, value, bodylen, indent+1) != 0) {
724                ND_PRINT((ndo, " %s", istr));
725                break;
726            }
727        }
728            break;
729
730        case HNCP_ASSIGNED_PREFIX: {
731            uint8_t prty;
732            int l;
733            if (bodylen < 6 || bodylen < 6 + (value[5] + 7) / 8) {
734                ND_PRINT((ndo, " %s", istr));
735                break;
736            }
737            prty = (uint8_t)(value[4] & 0xf);
738            ND_PRINT((ndo, " EPID: %08x Prty: %u",
739                EXTRACT_32BITS(value),
740                prty
741            ));
742            ND_PRINT((ndo, " Prefix: "));
743            if ((l = print_prefix(ndo, value + 5, bodylen - 5)) < 0) {
744                ND_PRINT((ndo, " %s", istr));
745                break;
746            }
747            l += 5;
748            l += -l & 3;
749
750            if (bodylen >= l)
751                hncp_print_rec(ndo, value + l, bodylen - l, indent+1);
752        }
753            break;
754
755        case HNCP_NODE_ADDRESS: {
756            uint32_t endpoint_identifier;
757            const char *ip_address;
758            if (bodylen < 20) {
759                ND_PRINT((ndo, " %s", istr));
760                break;
761            }
762            endpoint_identifier = EXTRACT_32BITS(value);
763            ip_address = format_ip6addr(ndo, value + 4);
764            ND_PRINT((ndo, " EPID: %08x IP Address: %s",
765                endpoint_identifier,
766                ip_address
767            ));
768
769            hncp_print_rec(ndo, value + 20, bodylen - 20, indent+1);
770        }
771            break;
772
773        case HNCP_DNS_DELEGATED_ZONE: {
774            const char *ip_address;
775            int len;
776            if (bodylen < 17) {
777                ND_PRINT((ndo, " %s", istr));
778                break;
779            }
780            ip_address = format_ip6addr(ndo, value);
781            ND_PRINT((ndo, " IP-Address: %s %c%c%c ",
782                ip_address,
783                (value[16] & 4) ? 'l' : '-',
784                (value[16] & 2) ? 'b' : '-',
785                (value[16] & 1) ? 's' : '-'
786            ));
787            len = print_dns_label(ndo, value+17, bodylen-17, 1);
788            if (len < 0) {
789                ND_PRINT((ndo, " %s", istr));
790                break;
791            }
792            len += 17;
793            len += -len & 3;
794            if (bodylen >= len)
795                hncp_print_rec(ndo, value+len, bodylen-len, indent+1);
796        }
797            break;
798
799        case HNCP_DOMAIN_NAME: {
800            if (bodylen == 0) {
801                ND_PRINT((ndo, " %s", istr));
802                break;
803            }
804            ND_PRINT((ndo, " Domain: "));
805            print_dns_label(ndo, value, bodylen, 1);
806        }
807            break;
808
809        case HNCP_NODE_NAME: {
810            u_int l;
811            if (bodylen < 17) {
812                ND_PRINT((ndo, " %s", istr));
813                break;
814            }
815            l = value[16];
816            if (bodylen < 17 + l) {
817                ND_PRINT((ndo, " %s", istr));
818                break;
819            }
820            ND_PRINT((ndo, " IP-Address: %s Name: ",
821                format_ip6addr(ndo, value)
822            ));
823            if (l < 64) {
824                safeputchar(ndo, '"');
825                safeputs(ndo, value + 17, l);
826                safeputchar(ndo, '"');
827            } else {
828                ND_PRINT((ndo, "%s", istr));
829            }
830            l += 17;
831            l += -l & 3;
832            if (bodylen >= l)
833                hncp_print_rec(ndo, value + l, bodylen - l, indent+1);
834        }
835            break;
836
837        case HNCP_MANAGED_PSK: {
838            if (bodylen < 32) {
839                ND_PRINT((ndo, " %s", istr));
840                break;
841            }
842            ND_PRINT((ndo, " PSK: %s", format_256(value)));
843            hncp_print_rec(ndo, value + 32, bodylen - 32, indent+1);
844        }
845            break;
846
847        case RANGE_DNCP_RESERVED:
848        case RANGE_HNCP_UNASSIGNED:
849        case RANGE_DNCP_PRIVATE_USE:
850        case RANGE_DNCP_FUTURE_USE:
851            break;
852
853        }
854    skip_multiline:
855
856        i += 4 + bodylen + (-bodylen & 3);
857    }
858    print_type_in_line(ndo, last_type_mask, last_type_count, indent, &first_one);
859
860    return;
861
862 trunc:
863    ND_PRINT((ndo, "%s", "[|hncp]"));
864    return;
865
866 invalid:
867    ND_PRINT((ndo, "%s", istr));
868    return;
869}
870#ifdef __rtems__
871#include "rtems-bsd-tcpdump-print-hncp-data.h"
872#endif /* __rtems__ */
Note: See TracBrowser for help on using the repository browser.