asn1: Add support for decoration w/ external types

This adds support for asn1_compile --decorate=... variation that causes
decoration of an ASN.1 SET/SEQUENCE type with a field of a non-ASN.1
type.

This means we can now have an ASN.1 type to represent a request that can
then have a "hidden" field -- hidden in that it is neither encoded nor
decoded.  This field will be copied and freed when the decoration is of
an ASN.1 type or of a external, C type that comes with copy constructor
and destructor functions.  Decoration with a `void *` field which is
neither copied nor freed is also supported.

We may end up using this to, for example, replace the `hdb_entry_ex`
type by decorating `HDB_entry` with a C type that points to the `HDB` in
which the entry was found or to which it should be written.
This commit is contained in:
Nicolas Williams
2022-01-05 23:16:48 -06:00
parent 10fc7730d0
commit df3e08485b
18 changed files with 958 additions and 244 deletions

View File

@@ -449,7 +449,10 @@ add_line_pointer(struct templatehead *t,
errx(1, "malloc");
va_end(ap);
q = add_line(t, "{ %s, %s, asn1_%s }", tt, offset, ptr);
if (ptr[0] == '&')
q = add_line(t, "{ %s, %s, %s }", tt, offset, ptr);
else
q = add_line(t, "{ %s, %s, asn1_%s }", tt, offset, ptr);
q->tt = tt;
q->offset = strdup(offset);
q->ptr = strdup(ptr);
@@ -1061,10 +1064,9 @@ template_members(struct templatehead *temp,
Field *opentypefield = NULL;
Field *typeidfield = NULL;
Member *m;
struct decoration deco;
size_t i = 0, typeididx = 0, opentypeidx = 0;
int is_array_of_open_type = 0;
int deco_opt;
char *ft, *fn;
if (isstruct && t->actual_parameter)
get_open_type_defn_fields(t, &typeidmember, &opentypemember,
@@ -1104,15 +1106,29 @@ template_members(struct templatehead *temp,
typeidfield, opentypefield, opentypemember,
is_array_of_open_type);
if (decorate_type(basetype, &ft, &fn, &deco_opt)) {
if (decorate_type(basetype, &deco)) {
char *poffset2;
poffset2 = partial_offset(basetype, fn, 1, isstruct);
add_line_pointer(temp, ft, poffset2, "A1_OP_TYPE_DECORATE %s",
deco_opt ? "|A1_FLAG_OPTIONAL" : "");
poffset2 = partial_offset(basetype, deco.field_name, 1, isstruct);
if (deco.ext) {
char *ptr = NULL;
/* Decorated with external C type */
if (asprintf(&ptr, "&asn1_extern_%s_%s",
basetype, deco.field_type) == -1 || ptr == NULL)
err(1, "out of memory");
add_line_pointer(temp, ptr, poffset2,
"A1_OP_TYPE_DECORATE_EXTERN %s",
deco.opt && !deco.void_star ? "|A1_FLAG_OPTIONAL" : "");
free(ptr);
} else
/* Decorated with a templated ASN.1 type */
add_line_pointer(temp, deco.field_type, poffset2,
"A1_OP_TYPE_DECORATE %s",
deco.opt ? "|A1_FLAG_OPTIONAL" : "");
free(poffset2);
free(ft);
free(fn);
free(deco.field_type);
}
if (isstruct)
@@ -1125,10 +1141,9 @@ template_members(struct templatehead *temp,
Field *opentypefield = NULL;
Field *typeidfield = NULL;
Member *m;
struct decoration deco;
size_t i = 0, typeididx = 0, opentypeidx = 0;
int is_array_of_open_type = 0;
int deco_opt;
char *ft, *fn;
if (isstruct && t->actual_parameter)
get_open_type_defn_fields(t, &typeidmember, &opentypemember,
@@ -1168,15 +1183,29 @@ template_members(struct templatehead *temp,
typeidfield, opentypefield, opentypemember,
is_array_of_open_type);
if (decorate_type(basetype, &ft, &fn, &deco_opt)) {
if (decorate_type(basetype, &deco)) {
char *poffset2;
poffset2 = partial_offset(basetype, fn, 1, isstruct);
add_line_pointer(temp, ft, poffset2, "A1_OP_TYPE_DECORATE %s",
deco_opt ? "|A1_FLAG_OPTIONAL" : "");
poffset2 = partial_offset(basetype, deco.field_name, 1, isstruct);
if (deco.ext) {
char *ptr = NULL;
/* Decorated with external C type */
if (asprintf(&ptr, "&asn1_extern_%s_%s",
basetype, deco.field_type) == -1 || ptr == NULL)
err(1, "out of memory");
add_line_pointer(temp, ptr, poffset2,
"A1_OP_TYPE_DECORATE_EXTERN %s",
deco.opt && !deco.void_star ? "|A1_FLAG_OPTIONAL" : "");
free(ptr);
} else
/* Decorated with a templated ASN.1 type */
add_line_pointer(temp, deco.field_type, poffset2,
"A1_OP_TYPE_DECORATE %s",
deco.opt ? "|A1_FLAG_OPTIONAL" : "");
free(poffset2);
free(ft);
free(fn);
free(deco.field_type);
}
if (isstruct)
@@ -1491,12 +1520,30 @@ generate_template(const Symbol *s)
{
FILE *f = get_code_file();
const char *dupname;
struct decoration deco;
if (use_extern(s)) {
gen_extern_stubs(f, s->gen_name);
return;
}
if (decorate_type(s->gen_name, &deco) && deco.ext) {
fprintf(f,
"static const struct asn1_type_func asn1_extern_%s_%s = {\n"
"\t(asn1_type_encode)0,\n"
"\t(asn1_type_decode)0,\n"
"\t(asn1_type_length)0,\n"
"\t(asn1_type_copy)%s,\n"
"\t(asn1_type_release)%s,\n"
"\t(asn1_type_print)0,\n"
"\tsizeof(%s)\n"
"};\n", s->gen_name, deco.field_type,
deco.copy_function_name && deco.copy_function_name[0] ? deco.copy_function_name : "0",
deco.free_function_name && deco.free_function_name[0] ? deco.free_function_name : "0",
deco.void_star ? "void *" : deco.field_type);
free(deco.field_type);
}
generate_template_type(s->gen_name, &dupname, s->name, s->gen_name, NULL, s->type, 0, 0, 1);
fprintf(f,