+ else
+ {
+ int col = 0;
+
+ ND_PRINT((ndo, "\n\t Advertised networks (total %u)",
+ (unsigned int) (msg_tlen / sizeof(struct olsr_hna4))));
+
+ while (msg_tlen >= sizeof(struct olsr_hna4)) {
+ ND_TCHECK_LEN(msg_data, sizeof(struct olsr_hna4));
+
+ ptr.hna = (const struct olsr_hna4 *)msg_data;
+
+ /* print 4 prefixes per line */
+ if (!ptr.hna->network[0] && !ptr.hna->network[1] &&
+ !ptr.hna->network[2] && !ptr.hna->network[3] &&
+ !ptr.hna->mask[GW_HNA_PAD] &&
+ ptr.hna->mask[GW_HNA_FLAGS]) {
+ /* smart gateway */
+ ND_PRINT((ndo, "%sSmart-Gateway:%s%s%s%s%s %u/%u",
+ col == 0 ? "\n\t " : ", ", /* indent */
+ /* sgw */
+ /* LINKSPEED */
+ (ptr.hna->mask[GW_HNA_FLAGS] &
+ GW_HNA_FLAG_LINKSPEED) ? " LINKSPEED" : "",
+ /* IPV4 */
+ (ptr.hna->mask[GW_HNA_FLAGS] &
+ GW_HNA_FLAG_IPV4) ? " IPV4" : "",
+ /* IPV4-NAT */
+ (ptr.hna->mask[GW_HNA_FLAGS] &
+ GW_HNA_FLAG_IPV4_NAT) ? " IPV4-NAT" : "",
+ /* IPV6 */
+ (ptr.hna->mask[GW_HNA_FLAGS] &
+ GW_HNA_FLAG_IPV6) ? " IPV6" : "",
+ /* IPv6PREFIX */
+ (ptr.hna->mask[GW_HNA_FLAGS] &
+ GW_HNA_FLAG_IPV6PREFIX) ? " IPv6-PREFIX" : "",
+ /* uplink */
+ (ptr.hna->mask[GW_HNA_FLAGS] &
+ GW_HNA_FLAG_LINKSPEED) ?
+ deserialize_gw_speed(ptr.hna->mask[GW_HNA_UPLINK]) : 0,
+ /* downlink */
+ (ptr.hna->mask[GW_HNA_FLAGS] &
+ GW_HNA_FLAG_LINKSPEED) ?
+ deserialize_gw_speed(ptr.hna->mask[GW_HNA_DOWNLINK]) : 0
+ ));
+ } else {
+ /* normal route */
+ ND_PRINT((ndo, "%s%s/%u",
+ col == 0 ? "\n\t " : ", ",
+ ipaddr_string(ndo, ptr.hna->network),
+ mask2plen(EXTRACT_BE_U_4(ptr.hna->mask))));
+ }
+
+ msg_data += sizeof(struct olsr_hna4);
+ msg_tlen -= sizeof(struct olsr_hna4);
+
+ col = (col + 1) % 4;
+ }
+ }
+ break;
+
+ case OLSR_NAMESERVICE_MSG:
+ {
+ u_int name_entries;
+ u_int addr_size;
+ int name_entries_valid;
+ u_int i;
+
+ if (msg_tlen < 4)
+ goto trunc;
+ ND_TCHECK_4(msg_data);
+
+ name_entries = EXTRACT_BE_U_2(msg_data + 2);
+ addr_size = 4;
+ if (is_ipv6)
+ addr_size = 16;
+
+ name_entries_valid = 0;
+ if ((name_entries > 0)
+ && ((name_entries * (4 + addr_size)) <= msg_tlen))
+ name_entries_valid = 1;
+
+ ND_PRINT((ndo, "\n\t Version %u, Entries %u%s",
+ EXTRACT_BE_U_2(msg_data),
+ name_entries, (name_entries_valid == 0) ? " (invalid)" : ""));
+
+ if (name_entries_valid == 0)
+ break;
+
+ msg_data += 4;
+ msg_tlen -= 4;
+
+ for (i = 0; i < name_entries; i++) {
+ int name_entry_len_valid = 0;
+
+ if (msg_tlen < 4)
+ break;
+ ND_TCHECK_4(msg_data);
+
+ name_entry_type = EXTRACT_BE_U_2(msg_data);
+ name_entry_len = EXTRACT_BE_U_2(msg_data + 2);
+
+ msg_data += 4;
+ msg_tlen -= 4;
+
+ if ((name_entry_len > 0) && ((addr_size + name_entry_len) <= msg_tlen))
+ name_entry_len_valid = 1;
+
+ ND_PRINT((ndo, "\n\t #%u: type %#06x, length %u%s",
+ (unsigned int) i, name_entry_type,
+ name_entry_len, (name_entry_len_valid == 0) ? " (invalid)" : ""));
+
+ if (name_entry_len_valid == 0)
+ break;
+
+ /* 32-bit alignment */
+ name_entry_padding = 0;
+ if (name_entry_len%4 != 0)
+ name_entry_padding = 4-(name_entry_len%4);
+
+ if (msg_tlen < addr_size + name_entry_len + name_entry_padding)
+ goto trunc;
+
+ ND_TCHECK_LEN(msg_data,
+ addr_size + name_entry_len + name_entry_padding);
+
+ if (is_ipv6)
+ ND_PRINT((ndo, ", address %s, name \"",
+ ip6addr_string(ndo, msg_data)));
+ else
+ ND_PRINT((ndo, ", address %s, name \"",
+ ipaddr_string(ndo, msg_data)));
+ (void)fn_printn(ndo, msg_data + addr_size, name_entry_len, NULL);
+ ND_PRINT((ndo, "\""));
+
+ msg_data += addr_size + name_entry_len + name_entry_padding;
+ msg_tlen -= addr_size + name_entry_len + name_entry_padding;
+ } /* for (i = 0; i < name_entries; i++) */