static gboolean val_from_unparsed(fvalue_t *fv, char *s, gboolean allow_partial_value _U_, LogFunc logfunc) { fvalue_t *fv_bytes; /* Free up the old value, if we have one */ string_fvalue_free(fv); /* Does this look like a byte-string? */ fv_bytes = fvalue_from_unparsed(FT_BYTES, s, TRUE, NULL); if (fv_bytes) { /* Copy the bytes over to a string and terminate it * with a NUL. XXX - what if the user embeds a NUL * in the middle of the byte string? */ int num_bytes = fv_bytes->value.bytes->len; fv->value.string = (gchar *)g_malloc(num_bytes + 1); memcpy(fv->value.string, fv_bytes->value.bytes->data, num_bytes); fv->value.string[num_bytes] = '\0'; FVALUE_FREE(fv_bytes); return TRUE; } /* Just turn it into a string */ return val_from_string(fv, s, logfunc); }
static gboolean val_from_unparsed(fvalue_t *fv, const char *s, gboolean allow_partial_value _U_, LogFunc logfunc) { guint32 addr; unsigned int nmask_bits; const char *has_slash; const char *net_str, *addr_str; fvalue_t *nmask_fvalue; /* Look for CIDR: Is there a single slash in the string? */ has_slash = strchr(s, '/'); if (has_slash) { /* Make a copy of the string up to but not including the * slash; that's the address portion. */ addr_str = ep_strndup(s, has_slash - s); } else { addr_str = s; } if (!get_host_ipaddr(addr_str, &addr)) { logfunc("\"%s\" is not a valid hostname or IPv4 address.", addr_str); return FALSE; } ipv4_addr_set_net_order_addr(&(fv->value.ipv4), addr); /* If CIDR, get netmask bits. */ if (has_slash) { /* Skip past the slash */ net_str = has_slash + 1; /* XXX - this is inefficient */ nmask_fvalue = fvalue_from_unparsed(FT_UINT32, net_str, FALSE, logfunc); if (!nmask_fvalue) { return FALSE; } nmask_bits = fvalue_get_uinteger(nmask_fvalue); FVALUE_FREE(nmask_fvalue); if (nmask_bits > 32) { logfunc("Netmask bits in a CIDR IPv4 address should be <= 32, not %u", nmask_bits); return FALSE; } ipv4_addr_set_netmask_bits(&fv->value.ipv4, nmask_bits); } else { /* Not CIDR; mask covers entire address. */ ipv4_addr_set_netmask_bits(&(fv->value.ipv4), 32); } return TRUE; }
static gboolean ipv6_from_unparsed(fvalue_t *fv, const char *s, gboolean allow_partial_value _U_, gchar **err_msg) { const char *slash; const char *addr_str; char *addr_str_to_free = NULL; unsigned int nmask_bits; fvalue_t *nmask_fvalue; /* Look for prefix: Is there a single slash in the string? */ slash = strchr(s, '/'); if (slash) { /* Make a copy of the string up to but not including the * slash; that's the address portion. */ addr_str_to_free = wmem_strndup(NULL, s, slash-s); addr_str = addr_str_to_free; } else addr_str = s; if (!get_host_ipaddr6(addr_str, &(fv->value.ipv6.addr))) { if (err_msg != NULL) *err_msg = g_strdup_printf("\"%s\" is not a valid hostname or IPv6 address.", s); if (addr_str_to_free) wmem_free(NULL, addr_str_to_free); return FALSE; } if (addr_str_to_free) wmem_free(NULL, addr_str_to_free); /* If prefix */ if (slash) { /* XXX - this is inefficient */ nmask_fvalue = fvalue_from_unparsed(FT_UINT32, slash+1, FALSE, err_msg); if (!nmask_fvalue) { return FALSE; } nmask_bits = fvalue_get_uinteger(nmask_fvalue); FVALUE_FREE(nmask_fvalue); if (nmask_bits > 128) { if (err_msg != NULL) { *err_msg = g_strdup_printf("Prefix in a IPv6 address should be <= 128, not %u", nmask_bits); } return FALSE; } fv->value.ipv6.prefix = nmask_bits; } else { /* Not CIDR; mask covers entire address. */ fv->value.ipv6.prefix = 128; } return TRUE; }
static void fvalue_free(gpointer value) { fvalue_t *fvalue = (fvalue_t*)value; /* If the data was not claimed with stnode_steal_data(), free it. */ if (fvalue) { FVALUE_FREE(fvalue); } }
static void dfvm_value_free(dfvm_value_t *v) { switch (v->type) { case FVALUE: FVALUE_FREE(v->value.fvalue); break; case DRANGE: drange_free(v->value.drange); break; default: /* nothing */ ; } g_free(v); }
fvalue_t* fvalue_from_string(ftenum_t ftype, char *s, LogFunc logfunc) { fvalue_t *fv; fv = fvalue_new(ftype); if (fv->ftype->val_from_string) { if (fv->ftype->val_from_string(fv, s, logfunc)) { return fv; } } else { logfunc("\"%s\" cannot be converted to %s.", s, ftype_pretty_name(ftype)); } FVALUE_FREE(fv); return NULL; }
fvalue_t* fvalue_from_unparsed(ftenum_t ftype, char *s, gboolean allow_partial_value, LogFunc logfunc) { fvalue_t *fv; fv = fvalue_new(ftype); if (fv->ftype->val_from_unparsed) { if (fv->ftype->val_from_unparsed(fv, s, allow_partial_value, logfunc)) { return fv; } } else { logfunc("\"%s\" cannot be converted to %s.", s, ftype_pretty_name(ftype)); } FVALUE_FREE(fv); return NULL; }
static gboolean ipv6_from_unparsed(fvalue_t *fv, char *s, gboolean allow_partial_value _U_, LogFunc logfunc) { char *has_slash, *addr_str; unsigned int nmask_bits; fvalue_t *nmask_fvalue; /* Look for prefix: Is there a single slash in the string? */ if ((has_slash = strchr(s, '/'))) addr_str = ep_strndup(s, has_slash-s); else addr_str = s; if (!get_host_ipaddr6(addr_str, &(fv->value.ipv6.addr))) { logfunc("\"%s\" is not a valid hostname or IPv6 address.", s); return FALSE; } /* If prefix */ if (has_slash) { /* XXX - this is inefficient */ nmask_fvalue = fvalue_from_unparsed(FT_UINT32, has_slash+1, FALSE, logfunc); if (!nmask_fvalue) { return FALSE; } nmask_bits = fvalue_get_uinteger(nmask_fvalue); FVALUE_FREE(nmask_fvalue); if (nmask_bits > 128) { logfunc("Prefix in a IPv6 address should be <= 128, not %u", nmask_bits); return FALSE; } fv->value.ipv6.prefix = nmask_bits; } else { /* Not CIDR; mask covers entire address. */ fv->value.ipv6.prefix = 128; } return TRUE; }
fvalue_t* fvalue_from_string(ftenum_t ftype, const char *s, gchar **err_msg) { fvalue_t *fv; fv = fvalue_new(ftype); if (fv->ftype->val_from_string) { if (fv->ftype->val_from_string(fv, s, err_msg)) { /* Success */ if (err_msg != NULL) *err_msg = NULL; return fv; } } else { if (err_msg != NULL) { *err_msg = g_strdup_printf("\"%s\" cannot be converted to %s.", s, ftype_pretty_name(ftype)); } } FVALUE_FREE(fv); return NULL; }
static void check_relation_LHS_RANGE(const char *relation_string, FtypeCanFunc can_func _U_, gboolean allow_partial_value, stnode_t *st_node, stnode_t *st_arg1, stnode_t *st_arg2) { stnode_t *new_st; sttype_id_t type2; header_field_info *hfinfo1, *hfinfo2; df_func_def_t *funcdef; ftenum_t ftype1, ftype2; fvalue_t *fvalue; char *s; drange_node *rn; int len_range; type2 = stnode_type_id(st_arg2); hfinfo1 = sttype_range_hfinfo(st_arg1); ftype1 = hfinfo1->type; DebugLog((" 5 check_relation_LHS_RANGE(%s)\n", relation_string)); if (!ftype_can_slice(ftype1)) { dfilter_fail("\"%s\" is a %s and cannot be sliced into a sequence of bytes.", hfinfo1->abbrev, ftype_pretty_name(ftype1)); THROW(TypeError); } check_drange_sanity(st_arg1); if (type2 == STTYPE_FIELD) { DebugLog((" 5 check_relation_LHS_RANGE(type2 = STTYPE_FIELD)\n")); hfinfo2 = stnode_data(st_arg2); ftype2 = hfinfo2->type; if (!is_bytes_type(ftype2)) { if (!ftype_can_slice(ftype2)) { dfilter_fail("\"%s\" is a %s and cannot be converted into a sequence of bytes.", hfinfo2->abbrev, ftype_pretty_name(ftype2)); THROW(TypeError); } /* Convert entire field to bytes */ new_st = stnode_new(STTYPE_RANGE, NULL); rn = drange_node_new(); drange_node_set_start_offset(rn, 0); drange_node_set_to_the_end(rn); /* st_arg2 is freed in this step */ sttype_range_set1(new_st, st_arg2, rn); sttype_test_set2_args(st_node, st_arg1, new_st); } } else if (type2 == STTYPE_STRING) { DebugLog((" 5 check_relation_LHS_RANGE(type2 = STTYPE_STRING)\n")); s = stnode_data(st_arg2); if (strcmp(relation_string, "matches") == 0) { /* Convert to a FT_PCRE */ fvalue = fvalue_from_string(FT_PCRE, s, dfilter_fail); } else { fvalue = fvalue_from_string(FT_BYTES, s, dfilter_fail); } if (!fvalue) { DebugLog((" 5 check_relation_LHS_RANGE(type2 = STTYPE_STRING): Could not convert from string!\n")); THROW(TypeError); } new_st = stnode_new(STTYPE_FVALUE, fvalue); sttype_test_set2_args(st_node, st_arg1, new_st); stnode_free(st_arg2); } else if (type2 == STTYPE_UNPARSED) { DebugLog((" 5 check_relation_LHS_RANGE(type2 = STTYPE_UNPARSED)\n")); s = stnode_data(st_arg2); len_range = drange_get_total_length(sttype_range_drange(st_arg1)); if (strcmp(relation_string, "matches") == 0) { /* Convert to a FT_PCRE */ fvalue = fvalue_from_unparsed(FT_PCRE, s, FALSE, dfilter_fail); } /* The RHS should be FT_BYTES. However, there is a special case where * the range slice on the LHS is one byte long. In that case, it is natural * for the user to specify a normal hex integer on the RHS, with the "0x" * notation, as in "slice[0] == 0x10". We can't allow this for any * slices that are longer than one byte, because then we'd have to know * which endianness the byte string should be in. */ else if (len_range == 1 && strlen(s) == 4 && strncmp(s, "0x", 2) == 0) { /* Even if the RHS string starts with "0x", it still could fail to * be an integer. Try converting it here. */ fvalue = fvalue_from_unparsed(FT_UINT8, s, allow_partial_value, dfilter_fail); if (fvalue) { FVALUE_FREE(fvalue); /* The value doees indeed fit into 8 bits. Create a BYTE_STRING * from it. Since we know that the last 2 characters are a valid * hex string, just use those directly. */ fvalue = fvalue_from_unparsed(FT_BYTES, s+2, allow_partial_value, dfilter_fail); } } else { fvalue = fvalue_from_unparsed(FT_BYTES, s, allow_partial_value, dfilter_fail); } if (!fvalue) { DebugLog((" 5 check_relation_LHS_RANGE(type2 = STTYPE_UNPARSED): Could not convert from string!\n")); THROW(TypeError); } new_st = stnode_new(STTYPE_FVALUE, fvalue); sttype_test_set2_args(st_node, st_arg1, new_st); stnode_free(st_arg2); } else if (type2 == STTYPE_RANGE) { DebugLog((" 5 check_relation_LHS_RANGE(type2 = STTYPE_RANGE)\n")); check_drange_sanity(st_arg2); } else if (type2 == STTYPE_FUNCTION) { funcdef = sttype_function_funcdef(st_arg2); ftype2 = funcdef->retval_ftype; if (!is_bytes_type(ftype2)) { if (!ftype_can_slice(ftype2)) { dfilter_fail("Return value of function \"%s\" is a %s and cannot be converted into a sequence of bytes.", funcdef->name, ftype_pretty_name(ftype2)); THROW(TypeError); } /* XXX should I add a new drange node? */ } check_function(st_arg2); } else { g_assert_not_reached(); } }
static gboolean val_from_unparsed(fvalue_t *fv, char *s, gboolean allow_partial_value _U_, LogFunc logfunc) { guint32 addr; unsigned int nmask_bits; char *has_slash, *s_copy = NULL; char *net_str, *addr_str; fvalue_t *nmask_fvalue; /* Look for CIDR: Is there a single slash in the string? */ has_slash = strchr(s, '/'); if (has_slash) { /* Make a copy of the string and use strtok() to * get the address portion. */ s_copy = ep_strdup(s); addr_str = strtok(s_copy, "/"); /* I just checked for slash! I shouldn't get NULL here. * Double check just in case. */ if (!addr_str) { logfunc("Unexpected strtok() error parsing IP address: %s", s_copy); return FALSE; } } else { addr_str = s; } if (!get_host_ipaddr(addr_str, &addr)) { logfunc("\"%s\" is not a valid hostname or IPv4 address.", addr_str); return FALSE; } ipv4_addr_set_host_order_addr(&(fv->value.ipv4), addr); /* If CIDR, get netmask bits. */ if (has_slash) { net_str = strtok(NULL, "/"); /* I checked for slash! I shouldn't get NULL here. * Double check just in case. */ if (!net_str) { logfunc("Unexpected strtok() error parsing netmask: %s", s_copy); return FALSE; } /* XXX - this is inefficient */ nmask_fvalue = fvalue_from_unparsed(FT_UINT32, net_str, FALSE, logfunc); if (!nmask_fvalue) { return FALSE; } nmask_bits = fvalue_get_uinteger(nmask_fvalue); FVALUE_FREE(nmask_fvalue); if (nmask_bits > 32) { logfunc("Netmask bits in a CIDR IPv4 address should be <= 32, not %u", nmask_bits); return FALSE; } ipv4_addr_set_netmask_bits(&fv->value.ipv4, nmask_bits); } else { /* Not CIDR; mask covers entire address. */ ipv4_addr_set_netmask_bits(&(fv->value.ipv4), 32); } return TRUE; }