Home | History | Annotate | Download | only in tcpdump
      1 /*
      2  * Copyright (c) 1998-2007 The TCPDUMP project
      3  * Copyright (c) 2009  Florian Forster
      4  *
      5  * Redistribution and use in source and binary forms, with or without
      6  * modification, are permitted provided that: (1) source code
      7  * distributions retain the above copyright notice and this paragraph
      8  * in its entirety, and (2) distributions including binary code include
      9  * the above copyright notice and this paragraph in its entirety in
     10  * the documentation or other materials provided with the distribution.
     11  * THIS SOFTWARE IS PROVIDED ``AS IS'' AND
     12  * WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, WITHOUT
     13  * LIMITATION, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
     14  * FOR A PARTICULAR PURPOSE.
     15  *
     16  * Optimized Link State Protocl (OLSR) as per rfc3626
     17  *
     18  * Original code by Hannes Gredler <hannes (at) juniper.net>
     19  * IPv6 additions by Florian Forster <octo at verplant.org>
     20  */
     21 
     22 #define NETDISSECT_REWORKED
     23 #ifdef HAVE_CONFIG_H
     24 #include "config.h"
     25 #endif
     26 
     27 #include <tcpdump-stdinc.h>
     28 
     29 #include "interface.h"
     30 #include "addrtoname.h"
     31 #include "extract.h"
     32 
     33 /*
     34  * RFC 3626 common header
     35  *
     36  *  0                   1                   2                   3
     37  *  0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
     38  * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
     39  * |         Packet Length         |    Packet Sequence Number     |
     40  * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
     41  * |  Message Type |     Vtime     |         Message Size          |
     42  * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
     43  * |                      Originator Address                       |
     44  * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
     45  * |  Time To Live |   Hop Count   |    Message Sequence Number    |
     46  * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
     47  * |                                                               |
     48  * :                            MESSAGE                            :
     49  * |                                                               |
     50  * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
     51  * |  Message Type |     Vtime     |         Message Size          |
     52  * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
     53  * |                      Originator Address                       |
     54  * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
     55  * |  Time To Live |   Hop Count   |    Message Sequence Number    |
     56  * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
     57  * |                                                               |
     58  * :                            MESSAGE                            :
     59  * |                                                               |
     60  * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
     61  * :                                                               :
     62  */
     63 
     64 struct olsr_common {
     65     uint8_t packet_len[2];
     66     uint8_t packet_seq[2];
     67 };
     68 
     69 #define OLSR_HELLO_MSG         1 /* rfc3626 */
     70 #define OLSR_TC_MSG            2 /* rfc3626 */
     71 #define OLSR_MID_MSG           3 /* rfc3626 */
     72 #define OLSR_HNA_MSG           4 /* rfc3626 */
     73 #define OLSR_POWERINFO_MSG   128
     74 #define OLSR_NAMESERVICE_MSG 130
     75 #define OLSR_HELLO_LQ_MSG    201 /* LQ extensions olsr.org */
     76 #define OLSR_TC_LQ_MSG       202 /* LQ extensions olsr.org */
     77 
     78 static const struct tok olsr_msg_values[] = {
     79     { OLSR_HELLO_MSG, "Hello" },
     80     { OLSR_TC_MSG, "TC" },
     81     { OLSR_MID_MSG, "MID" },
     82     { OLSR_HNA_MSG, "HNA" },
     83     { OLSR_POWERINFO_MSG, "Powerinfo" },
     84     { OLSR_NAMESERVICE_MSG, "Nameservice" },
     85     { OLSR_HELLO_LQ_MSG, "Hello-LQ" },
     86     { OLSR_TC_LQ_MSG, "TC-LQ" },
     87     { 0, NULL}
     88 };
     89 
     90 struct olsr_msg4 {
     91     uint8_t msg_type;
     92     uint8_t vtime;
     93     uint8_t msg_len[2];
     94     uint8_t originator[4];
     95     uint8_t ttl;
     96     uint8_t hopcount;
     97     uint8_t msg_seq[2];
     98 };
     99 
    100 struct olsr_msg6 {
    101     uint8_t msg_type;
    102     uint8_t vtime;
    103     uint8_t msg_len[2];
    104     uint8_t originator[16];
    105     uint8_t ttl;
    106     uint8_t hopcount;
    107     uint8_t msg_seq[2];
    108 };
    109 
    110 struct olsr_hello {
    111     uint8_t res[2];
    112     uint8_t htime;
    113     uint8_t will;
    114 };
    115 
    116 struct olsr_hello_link {
    117     uint8_t link_code;
    118     uint8_t res;
    119     uint8_t len[2];
    120 };
    121 
    122 struct olsr_tc {
    123     uint8_t ans_seq[2];
    124     uint8_t res[2];
    125 };
    126 
    127 struct olsr_hna4 {
    128     uint8_t network[4];
    129     uint8_t mask[4];
    130 };
    131 
    132 struct olsr_hna6 {
    133     uint8_t network[16];
    134     uint8_t mask[16];
    135 };
    136 
    137 
    138 #define OLSR_EXTRACT_LINK_TYPE(link_code) (link_code & 0x3)
    139 #define OLSR_EXTRACT_NEIGHBOR_TYPE(link_code) (link_code >> 2)
    140 
    141 static const struct tok olsr_link_type_values[] = {
    142     { 0, "Unspecified" },
    143     { 1, "Asymmetric" },
    144     { 2, "Symmetric" },
    145     { 3, "Lost" },
    146     { 0, NULL}
    147 };
    148 
    149 static const struct tok olsr_neighbor_type_values[] = {
    150     { 0, "Not-Neighbor" },
    151     { 1, "Symmetric" },
    152     { 2, "Symmetric-MPR" },
    153     { 0, NULL}
    154 };
    155 
    156 struct olsr_lq_neighbor4 {
    157     uint8_t neighbor[4];
    158     uint8_t link_quality;
    159     uint8_t neighbor_link_quality;
    160     uint8_t res[2];
    161 };
    162 
    163 struct olsr_lq_neighbor6 {
    164     uint8_t neighbor[16];
    165     uint8_t link_quality;
    166     uint8_t neighbor_link_quality;
    167     uint8_t res[2];
    168 };
    169 
    170 /*
    171  * macro to convert the 8-bit mantissa/exponent to a double float
    172  * taken from olsr.org.
    173  */
    174 #define VTIME_SCALE_FACTOR    0.0625
    175 #define ME_TO_DOUBLE(me) \
    176   (double)(VTIME_SCALE_FACTOR*(1+(double)(me>>4)/16)*(double)(1<<(me&0x0F)))
    177 
    178 /*
    179  * print a neighbor list with LQ extensions.
    180  */
    181 static int
    182 olsr_print_lq_neighbor4(netdissect_options *ndo,
    183                         const u_char *msg_data, u_int hello_len)
    184 {
    185     struct olsr_lq_neighbor4 *lq_neighbor;
    186 
    187     while (hello_len >= sizeof(struct olsr_lq_neighbor4)) {
    188 
    189         lq_neighbor = (struct olsr_lq_neighbor4 *)msg_data;
    190         if (!ND_TTEST(*lq_neighbor))
    191             return (-1);
    192 
    193         ND_PRINT((ndo, "\n\t      neighbor %s, link-quality %.2lf%%"
    194                ", neighbor-link-quality %.2lf%%",
    195                ipaddr_string(ndo, lq_neighbor->neighbor),
    196                ((double)lq_neighbor->link_quality/2.55),
    197                ((double)lq_neighbor->neighbor_link_quality/2.55)));
    198 
    199         msg_data += sizeof(struct olsr_lq_neighbor4);
    200         hello_len -= sizeof(struct olsr_lq_neighbor4);
    201     }
    202     return (0);
    203 }
    204 
    205 #if INET6
    206 static int
    207 olsr_print_lq_neighbor6(netdissect_options *ndo,
    208                         const u_char *msg_data, u_int hello_len)
    209 {
    210     struct olsr_lq_neighbor6 *lq_neighbor;
    211 
    212     while (hello_len >= sizeof(struct olsr_lq_neighbor6)) {
    213 
    214         lq_neighbor = (struct olsr_lq_neighbor6 *)msg_data;
    215         if (!ND_TTEST(*lq_neighbor))
    216             return (-1);
    217 
    218         ND_PRINT((ndo, "\n\t      neighbor %s, link-quality %.2lf%%"
    219                ", neighbor-link-quality %.2lf%%",
    220                ip6addr_string(ndo, lq_neighbor->neighbor),
    221                ((double)lq_neighbor->link_quality/2.55),
    222                ((double)lq_neighbor->neighbor_link_quality/2.55)));
    223 
    224         msg_data += sizeof(struct olsr_lq_neighbor6);
    225         hello_len -= sizeof(struct olsr_lq_neighbor6);
    226     }
    227     return (0);
    228 }
    229 #endif /* INET6 */
    230 
    231 /*
    232  * print a neighbor list.
    233  */
    234 static int
    235 olsr_print_neighbor(netdissect_options *ndo,
    236                     const u_char *msg_data, u_int hello_len)
    237 {
    238     int neighbor;
    239 
    240     ND_PRINT((ndo, "\n\t      neighbor\n\t\t"));
    241     neighbor = 1;
    242 
    243     while (hello_len >= sizeof(struct in_addr)) {
    244 
    245         if (!ND_TTEST2(*msg_data, sizeof(struct in_addr)))
    246             return (-1);
    247         /* print 4 neighbors per line */
    248 
    249         ND_PRINT((ndo, "%s%s", ipaddr_string(ndo, msg_data),
    250                neighbor % 4 == 0 ? "\n\t\t" : " "));
    251 
    252         msg_data += sizeof(struct in_addr);
    253         hello_len -= sizeof(struct in_addr);
    254     }
    255     return (0);
    256 }
    257 
    258 
    259 void
    260 olsr_print(netdissect_options *ndo,
    261            const u_char *pptr, u_int length, int is_ipv6)
    262 {
    263     union {
    264         const struct olsr_common *common;
    265         const struct olsr_msg4 *msg4;
    266         const struct olsr_msg6 *msg6;
    267         const struct olsr_hello *hello;
    268         const struct olsr_hello_link *hello_link;
    269         const struct olsr_tc *tc;
    270         const struct olsr_hna4 *hna;
    271     } ptr;
    272 
    273     u_int msg_type, msg_len, msg_tlen, hello_len;
    274     uint16_t name_entry_type, name_entry_len;
    275     u_int name_entry_padding;
    276     uint8_t link_type, neighbor_type;
    277     const u_char *tptr, *msg_data;
    278 
    279     tptr = pptr;
    280 
    281     if (length < sizeof(struct olsr_common)) {
    282         goto trunc;
    283     }
    284 
    285     ND_TCHECK2(*tptr, sizeof(struct olsr_common));
    286 
    287     ptr.common = (struct olsr_common *)tptr;
    288     length = min(length, EXTRACT_16BITS(ptr.common->packet_len));
    289 
    290     ND_PRINT((ndo, "OLSRv%i, seq 0x%04x, length %u",
    291             (is_ipv6 == 0) ? 4 : 6,
    292             EXTRACT_16BITS(ptr.common->packet_seq),
    293             length));
    294 
    295     tptr += sizeof(struct olsr_common);
    296 
    297     /*
    298      * In non-verbose mode, just print version.
    299      */
    300     if (ndo->ndo_vflag < 1) {
    301         return;
    302     }
    303 
    304     while (tptr < (pptr+length)) {
    305         union
    306         {
    307             struct olsr_msg4 *v4;
    308             struct olsr_msg6 *v6;
    309         } msgptr;
    310         int msg_len_valid = 0;
    311 
    312         ND_TCHECK2(*tptr, sizeof(struct olsr_msg4));
    313 
    314 #if INET6
    315         if (is_ipv6)
    316         {
    317             msgptr.v6 = (struct olsr_msg6 *) tptr;
    318             msg_type = msgptr.v6->msg_type;
    319             msg_len = EXTRACT_16BITS(msgptr.v6->msg_len);
    320             if ((msg_len >= sizeof (struct olsr_msg6))
    321                     && (msg_len <= length))
    322                 msg_len_valid = 1;
    323 
    324             /* infinite loop check */
    325             if (msg_type == 0 || msg_len == 0) {
    326                 return;
    327             }
    328 
    329             ND_PRINT((ndo, "\n\t%s Message (%#04x), originator %s, ttl %u, hop %u"
    330                     "\n\t  vtime %.3lfs, msg-seq 0x%04x, length %u%s",
    331                     tok2str(olsr_msg_values, "Unknown", msg_type),
    332                     msg_type, ip6addr_string(ndo, msgptr.v6->originator),
    333                     msgptr.v6->ttl,
    334                     msgptr.v6->hopcount,
    335                     ME_TO_DOUBLE(msgptr.v6->vtime),
    336                     EXTRACT_16BITS(msgptr.v6->msg_seq),
    337                     msg_len, (msg_len_valid == 0) ? " (invalid)" : ""));
    338             if (!msg_len_valid) {
    339                 return;
    340             }
    341 
    342             msg_tlen = msg_len - sizeof(struct olsr_msg6);
    343             msg_data = tptr + sizeof(struct olsr_msg6);
    344         }
    345         else /* (!is_ipv6) */
    346 #endif /* INET6 */
    347         {
    348             msgptr.v4 = (struct olsr_msg4 *) tptr;
    349             msg_type = msgptr.v4->msg_type;
    350             msg_len = EXTRACT_16BITS(msgptr.v4->msg_len);
    351             if ((msg_len >= sizeof (struct olsr_msg4))
    352                     && (msg_len <= length))
    353                 msg_len_valid = 1;
    354 
    355             /* infinite loop check */
    356             if (msg_type == 0 || msg_len == 0) {
    357                 return;
    358             }
    359 
    360             ND_PRINT((ndo, "\n\t%s Message (%#04x), originator %s, ttl %u, hop %u"
    361                     "\n\t  vtime %.3lfs, msg-seq 0x%04x, length %u%s",
    362                     tok2str(olsr_msg_values, "Unknown", msg_type),
    363                     msg_type, ipaddr_string(ndo, msgptr.v4->originator),
    364                     msgptr.v4->ttl,
    365                     msgptr.v4->hopcount,
    366                     ME_TO_DOUBLE(msgptr.v4->vtime),
    367                     EXTRACT_16BITS(msgptr.v4->msg_seq),
    368                     msg_len, (msg_len_valid == 0) ? " (invalid)" : ""));
    369             if (!msg_len_valid) {
    370                 return;
    371             }
    372 
    373             msg_tlen = msg_len - sizeof(struct olsr_msg4);
    374             msg_data = tptr + sizeof(struct olsr_msg4);
    375         }
    376 
    377         switch (msg_type) {
    378         case OLSR_HELLO_MSG:
    379         case OLSR_HELLO_LQ_MSG:
    380             if (msg_tlen < sizeof(struct olsr_hello))
    381                 goto trunc;
    382             ND_TCHECK2(*msg_data, sizeof(struct olsr_hello));
    383 
    384             ptr.hello = (struct olsr_hello *)msg_data;
    385             ND_PRINT((ndo, "\n\t  hello-time %.3lfs, MPR willingness %u",
    386                    ME_TO_DOUBLE(ptr.hello->htime), ptr.hello->will));
    387             msg_data += sizeof(struct olsr_hello);
    388             msg_tlen -= sizeof(struct olsr_hello);
    389 
    390             while (msg_tlen >= sizeof(struct olsr_hello_link)) {
    391                 int hello_len_valid = 0;
    392 
    393                 /*
    394                  * link-type.
    395                  */
    396                 ND_TCHECK2(*msg_data, sizeof(struct olsr_hello_link));
    397 
    398                 ptr.hello_link = (struct olsr_hello_link *)msg_data;
    399 
    400                 hello_len = EXTRACT_16BITS(ptr.hello_link->len);
    401                 link_type = OLSR_EXTRACT_LINK_TYPE(ptr.hello_link->link_code);
    402                 neighbor_type = OLSR_EXTRACT_NEIGHBOR_TYPE(ptr.hello_link->link_code);
    403 
    404                 if ((hello_len <= msg_tlen)
    405                         && (hello_len >= sizeof(struct olsr_hello_link)))
    406                     hello_len_valid = 1;
    407 
    408                 ND_PRINT((ndo, "\n\t    link-type %s, neighbor-type %s, len %u%s",
    409                        tok2str(olsr_link_type_values, "Unknown", link_type),
    410                        tok2str(olsr_neighbor_type_values, "Unknown", neighbor_type),
    411                        hello_len,
    412                        (hello_len_valid == 0) ? " (invalid)" : ""));
    413 
    414                 if (hello_len_valid == 0)
    415                     break;
    416 
    417                 msg_data += sizeof(struct olsr_hello_link);
    418                 msg_tlen -= sizeof(struct olsr_hello_link);
    419                 hello_len -= sizeof(struct olsr_hello_link);
    420 
    421                 ND_TCHECK2(*msg_data, hello_len);
    422                 if (msg_type == OLSR_HELLO_MSG) {
    423                     if (olsr_print_neighbor(ndo, msg_data, hello_len) == -1)
    424                         goto trunc;
    425                 } else {
    426 #if INET6
    427                     if (is_ipv6) {
    428                         if (olsr_print_lq_neighbor6(ndo, msg_data, hello_len) == -1)
    429                             goto trunc;
    430                     } else
    431 #endif
    432                     {
    433                         if (olsr_print_lq_neighbor4(ndo, msg_data, hello_len) == -1)
    434                             goto trunc;
    435                     }
    436                 }
    437 
    438                 msg_data += hello_len;
    439                 msg_tlen -= hello_len;
    440             }
    441             break;
    442 
    443         case OLSR_TC_MSG:
    444         case OLSR_TC_LQ_MSG:
    445             if (msg_tlen < sizeof(struct olsr_tc))
    446                 goto trunc;
    447             ND_TCHECK2(*msg_data, sizeof(struct olsr_tc));
    448 
    449             ptr.tc = (struct olsr_tc *)msg_data;
    450             ND_PRINT((ndo, "\n\t    advertised neighbor seq 0x%04x",
    451                    EXTRACT_16BITS(ptr.tc->ans_seq)));
    452             msg_data += sizeof(struct olsr_tc);
    453             msg_tlen -= sizeof(struct olsr_tc);
    454 
    455             if (msg_type == OLSR_TC_MSG) {
    456                 if (olsr_print_neighbor(ndo, msg_data, msg_tlen) == -1)
    457                     goto trunc;
    458             } else {
    459 #if INET6
    460                 if (is_ipv6) {
    461                     if (olsr_print_lq_neighbor6(ndo, msg_data, msg_tlen) == -1)
    462                         goto trunc;
    463                 } else
    464 #endif
    465                 {
    466                     if (olsr_print_lq_neighbor4(ndo, msg_data, msg_tlen) == -1)
    467                         goto trunc;
    468                 }
    469             }
    470             break;
    471 
    472         case OLSR_MID_MSG:
    473         {
    474             size_t addr_size = sizeof(struct in_addr);
    475 
    476 #if INET6
    477             if (is_ipv6)
    478                 addr_size = sizeof(struct in6_addr);
    479 #endif
    480 
    481             while (msg_tlen >= addr_size) {
    482                 ND_TCHECK2(*msg_data, addr_size);
    483 #if INET6
    484                 ND_PRINT((ndo, "\n\t  interface address %s",
    485                         is_ipv6 ? ip6addr_string(ndo, msg_data) :
    486                         ipaddr_string(ndo, msg_data)));
    487 #else
    488                 ND_PRINT((ndo, "\n\t  interface address %s",
    489                         ipaddr_string(ndo, msg_data)));
    490 #endif
    491 
    492                 msg_data += addr_size;
    493                 msg_tlen -= addr_size;
    494             }
    495             break;
    496         }
    497 
    498         case OLSR_HNA_MSG:
    499             ND_PRINT((ndo, "\n\t  Advertised networks (total %u)",
    500                     (unsigned int) (msg_tlen / sizeof(struct olsr_hna6))));
    501 #if INET6
    502             if (is_ipv6)
    503             {
    504                 int i = 0;
    505                 while (msg_tlen >= sizeof(struct olsr_hna6)) {
    506                     struct olsr_hna6 *hna6;
    507 
    508                     ND_TCHECK2(*msg_data, sizeof(struct olsr_hna6));
    509 
    510                     hna6 = (struct olsr_hna6 *)msg_data;
    511 
    512                     ND_PRINT((ndo, "\n\t    #%i: %s/%u",
    513                             i, ip6addr_string(ndo, hna6->network),
    514                             mask62plen (hna6->mask)));
    515 
    516                     msg_data += sizeof(struct olsr_hna6);
    517                     msg_tlen -= sizeof(struct olsr_hna6);
    518                 }
    519             }
    520             else
    521 #endif
    522             {
    523                 int col = 0;
    524                 while (msg_tlen >= sizeof(struct olsr_hna4)) {
    525                     ND_TCHECK2(*msg_data, sizeof(struct olsr_hna4));
    526 
    527                     ptr.hna = (struct olsr_hna4 *)msg_data;
    528 
    529                     /* print 4 prefixes per line */
    530                     ND_PRINT((ndo, "%s%s/%u",
    531                             col == 0 ? "\n\t    " : ", ",
    532                             ipaddr_string(ndo, ptr.hna->network),
    533                             mask2plen(EXTRACT_32BITS(ptr.hna->mask))));
    534 
    535                     msg_data += sizeof(struct olsr_hna4);
    536                     msg_tlen -= sizeof(struct olsr_hna4);
    537 
    538                     col = (col + 1) % 4;
    539                 }
    540             }
    541             break;
    542 
    543         case OLSR_NAMESERVICE_MSG:
    544         {
    545             u_int name_entries = EXTRACT_16BITS(msg_data+2);
    546             u_int addr_size = 4;
    547             int name_entries_valid = 0;
    548             u_int i;
    549 
    550             if (is_ipv6)
    551                 addr_size = 16;
    552 
    553             if ((name_entries > 0)
    554                     && ((name_entries * (4 + addr_size)) <= msg_tlen))
    555                 name_entries_valid = 1;
    556 
    557             if (msg_tlen < 4)
    558                 goto trunc;
    559             ND_TCHECK2(*msg_data, 4);
    560 
    561             ND_PRINT((ndo, "\n\t  Version %u, Entries %u%s",
    562                    EXTRACT_16BITS(msg_data),
    563                    name_entries, (name_entries_valid == 0) ? " (invalid)" : ""));
    564 
    565             if (name_entries_valid == 0)
    566                 break;
    567 
    568             msg_data += 4;
    569             msg_tlen -= 4;
    570 
    571             for (i = 0; i < name_entries; i++) {
    572                 int name_entry_len_valid = 0;
    573 
    574                 if (msg_tlen < 4)
    575                     break;
    576                 ND_TCHECK2(*msg_data, 4);
    577 
    578                 name_entry_type = EXTRACT_16BITS(msg_data);
    579                 name_entry_len = EXTRACT_16BITS(msg_data+2);
    580 
    581                 msg_data += 4;
    582                 msg_tlen -= 4;
    583 
    584                 if ((name_entry_len > 0) && ((addr_size + name_entry_len) <= msg_tlen))
    585                     name_entry_len_valid = 1;
    586 
    587                 ND_PRINT((ndo, "\n\t    #%u: type %#06x, length %u%s",
    588                         (unsigned int) i, name_entry_type,
    589                         name_entry_len, (name_entry_len_valid == 0) ? " (invalid)" : ""));
    590 
    591                 if (name_entry_len_valid == 0)
    592                     break;
    593 
    594                 /* 32-bit alignment */
    595                 name_entry_padding = 0;
    596                 if (name_entry_len%4 != 0)
    597                     name_entry_padding = 4-(name_entry_len%4);
    598 
    599                 if (msg_tlen < addr_size + name_entry_len + name_entry_padding)
    600                     goto trunc;
    601 
    602                 ND_TCHECK2(*msg_data, addr_size + name_entry_len + name_entry_padding);
    603 
    604 #if INET6
    605                 if (is_ipv6)
    606                     ND_PRINT((ndo, ", address %s, name \"",
    607                             ip6addr_string(ndo, msg_data)));
    608                 else
    609 #endif
    610                     ND_PRINT((ndo, ", address %s, name \"",
    611                             ipaddr_string(ndo, msg_data)));
    612                 (void)fn_printn(ndo, msg_data + addr_size, name_entry_len, NULL);
    613                 ND_PRINT((ndo, "\""));
    614 
    615                 msg_data += addr_size + name_entry_len + name_entry_padding;
    616                 msg_tlen -= addr_size + name_entry_len + name_entry_padding;
    617             } /* for (i = 0; i < name_entries; i++) */
    618             break;
    619         } /* case OLSR_NAMESERVICE_MSG */
    620 
    621             /*
    622              * FIXME those are the defined messages that lack a decoder
    623              * you are welcome to contribute code ;-)
    624              */
    625         case OLSR_POWERINFO_MSG:
    626         default:
    627             print_unknown_data(ndo, msg_data, "\n\t    ", msg_tlen);
    628             break;
    629         } /* switch (msg_type) */
    630         tptr += msg_len;
    631     } /* while (tptr < (pptr+length)) */
    632 
    633     return;
    634 
    635  trunc:
    636     ND_PRINT((ndo, "[|olsr]"));
    637 }
    638 
    639 /*
    640  * Local Variables:
    641  * c-style: whitesmith
    642  * c-basic-offset: 4
    643  * End:
    644  */
    645