/* Returns NULL if successful, otherwise a malloc()'d string describing the * error. The caller is responsible for freeing the returned string. */ static char * OVS_WARN_UNUSED_RESULT learn_parse_load_immediate(const char *s, struct ofpact_learn_spec *spec) { const char *full_s = s; const char *arrow = strstr(s, "->"); struct mf_subfield dst; union mf_subvalue imm; char *error; memset(&imm, 0, sizeof imm); if (s[0] == '0' && (s[1] == 'x' || s[1] == 'X') && arrow) { const char *in = arrow - 1; uint8_t *out = imm.u8 + sizeof imm.u8 - 1; int n = arrow - (s + 2); int i; for (i = 0; i < n; i++) { int hexit = hexit_value(in[-i]); if (hexit < 0) { return xasprintf("%s: bad hex digit in value", full_s); } out[-(i / 2)] |= i % 2 ? hexit << 4 : hexit; } s = arrow; } else { ovs_be64 *last_be64 = &imm.be64[ARRAY_SIZE(imm.be64) - 1]; *last_be64 = htonll(strtoull(s, (char **) &s, 0)); } if (strncmp(s, "->", 2)) { return xasprintf("%s: missing `->' following value", full_s); } s += 2; error = mf_parse_subfield(&dst, s); if (error) { return error; } if (!mf_nxm_header(dst.field->id)) { return xasprintf("%s: experimenter OXM field '%s' not supported", full_s, s); } if (!bitwise_is_all_zeros(&imm, sizeof imm, dst.n_bits, (8 * sizeof imm) - dst.n_bits)) { return xasprintf("%s: value does not fit into %u bits", full_s, dst.n_bits); } spec->n_bits = dst.n_bits; spec->src_type = NX_LEARN_SRC_IMMEDIATE; spec->src_imm = imm; spec->dst_type = NX_LEARN_DST_LOAD; spec->dst = dst; return NULL; }
/* Returns the number of characters at the beginning of 's' that are valid for * a UUID. For example, the "123" at the beginning of "123xyzzy" could begin a * UUID, so uuid_is_partial_string() would return 3; for "xyzzy", this function * would return 0, since "x" can't start a UUID. */ int uuid_is_partial_string(const char *s) { static const char tmpl[UUID_LEN] = "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx"; size_t i; for (i = 0; i < UUID_LEN; i++) { if (tmpl[i] == 'x' ? hexit_value(s[i]) < 0 : s[i] != '-') { break; } } return i; }
static void learn_parse_load_immediate(const char *s, struct ofpact_learn_spec *spec) { const char *full_s = s; const char *arrow = strstr(s, "->"); struct mf_subfield dst; union mf_subvalue imm; memset(&imm, 0, sizeof imm); if (s[0] == '0' && (s[1] == 'x' || s[1] == 'X') && arrow) { const char *in = arrow - 1; uint8_t *out = imm.u8 + sizeof imm.u8 - 1; int n = arrow - (s + 2); int i; for (i = 0; i < n; i++) { int hexit = hexit_value(in[-i]); if (hexit < 0) { ovs_fatal(0, "%s: bad hex digit in value", full_s); } out[-(i / 2)] |= i % 2 ? hexit << 4 : hexit; } s = arrow; } else { imm.be64[1] = htonll(strtoull(s, (char **) &s, 0)); } if (strncmp(s, "->", 2)) { ovs_fatal(0, "%s: missing `->' following value", full_s); } s += 2; s = mf_parse_subfield(&dst, s); if (*s != '\0') { ovs_fatal(0, "%s: trailing garbage following destination", full_s); } if (!bitwise_is_all_zeros(&imm, sizeof imm, dst.n_bits, (8 * sizeof imm) - dst.n_bits)) { ovs_fatal(0, "%s: value does not fit into %u bits", full_s, dst.n_bits); } spec->n_bits = dst.n_bits; spec->src_type = NX_LEARN_SRC_IMMEDIATE; spec->src_imm = imm; spec->dst_type = NX_LEARN_DST_LOAD; spec->dst = dst; }
static void lex_parse_hex_integer(const char *start, size_t len, struct lex_token *token) { const char *in = start + (len - 1); uint8_t *out = token->value.u8 + (sizeof token->value.u8 - 1); for (int i = 0; i < len; i++) { int hexit = hexit_value(in[-i]); if (hexit < 0) { lex_error(token, "Invalid syntax in hexadecimal constant."); return; } if (hexit && i / 2 >= sizeof token->value.u8) { lex_error(token, "Hexadecimal constant requires more than " "%"PRIuSIZE" bits.", 8 * sizeof token->value.u8); return; } out[-(i / 2)] |= i % 2 ? hexit << 4 : hexit; } token->format = LEX_F_HEXADECIMAL; }
/* Returns the integer value of the 'n' hexadecimal digits starting at 's', or * UINT_MAX if one of those "digits" is not really a hex digit. If 'ok' is * nonnull, '*ok' is set to true if the conversion succeeds or to false if a * non-hex digit is detected. */ unsigned int hexits_value(const char *s, size_t n, bool *ok) { unsigned int value; size_t i; value = 0; for (i = 0; i < n; i++) { int hexit = hexit_value(s[i]); if (hexit < 0) { if (ok) { *ok = false; } return UINT_MAX; } value = (value << 4) + hexit; } if (ok) { *ok = true; } return value; }