source: rtems-libbsd/freebsd/contrib/tcpdump/print-hncp.c @ 24631e2

5
Last change on this file since 24631e2 was 24631e2, checked in by Sebastian Huber <sebastian.huber@…>, on 03/11/19 at 08:33:28

tcpdump: Move static variables to special section

This fixes some issues if tcpdump is invoked a second time.

  • Property mode set to 100644
File size: 26.7 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#ifdef __rtems__
169        __section(".rtemsrwset.bsd_prog_tcpdump.content")
170#endif /* __rtems__ */
171    static int i = 0;
172    i = (i + 1) % 4;
173    snprintf(buf[i], 16, "%02x:%02x:%02x:%02x",
174             data[0], data[1], data[2], data[3]);
175    return buf[i];
176}
177
178static const char *
179format_256(const u_char *data)
180{
181    static char buf[4][64+5];
182#ifdef __rtems__
183        __section(".rtemsrwset.bsd_prog_tcpdump.content")
184#endif /* __rtems__ */
185    static int i = 0;
186    i = (i + 1) % 4;
187    snprintf(buf[i], 28, "%016" PRIx64 "%016" PRIx64 "%016" PRIx64 "%016" PRIx64,
188         EXTRACT_64BITS(data),
189         EXTRACT_64BITS(data + 8),
190         EXTRACT_64BITS(data + 16),
191         EXTRACT_64BITS(data + 24)
192    );
193    return buf[i];
194}
195
196static const char *
197format_interval(const uint32_t n)
198{
199    static char buf[4][sizeof("0000000.000s")];
200#ifdef __rtems__
201        __section(".rtemsrwset.bsd_prog_tcpdump.content")
202#endif /* __rtems__ */
203    static int i = 0;
204    i = (i + 1) % 4;
205    snprintf(buf[i], sizeof(buf[i]), "%u.%03us", n / 1000, n % 1000);
206    return buf[i];
207}
208
209static const char *
210format_ip6addr(netdissect_options *ndo, const u_char *cp)
211{
212    if (is_ipv4_mapped_address(cp))
213        return ipaddr_string(ndo, cp + IPV4_MAPPED_HEADING_LEN);
214    else
215        return ip6addr_string(ndo, cp);
216}
217
218static int
219print_prefix(netdissect_options *ndo, const u_char *prefix, u_int max_length)
220{
221    int plenbytes;
222    char buf[sizeof("xxxx:xxxx:xxxx:xxxx:xxxx:xxxx:xxxx:xxxx::/128")];
223
224    if (prefix[0] >= 96 && max_length >= IPV4_MAPPED_HEADING_LEN + 1 &&
225        is_ipv4_mapped_address(&prefix[1])) {
226        struct in_addr addr;
227        u_int plen;
228
229        plen = prefix[0]-96;
230        if (32 < plen)
231            return -1;
232        max_length -= 1;
233
234        memset(&addr, 0, sizeof(addr));
235        plenbytes = (plen + 7) / 8;
236        if (max_length < (u_int)plenbytes + IPV4_MAPPED_HEADING_LEN)
237            return -3;
238        memcpy(&addr, &prefix[1 + IPV4_MAPPED_HEADING_LEN], plenbytes);
239        if (plen % 8) {
240                ((u_char *)&addr)[plenbytes - 1] &=
241                        ((0xff00 >> (plen % 8)) & 0xff);
242        }
243        snprintf(buf, sizeof(buf), "%s/%d", ipaddr_string(ndo, &addr), plen);
244        plenbytes += 1 + IPV4_MAPPED_HEADING_LEN;
245    } else {
246        plenbytes = decode_prefix6(ndo, prefix, max_length, buf, sizeof(buf));
247    }
248
249    ND_PRINT((ndo, "%s", buf));
250    return plenbytes;
251}
252
253static int
254print_dns_label(netdissect_options *ndo,
255                const u_char *cp, u_int max_length, int print)
256{
257    u_int length = 0;
258    while (length < max_length) {
259        u_int lab_length = cp[length++];
260        if (lab_length == 0)
261            return (int)length;
262        if (length > 1 && print)
263            safeputchar(ndo, '.');
264        if (length+lab_length > max_length) {
265            if (print)
266                safeputs(ndo, cp+length, max_length-length);
267            break;
268        }
269        if (print)
270            safeputs(ndo, cp+length, lab_length);
271        length += lab_length;
272    }
273    if (print)
274        ND_PRINT((ndo, "[|DNS]"));
275    return -1;
276}
277
278static int
279dhcpv4_print(netdissect_options *ndo,
280             const u_char *cp, u_int length, int indent)
281{
282    u_int i, t;
283    const u_char *tlv, *value;
284    uint8_t type, optlen;
285
286    i = 0;
287    while (i < length) {
288        if (i + 2 > length)
289            return -1;
290        tlv = cp + i;
291        type = (uint8_t)tlv[0];
292        optlen = (uint8_t)tlv[1];
293        value = tlv + 2;
294
295        ND_PRINT((ndo, "\n"));
296        for (t = indent; t > 0; t--)
297            ND_PRINT((ndo, "\t"));
298
299        ND_PRINT((ndo, "%s", tok2str(dh4opt_str, "Unknown", type)));
300        ND_PRINT((ndo," (%u)", optlen + 2 ));
301        if (i + 2 + optlen > length)
302            return -1;
303
304        switch (type) {
305        case DH4OPT_DNS_SERVERS:
306        case DH4OPT_NTP_SERVERS: {
307            if (optlen < 4 || optlen % 4 != 0) {
308                return -1;
309            }
310            for (t = 0; t < optlen; t += 4)
311                ND_PRINT((ndo, " %s", ipaddr_string(ndo, value + t)));
312        }
313            break;
314        case DH4OPT_DOMAIN_SEARCH: {
315            const u_char *tp = value;
316            while (tp < value + optlen) {
317                ND_PRINT((ndo, " "));
318                if ((tp = ns_nprint(ndo, tp, value + optlen)) == NULL)
319                    return -1;
320            }
321        }
322            break;
323        }
324
325        i += 2 + optlen;
326    }
327    return 0;
328}
329
330static int
331dhcpv6_print(netdissect_options *ndo,
332             const u_char *cp, u_int length, int indent)
333{
334    u_int i, t;
335    const u_char *tlv, *value;
336    uint16_t type, optlen;
337
338    i = 0;
339    while (i < length) {
340        if (i + 4 > length)
341            return -1;
342        tlv = cp + i;
343        type = EXTRACT_16BITS(tlv);
344        optlen = EXTRACT_16BITS(tlv + 2);
345        value = tlv + 4;
346
347        ND_PRINT((ndo, "\n"));
348        for (t = indent; t > 0; t--)
349            ND_PRINT((ndo, "\t"));
350
351        ND_PRINT((ndo, "%s", tok2str(dh6opt_str, "Unknown", type)));
352        ND_PRINT((ndo," (%u)", optlen + 4 ));
353        if (i + 4 + optlen > length)
354            return -1;
355
356        switch (type) {
357            case DH6OPT_DNS_SERVERS:
358            case DH6OPT_SNTP_SERVERS: {
359                if (optlen % 16 != 0) {
360                    ND_PRINT((ndo, " %s", istr));
361                    return -1;
362                }
363                for (t = 0; t < optlen; t += 16)
364                    ND_PRINT((ndo, " %s", ip6addr_string(ndo, value + t)));
365            }
366                break;
367            case DH6OPT_DOMAIN_LIST: {
368                const u_char *tp = value;
369                while (tp < value + optlen) {
370                    ND_PRINT((ndo, " "));
371                    if ((tp = ns_nprint(ndo, tp, value + optlen)) == NULL)
372                        return -1;
373                }
374            }
375                break;
376        }
377
378        i += 4 + optlen;
379    }
380    return 0;
381}
382
383/* Determine in-line mode */
384static int
385is_in_line(netdissect_options *ndo, int indent)
386{
387    return indent - 1 >= ndo->ndo_vflag && ndo->ndo_vflag < 3;
388}
389
390static void
391print_type_in_line(netdissect_options *ndo,
392                   uint32_t type, int count, int indent, int *first_one)
393{
394    if (count > 0) {
395        if (*first_one) {
396            *first_one = 0;
397            if (indent > 1) {
398                u_int t;
399                ND_PRINT((ndo, "\n"));
400                for (t = indent; t > 0; t--)
401                    ND_PRINT((ndo, "\t"));
402            } else {
403                ND_PRINT((ndo, " "));
404            }
405        } else {
406            ND_PRINT((ndo, ", "));
407        }
408        ND_PRINT((ndo, "%s", tok2str(type_values, "Easter Egg", type)));
409        if (count > 1)
410            ND_PRINT((ndo, " (x%d)", count));
411    }
412}
413
414void
415hncp_print_rec(netdissect_options *ndo,
416               const u_char *cp, u_int length, int indent)
417{
418    const int in_line = is_in_line(ndo, indent);
419    int first_one = 1;
420
421    u_int i, t;
422
423    uint32_t last_type_mask = 0xffffffffU;
424    int last_type_count = -1;
425
426    const u_char *tlv, *value;
427    uint16_t type, bodylen;
428    uint32_t type_mask;
429
430    i = 0;
431    while (i < length) {
432        tlv = cp + i;
433
434        if (!in_line) {
435            ND_PRINT((ndo, "\n"));
436            for (t = indent; t > 0; t--)
437                ND_PRINT((ndo, "\t"));
438        }
439
440        ND_TCHECK2(*tlv, 4);
441        if (i + 4 > length)
442            goto invalid;
443
444        type = EXTRACT_16BITS(tlv);
445        bodylen = EXTRACT_16BITS(tlv + 2);
446        value = tlv + 4;
447        ND_TCHECK2(*value, bodylen);
448        if (i + bodylen + 4 > length)
449            goto invalid;
450
451        type_mask =
452            (type == 0)                   ? RANGE_DNCP_RESERVED:
453            (44 <= type && type <= 511)   ? RANGE_HNCP_UNASSIGNED:
454            (768 <= type && type <= 1023) ? RANGE_DNCP_PRIVATE_USE:
455                                            RANGE_DNCP_FUTURE_USE;
456        if (type == 6 || type == 7)
457            type_mask = RANGE_DNCP_FUTURE_USE;
458
459        /* defined types */
460        {
461            t = 0;
462            while (1) {
463                u_int key = type_values[t++].v;
464                if (key > 0xffff)
465                    break;
466                if (key == type) {
467                    type_mask = type;
468                    break;
469                }
470            }
471        }
472
473        if (in_line) {
474            if (last_type_mask == type_mask) {
475                last_type_count++;
476            } else {
477                print_type_in_line(ndo, last_type_mask, last_type_count, indent, &first_one);
478                last_type_mask = type_mask;
479                last_type_count = 1;
480            }
481
482            goto skip_multiline;
483        }
484
485        ND_PRINT((ndo,"%s", tok2str(type_values, "Easter Egg (42)", type_mask) ));
486        if (type_mask > 0xffff)
487            ND_PRINT((ndo,": type=%u", type ));
488        ND_PRINT((ndo," (%u)", bodylen + 4 ));
489
490        switch (type_mask) {
491
492        case DNCP_REQUEST_NETWORK_STATE: {
493            if (bodylen != 0)
494                ND_PRINT((ndo, " %s", istr));
495        }
496            break;
497
498        case DNCP_REQUEST_NODE_STATE: {
499            const char *node_identifier;
500            if (bodylen != 4) {
501                ND_PRINT((ndo, " %s", istr));
502                break;
503            }
504            node_identifier = format_nid(value);
505            ND_PRINT((ndo, " NID: %s", node_identifier));
506        }
507            break;
508
509        case DNCP_NODE_ENDPOINT: {
510            const char *node_identifier;
511            uint32_t endpoint_identifier;
512            if (bodylen != 8) {
513                ND_PRINT((ndo, " %s", istr));
514                break;
515            }
516            node_identifier = format_nid(value);
517            endpoint_identifier = EXTRACT_32BITS(value + 4);
518            ND_PRINT((ndo, " NID: %s EPID: %08x",
519                node_identifier,
520                endpoint_identifier
521            ));
522        }
523            break;
524
525        case DNCP_NETWORK_STATE: {
526            uint64_t hash;
527            if (bodylen != 8) {
528                ND_PRINT((ndo, " %s", istr));
529                break;
530            }
531            hash = EXTRACT_64BITS(value);
532            ND_PRINT((ndo, " hash: %016" PRIx64, hash));
533        }
534            break;
535
536        case DNCP_NODE_STATE: {
537            const char *node_identifier, *interval;
538            uint32_t sequence_number;
539            uint64_t hash;
540            if (bodylen < 20) {
541                ND_PRINT((ndo, " %s", istr));
542                break;
543            }
544            node_identifier = format_nid(value);
545            sequence_number = EXTRACT_32BITS(value + 4);
546            interval = format_interval(EXTRACT_32BITS(value + 8));
547            hash = EXTRACT_64BITS(value + 12);
548            ND_PRINT((ndo, " NID: %s seqno: %u %s hash: %016" PRIx64,
549                node_identifier,
550                sequence_number,
551                interval,
552                hash
553            ));
554            hncp_print_rec(ndo, value+20, bodylen-20, indent+1);
555        }
556            break;
557
558        case DNCP_PEER: {
559            const char *peer_node_identifier;
560            uint32_t peer_endpoint_identifier, endpoint_identifier;
561            if (bodylen != 12) {
562                ND_PRINT((ndo, " %s", istr));
563                break;
564            }
565            peer_node_identifier = format_nid(value);
566            peer_endpoint_identifier = EXTRACT_32BITS(value + 4);
567            endpoint_identifier = EXTRACT_32BITS(value + 8);
568            ND_PRINT((ndo, " Peer-NID: %s Peer-EPID: %08x Local-EPID: %08x",
569                peer_node_identifier,
570                peer_endpoint_identifier,
571                endpoint_identifier
572            ));
573        }
574            break;
575
576        case DNCP_KEEP_ALIVE_INTERVAL: {
577            uint32_t endpoint_identifier;
578            const char *interval;
579            if (bodylen < 8) {
580                ND_PRINT((ndo, " %s", istr));
581                break;
582            }
583            endpoint_identifier = EXTRACT_32BITS(value);
584            interval = format_interval(EXTRACT_32BITS(value + 4));
585            ND_PRINT((ndo, " EPID: %08x Interval: %s",
586                endpoint_identifier,
587                interval
588            ));
589        }
590            break;
591
592        case DNCP_TRUST_VERDICT: {
593            if (bodylen <= 36) {
594                ND_PRINT((ndo, " %s", istr));
595                break;
596            }
597            ND_PRINT((ndo, " Verdict: %u Fingerprint: %s Common Name: ",
598                *value,
599                format_256(value + 4)));
600            safeputs(ndo, value + 36, bodylen - 36);
601        }
602            break;
603
604        case HNCP_HNCP_VERSION: {
605            uint16_t capabilities;
606            uint8_t M, P, H, L;
607            if (bodylen < 5) {
608                ND_PRINT((ndo, " %s", istr));
609                break;
610            }
611            capabilities = EXTRACT_16BITS(value + 2);
612            M = (uint8_t)((capabilities >> 12) & 0xf);
613            P = (uint8_t)((capabilities >> 8) & 0xf);
614            H = (uint8_t)((capabilities >> 4) & 0xf);
615            L = (uint8_t)(capabilities & 0xf);
616            ND_PRINT((ndo, " M: %u P: %u H: %u L: %u User-agent: ",
617                M, P, H, L
618            ));
619            safeputs(ndo, value + 4, bodylen - 4);
620        }
621            break;
622
623        case HNCP_EXTERNAL_CONNECTION: {
624            /* Container TLV */
625            hncp_print_rec(ndo, value, bodylen, indent+1);
626        }
627            break;
628
629        case HNCP_DELEGATED_PREFIX: {
630            int l;
631            if (bodylen < 9 || bodylen < 9 + (value[8] + 7) / 8) {
632                ND_PRINT((ndo, " %s", istr));
633                break;
634            }
635            ND_PRINT((ndo, " VLSO: %s PLSO: %s Prefix: ",
636                format_interval(EXTRACT_32BITS(value)),
637                format_interval(EXTRACT_32BITS(value + 4))
638            ));
639            l = print_prefix(ndo, value + 8, bodylen - 8);
640            if (l == -1) {
641                ND_PRINT((ndo, "(length is invalid)"));
642                break;
643            }
644            if (l < 0) {
645                /*
646                 * We've already checked that we've captured the
647                 * entire TLV, based on its length, so this will
648                 * either be -1, meaning "the prefix length is
649                 * greater than the longest possible address of
650                 * that type" (i.e., > 32 for IPv4 or > 128 for
651                 * IPv6", or -3, meaning "the prefix runs past
652                 * the end of the TLV".
653                 */
654                ND_PRINT((ndo, " %s", istr));
655                break;
656            }
657            l += 8 + (-l & 3);
658
659            if (bodylen >= l)
660                hncp_print_rec(ndo, value + l, bodylen - l, indent+1);
661        }
662            break;
663
664        case HNCP_PREFIX_POLICY: {
665            uint8_t policy;
666            int l;
667            if (bodylen < 1) {
668                ND_PRINT((ndo, " %s", istr));
669                break;
670            }
671            policy = value[0];
672            ND_PRINT((ndo, " type: "));
673            if (policy == 0) {
674                if (bodylen != 1) {
675                    ND_PRINT((ndo, " %s", istr));
676                    break;
677                }
678                ND_PRINT((ndo, "Internet connectivity"));
679            } else if (policy >= 1 && policy <= 128) {
680                ND_PRINT((ndo, "Dest-Prefix: "));
681                l = print_prefix(ndo, value, bodylen);
682                if (l == -1) {
683                    ND_PRINT((ndo, "(length is invalid)"));
684                    break;
685                }
686                if (l < 0) {
687                    /*
688                     * We've already checked that we've captured the
689                     * entire TLV, based on its length, so this will
690                     * either be -1, meaning "the prefix length is
691                     * greater than the longest possible address of
692                     * that type" (i.e., > 32 for IPv4 or > 128 for
693                     * IPv6", or -3, meaning "the prefix runs past
694                     * the end of the TLV".
695                     */
696                    ND_PRINT((ndo, " %s", istr));
697                    break;
698                }
699            } else if (policy == 129) {
700                ND_PRINT((ndo, "DNS domain: "));
701                print_dns_label(ndo, value+1, bodylen-1, 1);
702            } else if (policy == 130) {
703                ND_PRINT((ndo, "Opaque UTF-8: "));
704                safeputs(ndo, value + 1, bodylen - 1);
705            } else if (policy == 131) {
706                if (bodylen != 1) {
707                    ND_PRINT((ndo, " %s", istr));
708                    break;
709                }
710                ND_PRINT((ndo, "Restrictive assignment"));
711            } else if (policy >= 132) {
712                ND_PRINT((ndo, "Unknown (%u)", policy)); /* Reserved for future additions */
713            }
714        }
715            break;
716
717        case HNCP_DHCPV4_DATA: {
718            if (bodylen == 0) {
719                ND_PRINT((ndo, " %s", istr));
720                break;
721            }
722            if (dhcpv4_print(ndo, value, bodylen, indent+1) != 0)
723                goto invalid;
724        }
725            break;
726
727        case HNCP_DHCPV6_DATA: {
728            if (bodylen == 0) {
729                ND_PRINT((ndo, " %s", istr));
730                break;
731            }
732            if (dhcpv6_print(ndo, value, bodylen, indent+1) != 0) {
733                ND_PRINT((ndo, " %s", istr));
734                break;
735            }
736        }
737            break;
738
739        case HNCP_ASSIGNED_PREFIX: {
740            uint8_t prty;
741            int l;
742            if (bodylen < 6 || bodylen < 6 + (value[5] + 7) / 8) {
743                ND_PRINT((ndo, " %s", istr));
744                break;
745            }
746            prty = (uint8_t)(value[4] & 0xf);
747            ND_PRINT((ndo, " EPID: %08x Prty: %u",
748                EXTRACT_32BITS(value),
749                prty
750            ));
751            ND_PRINT((ndo, " Prefix: "));
752            if ((l = print_prefix(ndo, value + 5, bodylen - 5)) < 0) {
753                ND_PRINT((ndo, " %s", istr));
754                break;
755            }
756            l += 5;
757            l += -l & 3;
758
759            if (bodylen >= l)
760                hncp_print_rec(ndo, value + l, bodylen - l, indent+1);
761        }
762            break;
763
764        case HNCP_NODE_ADDRESS: {
765            uint32_t endpoint_identifier;
766            const char *ip_address;
767            if (bodylen < 20) {
768                ND_PRINT((ndo, " %s", istr));
769                break;
770            }
771            endpoint_identifier = EXTRACT_32BITS(value);
772            ip_address = format_ip6addr(ndo, value + 4);
773            ND_PRINT((ndo, " EPID: %08x IP Address: %s",
774                endpoint_identifier,
775                ip_address
776            ));
777
778            hncp_print_rec(ndo, value + 20, bodylen - 20, indent+1);
779        }
780            break;
781
782        case HNCP_DNS_DELEGATED_ZONE: {
783            const char *ip_address;
784            int len;
785            if (bodylen < 17) {
786                ND_PRINT((ndo, " %s", istr));
787                break;
788            }
789            ip_address = format_ip6addr(ndo, value);
790            ND_PRINT((ndo, " IP-Address: %s %c%c%c ",
791                ip_address,
792                (value[16] & 4) ? 'l' : '-',
793                (value[16] & 2) ? 'b' : '-',
794                (value[16] & 1) ? 's' : '-'
795            ));
796            len = print_dns_label(ndo, value+17, bodylen-17, 1);
797            if (len < 0) {
798                ND_PRINT((ndo, " %s", istr));
799                break;
800            }
801            len += 17;
802            len += -len & 3;
803            if (bodylen >= len)
804                hncp_print_rec(ndo, value+len, bodylen-len, indent+1);
805        }
806            break;
807
808        case HNCP_DOMAIN_NAME: {
809            if (bodylen == 0) {
810                ND_PRINT((ndo, " %s", istr));
811                break;
812            }
813            ND_PRINT((ndo, " Domain: "));
814            print_dns_label(ndo, value, bodylen, 1);
815        }
816            break;
817
818        case HNCP_NODE_NAME: {
819            u_int l;
820            if (bodylen < 17) {
821                ND_PRINT((ndo, " %s", istr));
822                break;
823            }
824            l = value[16];
825            if (bodylen < 17 + l) {
826                ND_PRINT((ndo, " %s", istr));
827                break;
828            }
829            ND_PRINT((ndo, " IP-Address: %s Name: ",
830                format_ip6addr(ndo, value)
831            ));
832            if (l < 64) {
833                safeputchar(ndo, '"');
834                safeputs(ndo, value + 17, l);
835                safeputchar(ndo, '"');
836            } else {
837                ND_PRINT((ndo, "%s", istr));
838            }
839            l += 17;
840            l += -l & 3;
841            if (bodylen >= l)
842                hncp_print_rec(ndo, value + l, bodylen - l, indent+1);
843        }
844            break;
845
846        case HNCP_MANAGED_PSK: {
847            if (bodylen < 32) {
848                ND_PRINT((ndo, " %s", istr));
849                break;
850            }
851            ND_PRINT((ndo, " PSK: %s", format_256(value)));
852            hncp_print_rec(ndo, value + 32, bodylen - 32, indent+1);
853        }
854            break;
855
856        case RANGE_DNCP_RESERVED:
857        case RANGE_HNCP_UNASSIGNED:
858        case RANGE_DNCP_PRIVATE_USE:
859        case RANGE_DNCP_FUTURE_USE:
860            break;
861
862        }
863    skip_multiline:
864
865        i += 4 + bodylen + (-bodylen & 3);
866    }
867    print_type_in_line(ndo, last_type_mask, last_type_count, indent, &first_one);
868
869    return;
870
871 trunc:
872    ND_PRINT((ndo, "%s", "[|hncp]"));
873    return;
874
875 invalid:
876    ND_PRINT((ndo, "%s", istr));
877    return;
878}
879#ifdef __rtems__
880#include "rtems-bsd-tcpdump-print-hncp-data.h"
881#endif /* __rtems__ */
Note: See TracBrowser for help on using the repository browser.