const char * ni_print_hex(const unsigned char *data, unsigned int datalen) { static char addrbuf[512]; /* >= ni_opaque_t data * 3 */ addrbuf[0] = '\0'; return ni_format_hex(data, datalen, addrbuf, sizeof(addrbuf)); }
const char * ni_duid_format_hex(char **hex, const ni_opaque_t *duid) { ni_string_free(hex); if (duid->len > 0) { size_t len = duid->len * 3 + 1; *hex = xcalloc(1, len); ni_format_hex(duid->data, duid->len, *hex, len); } return *hex; }
static int __ni_config_parse_dhcp6_vendor_opt_node(xml_node_t *node, ni_var_array_t *opts, const char *parent) { const char *attrval; const char *code = NULL; enum { FORMAT_STR, /* normal string */ FORMAT_HEX, /* XX:XX format */ }; int format = FORMAT_STR; size_t len; if (strcmp(node->name, "option")) { ni_error("config: <%s> is not a valid <%s> option node", node->name, parent); return -1; } if ((attrval = xml_node_get_attr(node, "code")) != NULL) { char * err; long num; num = strtol(attrval, &err, 0); if (*err != '\0' || num < 0 || num > 0xffff) { ni_error("config: unable to parse %s <option code=\"%s\"", parent, attrval); return -1; } code = attrval; } else { ni_error("config: missed %s <option> without code attribute", parent); return -1; } if ((attrval = xml_node_get_attr(node, "format")) != NULL) { if (!strcmp(attrval, "hex") || !strcmp(attrval, "mac")) { format = FORMAT_HEX; } else if (!strcmp(attrval, "str") || !strcmp(attrval, "string")) { format = FORMAT_STR; } else { ni_error("config: unknown %s <option format=\"%s\"", parent, attrval); return -1; } } len = ni_string_len(node->cdata); if(format == FORMAT_HEX) { unsigned char *buf; /* verify the format early ... */ if (len > 0) { len = (len / 3) + 1; buf = xcalloc(1, len); if (ni_parse_hex(node->cdata, buf, len) <= 0) { ni_error("config: unable to parse %s hex option data", parent); free(buf); return -1; } free(buf); } ni_var_array_set(opts, code, node->cdata); } else { ni_stringbuf_t buf = NI_STRINGBUF_INIT_DYNAMIC; /* convert to hex-string format */ if (len > 0) { ni_stringbuf_grow(&buf, (len * 3)); ni_format_hex((unsigned char *)node->cdata, len, buf.string, buf.size); } ni_var_array_set(opts, code, buf.string); ni_stringbuf_destroy(&buf); } return 0; }
static int __ni_config_parse_dhcp6_class_data(xml_node_t *node, ni_string_array_t *data, const char *parent) { const char *attrval; enum { FORMAT_STR, /* normal string */ FORMAT_HEX, /* XX:XX format */ }; int format = FORMAT_STR; size_t len; if (strcmp(node->name, "class-data")) { ni_error("config: <%s> is not a valid <%s> class-data node", node->name, parent); return -1; } len = ni_string_len(node->cdata); if (len == 0) { ni_warn("config: empty %s <class-data> node", parent); return 0; } if ((attrval = xml_node_get_attr(node, "format")) != NULL) { if (!strcmp(attrval, "hex") || !strcmp(attrval, "mac")) { format = FORMAT_HEX; } else if (!strcmp(attrval, "str") || !strcmp(attrval, "string")) { format = FORMAT_STR; } else { ni_error("config: unknown %s <class-data format=\"%s\"", parent, attrval); return -1; } } if(format == FORMAT_HEX) { unsigned char *buf; /* verify the format early ... */ len = (len / 3) + 1; buf = xcalloc(1, len); if (ni_parse_hex(node->cdata, buf, len) <= 0) { ni_error("config: unable to parse %s hex class-data", parent); free(buf); return -1; } free(buf); ni_string_array_append(data, node->cdata); } else { ni_stringbuf_t buf = NI_STRINGBUF_INIT_DYNAMIC; /* convert to hex-string format */ ni_stringbuf_grow(&buf, (len * 3)); ni_format_hex((unsigned char *)node->cdata, len, buf.string, buf.size); ni_string_array_append(data, buf.string); ni_stringbuf_destroy(&buf); } return 0; }