static void dhcp_smach_set_msg_reqhost(dhcp_smach_t *dsmp, ipc_action_t *iap) { DHCP_OPT *d4o; dhcp_symbol_t *entry; char *value; if (dsmp->dsm_msg_reqhost != NULL) { dhcpmsg(MSG_DEBUG, "dhcp_smach_set_msg_reqhost: nullify former value, %s", dsmp->dsm_msg_reqhost); free(dsmp->dsm_msg_reqhost); dsmp->dsm_msg_reqhost = NULL; } /* * if a STANDARD/HOSTNAME was sent in the IPC request, then copy that * value into the state machine data if decoding succeeds. Otherwise, * log to indicate at what step the decoding stopped. */ if (dsmp->dsm_isv6) { dhcpmsg(MSG_DEBUG, "dhcp_smach_set_msg_reqhost: ipv6 is not" " handled"); return; } else if (iap->ia_request->data_type != DHCP_TYPE_OPTION) { dhcpmsg(MSG_DEBUG, "dhcp_smach_set_msg_reqhost: request type" " %d is not DHCP_TYPE_OPTION", iap->ia_request->data_type); return; } if (iap->ia_request->buffer == NULL || iap->ia_request->data_length <= DHCP_OPT_META_LEN) { dhcpmsg(MSG_WARNING, "dhcp_smach_set_msg_reqhost:" " DHCP_TYPE_OPTION ia_request buffer is NULL (0) or" " short (1): %d", iap->ia_request->buffer == NULL ? 0 : 1); return; } d4o = (DHCP_OPT *)iap->ia_request->buffer; if (d4o->code != CD_HOSTNAME) { dhcpmsg(MSG_DEBUG, "dhcp_smach_set_msg_reqhost: ignoring DHCPv4" " option %u", d4o->code); return; } else if (iap->ia_request->data_length - DHCP_OPT_META_LEN != d4o->len) { dhcpmsg(MSG_WARNING, "dhcp_smach_set_msg_reqhost:" " unexpected DHCP_OPT buffer length %u for CD_HOSTNAME" " option length %u", iap->ia_request->data_length, d4o->len); return; } entry = inittab_getbycode(ITAB_CAT_STANDARD, ITAB_CONS_INFO, CD_HOSTNAME); if (entry == NULL) { dhcpmsg(MSG_WARNING, "dhcp_smach_set_msg_reqhost: error getting" " ITAB_CAT_STANDARD ITAB_CONS_INFO" " CD_HOSTNAME entry"); return; } value = inittab_decode(entry, d4o->value, d4o->len, /* just_payload */ B_TRUE); if (value == NULL) { dhcpmsg(MSG_WARNING, "dhcp_smach_set_msg_reqhost: error decoding" " CD_HOSTNAME value from DHCP_OPT"); } else { dhcpmsg(MSG_DEBUG, "dhcp_smach_set_msg_reqhost: host %s", value); free(dsmp->dsm_msg_reqhost); dsmp->dsm_msg_reqhost = value; } free(entry); }
static void show_options(const uint8_t *data, int len) { dhcpv6_option_t d6o; uint_t olen, retlen; uint16_t val16; uint16_t type; uint32_t val32; const uint8_t *ostart; char *str, *sp; char *oldnest; /* * Be very careful with negative numbers; ANSI signed/unsigned * comparison doesn't work as expected. */ while (len >= (signed)sizeof (d6o)) { (void) memcpy(&d6o, data, sizeof (d6o)); d6o.d6o_code = ntohs(d6o.d6o_code); d6o.d6o_len = olen = ntohs(d6o.d6o_len); (void) snprintf(get_line(0, 0), get_line_remain(), "Option Code = %u (%s)", d6o.d6o_code, option_to_str(d6o.d6o_code)); ostart = data += sizeof (d6o); len -= sizeof (d6o); if (olen > len) { (void) strlcpy(get_line(0, 0), "Option truncated", get_line_remain()); olen = len; } switch (d6o.d6o_code) { case DHCPV6_OPT_CLIENTID: case DHCPV6_OPT_SERVERID: if (olen < sizeof (val16)) break; (void) memcpy(&val16, data, sizeof (val16)); data += sizeof (val16); olen -= sizeof (val16); type = ntohs(val16); (void) snprintf(get_line(0, 0), get_line_remain(), " DUID Type = %u (%s)", type, duidtype_to_str(type)); if (type == DHCPV6_DUID_LLT || type == DHCPV6_DUID_LL) { if (olen < sizeof (val16)) break; (void) memcpy(&val16, data, sizeof (val16)); data += sizeof (val16); olen -= sizeof (val16); val16 = ntohs(val16); (void) snprintf(get_line(0, 0), get_line_remain(), " Hardware Type = %u (%s)", val16, arp_htype(val16)); } if (type == DHCPV6_DUID_LLT) { time_t timevalue; if (olen < sizeof (val32)) break; (void) memcpy(&val32, data, sizeof (val32)); data += sizeof (val32); olen -= sizeof (val32); timevalue = ntohl(val32) + DUID_TIME_BASE; (void) snprintf(get_line(0, 0), get_line_remain(), " Time = %lu (%.24s)", ntohl(val32), ctime(&timevalue)); } if (type == DHCPV6_DUID_EN) { if (olen < sizeof (val32)) break; (void) memcpy(&val32, data, sizeof (val32)); data += sizeof (val32); olen -= sizeof (val32); val32 = ntohl(val32); (void) snprintf(get_line(0, 0), get_line_remain(), " Enterprise Number = %lu (%s)", val32, entr_to_str(val32)); } if (olen == 0) break; if ((str = malloc(olen * 3)) == NULL) pr_err("interpret_dhcpv6: no mem"); sp = str + snprintf(str, 3, "%02x", *data++); while (--olen > 0) { *sp++ = (type == DHCPV6_DUID_LLT || type == DHCPV6_DUID_LL) ? ':' : ' '; sp = sp + snprintf(sp, 3, "%02x", *data++); } (void) snprintf(get_line(0, 0), get_line_remain(), (type == DHCPV6_DUID_LLT || type == DHCPV6_DUID_LL) ? " Link Layer Address = %s" : " Identifier = %s", str); free(str); break; case DHCPV6_OPT_IA_NA: case DHCPV6_OPT_IA_PD: { dhcpv6_ia_na_t d6in; if (olen < sizeof (d6in) - sizeof (d6o)) break; (void) memcpy(&d6in, data - sizeof (d6o), sizeof (d6in)); data += sizeof (d6in) - sizeof (d6o); olen -= sizeof (d6in) - sizeof (d6o); (void) snprintf(get_line(0, 0), get_line_remain(), " IAID = %u", ntohl(d6in.d6in_iaid)); (void) snprintf(get_line(0, 0), get_line_remain(), " T1 (renew) = %u seconds", ntohl(d6in.d6in_t1)); (void) snprintf(get_line(0, 0), get_line_remain(), " T2 (rebind) = %u seconds", ntohl(d6in.d6in_t2)); nest_options(data, olen, "IA: ", "Identity Association"); break; } case DHCPV6_OPT_IA_TA: { dhcpv6_ia_ta_t d6it; if (olen < sizeof (d6it) - sizeof (d6o)) break; (void) memcpy(&d6it, data - sizeof (d6o), sizeof (d6it)); data += sizeof (d6it) - sizeof (d6o); olen -= sizeof (d6it) - sizeof (d6o); (void) snprintf(get_line(0, 0), get_line_remain(), " IAID = %u", ntohl(d6it.d6it_iaid)); nest_options(data, olen, "IA: ", "Identity Association"); break; } case DHCPV6_OPT_IAADDR: { dhcpv6_iaaddr_t d6ia; if (olen < sizeof (d6ia) - sizeof (d6o)) break; (void) memcpy(&d6ia, data - sizeof (d6o), sizeof (d6ia)); data += sizeof (d6ia) - sizeof (d6o); olen -= sizeof (d6ia) - sizeof (d6o); show_address(" Address", &d6ia.d6ia_addr); (void) snprintf(get_line(0, 0), get_line_remain(), " Preferred lifetime = %u seconds", ntohl(d6ia.d6ia_preflife)); (void) snprintf(get_line(0, 0), get_line_remain(), " Valid lifetime = %u seconds", ntohl(d6ia.d6ia_vallife)); nest_options(data, olen, "ADDR: ", "Address"); break; } case DHCPV6_OPT_ORO: while (olen >= sizeof (val16)) { (void) memcpy(&val16, data, sizeof (val16)); val16 = ntohs(val16); (void) snprintf(get_line(0, 0), get_line_remain(), " Requested Option Code = %u (%s)", val16, option_to_str(val16)); data += sizeof (val16); olen -= sizeof (val16); } break; case DHCPV6_OPT_PREFERENCE: if (olen > 0) { (void) snprintf(get_line(0, 0), get_line_remain(), *data == 255 ? " Preference = %u (immediate)" : " Preference = %u", *data); } break; case DHCPV6_OPT_ELAPSED_TIME: if (olen == sizeof (val16)) { (void) memcpy(&val16, data, sizeof (val16)); val16 = ntohs(val16); (void) snprintf(get_line(0, 0), get_line_remain(), " Elapsed Time = %u.%02u seconds", val16 / 100, val16 % 100); } break; case DHCPV6_OPT_RELAY_MSG: if (olen > 0) { oldnest = prot_nest_prefix; prot_nest_prefix = prot_prefix; retlen = interpret_dhcpv6(F_DTAIL, data, olen); prot_prefix = prot_nest_prefix; prot_nest_prefix = oldnest; } break; case DHCPV6_OPT_AUTH: { dhcpv6_auth_t d6a; if (olen < DHCPV6_AUTH_SIZE - sizeof (d6o)) break; (void) memcpy(&d6a, data - sizeof (d6o), DHCPV6_AUTH_SIZE); data += DHCPV6_AUTH_SIZE - sizeof (d6o); olen += DHCPV6_AUTH_SIZE - sizeof (d6o); (void) snprintf(get_line(0, 0), get_line_remain(), " Protocol = %u (%s)", d6a.d6a_proto, authproto_to_str(d6a.d6a_proto)); (void) snprintf(get_line(0, 0), get_line_remain(), " Algorithm = %u (%s)", d6a.d6a_alg, authalg_to_str(d6a.d6a_proto, d6a.d6a_alg)); (void) snprintf(get_line(0, 0), get_line_remain(), " Replay Detection Method = %u (%s)", d6a.d6a_rdm, authrdm_to_str(d6a.d6a_rdm)); show_hex(d6a.d6a_replay, sizeof (d6a.d6a_replay), " RDM Data"); if (olen > 0) show_hex(data, olen, " Auth Info"); break; } case DHCPV6_OPT_UNICAST: if (olen >= sizeof (in6_addr_t)) show_address(" Server Address", data); break; case DHCPV6_OPT_STATUS_CODE: if (olen < sizeof (val16)) break; (void) memcpy(&val16, data, sizeof (val16)); val16 = ntohs(val16); (void) snprintf(get_line(0, 0), get_line_remain(), " Status Code = %u (%s)", val16, status_to_str(val16)); data += sizeof (val16); olen -= sizeof (val16); if (olen > 0) (void) snprintf(get_line(0, 0), get_line_remain(), " Text = \"%.*s\"", olen, data); break; case DHCPV6_OPT_VENDOR_CLASS: if (olen < sizeof (val32)) break; (void) memcpy(&val32, data, sizeof (val32)); data += sizeof (val32); olen -= sizeof (val32); val32 = ntohl(val32); (void) snprintf(get_line(0, 0), get_line_remain(), " Enterprise Number = %lu (%s)", val32, entr_to_str(val32)); /* FALLTHROUGH */ case DHCPV6_OPT_USER_CLASS: while (olen >= sizeof (val16)) { (void) memcpy(&val16, data, sizeof (val16)); data += sizeof (val16); olen -= sizeof (val16); val16 = ntohs(val16); if (val16 > olen) { (void) strlcpy(get_line(0, 0), " Truncated class", get_line_remain()); val16 = olen; } show_hex(data, olen, " Class"); data += val16; olen -= val16; } break; case DHCPV6_OPT_VENDOR_OPT: { dhcpv6_option_t sd6o; if (olen < sizeof (val32)) break; (void) memcpy(&val32, data, sizeof (val32)); data += sizeof (val32); olen -= sizeof (val32); val32 = ntohl(val32); (void) snprintf(get_line(0, 0), get_line_remain(), " Enterprise Number = %lu (%s)", val32, entr_to_str(val32)); while (olen >= sizeof (sd6o)) { (void) memcpy(&sd6o, data, sizeof (sd6o)); sd6o.d6o_code = ntohs(sd6o.d6o_code); sd6o.d6o_len = ntohs(sd6o.d6o_len); (void) snprintf(get_line(0, 0), get_line_remain(), " Vendor Option Code = %u", d6o.d6o_code); data += sizeof (d6o); olen -= sizeof (d6o); if (sd6o.d6o_len > olen) { (void) strlcpy(get_line(0, 0), " Vendor Option truncated", get_line_remain()); sd6o.d6o_len = olen; } if (sd6o.d6o_len > 0) { show_hex(data, sd6o.d6o_len, " Data"); data += sd6o.d6o_len; olen -= sd6o.d6o_len; } } break; } case DHCPV6_OPT_REMOTE_ID: if (olen < sizeof (val32)) break; (void) memcpy(&val32, data, sizeof (val32)); data += sizeof (val32); olen -= sizeof (val32); val32 = ntohl(val32); (void) snprintf(get_line(0, 0), get_line_remain(), " Enterprise Number = %lu (%s)", val32, entr_to_str(val32)); /* FALLTHROUGH */ case DHCPV6_OPT_INTERFACE_ID: case DHCPV6_OPT_SUBSCRIBER: if (olen > 0) show_hex(data, olen, " ID"); break; case DHCPV6_OPT_RECONF_MSG: if (olen > 0) { (void) snprintf(get_line(0, 0), get_line_remain(), " Message Type = %u (%s)", *data, reconf_to_str(*data)); } break; case DHCPV6_OPT_SIP_NAMES: case DHCPV6_OPT_DNS_SEARCH: case DHCPV6_OPT_NIS_DOMAIN: case DHCPV6_OPT_BCMCS_SRV_D: { dhcp_symbol_t *symp; char *sp2; symp = inittab_getbycode( ITAB_CAT_STANDARD | ITAB_CAT_V6, ITAB_CONS_SNOOP, d6o.d6o_code); if (symp != NULL) { str = inittab_decode(symp, data, olen, B_TRUE); if (str != NULL) { sp = str; do { sp2 = strchr(sp, ' '); if (sp2 != NULL) *sp2++ = '\0'; (void) snprintf(get_line(0, 0), get_line_remain(), " Name = %s", sp); } while ((sp = sp2) != NULL); free(str); } free(symp); } break; } case DHCPV6_OPT_SIP_ADDR: case DHCPV6_OPT_DNS_ADDR: case DHCPV6_OPT_NIS_SERVERS: case DHCPV6_OPT_SNTP_SERVERS: case DHCPV6_OPT_BCMCS_SRV_A: while (olen >= sizeof (in6_addr_t)) { show_address(" Address", data); data += sizeof (in6_addr_t); olen -= sizeof (in6_addr_t); } break; case DHCPV6_OPT_IAPREFIX: { dhcpv6_iaprefix_t d6ip; if (olen < DHCPV6_IAPREFIX_SIZE - sizeof (d6o)) break; (void) memcpy(&d6ip, data - sizeof (d6o), DHCPV6_IAPREFIX_SIZE); data += DHCPV6_IAPREFIX_SIZE - sizeof (d6o); olen -= DHCPV6_IAPREFIX_SIZE - sizeof (d6o); show_address(" Prefix", d6ip.d6ip_addr); (void) snprintf(get_line(0, 0), get_line_remain(), " Preferred lifetime = %u seconds", ntohl(d6ip.d6ip_preflife)); (void) snprintf(get_line(0, 0), get_line_remain(), " Valid lifetime = %u seconds", ntohl(d6ip.d6ip_vallife)); (void) snprintf(get_line(0, 0), get_line_remain(), " Prefix length = %u", d6ip.d6ip_preflen); nest_options(data, olen, "ADDR: ", "Address"); break; } case DHCPV6_OPT_INFO_REFTIME: if (olen < sizeof (val32)) break; (void) memcpy(&val32, data, sizeof (val32)); (void) snprintf(get_line(0, 0), get_line_remain(), " Refresh Time = %lu seconds", ntohl(val32)); break; case DHCPV6_OPT_GEOCONF_CVC: { dhcpv6_civic_t d6c; int solen; if (olen < DHCPV6_CIVIC_SIZE - sizeof (d6o)) break; (void) memcpy(&d6c, data - sizeof (d6o), DHCPV6_CIVIC_SIZE); data += DHCPV6_CIVIC_SIZE - sizeof (d6o); olen -= DHCPV6_CIVIC_SIZE - sizeof (d6o); (void) snprintf(get_line(0, 0), get_line_remain(), " What Location = %u (%s)", d6c.d6c_what, cwhat_to_str(d6c.d6c_what)); (void) snprintf(get_line(0, 0), get_line_remain(), " Country Code = %.*s", sizeof (d6c.d6c_cc), d6c.d6c_cc); while (olen >= 2) { (void) snprintf(get_line(0, 0), get_line_remain(), " CA Element = %u (%s)", *data, catype_to_str(*data)); solen = data[1]; data += 2; olen -= 2; if (solen > olen) { (void) strlcpy(get_line(0, 0), " CA Element truncated", get_line_remain()); solen = olen; } if (solen > 0) { show_ascii(data, solen, " CA Data"); data += solen; olen -= solen; } } break; } case DHCPV6_OPT_CLIENT_FQDN: { dhcp_symbol_t *symp; if (olen == 0) break; (void) snprintf(get_line(0, 0), get_line_remain(), " Flags = %02x", *data); (void) snprintf(get_line(0, 0), get_line_remain(), " %s", getflag(*data, DHCPV6_FQDNF_S, "Perform AAAA RR updates", "No AAAA RR updates")); (void) snprintf(get_line(0, 0), get_line_remain(), " %s", getflag(*data, DHCPV6_FQDNF_O, "Server override updates", "No server override updates")); (void) snprintf(get_line(0, 0), get_line_remain(), " %s", getflag(*data, DHCPV6_FQDNF_N, "Server performs no updates", "Server performs updates")); symp = inittab_getbycode( ITAB_CAT_STANDARD | ITAB_CAT_V6, ITAB_CONS_SNOOP, d6o.d6o_code); if (symp != NULL) { str = inittab_decode(symp, data, olen, B_TRUE); if (str != NULL) { (void) snprintf(get_line(0, 0), get_line_remain(), " FQDN = %s", str); free(str); } free(symp); } break; } } data = ostart + d6o.d6o_len; len -= d6o.d6o_len; } if (len != 0) { (void) strlcpy(get_line(0, 0), "Option entry truncated", get_line_remain()); } }