Combined constraints and introduced value randomizer.
diff --git a/skeletons/ANY.c b/skeletons/ANY.c
index 1e670ba..6b2c08e 100644
--- a/skeletons/ANY.c
+++ b/skeletons/ANY.c
@@ -32,16 +32,15 @@
 	ANY_decode_uper,
 	ANY_encode_uper,
 #endif  /* ASN_DISABLE_PER_SUPPORT */
+	0,	/* Random fill is not defined for ANY type */
 	0	/* Use generic outmost tag fetcher */
 };
 asn_TYPE_descriptor_t asn_DEF_ANY = {
 	"ANY",
 	"ANY",
 	&asn_OP_ANY,
-	asn_generic_no_constraint,
 	0, 0, 0, 0,
-	0,	/* No OER visible constraints */
-	0,	/* No PER visible constraints */
+	{ 0, 0, asn_generic_no_constraint },	/* No constraints */
 	0, 0,	/* No members */
 	&asn_SPC_ANY_specs,
 };
diff --git a/skeletons/BIT_STRING.c b/skeletons/BIT_STRING.c
index a68621a..b5ab945 100644
--- a/skeletons/BIT_STRING.c
+++ b/skeletons/BIT_STRING.c
@@ -39,21 +39,20 @@
 	OCTET_STRING_decode_uper,	/* Unaligned PER decoder */
 	OCTET_STRING_encode_uper,	/* Unaligned PER encoder */
 #endif  /* ASN_DISABLE_PER_SUPPORT */
+	BIT_STRING_random_fill,
 	0	/* Use generic outmost tag fetcher */
 };
 asn_TYPE_descriptor_t asn_DEF_BIT_STRING = {
 	"BIT STRING",
 	"BIT_STRING",
 	&asn_OP_BIT_STRING,
-	BIT_STRING_constraint,
 	asn_DEF_BIT_STRING_tags,
 	sizeof(asn_DEF_BIT_STRING_tags)
 	  / sizeof(asn_DEF_BIT_STRING_tags[0]),
 	asn_DEF_BIT_STRING_tags,	/* Same as above */
 	sizeof(asn_DEF_BIT_STRING_tags)
 	  / sizeof(asn_DEF_BIT_STRING_tags[0]),
-	0,	/* No OER visible constraints */
-	0,	/* No PER visible constraints */
+	{ 0, 0, BIT_STRING_constraint },
 	0, 0,	/* No members */
 	&asn_SPC_BIT_STRING_specs
 };
@@ -244,3 +243,84 @@
     }
 }
 
+
+asn_random_fill_result_t
+BIT_STRING_random_fill(const asn_TYPE_descriptor_t *td, void **sptr,
+                       const asn_encoding_constraints_t *constraints,
+                       size_t max_length) {
+    asn_OCTET_STRING_specifics_t *specs =
+        td->specifics ? (asn_OCTET_STRING_specifics_t *)td->specifics
+                      : &asn_SPC_BIT_STRING_specs;
+    asn_random_fill_result_t result_ok = {ARFILL_OK, 1};
+    asn_random_fill_result_t result_failed = {ARFILL_FAILED, 0};
+    asn_random_fill_result_t result_skipped = {ARFILL_SKIPPED, 0};
+    static unsigned lengths[] = {0,     1,     2,     3,     4,     8,
+                                 126,   127,   128,   16383, 16384, 16385,
+                                 65534, 65535, 65536, 65537};
+    uint8_t *buf;
+    uint8_t *bend;
+    uint8_t *b;
+    size_t rnd_bits, rnd_len;
+    BIT_STRING_t *st;
+
+    if(max_length == 0) return result_skipped;
+
+    switch(specs->subvariant) {
+    case ASN_OSUBV_ANY:
+        return result_failed;
+    case ASN_OSUBV_BIT:
+        break;
+    default:
+        break;
+    }
+
+    /* Figure out how far we should go */
+    rnd_bits = lengths[asn_random_between(
+        0, sizeof(lengths) / sizeof(lengths[0]) - 1)];
+    if(constraints->per_constraints) {
+        const asn_per_constraint_t *pc =
+            &td->encoding_constraints.per_constraints->size;
+        if(pc->flags & APC_CONSTRAINED) {
+            if(max_length < (size_t)pc->lower_bound) {
+                return result_skipped;
+            }
+            rnd_bits = asn_random_between(pc->lower_bound, pc->upper_bound);
+        } else {
+            rnd_bits = asn_random_between(0, max_length - 1);
+        }
+    } else if(rnd_bits >= max_length) {
+        rnd_bits = asn_random_between(0, max_length - 1);
+    }
+
+    rnd_len = (rnd_bits + 7) / 8;
+    buf = CALLOC(1, rnd_len + 1);
+    if(!buf) return result_failed;
+
+    bend = &buf[rnd_len];
+
+    for(b = buf; b < bend; b++) {
+        *(uint8_t *)b = asn_random_between(0, 255);
+    }
+
+    if(*sptr) {
+        st = *sptr;
+        FREEMEM(st->buf);
+    } else {
+        st = (BIT_STRING_t *)(*sptr = CALLOC(1, specs->struct_size));
+        if(!st) {
+            FREEMEM(buf);
+            return result_failed;
+        }
+    }
+
+    st->buf = buf;
+    st->size = rnd_len;
+    st->bits_unused = (8 - (rnd_bits & 0x7)) & 0x7;
+    if(st->bits_unused) {
+        assert(st->size > 0);
+        st->buf[st->size-1] &= 0xff << st->bits_unused;
+    }
+
+    result_ok.length = st->size;
+    return result_ok;
+}
diff --git a/skeletons/BIT_STRING.h b/skeletons/BIT_STRING.h
index 2b19584..dd7a611 100644
--- a/skeletons/BIT_STRING.h
+++ b/skeletons/BIT_STRING.h
@@ -30,6 +30,7 @@
 xer_type_encoder_f BIT_STRING_encode_xer;
 oer_type_decoder_f BIT_STRING_decode_oer;
 oer_type_encoder_f BIT_STRING_encode_oer;
+asn_random_fill_f  BIT_STRING_random_fill;
 
 #define BIT_STRING_free              OCTET_STRING_free
 #define BIT_STRING_decode_ber        OCTET_STRING_decode_ber
diff --git a/skeletons/BIT_STRING_oer.c b/skeletons/BIT_STRING_oer.c
index a470e09..e887228 100644
--- a/skeletons/BIT_STRING_oer.c
+++ b/skeletons/BIT_STRING_oer.c
@@ -15,7 +15,7 @@
                       const void *ptr, size_t size) {
     BIT_STRING_t *st = (BIT_STRING_t *)*sptr;
     const asn_oer_constraints_t *cts =
-        constraints ? constraints : td->oer_constraints;
+        constraints ? constraints : td->encoding_constraints.oer_constraints;
     ssize_t ct_size = cts ? cts->size : -1;
     asn_dec_rval_t rval = {RC_OK, 0};
     size_t expected_length = 0;
@@ -93,7 +93,7 @@
     BIT_STRING_t *st = (BIT_STRING_t *)sptr;
     asn_enc_rval_t erval = {0, 0, 0};
     const asn_oer_constraints_t *cts =
-        constraints ? constraints : td->oer_constraints;
+        constraints ? constraints : td->encoding_constraints.oer_constraints;
     ssize_t ct_size = cts ? cts->size : -1;
     size_t trailing_zeros = 0;
     int fix_last_byte = 0;
diff --git a/skeletons/BMPString.c b/skeletons/BMPString.c
index 80a3f8b..8fa583b 100644
--- a/skeletons/BMPString.c
+++ b/skeletons/BMPString.c
@@ -45,21 +45,20 @@
 	OCTET_STRING_decode_uper,
 	OCTET_STRING_encode_uper,
 #endif	/* ASN_DISABLE_PER_SUPPORT */
+	OCTET_STRING_random_fill,
 	0	/* Use generic outmost tag fetcher */
 };
 asn_TYPE_descriptor_t asn_DEF_BMPString = {
 	"BMPString",
 	"BMPString",
 	&asn_OP_BMPString,
-	BMPString_constraint,
 	asn_DEF_BMPString_tags,
 	sizeof(asn_DEF_BMPString_tags)
 	  / sizeof(asn_DEF_BMPString_tags[0]) - 1,
 	asn_DEF_BMPString_tags,
 	sizeof(asn_DEF_BMPString_tags)
 	  / sizeof(asn_DEF_BMPString_tags[0]),
-	0,	/* No OER visible constraints */
-	&asn_DEF_BMPString_per_constraints,
+	{ 0, &asn_DEF_BMPString_per_constraints, BMPString_constraint },
 	0, 0,	/* No members */
 	&asn_SPC_BMPString_specs
 };
diff --git a/skeletons/BOOLEAN.c b/skeletons/BOOLEAN.c
index 21a858c..3534003 100644
--- a/skeletons/BOOLEAN.c
+++ b/skeletons/BOOLEAN.c
@@ -34,19 +34,18 @@
 	BOOLEAN_decode_uper,	/* Unaligned PER decoder */
 	BOOLEAN_encode_uper,	/* Unaligned PER encoder */
 #endif	/* ASN_DISABLE_PER_SUPPORT */
+	BOOLEAN_random_fill,
 	0	/* Use generic outmost tag fetcher */
 };
 asn_TYPE_descriptor_t asn_DEF_BOOLEAN = {
 	"BOOLEAN",
 	"BOOLEAN",
 	&asn_OP_BOOLEAN,
-	asn_generic_no_constraint,
 	asn_DEF_BOOLEAN_tags,
 	sizeof(asn_DEF_BOOLEAN_tags) / sizeof(asn_DEF_BOOLEAN_tags[0]),
 	asn_DEF_BOOLEAN_tags,	/* Same as above */
 	sizeof(asn_DEF_BOOLEAN_tags) / sizeof(asn_DEF_BOOLEAN_tags[0]),
-	0,	/* No OER visible constraints */
-	0,	/* No PER visible constraints */
+	{ 0, 0, asn_generic_no_constraint },
 	0, 0,	/* No members */
 	0	/* No specifics */
 };
@@ -332,3 +331,29 @@
         return 1;
     }
 }
+
+asn_random_fill_result_t
+BOOLEAN_random_fill(const asn_TYPE_descriptor_t *td, void **sptr,
+                    const asn_encoding_constraints_t *constr,
+                    size_t max_length) {
+    asn_random_fill_result_t result_ok = {ARFILL_OK, 1};
+    asn_random_fill_result_t result_failed = {ARFILL_FAILED, 0};
+    asn_random_fill_result_t result_skipped = {ARFILL_SKIPPED, 0};
+    BOOLEAN_t *st = *sptr;
+
+    (void)td;
+    (void)constr;
+
+    if(max_length == 0) return result_skipped;
+
+    if(st == NULL) {
+        st = (BOOLEAN_t *)(*sptr = CALLOC(1, sizeof(*st)));
+        if(st == NULL) {
+            return result_failed;
+        }
+    }
+
+    *st = asn_random_between(0, 1);
+
+    return result_ok;
+}
diff --git a/skeletons/BOOLEAN.h b/skeletons/BOOLEAN.h
index b399b3e..b58fdd7 100644
--- a/skeletons/BOOLEAN.h
+++ b/skeletons/BOOLEAN.h
@@ -30,6 +30,7 @@
 xer_type_encoder_f BOOLEAN_encode_xer;
 per_type_decoder_f BOOLEAN_decode_uper;
 per_type_encoder_f BOOLEAN_encode_uper;
+asn_random_fill_f  BOOLEAN_random_fill;
 
 #define BOOLEAN_constraint     asn_generic_no_constraint
 
diff --git a/skeletons/ENUMERATED.c b/skeletons/ENUMERATED.c
index ffc61e3..dc6ecff 100644
--- a/skeletons/ENUMERATED.c
+++ b/skeletons/ENUMERATED.c
@@ -36,19 +36,18 @@
 	ENUMERATED_decode_uper,	/* Unaligned PER decoder */
 	ENUMERATED_encode_uper,	/* Unaligned PER encoder */
 #endif	/* ASN_DISABLE_PER_SUPPORT */
+	ENUMERATED_random_fill,
 	0	/* Use generic outmost tag fetcher */
 };
 asn_TYPE_descriptor_t asn_DEF_ENUMERATED = {
 	"ENUMERATED",
 	"ENUMERATED",
 	&asn_OP_ENUMERATED,
-	asn_generic_no_constraint,
 	asn_DEF_ENUMERATED_tags,
 	sizeof(asn_DEF_ENUMERATED_tags) / sizeof(asn_DEF_ENUMERATED_tags[0]),
 	asn_DEF_ENUMERATED_tags,	/* Same as above */
 	sizeof(asn_DEF_ENUMERATED_tags) / sizeof(asn_DEF_ENUMERATED_tags[0]),
-	0,	/* No OER visible constraints */
-	0,	/* No PER visible constraints */
+	{ 0, 0, asn_generic_no_constraint },
 	0, 0,	/* No members */
 	0	/* No specifics */
 };
diff --git a/skeletons/ENUMERATED.h b/skeletons/ENUMERATED.h
index e4df29b..6c878c4 100644
--- a/skeletons/ENUMERATED.h
+++ b/skeletons/ENUMERATED.h
@@ -27,6 +27,7 @@
 #define ENUMERATED_encode_der INTEGER_encode_der
 #define ENUMERATED_decode_xer INTEGER_decode_xer
 #define ENUMERATED_encode_xer INTEGER_encode_xer
+#define ENUMERATED_random_fill INTEGER_random_fill
 
 #ifdef __cplusplus
 }
diff --git a/skeletons/GeneralString.c b/skeletons/GeneralString.c
index c833dd5..16b6f2f 100644
--- a/skeletons/GeneralString.c
+++ b/skeletons/GeneralString.c
@@ -34,21 +34,20 @@
 	OCTET_STRING_decode_uper,    /* Implemented in terms of OCTET STRING */
 	OCTET_STRING_encode_uper,
 #endif	/* ASN_DISABLE_PER_SUPPORT */
+	OCTET_STRING_random_fill,
 	0	/* Use generic outmost tag fetcher */
 };
 asn_TYPE_descriptor_t asn_DEF_GeneralString = {
 	"GeneralString",
 	"GeneralString",
 	&asn_OP_GeneralString,
-	asn_generic_unknown_constraint,
 	asn_DEF_GeneralString_tags,
 	sizeof(asn_DEF_GeneralString_tags)
 	  / sizeof(asn_DEF_GeneralString_tags[0]) - 1,
 	asn_DEF_GeneralString_tags,
 	sizeof(asn_DEF_GeneralString_tags)
 	  / sizeof(asn_DEF_GeneralString_tags[0]),
-	0,	/* No OER visible constraints */
-	0,	/* No PER visible constraints */
+	{ 0, 0, asn_generic_unknown_constraint },
 	0, 0,	/* No members */
 	0	/* No specifics */
 };
diff --git a/skeletons/GeneralizedTime.c b/skeletons/GeneralizedTime.c
index aeebafd..97a381d 100644
--- a/skeletons/GeneralizedTime.c
+++ b/skeletons/GeneralizedTime.c
@@ -1,5 +1,5 @@
 /*-
- * Copyright (c) 2003, 2004 Lev Walkin <vlm@lionet.info>. All rights reserved.
+ * Copyright (c) 2003-2017 Lev Walkin <vlm@lionet.info>. All rights reserved.
  * Redistribution and modifications are permitted subject to BSD license.
  */
 #define	_POSIX_PTHREAD_SEMANTICS	/* for Sun */
@@ -166,7 +166,7 @@
 	(ASN_TAG_CLASS_UNIVERSAL | (26 << 2)),  /* [UNIVERSAL 26] IMPLICIT ...*/
 	(ASN_TAG_CLASS_UNIVERSAL | (4 << 2))    /* ... OCTET STRING */
 };
-static asn_per_constraints_t asn_DEF_GeneralizedTime_constraints = {
+static asn_per_constraints_t asn_DEF_GeneralizedTime_per_constraints = {
 	{ APC_CONSTRAINED, 7, 7, 0x20, 0x7e },  /* Value */
 	{ APC_SEMI_CONSTRAINED, -1, -1, 0, 0 }, /* Size */
 	0, 0
@@ -193,21 +193,20 @@
 	OCTET_STRING_decode_uper,
 	OCTET_STRING_encode_uper,
 #endif	/* ASN_DISABLE_PER_SUPPORT */
+	GeneralizedTime_random_fill,
 	0	/* Use generic outmost tag fetcher */
 };
 asn_TYPE_descriptor_t asn_DEF_GeneralizedTime = {
 	"GeneralizedTime",
 	"GeneralizedTime",
 	&asn_OP_GeneralizedTime,
-	GeneralizedTime_constraint, /* Check validity of time */
 	asn_DEF_GeneralizedTime_tags,
 	sizeof(asn_DEF_GeneralizedTime_tags)
 	  / sizeof(asn_DEF_GeneralizedTime_tags[0]) - 2,
 	asn_DEF_GeneralizedTime_tags,
 	sizeof(asn_DEF_GeneralizedTime_tags)
 	  / sizeof(asn_DEF_GeneralizedTime_tags[0]),
-	0,	/* No OER visible constraints */
-	&asn_DEF_GeneralizedTime_constraints,
+	{ 0, &asn_DEF_GeneralizedTime_per_constraints, GeneralizedTime_constraint },
 	0, 0,	/* No members */
 	0	/* No specifics */
 };
@@ -722,4 +721,34 @@
 	return opt_gt;
 }
 
+asn_random_fill_result_t
+GeneralizedTime_random_fill(const asn_TYPE_descriptor_t *td, void **sptr,
+                              const asn_encoding_constraints_t *constraints,
+                              size_t max_length) {
+    asn_random_fill_result_t result_ok = {ARFILL_OK, 1};
+    asn_random_fill_result_t result_failed = {ARFILL_FAILED, 0};
+    asn_random_fill_result_t result_skipped = {ARFILL_SKIPPED, 0};
+    static const char *values[] = {
+        "19700101000000",    "19700101000000-0000",   "19700101000000+0000",
+        "19700101000000Z",   "19700101000000.3Z",     "19821106210623.3",
+        "19821106210629.3Z", "19691106210827.3-0500", "19821106210629.456",
+    };
+    size_t rnd = asn_random_between(0, sizeof(values)/sizeof(values[0])-1);
 
+    (void)constraints;
+
+    if(max_length < sizeof("yyyymmddhhmmss")) {
+        return result_skipped;
+    }
+
+    if(*sptr) {
+        if(OCTET_STRING_fromBuf(*sptr, values[rnd], -1) != 0) {
+            if(!sptr) return result_failed;
+        }
+    } else {
+        *sptr = OCTET_STRING_new_fromBuf(td, values[rnd], -1);
+        if(!sptr) return result_failed;
+    }
+
+    return result_ok;
+}
diff --git a/skeletons/GeneralizedTime.h b/skeletons/GeneralizedTime.h
index ace9c02..84ee481 100644
--- a/skeletons/GeneralizedTime.h
+++ b/skeletons/GeneralizedTime.h
@@ -20,6 +20,7 @@
 asn_constr_check_f GeneralizedTime_constraint;
 der_type_encoder_f GeneralizedTime_encode_der;
 xer_type_encoder_f GeneralizedTime_encode_xer;
+asn_random_fill_f  GeneralizedTime_random_fill;
 
 #define GeneralizedTime_free           OCTET_STRING_free
 #define GeneralizedTime_compare        OCTET_STRING_compare
diff --git a/skeletons/GraphicString.c b/skeletons/GraphicString.c
index ecf4e52..7ec7945 100644
--- a/skeletons/GraphicString.c
+++ b/skeletons/GraphicString.c
@@ -34,21 +34,20 @@
 	OCTET_STRING_decode_uper,    /* Implemented in terms of OCTET STRING */
 	OCTET_STRING_encode_uper,
 #endif	/* ASN_DISABLE_PER_SUPPORT */
+	OCTET_STRING_random_fill,
 	0	/* Use generic outmost tag fetcher */
 };
 asn_TYPE_descriptor_t asn_DEF_GraphicString = {
 	"GraphicString",
 	"GraphicString",
 	&asn_OP_GraphicString,
-	asn_generic_unknown_constraint,
 	asn_DEF_GraphicString_tags,
 	sizeof(asn_DEF_GraphicString_tags)
 	  / sizeof(asn_DEF_GraphicString_tags[0]) - 1,
 	asn_DEF_GraphicString_tags,
 	sizeof(asn_DEF_GraphicString_tags)
 	  / sizeof(asn_DEF_GraphicString_tags[0]),
-	0,	/* No OER visible constraints */
-	0,	/* No PER visible constraints */
+	{ 0, 0, asn_generic_unknown_constraint },
 	0, 0,	/* No members */
 	0	/* No specifics */
 };
diff --git a/skeletons/IA5String.c b/skeletons/IA5String.c
index b0e06c3..6530ba3 100644
--- a/skeletons/IA5String.c
+++ b/skeletons/IA5String.c
@@ -39,21 +39,20 @@
 	OCTET_STRING_decode_uper,
 	OCTET_STRING_encode_uper,
 #endif	/* ASN_DISABLE_PER_SUPPORT */
+	OCTET_STRING_random_fill,
 	0	/* Use generic outmost tag fetcher */
 };
 asn_TYPE_descriptor_t asn_DEF_IA5String = {
 	"IA5String",
 	"IA5String",
 	&asn_OP_IA5String,
-	IA5String_constraint,       /* Constraint on the alphabet */
 	asn_DEF_IA5String_tags,
 	sizeof(asn_DEF_IA5String_tags)
 	  / sizeof(asn_DEF_IA5String_tags[0]) - 1,
 	asn_DEF_IA5String_tags,
 	sizeof(asn_DEF_IA5String_tags)
 	  / sizeof(asn_DEF_IA5String_tags[0]),
-	0,	/* No OER visible constraints */
-	&asn_DEF_IA5String_per_constraints,
+	{ 0, &asn_DEF_IA5String_per_constraints, IA5String_constraint },
 	0, 0,	/* No members */
 	0	/* No specifics */
 };
diff --git a/skeletons/INTEGER.c b/skeletons/INTEGER.c
index 9d5baff..38806db 100644
--- a/skeletons/INTEGER.c
+++ b/skeletons/INTEGER.c
@@ -36,19 +36,18 @@
 	INTEGER_decode_uper,	/* Unaligned PER decoder */
 	INTEGER_encode_uper,	/* Unaligned PER encoder */
 #endif	/* ASN_DISABLE_PER_SUPPORT */
+	INTEGER_random_fill,
 	0	/* Use generic outmost tag fetcher */
 };
 asn_TYPE_descriptor_t asn_DEF_INTEGER = {
 	"INTEGER",
 	"INTEGER",
 	&asn_OP_INTEGER,
-	asn_generic_no_constraint,
 	asn_DEF_INTEGER_tags,
 	sizeof(asn_DEF_INTEGER_tags) / sizeof(asn_DEF_INTEGER_tags[0]),
 	asn_DEF_INTEGER_tags,	/* Same as above */
 	sizeof(asn_DEF_INTEGER_tags) / sizeof(asn_DEF_INTEGER_tags[0]),
-	0,	/* No OER visible constraints */
-	0,	/* No PER visible constraints */
+	{ 0, 0, asn_generic_no_constraint },
 	0, 0,	/* No members */
 	0	/* No specifics */
 };
@@ -589,7 +588,7 @@
 		if(!st) ASN__DECODE_FAILED;
 	}
 
-	if(!constraints) constraints = td->per_constraints;
+	if(!constraints) constraints = td->encoding_constraints.per_constraints;
 	ct = constraints ? &constraints->value : 0;
 
 	if(ct && ct->flags & APC_EXTENSIBLE) {
@@ -701,7 +700,7 @@
 
 	if(!st || st->size == 0) ASN__ENCODE_FAILED;
 
-	if(!constraints) constraints = td->per_constraints;
+	if(!constraints) constraints = td->encoding_constraints.per_constraints;
 	ct = constraints ? &constraints->value : 0;
 
 	er.encoded = 0;
@@ -1152,3 +1151,80 @@
 
 }
 
+asn_random_fill_result_t
+INTEGER_random_fill(const asn_TYPE_descriptor_t *td, void **sptr,
+                    const asn_encoding_constraints_t *constraints,
+                    size_t max_length) {
+    const asn_INTEGER_specifics_t *specs =
+        (const asn_INTEGER_specifics_t *)td->specifics;
+    asn_random_fill_result_t result_ok = {ARFILL_OK, 1};
+    asn_random_fill_result_t result_failed = {ARFILL_FAILED, 0};
+    asn_random_fill_result_t result_skipped = {ARFILL_SKIPPED, 0};
+    INTEGER_t *st = *sptr;
+    const asn_INTEGER_enum_map_t *emap;
+    size_t emap_len;
+    intmax_t value;
+    int find_inside_map;
+
+    if(max_length == 0) return result_skipped;
+
+    if(st == NULL) {
+        st = (INTEGER_t *)CALLOC(1, sizeof(*st));
+        if(st == NULL) {
+            return result_failed;
+        }
+    }
+
+    if(specs) {
+        emap = specs->value2enum;
+        emap_len = specs->map_count;
+        if(specs->strict_enumeration) {
+            find_inside_map = emap_len > 0;
+        } else {
+            find_inside_map = emap_len ? asn_random_between(0, 1) : 0;
+        }
+    } else {
+        emap = 0;
+        emap_len = 0;
+        find_inside_map = 0;
+    }
+
+    if(find_inside_map) {
+        assert(emap_len > 0);
+        value = emap[asn_random_between(0, emap_len - 1)].nat_value;
+    } else {
+        const asn_per_constraint_t *ct;
+
+        static const long variants[] = {
+            -65536, -65535, -65534, -32769, -32768, -32767, -16385, -16384,
+            -16383, -257,   -256,   -255,   -254,   -129,   -128,   -127,
+            -126,   -1,     0,      1,      126,    127,    128,    129,
+            254,    255,    256,    257,    16383,  16384,  16385,  32767,
+            32768,  32769,  65534,  65535,  65536,  65537};
+        if(specs && specs->field_unsigned) {
+            assert(variants[18] == 0);
+            value = variants[asn_random_between(
+                18, sizeof(variants) / sizeof(variants[0]) - 1)];
+        } else {
+            value = variants[asn_random_between(
+                0, sizeof(variants) / sizeof(variants[0]) - 1)];
+        }
+
+        if(!constraints) constraints = &td->encoding_constraints;
+        ct = constraints ? &constraints->per_constraints->value : 0;
+        (void)ct;
+    }
+
+
+    if(asn_imax2INTEGER(st, value)) {
+        if(st == *sptr) {
+            ASN_STRUCT_RESET(*td, st);
+        } else {
+            ASN_STRUCT_FREE(*td, st);
+        }
+        return result_failed;
+    } else {
+        result_ok.length = st->size;
+        return result_ok;
+    }
+}
diff --git a/skeletons/INTEGER.h b/skeletons/INTEGER.h
index 2754b4b..70d6a3c 100644
--- a/skeletons/INTEGER.h
+++ b/skeletons/INTEGER.h
@@ -48,6 +48,7 @@
 oer_type_encoder_f INTEGER_encode_oer;
 per_type_decoder_f INTEGER_decode_uper;
 per_type_encoder_f INTEGER_encode_uper;
+asn_random_fill_f  INTEGER_random_fill;
 
 /***********************************
  * Some handy conversion routines. *
diff --git a/skeletons/INTEGER_oer.c b/skeletons/INTEGER_oer.c
index 240da87..bea2e07 100644
--- a/skeletons/INTEGER_oer.c
+++ b/skeletons/INTEGER_oer.c
@@ -32,7 +32,7 @@
     st->buf = 0;
     st->size = 0;
 
-    if(!constraints) constraints = td->oer_constraints;
+    if(!constraints) constraints = td->encoding_constraints.oer_constraints;
     if(constraints) ct = constraints->value;
 
     if(ct.width) {
@@ -113,7 +113,7 @@
 
     if(!st || st->size == 0) ASN__ENCODE_FAILED;
 
-    if(!constraints) constraints = td->oer_constraints;
+    if(!constraints) constraints = td->encoding_constraints.oer_constraints;
     if(constraints) ct = constraints->value;
 
     er.encoded = 0;
diff --git a/skeletons/ISO646String.c b/skeletons/ISO646String.c
index 6445564..86b128b 100644
--- a/skeletons/ISO646String.c
+++ b/skeletons/ISO646String.c
@@ -39,21 +39,20 @@
 	OCTET_STRING_decode_uper,
 	OCTET_STRING_encode_uper,
 #endif	/* ASN_DISABLE_PER_SUPPORT */
+	OCTET_STRING_random_fill,
 	0	/* Use generic outmost tag fetcher */
 };
 asn_TYPE_descriptor_t asn_DEF_ISO646String = {
 	"ISO646String",
 	"ISO646String",
 	&asn_OP_ISO646String,
-	VisibleString_constraint,
 	asn_DEF_ISO646String_tags,
 	sizeof(asn_DEF_ISO646String_tags)
 	  / sizeof(asn_DEF_ISO646String_tags[0]) - 1,
 	asn_DEF_ISO646String_tags,
 	sizeof(asn_DEF_ISO646String_tags)
 	  / sizeof(asn_DEF_ISO646String_tags[0]),
-	0,	/* No OER visible constraints */
-	&asn_DEF_ISO646String_per_constraints,
+	{ 0, &asn_DEF_ISO646String_per_constraints, ISO646String_constraint },
 	0, 0,	/* No members */
 	0	/* No specifics */
 };
diff --git a/skeletons/Makefile.am b/skeletons/Makefile.am
index 3d8ae04..6c66333 100644
--- a/skeletons/Makefile.am
+++ b/skeletons/Makefile.am
@@ -65,6 +65,7 @@
     asn_codecs_prim.c asn_codecs_prim.h         \
     asn_internal.h asn_system.h                 \
     asn_bit_data.c asn_bit_data.h               \
+    asn_random_fill.c asn_random_fill.h         \
     ber_decoder.c ber_decoder.h                 \
     ber_tlv_length.c ber_tlv_length.h           \
     ber_tlv_tag.c ber_tlv_tag.h                 \
diff --git a/skeletons/NULL.c b/skeletons/NULL.c
index 1354ea4..ed7f853 100644
--- a/skeletons/NULL.c
+++ b/skeletons/NULL.c
@@ -35,19 +35,18 @@
 	NULL_decode_uper,	/* Unaligned PER decoder */
 	NULL_encode_uper,	/* Unaligned PER encoder */
 #endif	/* ASN_DISABLE_PER_SUPPORT */
+	NULL_random_fill,
 	0	/* Use generic outmost tag fetcher */
 };
 asn_TYPE_descriptor_t asn_DEF_NULL = {
 	"NULL",
 	"NULL",
 	&asn_OP_NULL,
-	asn_generic_no_constraint,
 	asn_DEF_NULL_tags,
 	sizeof(asn_DEF_NULL_tags) / sizeof(asn_DEF_NULL_tags[0]),
 	asn_DEF_NULL_tags,	/* Same as above */
 	sizeof(asn_DEF_NULL_tags) / sizeof(asn_DEF_NULL_tags[0]),
-	0,	/* No OER visible constraints */
-	0,	/* No PER visible constraints */
+	{ 0, 0, asn_generic_no_constraint },
 	0, 0,	/* No members */
 	0	/* No specifics */
 };
@@ -215,3 +214,28 @@
 }
 
 #endif  /* ASN_DISABLE_PER_SUPPORT */
+
+asn_random_fill_result_t
+NULL_random_fill(const asn_TYPE_descriptor_t *td, void **sptr,
+                    const asn_encoding_constraints_t *constr,
+                    size_t max_length) {
+    asn_random_fill_result_t result_ok = {ARFILL_OK, 1};
+    asn_random_fill_result_t result_failed = {ARFILL_FAILED, 0};
+    asn_random_fill_result_t result_skipped = {ARFILL_SKIPPED, 0};
+    NULL_t *st = *sptr;
+
+    (void)td;
+    (void)constr;
+
+    if(max_length == 0) return result_skipped;
+
+    if(st == NULL) {
+        st = (NULL_t *)(*sptr = CALLOC(1, sizeof(*st)));
+        if(st == NULL) {
+            return result_failed;
+        }
+    }
+
+    return result_ok;
+}
+
diff --git a/skeletons/NULL.h b/skeletons/NULL.h
index a9bdb9f..050840a 100644
--- a/skeletons/NULL.h
+++ b/skeletons/NULL.h
@@ -30,6 +30,7 @@
 oer_type_encoder_f NULL_encode_oer;
 per_type_decoder_f NULL_decode_uper;
 per_type_encoder_f NULL_encode_uper;
+asn_random_fill_f  NULL_random_fill;
 
 #define NULL_free	BOOLEAN_free
 #define NULL_decode_ber	BOOLEAN_decode_ber
diff --git a/skeletons/NativeEnumerated.c b/skeletons/NativeEnumerated.c
index 137b951..fd24b32 100644
--- a/skeletons/NativeEnumerated.c
+++ b/skeletons/NativeEnumerated.c
@@ -40,19 +40,18 @@
 	NativeEnumerated_decode_uper,
 	NativeEnumerated_encode_uper,
 #endif	/* ASN_DISABLE_PER_SUPPORT */
+	NativeEnumerated_random_fill,
 	0	/* Use generic outmost tag fetcher */
 };
 asn_TYPE_descriptor_t asn_DEF_NativeEnumerated = {
 	"ENUMERATED",			/* The ASN.1 type is still ENUMERATED */
 	"ENUMERATED",
 	&asn_OP_NativeEnumerated,
-	asn_generic_no_constraint,
 	asn_DEF_NativeEnumerated_tags,
 	sizeof(asn_DEF_NativeEnumerated_tags) / sizeof(asn_DEF_NativeEnumerated_tags[0]),
 	asn_DEF_NativeEnumerated_tags,	/* Same as above */
 	sizeof(asn_DEF_NativeEnumerated_tags) / sizeof(asn_DEF_NativeEnumerated_tags[0]),
-	0,	/* No OER visible constraints */
-	0,	/* No PER visible constraints */
+	{ 0, 0, asn_generic_no_constraint },
 	0, 0,	/* No members */
 	0	/* No specifics */
 };
@@ -103,7 +102,8 @@
 	(void)opt_codec_ctx;
 
 	if(constraints) ct = &constraints->value;
-	else if(td->per_constraints) ct = &td->per_constraints->value;
+	else if(td->encoding_constraints.per_constraints)
+		ct = &td->encoding_constraints.per_constraints->value;
 	else ASN__DECODE_FAILED;	/* Mandatory! */
 	if(!specs) ASN__DECODE_FAILED;
 
@@ -173,7 +173,8 @@
 	if(!specs) ASN__ENCODE_FAILED;
 
 	if(constraints) ct = &constraints->value;
-	else if(td->per_constraints) ct = &td->per_constraints->value;
+	else if(td->encoding_constraints.per_constraints)
+		ct = &td->encoding_constraints.per_constraints->value;
 	else ASN__ENCODE_FAILED;	/* Mandatory! */
 
 	ASN_DEBUG("Encoding %s as NativeEnumerated", td->name);
diff --git a/skeletons/NativeEnumerated.h b/skeletons/NativeEnumerated.h
index fb4b588..dc4e323 100644
--- a/skeletons/NativeEnumerated.h
+++ b/skeletons/NativeEnumerated.h
@@ -1,5 +1,5 @@
 /*-
- * Copyright (c) 2004, 2005, 2006 Lev Walkin <vlm@lionet.info>.
+ * Copyright (c) 2004-2017 Lev Walkin <vlm@lionet.info>.
  * All rights reserved.
  * Redistribution and modifications are permitted subject to BSD license.
  */
@@ -31,6 +31,7 @@
 #define NativeEnumerated_free       NativeInteger_free
 #define NativeEnumerated_print      NativeInteger_print
 #define NativeEnumerated_compare    NativeInteger_compare
+#define NativeEnumerated_random_fill NativeInteger_random_fill
 #define NativeEnumerated_constraint asn_generic_no_constraint
 #define NativeEnumerated_decode_ber NativeInteger_decode_ber
 #define NativeEnumerated_encode_der NativeInteger_encode_der
diff --git a/skeletons/NativeInteger.c b/skeletons/NativeInteger.c
index 5ba65e1..dd40fef 100644
--- a/skeletons/NativeInteger.c
+++ b/skeletons/NativeInteger.c
@@ -41,19 +41,18 @@
 	NativeInteger_decode_uper,	/* Unaligned PER decoder */
 	NativeInteger_encode_uper,	/* Unaligned PER encoder */
 #endif	/* ASN_DISABLE_PER_SUPPORT */
+	NativeInteger_random_fill,
 	0	/* Use generic outmost tag fetcher */
 };
 asn_TYPE_descriptor_t asn_DEF_NativeInteger = {
 	"INTEGER",			/* The ASN.1 type is still INTEGER */
 	"INTEGER",
 	&asn_OP_NativeInteger,
-	asn_generic_no_constraint,
 	asn_DEF_NativeInteger_tags,
 	sizeof(asn_DEF_NativeInteger_tags) / sizeof(asn_DEF_NativeInteger_tags[0]),
 	asn_DEF_NativeInteger_tags,	/* Same as above */
 	sizeof(asn_DEF_NativeInteger_tags) / sizeof(asn_DEF_NativeInteger_tags[0]),
-	0,	/* No OER visible constraints */
-	0,	/* No PER visible constraints */
+	{ 0, 0, asn_generic_no_constraint },
 	0, 0,	/* No members */
 	0	/* No specifics */
 };
@@ -409,3 +408,71 @@
         return 1;
     }
 }
+
+asn_random_fill_result_t
+NativeInteger_random_fill(const asn_TYPE_descriptor_t *td, void **sptr,
+                          const asn_encoding_constraints_t *constraints,
+                          size_t max_length) {
+    const asn_INTEGER_specifics_t *specs =
+        (const asn_INTEGER_specifics_t *)td->specifics;
+    asn_random_fill_result_t result_ok = {ARFILL_OK, 1};
+    asn_random_fill_result_t result_failed = {ARFILL_FAILED, 0};
+    asn_random_fill_result_t result_skipped = {ARFILL_SKIPPED, 0};
+    long *st = *sptr;
+    const asn_INTEGER_enum_map_t *emap;
+    size_t emap_len;
+    intmax_t value;
+    int find_inside_map;
+
+    if(max_length == 0) return result_skipped;
+
+    if(st == NULL) {
+        st = (long *)CALLOC(1, sizeof(*st));
+        if(st == NULL) {
+            return result_failed;
+        }
+    }
+
+    if(specs) {
+        emap = specs->value2enum;
+        emap_len = specs->map_count;
+        if(specs->strict_enumeration) {
+            find_inside_map = emap_len > 0;
+        } else {
+            find_inside_map = emap_len ? asn_random_between(0, 1) : 0;
+        }
+    } else {
+        emap = 0;
+        emap_len = 0;
+        find_inside_map = 0;
+    }
+
+    if(find_inside_map) {
+        assert(emap_len > 0);
+        value = emap[asn_random_between(0, emap_len - 1)].nat_value;
+    } else {
+        const asn_per_constraint_t *ct;
+
+        static const long variants[] = {
+            -65536, -65535, -65534, -32769, -32768, -32767, -16385, -16384,
+            -16383, -257,   -256,   -255,   -254,   -129,   -128,   -127,
+            -126,   -1,     0,      1,      126,    127,    128,    129,
+            254,    255,    256,    257,    16383,  16384,  16385,  32767,
+            32768,  32769,  65534,  65535,  65536,  65537};
+        if(specs && specs->field_unsigned) {
+            assert(variants[18] == 0);
+            value = variants[asn_random_between(
+                18, sizeof(variants) / sizeof(variants[0]) - 1)];
+        } else {
+            value = variants[asn_random_between(
+                0, sizeof(variants) / sizeof(variants[0]) - 1)];
+        }
+
+        if(!constraints) constraints = &td->encoding_constraints;
+        ct = constraints ? &constraints->per_constraints->value : 0;
+        (void)ct;
+    }
+
+    *st = value;
+    return result_ok;
+}
diff --git a/skeletons/NativeInteger.h b/skeletons/NativeInteger.h
index 19ff2c8..17a6486 100644
--- a/skeletons/NativeInteger.h
+++ b/skeletons/NativeInteger.h
@@ -33,6 +33,7 @@
 oer_type_encoder_f NativeInteger_encode_oer;
 per_type_decoder_f NativeInteger_decode_uper;
 per_type_encoder_f NativeInteger_encode_uper;
+asn_random_fill_f  NativeInteger_random_fill;
 
 #define NativeInteger_constraint  asn_generic_no_constraint
 
diff --git a/skeletons/NativeReal.c b/skeletons/NativeReal.c
index 1983a3b..aba278c 100644
--- a/skeletons/NativeReal.c
+++ b/skeletons/NativeReal.c
@@ -61,19 +61,18 @@
 	NativeReal_decode_uper,
 	NativeReal_encode_uper,
 #endif	/* ASN_DISABLE_PER_SUPPORT */
+	NativeReal_random_fill,
 	0	/* Use generic outmost tag fetcher */
 };
 asn_TYPE_descriptor_t asn_DEF_NativeReal = {
 	"REAL",			/* The ASN.1 type is still REAL */
 	"REAL",
 	&asn_OP_NativeReal,
-	asn_generic_no_constraint,
 	asn_DEF_NativeReal_tags,
 	sizeof(asn_DEF_NativeReal_tags) / sizeof(asn_DEF_NativeReal_tags[0]),
 	asn_DEF_NativeReal_tags,	/* Same as above */
 	sizeof(asn_DEF_NativeReal_tags) / sizeof(asn_DEF_NativeReal_tags[0]),
-	0,	/* No OER visible constraints */
-	0,	/* No PER visible constraints */
+	{ 0, 0, asn_generic_no_constraint },
 	0, 0,	/* No members */
 	0	/* No specifics */
 };
@@ -422,3 +421,36 @@
     }
 }
 
+
+asn_random_fill_result_t
+NativeReal_random_fill(const asn_TYPE_descriptor_t *td, void **sptr,
+                       const asn_encoding_constraints_t *constraints,
+                       size_t max_length) {
+    asn_random_fill_result_t result_ok = {ARFILL_OK, 1};
+    asn_random_fill_result_t result_failed = {ARFILL_FAILED, 0};
+    asn_random_fill_result_t result_skipped = {ARFILL_SKIPPED, 0};
+    static const double values[] = {0, -0.0, -1, 1, INFINITY, -INFINITY, NAN};
+    double *st;
+    double d;
+
+    (void)td;
+    (void)constraints;
+
+    if(max_length == 0) return result_skipped;
+
+    d = values[asn_random_between(0, sizeof(values) / sizeof(values[0]) - 1)];
+
+    if(*sptr) {
+        st = *sptr;
+    } else {
+        st = (double *)(*sptr = CALLOC(1, sizeof(double)));
+        if(!st) {
+            return result_failed;
+        }
+    }
+
+    *st = d;
+
+    result_ok.length = sizeof(double);
+    return result_ok;
+}
diff --git a/skeletons/NativeReal.h b/skeletons/NativeReal.h
index cfdd1bd..b373923 100644
--- a/skeletons/NativeReal.h
+++ b/skeletons/NativeReal.h
@@ -29,6 +29,7 @@
 xer_type_encoder_f NativeReal_encode_xer;
 per_type_decoder_f NativeReal_decode_uper;
 per_type_encoder_f NativeReal_encode_uper;
+asn_random_fill_f  NativeReal_random_fill;
 
 #define NativeReal_constraint  asn_generic_no_constraint
 
diff --git a/skeletons/NumericString.c b/skeletons/NumericString.c
index 4dd4c2f..891e4f5 100644
--- a/skeletons/NumericString.c
+++ b/skeletons/NumericString.c
@@ -59,21 +59,20 @@
 	OCTET_STRING_decode_uper,
 	OCTET_STRING_encode_uper,
 #endif	/* ASN_DISABLE_PER_SUPPORT */
+	OCTET_STRING_random_fill,
 	0	/* Use generic outmost tag fetcher */
 };
 asn_TYPE_descriptor_t asn_DEF_NumericString = {
 	"NumericString",
 	"NumericString",
 	&asn_OP_NumericString,
-	NumericString_constraint,
 	asn_DEF_NumericString_tags,
 	sizeof(asn_DEF_NumericString_tags)
 	  / sizeof(asn_DEF_NumericString_tags[0]) - 1,
 	asn_DEF_NumericString_tags,
 	sizeof(asn_DEF_NumericString_tags)
 	  / sizeof(asn_DEF_NumericString_tags[0]),
-	0,	/* No OER visible constraints */
-	&asn_DEF_NumericString_per_constraints,
+	{ 0, &asn_DEF_NumericString_per_constraints, NumericString_constraint },
 	0, 0,	/* No members */
 	0	/* No specifics */
 };
diff --git a/skeletons/OBJECT_IDENTIFIER.c b/skeletons/OBJECT_IDENTIFIER.c
index c0142ee..e7478a0 100644
--- a/skeletons/OBJECT_IDENTIFIER.c
+++ b/skeletons/OBJECT_IDENTIFIER.c
@@ -37,21 +37,20 @@
 	OCTET_STRING_decode_uper,
 	OCTET_STRING_encode_uper,
 #endif	/* ASN_DISABLE_PER_SUPPORT */
+	OBJECT_IDENTIFIER_random_fill,
 	0	/* Use generic outmost tag fetcher */
 };
 asn_TYPE_descriptor_t asn_DEF_OBJECT_IDENTIFIER = {
 	"OBJECT IDENTIFIER",
 	"OBJECT_IDENTIFIER",
 	&asn_OP_OBJECT_IDENTIFIER,
-	OBJECT_IDENTIFIER_constraint,
 	asn_DEF_OBJECT_IDENTIFIER_tags,
 	sizeof(asn_DEF_OBJECT_IDENTIFIER_tags)
 	    / sizeof(asn_DEF_OBJECT_IDENTIFIER_tags[0]),
 	asn_DEF_OBJECT_IDENTIFIER_tags,	/* Same as above */
 	sizeof(asn_DEF_OBJECT_IDENTIFIER_tags)
 	    / sizeof(asn_DEF_OBJECT_IDENTIFIER_tags[0]),
-	0,	/* No OER visible constraints */
-	0,	/* No PER visible constraints */
+	{ 0, 0, OBJECT_IDENTIFIER_constraint },
 	0, 0,	/* No members */
 	0	/* No specifics */
 };
@@ -781,4 +780,61 @@
 	return -1;
 }
 
+/*
+ * Generate values from the list of interesting values, or just a random
+ * value up to the upper limit.
+ */
+static uint32_t
+OBJECT_IDENTIFIER__biased_random_arc(int32_t upper_bound) {
+    static const uint16_t values[] = {0, 1, 127, 128, 129, 254, 255, 256};
 
+    size_t idx = asn_random_between(0, 2 * sizeof(values)/sizeof(values[0]));
+    if(idx < sizeof(values) / sizeof(values[0])) {
+        if(values[idx] < upper_bound) {
+            return values[idx];
+        }
+    }
+
+    return asn_random_between(0, upper_bound);
+}
+
+asn_random_fill_result_t
+OBJECT_IDENTIFIER_random_fill(const asn_TYPE_descriptor_t *td, void **sptr,
+                              const asn_encoding_constraints_t *constraints,
+                              size_t max_length) {
+    asn_random_fill_result_t result_ok = {ARFILL_OK, 1};
+    asn_random_fill_result_t result_failed = {ARFILL_FAILED, 0};
+    asn_random_fill_result_t result_skipped = {ARFILL_SKIPPED, 0};
+    OBJECT_IDENTIFIER_t *st;
+    uint32_t arcs[5];
+    size_t arcs_len = asn_random_between(2, 5);
+    size_t i;
+
+    (void)constraints;
+
+    if(max_length < arcs_len) return result_skipped;
+
+    if(*sptr) {
+        st = *sptr;
+    } else {
+        st = CALLOC(1, sizeof(*st));
+    }
+
+    arcs[0] = asn_random_between(0, 2);
+    arcs[1] =
+        OBJECT_IDENTIFIER__biased_random_arc(arcs[0] <= 1 ? 39 : INT32_MAX);
+    for(i = 2; i < arcs_len; i++) {
+        arcs[i] = OBJECT_IDENTIFIER__biased_random_arc(INT32_MAX);
+    }
+
+    if(OBJECT_IDENTIFIER_set_arcs(st, arcs, sizeof(arcs[0]), arcs_len)) {
+        if(st != *sptr) {
+            ASN_STRUCT_FREE(*td, st);
+        }
+        return result_failed;
+    }
+
+    *sptr = st;
+
+    return result_ok;
+}
diff --git a/skeletons/OBJECT_IDENTIFIER.h b/skeletons/OBJECT_IDENTIFIER.h
index 2501a54..02dde9c 100644
--- a/skeletons/OBJECT_IDENTIFIER.h
+++ b/skeletons/OBJECT_IDENTIFIER.h
@@ -24,6 +24,7 @@
 der_type_encoder_f OBJECT_IDENTIFIER_encode_der;
 xer_type_decoder_f OBJECT_IDENTIFIER_decode_xer;
 xer_type_encoder_f OBJECT_IDENTIFIER_encode_xer;
+asn_random_fill_f  OBJECT_IDENTIFIER_random_fill;
 
 #define OBJECT_IDENTIFIER_free           ASN__PRIMITIVE_TYPE_free
 #define OBJECT_IDENTIFIER_compare        OCTET_STRING_compare
diff --git a/skeletons/OCTET_STRING.c b/skeletons/OCTET_STRING.c
index 2f2efc4..05ef112 100644
--- a/skeletons/OCTET_STRING.c
+++ b/skeletons/OCTET_STRING.c
@@ -42,21 +42,20 @@
 	OCTET_STRING_decode_uper,	/* Unaligned PER decoder */
 	OCTET_STRING_encode_uper,	/* Unaligned PER encoder */
 #endif	/* ASN_DISABLE_PER_SUPPORT */
+	OCTET_STRING_random_fill,
 	0	/* Use generic outmost tag fetcher */
 };
 asn_TYPE_descriptor_t asn_DEF_OCTET_STRING = {
 	"OCTET STRING",		/* Canonical name */
 	"OCTET_STRING",		/* XML tag name */
 	&asn_OP_OCTET_STRING,
-	asn_generic_no_constraint,
 	asn_DEF_OCTET_STRING_tags,
 	sizeof(asn_DEF_OCTET_STRING_tags)
 	  / sizeof(asn_DEF_OCTET_STRING_tags[0]),
 	asn_DEF_OCTET_STRING_tags,	/* Same as above */
 	sizeof(asn_DEF_OCTET_STRING_tags)
 	  / sizeof(asn_DEF_OCTET_STRING_tags[0]),
-	0,	/* No OER visible constraints */
-	0,	/* No PER visible constraints */
+	{ 0, 0, asn_generic_no_constraint },
 	0, 0,	/* No members */
 	&asn_SPC_OCTET_STRING_specs
 };
@@ -1353,7 +1352,7 @@
 		? (asn_OCTET_STRING_specifics_t *)td->specifics
 		: &asn_SPC_OCTET_STRING_specs;
     const asn_per_constraints_t *pc =
-        constraints ? constraints : td->per_constraints;
+        constraints ? constraints : td->encoding_constraints.per_constraints;
     const asn_per_constraint_t *cval;
 	const asn_per_constraint_t *csiz;
 	asn_dec_rval_t rval = { RC_OK, 0 };
@@ -1524,7 +1523,7 @@
 		? (asn_OCTET_STRING_specifics_t *)td->specifics
 		: &asn_SPC_OCTET_STRING_specs;
 	const asn_per_constraints_t *pc = constraints ? constraints
-				: td->per_constraints;
+				: td->encoding_constraints.per_constraints;
 	const asn_per_constraint_t *cval;
 	const asn_per_constraint_t *csiz;
 	const BIT_STRING_t *st = (const BIT_STRING_t *)sptr;
@@ -1834,11 +1833,12 @@
 }
 
 OCTET_STRING_t *
-OCTET_STRING_new_fromBuf(asn_TYPE_descriptor_t *td, const char *str, int len) {
-	asn_OCTET_STRING_specifics_t *specs = td->specifics
-				? (asn_OCTET_STRING_specifics_t *)td->specifics
-				: &asn_SPC_OCTET_STRING_specs;
-	OCTET_STRING_t *st;
+OCTET_STRING_new_fromBuf(const asn_TYPE_descriptor_t *td, const char *str,
+                         int len) {
+    const asn_OCTET_STRING_specifics_t *specs =
+        td->specifics ? (const asn_OCTET_STRING_specifics_t *)td->specifics
+                      : &asn_SPC_OCTET_STRING_specs;
+    OCTET_STRING_t *st;
 
 	st = (OCTET_STRING_t *)CALLOC(1, specs->struct_size);
 	if(st && str && OCTET_STRING_fromBuf(st, str, len)) {
@@ -1898,3 +1898,146 @@
 
 }
 
+/*
+ * Biased function for randomizing character values around their limits.
+ */
+static uint32_t
+OCTET_STRING__random_char(unsigned long lb, unsigned long ub) {
+    assert(lb <= ub);
+    switch(asn_random_between(0, 16)) {
+    case 0:
+        if(lb < ub) return lb + 1;
+        /* Fall through */
+    case 1:
+        return lb;
+    case 2:
+        if(lb < ub) return ub - 1;
+        /* Fall through */
+    case 3:
+        return ub;
+    default:
+        return asn_random_between(lb, ub);
+    }
+}
+
+asn_random_fill_result_t
+OCTET_STRING_random_fill(const asn_TYPE_descriptor_t *td, void **sptr,
+                         const asn_encoding_constraints_t *constraints,
+                         size_t max_length) {
+	asn_OCTET_STRING_specifics_t *specs = td->specifics
+				? (asn_OCTET_STRING_specifics_t *)td->specifics
+				: &asn_SPC_OCTET_STRING_specs;
+    asn_random_fill_result_t result_ok = {ARFILL_OK, 1};
+    asn_random_fill_result_t result_failed = {ARFILL_FAILED, 0};
+    asn_random_fill_result_t result_skipped = {ARFILL_SKIPPED, 0};
+    static unsigned lengths[] = {0,     1,     2,     3,     4,     8,
+                                 126,   127,   128,   16383, 16384, 16385,
+                                 65534, 65535, 65536, 65537};
+    unsigned int unit_bytes = 1;
+    unsigned long clb = 0;  /* Lower bound on char */
+    unsigned long cub = 255;  /* Higher bound on char value */
+    uint8_t *buf;
+    uint8_t *bend;
+    uint8_t *b;
+    size_t rnd_len;
+    OCTET_STRING_t *st;
+
+    if(max_length == 0) return result_skipped;
+
+    switch(specs->subvariant) {
+    default:
+    case ASN_OSUBV_ANY:
+        return result_failed;
+    case ASN_OSUBV_BIT:
+        /* Handled by BIT_STRING itself. */
+        return result_failed;
+	case ASN_OSUBV_STR:
+        unit_bytes = 1;
+        clb = 0;
+        cub = 255;
+		break;
+	case ASN_OSUBV_U16:
+        unit_bytes = 2;
+        clb = 0;
+        cub = 65535;
+		break;
+	case ASN_OSUBV_U32:
+        unit_bytes = 4;
+        clb = 0;
+        cub = 0x10FFFF;
+		break;
+	}
+
+    if(!constraints) constraints = &td->encoding_constraints;
+    if(constraints->per_constraints) {
+        const asn_per_constraint_t *pc =
+            &td->encoding_constraints.per_constraints->value;
+        if(pc->flags & APC_SEMI_CONSTRAINED) {
+            clb = pc->lower_bound;
+        } else if(pc->flags & APC_CONSTRAINED) {
+            clb = pc->lower_bound;
+            cub = pc->upper_bound;
+        }
+    }
+
+    /* Figure out how far we should go */
+    rnd_len = lengths[asn_random_between(
+        0, sizeof(lengths) / sizeof(lengths[0]) - 1)];
+    if(constraints->per_constraints) {
+        const asn_per_constraint_t *pc =
+            &td->encoding_constraints.per_constraints->size;
+        if(pc->flags & APC_CONSTRAINED) {
+            if(max_length < (size_t)pc->lower_bound) {
+                return result_skipped;
+            }
+            rnd_len = asn_random_between(pc->lower_bound, pc->upper_bound);
+        } else {
+            rnd_len = asn_random_between(0, max_length - 1);
+        }
+    } else if(rnd_len >= max_length) {
+        rnd_len = asn_random_between(0, max_length - 1);
+    }
+
+    buf = CALLOC(unit_bytes, rnd_len + 1);
+    if(!buf) return result_failed;
+
+    bend = &buf[unit_bytes * rnd_len];
+
+    switch(unit_bytes) {
+    case 1:
+        for(b = buf; b < bend; b += unit_bytes) {
+            *(uint8_t *)b = OCTET_STRING__random_char(clb, cub);
+        }
+        *(uint8_t *)b = 0;
+        break;
+    case 2:
+        for(b = buf; b < bend; b += unit_bytes) {
+            *(uint16_t *)b = OCTET_STRING__random_char(clb, cub);
+        }
+        *(uint16_t *)b = 0;
+        break;
+    case 4:
+        for(b = buf; b < bend; b += unit_bytes) {
+            *(uint32_t *)b = OCTET_STRING__random_char(clb, cub);
+        }
+        *(uint32_t *)b = 0;
+        break;
+    }
+
+    if(*sptr) {
+        st = *sptr;
+        FREEMEM(st->buf);
+    } else {
+        st = (OCTET_STRING_t *)(*sptr = CALLOC(1, specs->struct_size));
+        if(!st) {
+            FREEMEM(buf);
+            return result_failed;
+        }
+    }
+
+    st->buf = buf;
+    st->size = unit_bytes * rnd_len;
+
+    result_ok.length = st->size;
+    return result_ok;
+}
diff --git a/skeletons/OCTET_STRING.h b/skeletons/OCTET_STRING.h
index 211bc14..ade23bf 100644
--- a/skeletons/OCTET_STRING.h
+++ b/skeletons/OCTET_STRING.h
@@ -36,6 +36,7 @@
 oer_type_encoder_f OCTET_STRING_encode_oer;
 per_type_decoder_f OCTET_STRING_decode_uper;
 per_type_encoder_f OCTET_STRING_encode_uper;
+asn_random_fill_f  OCTET_STRING_random_fill;
 
 #define OCTET_STRING_constraint  asn_generic_no_constraint
 #define OCTET_STRING_decode_xer  OCTET_STRING_decode_xer_hex
@@ -63,8 +64,8 @@
  * allocated object. NULL is permitted in str: the function will just allocate
  * empty OCTET STRING.
  */
-OCTET_STRING_t *OCTET_STRING_new_fromBuf(asn_TYPE_descriptor_t *td,
-	const char *str, int size);
+OCTET_STRING_t *OCTET_STRING_new_fromBuf(const asn_TYPE_descriptor_t *td,
+                                         const char *str, int size);
 
 /****************************
  * Internally useful stuff. *
diff --git a/skeletons/OCTET_STRING_oer.c b/skeletons/OCTET_STRING_oer.c
index 4ea705a..646ce68 100644
--- a/skeletons/OCTET_STRING_oer.c
+++ b/skeletons/OCTET_STRING_oer.c
@@ -20,7 +20,7 @@
             : (asn_OCTET_STRING_specifics_t *)&asn_SPC_OCTET_STRING_specs;
     OCTET_STRING_t *st = (OCTET_STRING_t *)*sptr;
     const asn_oer_constraints_t *cts =
-        constraints ? constraints : td->oer_constraints;
+        constraints ? constraints : td->encoding_constraints.oer_constraints;
     ssize_t ct_size = cts ? cts->size : -1;
     asn_dec_rval_t rval = {RC_OK, 0};
     size_t expected_length = 0;
@@ -110,7 +110,7 @@
             : (asn_OCTET_STRING_specifics_t *)&asn_SPC_OCTET_STRING_specs;
     OCTET_STRING_t *st = (OCTET_STRING_t *)sptr;
     const asn_oer_constraints_t *cts =
-        constraints ? constraints : td->oer_constraints;
+        constraints ? constraints : td->encoding_constraints.oer_constraints;
     ssize_t ct_size = cts ? cts->size : -1;
     asn_enc_rval_t er = {0, 0, 0};
 
diff --git a/skeletons/OPEN_TYPE.c b/skeletons/OPEN_TYPE.c
index 9417d9a..e490504 100644
--- a/skeletons/OPEN_TYPE.c
+++ b/skeletons/OPEN_TYPE.c
@@ -23,6 +23,7 @@
 	OPEN_TYPE_decode_uper,
 	OPEN_TYPE_encode_uper,
 #endif
+	0,  /* Random fill is not supported for open type */
 	0,	/* Use generic outmost tag fetcher */
 };
 
diff --git a/skeletons/ObjectDescriptor.c b/skeletons/ObjectDescriptor.c
index 145e24a..79042c0 100644
--- a/skeletons/ObjectDescriptor.c
+++ b/skeletons/ObjectDescriptor.c
@@ -34,21 +34,20 @@
 	OCTET_STRING_decode_uper,
 	OCTET_STRING_encode_uper,
 #endif	/* ASN_DISABLE_PER_SUPPORT */
+	0,	/* Not supported for ObjectDescriptor */
 	0	/* Use generic outmost tag fetcher */
 };
 asn_TYPE_descriptor_t asn_DEF_ObjectDescriptor = {
 	"ObjectDescriptor",
 	"ObjectDescriptor",
 	&asn_OP_ObjectDescriptor,
-	asn_generic_unknown_constraint,
 	asn_DEF_ObjectDescriptor_tags,
 	sizeof(asn_DEF_ObjectDescriptor_tags)
 	  / sizeof(asn_DEF_ObjectDescriptor_tags[0]) - 1,
 	asn_DEF_ObjectDescriptor_tags,
 	sizeof(asn_DEF_ObjectDescriptor_tags)
 	  / sizeof(asn_DEF_ObjectDescriptor_tags[0]),
-	0,	/* No OER visible constraints */
-	0,	/* No PER visible constraints */
+	{ 0, 0, asn_generic_unknown_constraint },
 	0, 0,	/* No members */
 	0	/* No specifics */
 };
diff --git a/skeletons/PrintableString.c b/skeletons/PrintableString.c
index 7c634f1..0cf1741 100644
--- a/skeletons/PrintableString.c
+++ b/skeletons/PrintableString.c
@@ -69,21 +69,20 @@
 	OCTET_STRING_decode_uper,
 	OCTET_STRING_encode_uper,
 #endif	/* ASN_DISABLE_PER_SUPPORT */
+	OCTET_STRING_random_fill,
 	0	/* Use generic outmost tag fetcher */
 };
 asn_TYPE_descriptor_t asn_DEF_PrintableString = {
 	"PrintableString",
 	"PrintableString",
 	&asn_OP_PrintableString,
-	PrintableString_constraint,
 	asn_DEF_PrintableString_tags,
 	sizeof(asn_DEF_PrintableString_tags)
 	  / sizeof(asn_DEF_PrintableString_tags[0]) - 1,
 	asn_DEF_PrintableString_tags,
 	sizeof(asn_DEF_PrintableString_tags)
 	  / sizeof(asn_DEF_PrintableString_tags[0]),
-	0,	/* No OER visible constraints */
-	&asn_DEF_PrintableString_per_constraints,
+	{ 0, &asn_DEF_PrintableString_per_constraints, PrintableString_constraint },
 	0, 0,	/* No members */
 	0	/* No specifics */
 };
diff --git a/skeletons/REAL.c b/skeletons/REAL.c
index cc7d641..53961a4 100644
--- a/skeletons/REAL.c
+++ b/skeletons/REAL.c
@@ -1,5 +1,5 @@
 /*-
- * Copyright (c) 2004-2013 Lev Walkin <vlm@lionet.info>. All rights reserved.
+ * Copyright (c) 2004-2017 Lev Walkin <vlm@lionet.info>. All rights reserved.
  * Redistribution and modifications are permitted subject to BSD license.
  */
 #define	_ISOC99_SOURCE		/* For ilogb() and quiet NAN */
@@ -88,19 +88,18 @@
 	REAL_decode_uper,
 	REAL_encode_uper,
 #endif	/* ASN_DISABLE_PER_SUPPORT */
+	REAL_random_fill,
 	0	/* Use generic outmost tag fetcher */
 };
 asn_TYPE_descriptor_t asn_DEF_REAL = {
 	"REAL",
 	"REAL",
 	&asn_OP_REAL,
-	asn_generic_no_constraint,
 	asn_DEF_REAL_tags,
 	sizeof(asn_DEF_REAL_tags) / sizeof(asn_DEF_REAL_tags[0]),
 	asn_DEF_REAL_tags, /* Same as above */
 	sizeof(asn_DEF_REAL_tags) / sizeof(asn_DEF_REAL_tags[0]),
-	0,	/* No OER visible constraints */
-	0,	/* No PER visible constraints */
+	{ 0, 0, asn_generic_no_constraint },
 	0,
 	0,	/* No members */
 	0	/* No specifics */
@@ -848,3 +847,43 @@
 }
 
 #endif  /* ASN_DISABLE_PER_SUPPORT */
+
+
+asn_random_fill_result_t
+REAL_random_fill(const asn_TYPE_descriptor_t *td, void **sptr,
+                       const asn_encoding_constraints_t *constraints,
+                       size_t max_length) {
+    asn_random_fill_result_t result_ok = {ARFILL_OK, 1};
+    asn_random_fill_result_t result_failed = {ARFILL_FAILED, 0};
+    asn_random_fill_result_t result_skipped = {ARFILL_SKIPPED, 0};
+    static const double values[] = {0, -0.0, -1, 1, INFINITY, -INFINITY, NAN};
+    REAL_t *st;
+    double d;
+
+    (void)constraints;
+
+    if(max_length == 0) return result_skipped;
+
+    d = values[asn_random_between(0, sizeof(values) / sizeof(values[0]) - 1)];
+
+    if(*sptr) {
+        st = *sptr;
+    } else {
+        st = (REAL_t*)(*sptr = CALLOC(1, sizeof(REAL_t)));
+        if(!st) {
+            return result_failed;
+        }
+    }
+
+    if(asn_double2REAL(st, d)) {
+        if(st == *sptr) {
+            ASN_STRUCT_RESET(*td, st);
+        } else {
+            ASN_STRUCT_FREE(*td, st);
+        }
+        return result_failed;
+    }
+
+    result_ok.length = st->size;
+    return result_ok;
+}
diff --git a/skeletons/REAL.h b/skeletons/REAL.h
index 8bc0623..6c26ef1 100644
--- a/skeletons/REAL.h
+++ b/skeletons/REAL.h
@@ -23,6 +23,7 @@
 xer_type_encoder_f REAL_encode_xer;
 per_type_decoder_f REAL_decode_uper;
 per_type_encoder_f REAL_encode_uper;
+asn_random_fill_f  REAL_random_fill;
 
 #define REAL_free          ASN__PRIMITIVE_TYPE_free,
 #define REAL_constraint    asn_generic_no_constraint
diff --git a/skeletons/RELATIVE-OID.c b/skeletons/RELATIVE-OID.c
index 82850f1..6edecfa 100644
--- a/skeletons/RELATIVE-OID.c
+++ b/skeletons/RELATIVE-OID.c
@@ -1,5 +1,5 @@
 /*-
- * Copyright (c) 2003, 2004, 2005 Lev Walkin <vlm@lionet.info>.
+ * Copyright (c) 2003-2017 Lev Walkin <vlm@lionet.info>.
  * 	All rights reserved.
  * Redistribution and modifications are permitted subject to BSD license.
  */
@@ -38,21 +38,20 @@
 	OCTET_STRING_decode_uper,
 	OCTET_STRING_encode_uper,
 #endif	/* ASN_DISABLE_PER_SUPPORT */
+	RELATIVE_OID_random_fill,
 	0	/* Use generic outmost tag fetcher */
 };
 asn_TYPE_descriptor_t asn_DEF_RELATIVE_OID = {
 	"RELATIVE-OID",
 	"RELATIVE_OID",
 	&asn_OP_RELATIVE_OID,
-	asn_generic_no_constraint,
 	asn_DEF_RELATIVE_OID_tags,
 	sizeof(asn_DEF_RELATIVE_OID_tags)
 	    / sizeof(asn_DEF_RELATIVE_OID_tags[0]),
 	asn_DEF_RELATIVE_OID_tags,	/* Same as above */
 	sizeof(asn_DEF_RELATIVE_OID_tags)
 	    / sizeof(asn_DEF_RELATIVE_OID_tags[0]),
-	0,	/* No OER visible constraints */
-	0,	/* No PER visible constraints */
+	{ 0, 0, asn_generic_no_constraint },
 	0, 0,	/* No members */
 	0	/* No specifics */
 };
@@ -255,3 +254,56 @@
 	return 0;
 }
 
+
+/*
+ * Generate values from the list of interesting values, or just a random value.
+ */
+static uint32_t
+RELATIVE_OID__biased_random_arc() {
+    static const uint16_t values[] = {0, 1, 127, 128, 129, 254, 255, 256};
+
+    size_t idx = asn_random_between(0, 2 * sizeof(values)/sizeof(values[0]));
+    if(idx < sizeof(values) / sizeof(values[0])) {
+        return values[idx];
+    }
+
+    return asn_random_between(0, INT32_MAX);
+}
+
+asn_random_fill_result_t
+RELATIVE_OID_random_fill(const asn_TYPE_descriptor_t *td, void **sptr,
+                              const asn_encoding_constraints_t *constraints,
+                              size_t max_length) {
+    asn_random_fill_result_t result_ok = {ARFILL_OK, 1};
+    asn_random_fill_result_t result_failed = {ARFILL_FAILED, 0};
+    asn_random_fill_result_t result_skipped = {ARFILL_SKIPPED, 0};
+    RELATIVE_OID_t *st;
+    uint32_t arcs[3];
+    size_t arcs_len = asn_random_between(0, 3);
+    size_t i;
+
+    (void)constraints;
+
+    if(max_length < arcs_len) return result_skipped;
+
+    if(*sptr) {
+        st = *sptr;
+    } else {
+        st = CALLOC(1, sizeof(*st));
+    }
+
+    for(i = 0; i < arcs_len; i++) {
+        arcs[i] = RELATIVE_OID__biased_random_arc();
+    }
+
+    if(RELATIVE_OID_set_arcs(st, arcs, sizeof(arcs[0]), arcs_len)) {
+        if(st != *sptr) {
+            ASN_STRUCT_FREE(*td, st);
+        }
+        return result_failed;
+    }
+
+    *sptr = st;
+
+    return result_ok;
+}
diff --git a/skeletons/RELATIVE-OID.h b/skeletons/RELATIVE-OID.h
index 4a73d27..f24c392 100644
--- a/skeletons/RELATIVE-OID.h
+++ b/skeletons/RELATIVE-OID.h
@@ -20,6 +20,7 @@
 asn_struct_print_f RELATIVE_OID_print;
 xer_type_decoder_f RELATIVE_OID_decode_xer;
 xer_type_encoder_f RELATIVE_OID_encode_xer;
+asn_random_fill_f  RELATIVE_OID_random_fill;
 
 #define RELATIVE_OID_free         ASN__PRIMITIVE_TYPE_free
 #define RELATIVE_OID_compare      OCTET_STRING_compare
diff --git a/skeletons/T61String.c b/skeletons/T61String.c
index efb7df8..c7e5f00 100644
--- a/skeletons/T61String.c
+++ b/skeletons/T61String.c
@@ -34,21 +34,20 @@
 	OCTET_STRING_decode_uper,
 	OCTET_STRING_encode_uper,
 #endif	/* ASN_DISABLE_PER_SUPPORT */
+	OCTET_STRING_random_fill,
 	0	/* Use generic outmost tag fetcher */
 };
 asn_TYPE_descriptor_t asn_DEF_T61String = {
 	"T61String",
 	"T61String",
 	&asn_OP_T61String,
-	asn_generic_unknown_constraint,
 	asn_DEF_T61String_tags,
 	sizeof(asn_DEF_T61String_tags)
 	  / sizeof(asn_DEF_T61String_tags[0]) - 1,
 	asn_DEF_T61String_tags,
 	sizeof(asn_DEF_T61String_tags)
 	  / sizeof(asn_DEF_T61String_tags[0]),
-	0,	/* No OER visible constraints */
-	0,	/* No PER visible constraints */
+	{ 0, 0, asn_generic_unknown_constraint },
 	0, 0,	/* No members */
 	0	/* No specifics */
 };
diff --git a/skeletons/TeletexString.c b/skeletons/TeletexString.c
index 31f8433..6c13f73 100644
--- a/skeletons/TeletexString.c
+++ b/skeletons/TeletexString.c
@@ -34,21 +34,20 @@
 	OCTET_STRING_decode_uper,
 	OCTET_STRING_encode_uper,
 #endif	/* ASN_DISABLE_PER_SUPPORT */
+	OCTET_STRING_random_fill,
 	0	/* Use generic outmost tag fetcher */
 };
 asn_TYPE_descriptor_t asn_DEF_TeletexString = {
 	"TeletexString",
 	"TeletexString",
 	&asn_OP_TeletexString,
-	asn_generic_unknown_constraint,
 	asn_DEF_TeletexString_tags,
 	sizeof(asn_DEF_TeletexString_tags)
 	  / sizeof(asn_DEF_TeletexString_tags[0]) - 1,
 	asn_DEF_TeletexString_tags,
 	sizeof(asn_DEF_TeletexString_tags)
 	  / sizeof(asn_DEF_TeletexString_tags[0]),
-	0,	/* No OER visible constraints */
-	0,	/* No PER visible constraints */
+	{ 0, 0, asn_generic_unknown_constraint },
 	0, 0,	/* No members */
 	0	/* No specifics */
 };
diff --git a/skeletons/UTCTime.c b/skeletons/UTCTime.c
index 32c5817..55c7506 100644
--- a/skeletons/UTCTime.c
+++ b/skeletons/UTCTime.c
@@ -50,21 +50,20 @@
 	OCTET_STRING_decode_uper,
 	OCTET_STRING_encode_uper,
 #endif	/* ASN_DISABLE_PER_SUPPORT */
+	UTCTime_random_fill,
 	0	/* Use generic outmost tag fetcher */
 };
 asn_TYPE_descriptor_t asn_DEF_UTCTime = {
 	"UTCTime",
 	"UTCTime",
 	&asn_OP_UTCTime,
-	UTCTime_constraint,
 	asn_DEF_UTCTime_tags,
 	sizeof(asn_DEF_UTCTime_tags)
 	  / sizeof(asn_DEF_UTCTime_tags[0]) - 2,
 	asn_DEF_UTCTime_tags,
 	sizeof(asn_DEF_UTCTime_tags)
 	  / sizeof(asn_DEF_UTCTime_tags[0]),
-	0,	/* No OER visible constraints */
-	&asn_DEF_UTCTime_constraints,
+	{ 0, &asn_DEF_UTCTime_constraints, UTCTime_constraint },
 	0, 0,	/* No members */
 	0	/* No specifics */
 };
@@ -194,3 +193,35 @@
 	return (UTCTime_t *)gt;
 }
 
+
+asn_random_fill_result_t
+UTCTime_random_fill(const asn_TYPE_descriptor_t *td, void **sptr,
+                    const asn_encoding_constraints_t *constraints,
+                    size_t max_length) {
+    asn_random_fill_result_t result_ok = {ARFILL_OK, 1};
+    asn_random_fill_result_t result_failed = {ARFILL_FAILED, 0};
+    asn_random_fill_result_t result_skipped = {ARFILL_SKIPPED, 0};
+    static const char *values[] = {
+        "700101000000",  "700101000000-0000", "700101000000+0000",
+        "700101000000Z", "821106210623",      "691106210827-0500",
+        "821106210629Z",
+    };
+    size_t rnd = asn_random_between(0, sizeof(values)/sizeof(values[0])-1);
+
+    (void)constraints;
+
+    if(max_length < sizeof("yymmddhhmmss")) {
+        return result_skipped;
+    }
+
+    if(*sptr) {
+        if(OCTET_STRING_fromBuf(*sptr, values[rnd], -1) != 0) {
+            if(!sptr) return result_failed;
+        }
+    } else {
+        *sptr = OCTET_STRING_new_fromBuf(td, values[rnd], -1);
+        if(!sptr) return result_failed;
+    }
+
+    return result_ok;
+}
diff --git a/skeletons/UTCTime.h b/skeletons/UTCTime.h
index 5537020..629bf06 100644
--- a/skeletons/UTCTime.h
+++ b/skeletons/UTCTime.h
@@ -19,6 +19,7 @@
 asn_struct_print_f UTCTime_print;
 asn_constr_check_f UTCTime_constraint;
 xer_type_encoder_f UTCTime_encode_xer;
+asn_random_fill_f  UTCTime_random_fill;
 
 #define UTCTime_free         OCTET_STRING_free
 #define UTCTime_compare      OCTET_STRING_compare
diff --git a/skeletons/UTF8String.c b/skeletons/UTF8String.c
index 7a6de6d..7d7cd8b 100644
--- a/skeletons/UTF8String.c
+++ b/skeletons/UTF8String.c
@@ -35,21 +35,20 @@
 	OCTET_STRING_decode_uper,
 	OCTET_STRING_encode_uper,
 #endif	/* ASN_DISABLE_PER_SUPPORT */
+	UTF8String_random_fill,
 	0	/* Use generic outmost tag fetcher */
 };
 asn_TYPE_descriptor_t asn_DEF_UTF8String = {
 	"UTF8String",
 	"UTF8String",
 	&asn_OP_UTF8String,
-	UTF8String_constraint,      /* Check for invalid codes, etc. */
 	asn_DEF_UTF8String_tags,
 	sizeof(asn_DEF_UTF8String_tags)
 	  / sizeof(asn_DEF_UTF8String_tags[0]) - 1,
 	asn_DEF_UTF8String_tags,
 	sizeof(asn_DEF_UTF8String_tags)
 	  / sizeof(asn_DEF_UTF8String_tags[0]),
-	0,	/* No OER visible constraints */
-	0,	/* No PER visible constraints */
+	{ 0, 0, UTF8String_constraint },
 	0, 0,	/* No members */
 	0	/* No specifics */
 };
@@ -199,3 +198,100 @@
 		return (cb("<absent>", 8, app_key) < 0) ? -1 : 0;
 	}
 }
+
+
+/*
+ * Biased function for randomizing UTF-8 sequences.
+ */
+static uint32_t
+UTF8String__random_char(uint8_t *b, size_t size) {
+    struct rnd_value {
+        const char *value;
+        size_t size;
+    };
+    static const struct rnd_value values[] = {{"\0", 1},
+                                              {"\x01", 1},
+                                              {"\x7f", 1},
+                                              {"\xc2\xa2", 2},
+                                              {"\xe2\x82\xac", 3},
+                                              {"\xf0\x90\x8d\x88", 4},
+                                              {"\xf4\x8f\xbf\xbf", 4}};
+
+    const struct rnd_value *v;
+    size_t max_idx;
+
+    switch(size) {
+    case 0:
+        assert(size != 0);
+        return 0;
+    case 1:
+        max_idx = 2;
+        break;
+    case 2:
+        max_idx = 3;
+        break;
+    case 4:
+        return sizeof(values) / sizeof(values[0]) - 1;
+    }
+
+    v = &values[asn_random_between(0, max_idx)];
+    memcpy(b, v->value, v->size);
+    return v->size;
+}
+
+asn_random_fill_result_t
+UTF8String_random_fill(const asn_TYPE_descriptor_t *td, void **sptr,
+                       const asn_encoding_constraints_t *constraints,
+                       size_t max_length) {
+    asn_random_fill_result_t result_ok = {ARFILL_OK, 1};
+    asn_random_fill_result_t result_failed = {ARFILL_FAILED, 0};
+    asn_random_fill_result_t result_skipped = {ARFILL_SKIPPED, 0};
+    static unsigned lengths[] = {0,     1,     2,     3,     4,     8,
+                                 126,   127,   128,   16383, 16384, 16385,
+                                 65534, 65535, 65536, 65537};
+    uint8_t *buf;
+    uint8_t *bend;
+    uint8_t *b;
+    size_t rnd_len;
+    size_t idx;
+    UTF8String_t *st;
+
+    (void)td;
+    (void)constraints;
+
+    if(max_length == 0) return result_skipped;
+
+    /* Figure out how far we should go */
+    rnd_len = lengths[asn_random_between(
+        0, sizeof(lengths) / sizeof(lengths[0]) - 1)];
+    if(4 * rnd_len >= max_length) {
+        rnd_len = asn_random_between(0, (max_length - 1) / 4);
+    }
+
+    buf = CALLOC(4, rnd_len + 1);
+    if(!buf) return result_failed;
+
+    bend = &buf[4 * rnd_len];
+
+    for(b = buf, idx = 0; idx < rnd_len; idx++) {
+        b += UTF8String__random_char(b, (bend - b));
+    }
+    *(uint8_t *)b = 0;
+
+    if(*sptr) {
+        st = *sptr;
+        FREEMEM(st->buf);
+    } else {
+        st = (OCTET_STRING_t *)(*sptr = CALLOC(1, sizeof(UTF8String_t)));
+        if(!st) {
+            FREEMEM(buf);
+            return result_failed;
+        }
+    }
+    assert(UTF8String_length(st) == (ssize_t)rnd_len);
+
+    st->buf = buf;
+    st->size = b - buf;
+
+    return result_ok;
+}
diff --git a/skeletons/UTF8String.h b/skeletons/UTF8String.h
index 1853573..4deec26 100644
--- a/skeletons/UTF8String.h
+++ b/skeletons/UTF8String.h
@@ -18,6 +18,7 @@
 
 asn_struct_print_f UTF8String_print;
 asn_constr_check_f UTF8String_constraint;
+asn_random_fill_f  UTF8String_random_fill;
 
 #define UTF8String_free         OCTET_STRING_free
 #define UTF8String_compare      OCTET_STRING_compare
diff --git a/skeletons/UniversalString.c b/skeletons/UniversalString.c
index 453c6a8..8d99cad 100644
--- a/skeletons/UniversalString.c
+++ b/skeletons/UniversalString.c
@@ -45,21 +45,20 @@
 	OCTET_STRING_decode_uper,
 	OCTET_STRING_encode_uper,
 #endif	/* ASN_DISABLE_PER_SUPPORT */
+	OCTET_STRING_random_fill,
 	0	/* Use generic outmost tag fetcher */
 };
 asn_TYPE_descriptor_t asn_DEF_UniversalString = {
 	"UniversalString",
 	"UniversalString",
 	&asn_OP_UniversalString,
-	UniversalString_constraint,
 	asn_DEF_UniversalString_tags,
 	sizeof(asn_DEF_UniversalString_tags)
 	  / sizeof(asn_DEF_UniversalString_tags[0]) - 1,
 	asn_DEF_UniversalString_tags,
 	sizeof(asn_DEF_UniversalString_tags)
 	  / sizeof(asn_DEF_UniversalString_tags[0]),
-	0,	/* No OER visible constraints */
-	&asn_DEF_UniversalString_per_constraints,
+	{ 0, &asn_DEF_UniversalString_per_constraints, UniversalString_constraint },
 	0, 0,	/* No members */
 	&asn_SPC_UniversalString_specs
 };
diff --git a/skeletons/VideotexString.c b/skeletons/VideotexString.c
index 6e4fc36..06fe4a7 100644
--- a/skeletons/VideotexString.c
+++ b/skeletons/VideotexString.c
@@ -34,21 +34,20 @@
 	OCTET_STRING_decode_uper,    /* Implemented in terms of OCTET STRING */
 	OCTET_STRING_encode_uper,
 #endif	/* ASN_DISABLE_PER_SUPPORT */
+	OCTET_STRING_random_fill,
 	0	/* Use generic outmost tag fetcher */
 };
 asn_TYPE_descriptor_t asn_DEF_VideotexString = {
 	"VideotexString",
 	"VideotexString",
 	&asn_OP_VideotexString,
-	asn_generic_unknown_constraint,
 	asn_DEF_VideotexString_tags,
 	sizeof(asn_DEF_VideotexString_tags)
 	  / sizeof(asn_DEF_VideotexString_tags[0]) - 1,
 	asn_DEF_VideotexString_tags,
 	sizeof(asn_DEF_VideotexString_tags)
 	  / sizeof(asn_DEF_VideotexString_tags[0]),
-	0,	/* No OER visible constraints */
-	0,	/* No PER visible constraints */
+	{ 0, 0, asn_generic_unknown_constraint },
 	0, 0,	/* No members */
 	0	/* No specifics */
 };
diff --git a/skeletons/VisibleString.c b/skeletons/VisibleString.c
index f8d651b..fe2762f 100644
--- a/skeletons/VisibleString.c
+++ b/skeletons/VisibleString.c
@@ -39,21 +39,20 @@
 	OCTET_STRING_decode_uper,
 	OCTET_STRING_encode_uper,
 #endif	/* ASN_DISABLE_PER_SUPPORT */
+	OCTET_STRING_random_fill,
 	0	/* Use generic outmost tag fetcher */
 };
 asn_TYPE_descriptor_t asn_DEF_VisibleString = {
 	"VisibleString",
 	"VisibleString",
 	&asn_OP_VisibleString,
-	VisibleString_constraint,
 	asn_DEF_VisibleString_tags,
 	sizeof(asn_DEF_VisibleString_tags)
 	  / sizeof(asn_DEF_VisibleString_tags[0]) - 1,
 	asn_DEF_VisibleString_tags,
 	sizeof(asn_DEF_VisibleString_tags)
 	  / sizeof(asn_DEF_VisibleString_tags[0]),
-	0,	/* No OER visible constraints */
-	&asn_DEF_VisibleString_constraints,
+	{ 0, &asn_DEF_VisibleString_constraints, VisibleString_constraint },
 	0, 0,	/* No members */
 	0	/* No specifics */
 };
diff --git a/skeletons/asn_application.c b/skeletons/asn_application.c
index 46f1aa8..b558d46 100644
--- a/skeletons/asn_application.c
+++ b/skeletons/asn_application.c
@@ -151,6 +151,35 @@
     }
 
     switch(syntax) {
+    case ATS_NONSTANDARD_PLAINTEXT:
+        if(td->op->print_struct) {
+            struct callback_count_bytes_key cb_key;
+            cb_key.callback = callback;
+            cb_key.callback_key = callback_key;
+            cb_key.computed_size = 0;
+            if(td->op->print_struct(td, sptr, 1, callback_count_bytes_cb,
+                                    &cb_key)
+                   < 0
+               || callback_count_bytes_cb("\n", 1, &cb_key) < 0) {
+                errno = EBADF; /* Structure has incorrect form. */
+                er.encoded = -1;
+                er.failed_type = td;
+                er.structure_ptr = sptr;
+            } else {
+                er.encoded = cb_key.computed_size;
+                er.failed_type = 0;
+                er.structure_ptr = 0;
+            }
+        } else {
+            errno = ENOENT; /* Transfer syntax is not defined for this type. */
+            ASN__ENCODE_FAILED;
+        }
+        break;
+
+    case ATS_RANDOM:
+        errno = ENOENT; /* Randomization doesn't make sense on output. */
+        ASN__ENCODE_FAILED;
+
     case ATS_BER:
         /* BER is a superset of DER. */
         /* Fall through. */
@@ -260,31 +289,6 @@
         }
         break;
 
-    case ATS_NONSTANDARD_PLAINTEXT:
-        if(td->op->print_struct) {
-            struct callback_count_bytes_key cb_key;
-            cb_key.callback = callback;
-            cb_key.callback_key = callback_key;
-            cb_key.computed_size = 0;
-            if(td->op->print_struct(td, sptr, 1, callback_count_bytes_cb,
-                                    &cb_key)
-                   < 0
-               || callback_count_bytes_cb("\n", 1, &cb_key) < 0) {
-                errno = EBADF; /* Structure has incorrect form. */
-                er.encoded = -1;
-                er.failed_type = td;
-                er.structure_ptr = sptr;
-            } else {
-                er.encoded = cb_key.computed_size;
-                er.failed_type = 0;
-                er.structure_ptr = 0;
-            }
-        } else {
-            errno = ENOENT; /* Transfer syntax is not defined for this type. */
-            ASN__ENCODE_FAILED;
-        }
-        break;
-
     default:
         errno = ENOENT;
         ASN__ENCODE_FAILED;
@@ -298,7 +302,7 @@
            enum asn_transfer_syntax syntax, struct asn_TYPE_descriptor_s *td,
            void **sptr, const void *buffer, size_t size) {
 
-    if(!td || !sptr || (size && !buffer)) {
+    if(!td || !td->op || !sptr || (size && !buffer)) {
         ASN__DECODE_FAILED;
     }
 
@@ -309,6 +313,19 @@
         errno = ENOENT;
         ASN__DECODE_FAILED;
 
+    case ATS_RANDOM:
+        if(!td->op->random_fill) {
+            ASN__DECODE_FAILED;
+        } else {
+            if(asn_random_fill(td, sptr, 16000) == 0) {
+                asn_dec_rval_t ret = {RC_OK, 0};
+                return ret;
+            } else {
+                ASN__DECODE_FAILED;
+            }
+        }
+        break;
+
     case ATS_DER:
     case ATS_BER:
         return ber_decode(opt_codec_ctx, td, sptr, buffer, size);
diff --git a/skeletons/asn_application.h b/skeletons/asn_application.h
index b8b0b9e..d75a2ce 100644
--- a/skeletons/asn_application.h
+++ b/skeletons/asn_application.h
@@ -22,8 +22,10 @@
 enum asn_transfer_syntax {
     /* Avoid appearance of a default transfer syntax. */
     ATS_INVALID = 0,
-    /* Plaintext output, useful for debugging. */
+    /* Plaintext output (not conforming to any standard), for debugging. */
     ATS_NONSTANDARD_PLAINTEXT,
+    /* Returns a randomly generatede structure. */
+    ATS_RANDOM,
     /*
      * X.690:
      * BER: Basic Encoding Rules.
diff --git a/skeletons/asn_random_fill.c b/skeletons/asn_random_fill.c
new file mode 100644
index 0000000..39e7eaa
--- /dev/null
+++ b/skeletons/asn_random_fill.c
@@ -0,0 +1,30 @@
+/*
+ * Copyright (c) 2017 Lev Walkin <vlm@lionet.info>.
+ * All rights reserved.
+ * Redistribution and modifications are permitted subject to BSD license.
+ */
+
+#include <asn_internal.h>
+#include <asn_random_fill.h>
+#include <constr_TYPE.h>
+
+int
+asn_random_fill(const struct asn_TYPE_descriptor_s *td, void **struct_ptr,
+                size_t length) {
+
+    if(td && td->op->random_fill) {
+        asn_random_fill_result_t res =
+            td->op->random_fill(td, struct_ptr, 0, length);
+        return (res.code == ARFILL_OK) ? 0 : -1;
+    } else {
+        return -1;
+    }
+}
+
+intmax_t
+asn_random_between(intmax_t a, intmax_t b) {
+    assert(a <= b);
+    assert((b-a) < RAND_MAX);
+    if(a == b) return a;
+    return a + (random() % (b - a));
+}
diff --git a/skeletons/asn_random_fill.h b/skeletons/asn_random_fill.h
new file mode 100644
index 0000000..bfaa13e
--- /dev/null
+++ b/skeletons/asn_random_fill.h
@@ -0,0 +1,52 @@
+/*
+ * Copyright (c) 2017 Lev Walkin <vlm@lionet.info>.
+ * All rights reserved.
+ * Redistribution and modifications are permitted subject to BSD license.
+ */
+#ifndef	ASN_RANDOM_FILL
+#define	ASN_RANDOM_FILL
+
+/* Forward declarations */
+struct asn_TYPE_descriptor_s;
+struct asn_encoding_constraints_s;
+
+/*
+ * Initialize a structure with random data according to the type specification
+ * and optional member constraints.
+ * ARGUMENTS:
+ *  (max_length)        - See (approx_max_length_limit).
+ *  (memb_constraints)  - Member constraints, if exist.
+ *                        The type can be constrained differently according
+ *                        to PER and OER specifications, so we find a value
+ *                        at the intersection of these constraints.
+ * In case the return differs from ARFILL_OK, the (struct_ptr) contents
+ * and (current_length) value remain in their original state.
+ */
+typedef struct asn_random_fill_result_s {
+    enum {
+        ARFILL_FAILED = -1, /* System error (memory?) */
+        ARFILL_OK = 0,      /* Initialization succeeded */
+        ARFILL_SKIPPED = 1  /* Not done due to (length?) constraint */
+    } code;
+    size_t length; /* Approximate number of bytes created. */
+} asn_random_fill_result_t;
+typedef asn_random_fill_result_t(asn_random_fill_f)(
+    const struct asn_TYPE_descriptor_s *td, void **struct_ptr,
+    const struct asn_encoding_constraints_s *memb_constraints,
+    size_t max_length);
+
+/*
+ * Returns 0 if the structure was properly initialized, -1 otherwise.
+ * The (approx_max_length_limit) specifies the approximate limit of the
+ * resulting structure in units closely resembling bytes. The actual result
+ * might be several times larger or smaller than the length limit.
+ */
+int asn_random_fill(const struct asn_TYPE_descriptor_s *td, void **struct_ptr,
+                    size_t approx_max_length_limit);
+
+/*
+ * Returns a random number between min and max.
+ */
+intmax_t asn_random_between(intmax_t min, intmax_t max);
+
+#endif	/* ASN_RANDOM_FILL */
diff --git a/skeletons/constr_CHOICE.c b/skeletons/constr_CHOICE.c
index d99e1bd..b4b5c88 100644
--- a/skeletons/constr_CHOICE.c
+++ b/skeletons/constr_CHOICE.c
@@ -516,18 +516,12 @@
 			memb_ptr = (const void *)((const char *)sptr + elm->memb_offset);
 		}
 
-		if(elm->memb_constraints) {
-			return elm->memb_constraints(elm->type, memb_ptr,
+		if(elm->encoding_constraints.general_constraints) {
+			return elm->encoding_constraints.general_constraints(elm->type, memb_ptr,
 				ctfailcb, app_key);
 		} else {
-			int ret = elm->type->check_constraints(elm->type,
+			return elm->type->encoding_constraints.general_constraints(elm->type,
 					memb_ptr, ctfailcb, app_key);
-			/*
-			 * Cannot inherit it eralier:
-			 * need to make sure we get the updated version.
-			 */
-			elm->memb_constraints = elm->type->check_constraints;
-			return ret;
 		}
 	} else {
 		ASN__CTFAIL(app_key, td, sptr,
@@ -855,7 +849,7 @@
 	}
 
 	if(constraints) ct = &constraints->value;
-	else if(td->per_constraints) ct = &td->per_constraints->value;
+	else if(td->encoding_constraints.per_constraints) ct = &td->encoding_constraints.per_constraints->value;
 	else ct = 0;
 
 	if(ct && ct->flags & APC_EXTENSIBLE) {
@@ -900,10 +894,10 @@
 
 	if(ct && ct->range_bits >= 0) {
 		rv = elm->type->op->uper_decoder(opt_codec_ctx, elm->type,
-			elm->per_constraints, memb_ptr2, pd);
+			elm->encoding_constraints.per_constraints, memb_ptr2, pd);
 	} else {
 		rv = uper_open_type_get(opt_codec_ctx, elm->type,
-			elm->per_constraints, memb_ptr2, pd);
+			elm->encoding_constraints.per_constraints, memb_ptr2, pd);
 	}
 
 	if(rv.code != RC_OK)
@@ -928,7 +922,8 @@
 	ASN_DEBUG("Encoding %s as CHOICE", td->name);
 
 	if(constraints) ct = &constraints->value;
-	else if(td->per_constraints) ct = &td->per_constraints->value;
+	else if(td->encoding_constraints.per_constraints)
+		ct = &td->encoding_constraints.per_constraints->value;
 	else ct = 0;
 
 	present = _fetch_present_idx(sptr, specs->pres_offset, specs->pres_size);
@@ -979,7 +974,7 @@
 		if(per_put_few_bits(po, present_enc, ct->range_bits))
 			ASN__ENCODE_FAILED;
 
-		return elm->type->op->uper_encoder(elm->type, elm->per_constraints,
+		return elm->type->op->uper_encoder(elm->type, elm->encoding_constraints.per_constraints,
 			memb_ptr, po);
 	} else {
 		asn_enc_rval_t rval;
@@ -987,7 +982,7 @@
 			ASN__ENCODE_FAILED;
 		if(uper_put_nsnnwn(po, present_enc - specs->ext_start))
 			ASN__ENCODE_FAILED;
-		if(uper_open_type_put(elm->type, elm->per_constraints,
+		if(uper_open_type_put(elm->type, elm->encoding_constraints.per_constraints,
 			memb_ptr, po))
 			ASN__ENCODE_FAILED;
 		rval.encoded = 0;
@@ -1239,6 +1234,61 @@
     return 0;
 }
 
+
+asn_random_fill_result_t
+CHOICE_random_fill(const asn_TYPE_descriptor_t *td, void **sptr,
+                   const asn_encoding_constraints_t *constr,
+                   size_t max_length) {
+    const asn_CHOICE_specifics_t *specs =
+        (const asn_CHOICE_specifics_t *)td->specifics;
+    asn_random_fill_result_t res;
+    asn_random_fill_result_t result_failed = {ARFILL_FAILED, 0};
+    asn_random_fill_result_t result_skipped = {ARFILL_SKIPPED, 0};
+    const asn_TYPE_member_t *elm;
+    unsigned present;
+    void *memb_ptr;   /* Pointer to the member */
+    void **memb_ptr2; /* Pointer to that pointer */
+    void *st = *sptr;
+
+    if(max_length == 0) return result_skipped;
+
+    (void)constr;
+
+    if(st == NULL) {
+        st = CALLOC(1, specs->struct_size);
+        if(st == NULL) {
+            return result_failed;
+        }
+    }
+
+    present = asn_random_between(1, td->elements_count);
+    elm = &td->elements[present - 1];
+
+	if(elm->flags & ATF_POINTER) {
+		/* Member is a pointer to another structure */
+		memb_ptr2 = (void **)((char *)st + elm->memb_offset);
+	} else {
+		memb_ptr = (char *)st + elm->memb_offset;
+		memb_ptr2 = &memb_ptr;
+	}
+
+    res = elm->type->op->random_fill(elm->type, memb_ptr2,
+                                    &elm->encoding_constraints, max_length);
+    _set_present_idx(st, specs->pres_offset, specs->pres_size, present);
+    if(res.code == ARFILL_OK) {
+        *sptr = st;
+    } else {
+        if(st == *sptr) {
+            ASN_STRUCT_RESET(*td, st);
+        } else {
+            ASN_STRUCT_FREE(*td, st);
+        }
+    }
+
+    return res;
+}
+
+
 asn_TYPE_operation_t asn_OP_CHOICE = {
 	CHOICE_free,
 	CHOICE_print,
@@ -1261,5 +1311,6 @@
 	CHOICE_decode_uper,
 	CHOICE_encode_uper,
 #endif	/* ASN_DISABLE_PER_SUPPORT */
+	CHOICE_random_fill,
 	CHOICE_outmost_tag
 };
diff --git a/skeletons/constr_CHOICE.h b/skeletons/constr_CHOICE.h
index c7e0b90..c23d8e1 100644
--- a/skeletons/constr_CHOICE.h
+++ b/skeletons/constr_CHOICE.h
@@ -52,6 +52,7 @@
 per_type_decoder_f CHOICE_decode_uper;
 per_type_encoder_f CHOICE_encode_uper;
 asn_outmost_tag_f CHOICE_outmost_tag;
+asn_random_fill_f CHOICE_random_fill;
 extern asn_TYPE_operation_t asn_OP_CHOICE;
 
 /*
diff --git a/skeletons/constr_CHOICE_oer.c b/skeletons/constr_CHOICE_oer.c
index b975fd1..ed8c761 100644
--- a/skeletons/constr_CHOICE_oer.c
+++ b/skeletons/constr_CHOICE_oer.c
@@ -244,7 +244,7 @@
         }
 
         rval = elm->type->op->oer_decoder(opt_codec_ctx, elm->type,
-                                          elm->oer_constraints, memb_ptr2, ptr,
+                                          elm->encoding_constraints.oer_constraints, memb_ptr2, ptr,
                                           size);
         rval.consumed += consumed_myself;
         switch(rval.code) {
@@ -353,7 +353,7 @@
         ASN__ENCODE_FAILED;
     }
 
-    er = elm->type->op->oer_encoder(elm->type, elm->oer_constraints, memb_ptr,
+    er = elm->type->op->oer_encoder(elm->type, elm->encoding_constraints.oer_constraints, memb_ptr,
                                     cb, app_key);
     if(er.encoded > 0)
         er.encoded += tag_len;
diff --git a/skeletons/constr_SEQUENCE.c b/skeletons/constr_SEQUENCE.c
index 4ba4b08..0b9693e 100644
--- a/skeletons/constr_SEQUENCE.c
+++ b/skeletons/constr_SEQUENCE.c
@@ -1059,19 +1059,13 @@
 			memb_ptr = (const void *)((const char *)sptr + elm->memb_offset);
 		}
 
-		if(elm->memb_constraints) {
-			int ret = elm->memb_constraints(elm->type, memb_ptr,
+		if(elm->encoding_constraints.general_constraints) {
+			int ret = elm->encoding_constraints.general_constraints(elm->type, memb_ptr,
 				ctfailcb, app_key);
 			if(ret) return ret;
 		} else {
-			int ret = elm->type->check_constraints(elm->type,
+			return elm->type->encoding_constraints.general_constraints(elm->type,
 				memb_ptr, ctfailcb, app_key);
-			if(ret) return ret;
-			/*
-			 * Cannot inherit it earlier:
-			 * need to make sure we get the updated version.
-			 */
-			elm->memb_constraints = elm->type->check_constraints;
 		}
 	}
 
@@ -1178,7 +1172,7 @@
 			rv = OPEN_TYPE_uper_get(opt_codec_ctx, td, st, elm, pd);
 		} else {
 			rv = elm->type->op->uper_decoder(opt_codec_ctx, elm->type,
-					elm->per_constraints, memb_ptr2, pd);
+					elm->encoding_constraints.per_constraints, memb_ptr2, pd);
 		}
 		if(rv.code != RC_OK) {
 			ASN_DEBUG("Failed decode %s in %s",
@@ -1247,7 +1241,7 @@
 
 		ASN_DEBUG("Decoding member %s in %s %p", elm->name, td->name, *memb_ptr2);
 		rv = uper_open_type_get(opt_codec_ctx, elm->type,
-			elm->per_constraints, memb_ptr2, pd);
+			elm->encoding_constraints.per_constraints, memb_ptr2, pd);
 		if(rv.code != RC_OK) {
 			FREEMEM(epres);
 			return rv;
@@ -1345,7 +1339,7 @@
 			return -1;
 		/* Encode as open type field */
 		if(po2 && present && uper_open_type_put(elm->type,
-				elm->per_constraints, *memb_ptr2, po2))
+				elm->encoding_constraints.per_constraints, *memb_ptr2, po2))
 			return -1;
 
 	}
@@ -1458,7 +1452,7 @@
 			continue;
 
 		ASN_DEBUG("Encoding %s->%s", td->name, elm->name);
-		er = elm->type->op->uper_encoder(elm->type, elm->per_constraints,
+		er = elm->type->op->uper_encoder(elm->type, elm->encoding_constraints.per_constraints,
 			*memb_ptr2, po);
 		if(er.encoded == -1)
 			return er;
@@ -1544,6 +1538,75 @@
 	SEQUENCE_decode_uper,
 	SEQUENCE_encode_uper,
 #endif /* ASN_DISABLE_PER_SUPPORT */
+	SEQUENCE_random_fill,
 	0	/* Use generic outmost tag fetcher */
 };
 
+
+asn_random_fill_result_t
+SEQUENCE_random_fill(const asn_TYPE_descriptor_t *td, void **sptr,
+                   const asn_encoding_constraints_t *constr,
+                   size_t max_length) {
+    const asn_SEQUENCE_specifics_t *specs =
+        (const asn_SEQUENCE_specifics_t *)td->specifics;
+    asn_random_fill_result_t result_ok = {ARFILL_OK, 0};
+    asn_random_fill_result_t result_failed = {ARFILL_FAILED, 0};
+    asn_random_fill_result_t result_skipped = {ARFILL_SKIPPED, 0};
+    void *st = *sptr;
+    size_t edx;
+
+    if(max_length == 0) return result_skipped;
+
+    (void)constr;
+
+    if(st == NULL) {
+        st = CALLOC(1, specs->struct_size);
+        if(st == NULL) {
+            return result_failed;
+        }
+    }
+
+    for(edx = 0; edx < td->elements_count; edx++) {
+        const asn_TYPE_member_t *elm = &td->elements[edx];
+        void *memb_ptr;   /* Pointer to the member */
+        void **memb_ptr2; /* Pointer to that pointer */
+        asn_random_fill_result_t tmpres;
+
+        if(elm->optional && asn_random_between(0, 4) == 2) {
+            /* Sometimes decide not to fill the optional value */
+            continue;
+        }
+
+        if(elm->flags & ATF_POINTER) {
+            /* Member is a pointer to another structure */
+            memb_ptr2 = (void **)((char *)st + elm->memb_offset);
+        } else {
+            memb_ptr = (char *)st + elm->memb_offset;
+            memb_ptr2 = &memb_ptr;
+        }
+
+        tmpres = elm->type->op->random_fill(
+            elm->type, memb_ptr2, &elm->encoding_constraints,
+            max_length > result_ok.length ? max_length - result_ok.length : 0);
+        switch(tmpres.code) {
+        case ARFILL_OK:
+            result_ok.length += tmpres.length;
+            continue;
+        case ARFILL_SKIPPED:
+            assert(!(elm->flags & ATF_POINTER) || *memb_ptr2 == NULL);
+            continue;
+        case ARFILL_FAILED:
+            if(st == *sptr) {
+                ASN_STRUCT_RESET(*td, st);
+            } else {
+                ASN_STRUCT_FREE(*td, st);
+            }
+            return tmpres;
+        }
+    }
+
+    *sptr = st;
+
+    return result_ok;
+}
+
diff --git a/skeletons/constr_SEQUENCE.h b/skeletons/constr_SEQUENCE.h
index e4d3801..e2df003 100644
--- a/skeletons/constr_SEQUENCE.h
+++ b/skeletons/constr_SEQUENCE.h
@@ -55,6 +55,7 @@
 oer_type_encoder_f SEQUENCE_encode_oer;
 per_type_decoder_f SEQUENCE_decode_uper;
 per_type_encoder_f SEQUENCE_encode_uper;
+asn_random_fill_f  SEQUENCE_random_fill;
 extern asn_TYPE_operation_t asn_OP_SEQUENCE;
 
 #ifdef __cplusplus
diff --git a/skeletons/constr_SEQUENCE_OF.c b/skeletons/constr_SEQUENCE_OF.c
index a8e20ec..2d278c2 100644
--- a/skeletons/constr_SEQUENCE_OF.c
+++ b/skeletons/constr_SEQUENCE_OF.c
@@ -157,7 +157,8 @@
 	ASN_DEBUG("Encoding %s as SEQUENCE OF (%d)", td->name, list->count);
 
 	if(constraints) ct = &constraints->size;
-	else if(td->per_constraints) ct = &td->per_constraints->size;
+	else if(td->encoding_constraints.per_constraints)
+		ct = &td->encoding_constraints.per_constraints->size;
 	else ct = 0;
 
 	/* If extensible constraint, check if size is in root */
@@ -197,7 +198,7 @@
 			void *memb_ptr = list->array[seq++];
 			if(!memb_ptr) ASN__ENCODE_FAILED;
 			er = elm->type->op->uper_encoder(elm->type,
-				elm->per_constraints, memb_ptr, po);
+				elm->encoding_constraints.per_constraints, memb_ptr, po);
 			if(er.encoded == -1)
 				ASN__ENCODE_FAILED;
 		}
@@ -228,6 +229,7 @@
 	SEQUENCE_OF_decode_uper,
 	SEQUENCE_OF_encode_uper,
 #endif /* ASN_DISABLE_PER_SUPPORT */
+	SEQUENCE_OF_random_fill,
 	0	/* Use generic outmost tag fetcher */
 };
 
diff --git a/skeletons/constr_SEQUENCE_OF.h b/skeletons/constr_SEQUENCE_OF.h
index 22d816b..c2acc6a 100644
--- a/skeletons/constr_SEQUENCE_OF.h
+++ b/skeletons/constr_SEQUENCE_OF.h
@@ -25,6 +25,7 @@
 #define	SEQUENCE_OF_decode_uper	SET_OF_decode_uper
 #define	SEQUENCE_OF_decode_oer  SET_OF_decode_oer
 #define	SEQUENCE_OF_encode_oer  SET_OF_encode_oer
+#define	SEQUENCE_OF_random_fill SET_OF_random_fill
 der_type_encoder_f SEQUENCE_OF_encode_der;
 xer_type_encoder_f SEQUENCE_OF_encode_xer;
 per_type_encoder_f SEQUENCE_OF_encode_uper;
diff --git a/skeletons/constr_SEQUENCE_oer.c b/skeletons/constr_SEQUENCE_oer.c
index eb5d6d4..ef2cda2 100644
--- a/skeletons/constr_SEQUENCE_oer.c
+++ b/skeletons/constr_SEQUENCE_oer.c
@@ -204,7 +204,7 @@
                 memb_ptr2 = element_ptrptr(st, elm, &save_memb_ptr);
 
                 rval = elm->type->op->oer_decoder(opt_codec_ctx, elm->type,
-                                                  elm->oer_constraints,
+                                                  elm->encoding_constraints.oer_constraints,
                                                   memb_ptr2, ptr, size);
             }
             switch(rval.code) {
@@ -328,7 +328,7 @@
             case 1: {
                 /* Read OER open type */
                 ssize_t ot_size = oer_open_type_get(opt_codec_ctx, elm->type,
-                                                    elm->oer_constraints,
+                                                    elm->encoding_constraints.oer_constraints,
                                                     memb_ptr2, ptr, size);
                 if(ot_size > 0) {
                     ADVANCE(ot_size);
@@ -482,8 +482,9 @@
             ASN_DEBUG("OER encoder is not defined for type %s", elm->type->name);
             ASN__ENCODE_FAILED;
         }
-        er = elm->type->op->oer_encoder(elm->type, elm->oer_constraints, memb_ptr,
-                                    cb, app_key);
+        er = elm->type->op->oer_encoder(
+            elm->type, elm->encoding_constraints.oer_constraints, memb_ptr, cb,
+            app_key);
         if(er.encoded == -1) {
             ASN_DEBUG("... while encoding %s member \"%s\"\n", td->name,
                       elm->name);
@@ -546,7 +547,8 @@
                     /* Do not encode default value. */
                 } else {
                     asn_enc_rval_t er = elm->type->op->oer_encoder(
-                        elm->type, elm->oer_constraints, memb_ptr, cb, app_key);
+                        elm->type, elm->encoding_constraints.oer_constraints,
+                        memb_ptr, cb, app_key);
                     if(er.encoded == -1) {
                         return er;
                     }
diff --git a/skeletons/constr_SET.c b/skeletons/constr_SET.c
index 8e614ec..e9a25ae 100644
--- a/skeletons/constr_SET.c
+++ b/skeletons/constr_SET.c
@@ -996,19 +996,12 @@
 			memb_ptr = (const void *)((const char *)sptr + elm->memb_offset);
 		}
 
-		if(elm->memb_constraints) {
-			int ret = elm->memb_constraints(elm->type, memb_ptr,
-				ctfailcb, app_key);
-			if(ret) return ret;
+		if(elm->encoding_constraints.general_constraints) {
+			return elm->encoding_constraints.general_constraints(
+					elm->type, memb_ptr, ctfailcb, app_key);
 		} else {
-			int ret = elm->type->check_constraints(elm->type,
-				memb_ptr, ctfailcb, app_key);
-			if(ret) return ret;
-			/*
-			 * Cannot inherit it earlier:
-			 * need to make sure we get the updated version.
-			 */
-			elm->memb_constraints = elm->type->check_constraints;
+			return elm->type->encoding_constraints.general_constraints(
+					elm->type, memb_ptr, ctfailcb, app_key);
 		}
 	}
 
@@ -1062,6 +1055,75 @@
 	0,	/* SET_encode_oer */
 	0,	/* SET_decode_uper */
 	0,	/* SET_encode_uper */
+	SET_random_fill,
 	0	/* Use generic outmost tag fetcher */
 };
 
+
+asn_random_fill_result_t
+SET_random_fill(const asn_TYPE_descriptor_t *td, void **sptr,
+                   const asn_encoding_constraints_t *constr,
+                   size_t max_length) {
+    const asn_SET_specifics_t *specs =
+        (const asn_SET_specifics_t *)td->specifics;
+    asn_random_fill_result_t result_ok = {ARFILL_OK, 0};
+    asn_random_fill_result_t result_failed = {ARFILL_FAILED, 0};
+    asn_random_fill_result_t result_skipped = {ARFILL_SKIPPED, 0};
+    void *st = *sptr;
+    size_t edx;
+
+    if(max_length == 0) return result_skipped;
+
+    (void)constr;
+
+    if(st == NULL) {
+        st = CALLOC(1, specs->struct_size);
+        if(st == NULL) {
+            return result_failed;
+        }
+    }
+
+    for(edx = 0; edx < td->elements_count; edx++) {
+        const asn_TYPE_member_t *elm = &td->elements[edx];
+        void *memb_ptr;   /* Pointer to the member */
+        void **memb_ptr2; /* Pointer to that pointer */
+        asn_random_fill_result_t tmpres;
+
+        if(elm->optional && asn_random_between(0, 4) == 2) {
+            /* Sometimes decide not to fill the optional value */
+            continue;
+        }
+
+        if(elm->flags & ATF_POINTER) {
+            /* Member is a pointer to another structure */
+            memb_ptr2 = (void **)((char *)st + elm->memb_offset);
+        } else {
+            memb_ptr = (char *)st + elm->memb_offset;
+            memb_ptr2 = &memb_ptr;
+        }
+
+        tmpres = elm->type->op->random_fill(
+            elm->type, memb_ptr2, &elm->encoding_constraints,
+            max_length > result_ok.length ? max_length - result_ok.length : 0);
+        switch(tmpres.code) {
+        case ARFILL_OK:
+            result_ok.length += tmpres.length;
+            continue;
+        case ARFILL_SKIPPED:
+            assert(!(elm->flags & ATF_POINTER) || *memb_ptr2 == NULL);
+            continue;
+        case ARFILL_FAILED:
+            if(st == *sptr) {
+                ASN_STRUCT_RESET(*td, st);
+            } else {
+                ASN_STRUCT_FREE(*td, st);
+            }
+            return tmpres;
+        }
+    }
+
+    *sptr = st;
+
+    return result_ok;
+}
+
diff --git a/skeletons/constr_SET.h b/skeletons/constr_SET.h
index 6a8d077..a83ca1e 100644
--- a/skeletons/constr_SET.h
+++ b/skeletons/constr_SET.h
@@ -55,6 +55,7 @@
 xer_type_encoder_f SET_encode_xer;
 per_type_decoder_f SET_decode_uper;
 per_type_encoder_f SET_encode_uper;
+asn_random_fill_f  SET_random_fill;
 extern asn_TYPE_operation_t asn_OP_SET;
 
 /***********************
diff --git a/skeletons/constr_SET_OF.c b/skeletons/constr_SET_OF.c
index ba61496..2deb8bd 100644
--- a/skeletons/constr_SET_OF.c
+++ b/skeletons/constr_SET_OF.c
@@ -839,8 +839,8 @@
 		return -1;
 	}
 
-	constr = elm->memb_constraints;
-	if(!constr) constr = elm->type->check_constraints;
+	constr = elm->encoding_constraints.general_constraints;
+	if(!constr) constr = elm->type->encoding_constraints.general_constraints;
 
 	/*
 	 * Iterate over the members of an array.
@@ -856,13 +856,6 @@
 		if(ret) return ret;
 	}
 
-	/*
-	 * Cannot inherit it eralier:
-	 * need to make sure we get the updated version.
-	 */
-	if(!elm->memb_constraints)
-		elm->memb_constraints = elm->type->check_constraints;
-
 	return 0;
 }
 
@@ -893,7 +886,8 @@
 
 	/* Figure out which constraints to use */
 	if(constraints) ct = &constraints->size;
-	else if(td->per_constraints) ct = &td->per_constraints->size;
+	else if(td->encoding_constraints.per_constraints)
+		ct = &td->encoding_constraints.per_constraints->size;
 	else ct = 0;
 
 	if(ct && ct->flags & APC_EXTENSIBLE) {
@@ -927,7 +921,7 @@
 			void *ptr = 0;
 			ASN_DEBUG("SET OF %s decoding", elm->type->name);
 			rv = elm->type->op->uper_decoder(opt_codec_ctx, elm->type,
-				elm->per_constraints, &ptr, pd);
+				elm->encoding_constraints.per_constraints, &ptr, pd);
 			ASN_DEBUG("%s SET OF %s decoded %d, %p",
 				td->name, elm->type->name, rv.code, ptr);
 			if(rv.code == RC_OK) {
@@ -988,5 +982,55 @@
 	SET_OF_decode_uper,
 	0,	/* SET_OF_encode_uper */
 #endif /* ASN_DISABLE_PER_SUPPORT */
+	SET_OF_random_fill,
 	0	/* Use generic outmost tag fetcher */
 };
+
+
+asn_random_fill_result_t
+SET_OF_random_fill(const asn_TYPE_descriptor_t *td, void **sptr,
+                   const asn_encoding_constraints_t *constr,
+                   size_t max_length) {
+    const asn_SET_OF_specifics_t *specs =
+        (const asn_SET_OF_specifics_t *)td->specifics;
+    asn_random_fill_result_t res_ok = {ARFILL_OK, 0};
+    asn_random_fill_result_t result_failed = {ARFILL_FAILED, 0};
+    asn_random_fill_result_t result_skipped = {ARFILL_SKIPPED, 0};
+    const asn_TYPE_member_t *elm = td->elements;
+    void *st = *sptr;
+    size_t rnd_len;
+
+    if(max_length == 0) return result_skipped;
+
+    (void)constr;
+
+    if(st == NULL) {
+        st = (*sptr = CALLOC(1, specs->struct_size));
+        if(st == NULL) {
+            return result_failed;
+        }
+    }
+
+    rnd_len = asn_random_between(0, 5);
+    for(; rnd_len > 0; rnd_len--) {
+        asn_anonymous_set_ *list = _A_SET_FROM_VOID(st);
+        void *ptr = 0;
+        asn_random_fill_result_t tmpres = elm->type->op->random_fill(
+            elm->type, &ptr, &elm->encoding_constraints,
+            max_length > res_ok.length ? max_length - res_ok.length : 0);
+        switch(tmpres.code) {
+        case ARFILL_OK:
+            ASN_SET_ADD(list, ptr);
+            res_ok.length += tmpres.code;
+            break;
+        case ARFILL_SKIPPED:
+            break;
+        case ARFILL_FAILED:
+            assert(ptr == 0);
+            return tmpres;
+        }
+    }
+
+    return res_ok;
+}
+
diff --git a/skeletons/constr_SET_OF.h b/skeletons/constr_SET_OF.h
index 8b51611..86609e8 100644
--- a/skeletons/constr_SET_OF.h
+++ b/skeletons/constr_SET_OF.h
@@ -37,6 +37,7 @@
 oer_type_encoder_f SET_OF_encode_oer;
 per_type_decoder_f SET_OF_decode_uper;
 per_type_encoder_f SET_OF_encode_uper;
+asn_random_fill_f  SET_OF_random_fill;
 extern asn_TYPE_operation_t asn_OP_SET_OF;
 
 #ifdef __cplusplus
diff --git a/skeletons/constr_SET_OF_oer.c b/skeletons/constr_SET_OF_oer.c
index 49f56c5..332c11b 100644
--- a/skeletons/constr_SET_OF_oer.c
+++ b/skeletons/constr_SET_OF_oer.c
@@ -168,7 +168,8 @@
 
         for(; ctx->left > 0; ctx->left--) {
             asn_dec_rval_t rv = elm->type->op->oer_decoder(
-                opt_codec_ctx, elm->type, elm->oer_constraints, &ctx->ptr, ptr,
+                opt_codec_ctx, elm->type,
+                elm->encoding_constraints.oer_constraints, &ctx->ptr, ptr,
                 size);
             ADVANCE(rv.consumed);
             switch(rv.code) {
@@ -251,8 +252,9 @@
     for(n = 0; n < list->count; n++) {
         void *memb_ptr = list->array[n];
         asn_enc_rval_t er;
-        er = elm->type->op->oer_encoder(elm->type, elm->oer_constraints,
-                                        memb_ptr, cb, app_key);
+        er = elm->type->op->oer_encoder(
+            elm->type, elm->encoding_constraints.oer_constraints, memb_ptr, cb,
+            app_key);
         if(er.encoded < 0) {
             return er;
         } else {
diff --git a/skeletons/constr_TYPE.h b/skeletons/constr_TYPE.h
index b8247f4..7810349 100644
--- a/skeletons/constr_TYPE.h
+++ b/skeletons/constr_TYPE.h
@@ -42,6 +42,7 @@
 #include <per_decoder.h>	/* Packet Encoding Rules decoder */
 #include <per_encoder.h>	/* Packet Encoding Rules encoder */
 #include <constraints.h>	/* Subtype constraints support */
+#include <asn_random_fill.h>	/* Random structures support */
 
 #ifdef  ASN_DISABLE_OER_SUPPORT
 typedef void (oer_type_decoder_f)();
@@ -142,60 +143,69 @@
  * May be directly invoked by applications.
  */
 typedef struct asn_TYPE_operation_s {
-	asn_struct_free_f  *free_struct;	/* Free the structure */
-	asn_struct_print_f *print_struct;	/* Human readable output */
-	asn_struct_compare_f *compare_struct;	/* Compare two structures */
-	ber_type_decoder_f *ber_decoder;	/* Generic BER decoder */
-	der_type_encoder_f *der_encoder;	/* Canonical DER encoder */
-	xer_type_decoder_f *xer_decoder;	/* Generic XER decoder */
-	xer_type_encoder_f *xer_encoder;	/* [Canonical] XER encoder */
-	oer_type_decoder_f *oer_decoder;	/* Generic OER decoder */
-	oer_type_encoder_f *oer_encoder;	/* Canonical OER encoder */
-	per_type_decoder_f *uper_decoder;	/* Unaligned PER decoder */
-	per_type_encoder_f *uper_encoder;	/* Unaligned PER encoder */
-	asn_outmost_tag_f  *outmost_tag;	/* <optional, internal> */
+    asn_struct_free_f *free_struct;     /* Free the structure */
+    asn_struct_print_f *print_struct;   /* Human readable output */
+    asn_struct_compare_f *compare_struct; /* Compare two structures */
+    ber_type_decoder_f *ber_decoder;      /* Generic BER decoder */
+    der_type_encoder_f *der_encoder;      /* Canonical DER encoder */
+    xer_type_decoder_f *xer_decoder;      /* Generic XER decoder */
+    xer_type_encoder_f *xer_encoder;      /* [Canonical] XER encoder */
+    oer_type_decoder_f *oer_decoder;      /* Generic OER decoder */
+    oer_type_encoder_f *oer_encoder;      /* Canonical OER encoder */
+    per_type_decoder_f *uper_decoder;     /* Unaligned PER decoder */
+    per_type_encoder_f *uper_encoder;     /* Unaligned PER encoder */
+    asn_random_fill_f *random_fill;       /* Initialize with a random value */
+    asn_outmost_tag_f *outmost_tag;       /* <optional, internal> */
 } asn_TYPE_operation_t;
 
 /*
+ * A constraints tuple specifying both the OER and PER constraints.
+ */
+typedef struct asn_encoding_constraints_s {
+    const struct asn_oer_constraints_s *oer_constraints;
+    const struct asn_per_constraints_s *per_constraints;
+    asn_constr_check_f *general_constraints;
+} asn_encoding_constraints_t;
+
+/*
  * The definitive description of the destination language's structure.
  */
 typedef struct asn_TYPE_descriptor_s {
-	const char *name;	/* A name of the ASN.1 type. "" in some cases. */
-	const char *xml_tag;	/* Name used in XML tag */
+    const char *name;       /* A name of the ASN.1 type. "" in some cases. */
+    const char *xml_tag;    /* Name used in XML tag */
 
-	/*
-	 * Generalized functions for dealing with the specific type.
-	 * May be directly invoked by applications.
-	 */
-	asn_TYPE_operation_t *op;
-	asn_constr_check_f *check_constraints;	/* Constraints validator */
+    /*
+     * Generalized functions for dealing with the specific type.
+     * May be directly invoked by applications.
+     */
+    asn_TYPE_operation_t *op;
 
-	/***********************************************************************
-	 * Internally useful members. Not to be used by applications directly. *
-	 **********************************************************************/
+    /***********************************************************************
+     * Internally useful members. Not to be used by applications directly. *
+     **********************************************************************/
 
-	/*
-	 * Tags that are expected to occur.
-	 */
-	const ber_tlv_tag_t *tags;	/* Effective tags sequence for this type */
-	unsigned tags_count;			/* Number of tags which are expected */
-	const ber_tlv_tag_t *all_tags;	/* Every tag for BER/containment */
-	unsigned all_tags_count;		/* Number of tags */
+    /*
+     * Tags that are expected to occur.
+     */
+    const ber_tlv_tag_t *tags;      /* Effective tags sequence for this type */
+    unsigned tags_count;            /* Number of tags which are expected */
+    const ber_tlv_tag_t *all_tags;  /* Every tag for BER/containment */
+    unsigned all_tags_count;        /* Number of tags */
 
-	asn_oer_constraints_t *oer_constraints;	/* OER constraints */
-	asn_per_constraints_t *per_constraints;	/* PER constraints */
+    /* OER, PER, and general constraints */
+    asn_encoding_constraints_t encoding_constraints;
 
-	/*
-	 * An ASN.1 production type members (members of SEQUENCE, SET, CHOICE).
-	 */
-	struct asn_TYPE_member_s *elements;
-	unsigned elements_count;
+    /*
+     * An ASN.1 production type members (members of SEQUENCE, SET, CHOICE).
+     */
+    struct asn_TYPE_member_s *elements;
+    unsigned elements_count;
 
-	/*
-	 * Additional information describing the type, used by appropriate
-	 * functions above.
-	 */
-	const void *specifics;
+    /*
+     * Additional information describing the type, used by appropriate
+     * functions above.
+     */
+    const void *specifics;
 } asn_TYPE_descriptor_t;
 
 /*
@@ -216,9 +226,7 @@
     int tag_mode;           /* IMPLICIT/no/EXPLICIT tag at current level */
     asn_TYPE_descriptor_t *type;            /* Member type descriptor */
     asn_type_selector_f *type_selector;     /* IoS runtime type selector */
-    asn_constr_check_f *memb_constraints;   /* Constraints validator */
-    asn_oer_constraints_t *oer_constraints; /* OER compiled constraints */
-    asn_per_constraints_t *per_constraints; /* PER compiled constraints */
+    asn_encoding_constraints_t encoding_constraints;
     int (*default_value)(int setval, void **sptr); /* DEFAULT <value> */
     const char *name; /* ASN.1 identifier of the element */
 } asn_TYPE_member_t;
diff --git a/skeletons/constraints.c b/skeletons/constraints.c
index 6c8287a..c260997 100644
--- a/skeletons/constraints.c
+++ b/skeletons/constraints.c
@@ -74,20 +74,19 @@
 
 int
 asn_check_constraints(asn_TYPE_descriptor_t *type_descriptor,
-		const void *struct_ptr, char *errbuf, size_t *errlen) {
-	struct errbufDesc arg;
-	int ret;
+                      const void *struct_ptr, char *errbuf, size_t *errlen) {
+    struct errbufDesc arg;
+    int ret;
 
-	arg.failed_type = 0;
-	arg.failed_struct_ptr = 0;
-	arg.errbuf = errbuf;
-	arg.errlen = errlen ? *errlen : 0;
+    arg.failed_type = 0;
+    arg.failed_struct_ptr = 0;
+    arg.errbuf = errbuf;
+    arg.errlen = errlen ? *errlen : 0;
 
-	ret = type_descriptor->check_constraints(type_descriptor,
-		struct_ptr, _asn_i_ctfailcb, &arg);
-	if(ret == -1 && errlen)
-		*errlen = arg.errlen;
+    ret = type_descriptor->encoding_constraints.general_constraints(
+        type_descriptor, struct_ptr, _asn_i_ctfailcb, &arg);
+    if(ret == -1 && errlen) *errlen = arg.errlen;
 
-	return ret;
+    return ret;
 }
 
diff --git a/skeletons/converter-example.c b/skeletons/converter-example.c
index a1dc8f4..ec1cc10 100644
--- a/skeletons/converter-example.c
+++ b/skeletons/converter-example.c
@@ -58,14 +58,35 @@
 static int opt_onepdu;  /* -1 (decode single PDU) */
 
 #ifdef    JUNKTEST        /* Enable -J <probability> */
-#define    JUNKOPT    "J:"
+#define JUNKOPT "J:"
 static double opt_jprob;    /* Junk bit probability */
 static int    junk_failures;
 static void   junk_bytes_with_probability(uint8_t *, size_t, double prob);
-#else
-#define    JUNKOPT
+
+#define RANDOPT "R:"
+static ssize_t random_max_size = 0; /* Size of the random data */
+
+#if !defined(__FreeBSD__) && !(defined(__APPLE__) && defined(__MACH__))
+static void
+srandomdev(void) {
+    FILE *f = fopen("/dev/urandom", "rb");
+    unsigned seed;
+    if(f) {
+        if(fread(&seed, 1, sizeof(seed), f) != sizeof(seed)) {
+            seed = time(NULL);
+        }
+        fclose(f);
+    } else {
+        seed = time(NULL);
+    }
+    srandom(seed);
+}
 #endif
 
+#else   /* !JUNKTEST */
+#define    JUNKOPT
+#endif  /* JUNKTEST */
+
 /* Debug output function */
 static void
 DEBUG(const char *fmt, ...) {
@@ -195,7 +216,7 @@
     /*
      * Pocess the command-line argments.
      */
-    while((ch = getopt(ac, av, "i:o:1b:cdn:p:hs:" JUNKOPT)) != -1)
+    while((ch = getopt(ac, av, "i:o:1b:cdn:p:hs:" JUNKOPT RANDOPT)) != -1)
     switch(ch) {
     case 'i':
         sel = ats_by_name(optarg, pduType, input_encodings);
@@ -296,6 +317,17 @@
             exit(EX_UNAVAILABLE);
         }
         break;
+    case 'R':
+        isyntax = ATS_RANDOM;
+        random_max_size = atoi(optarg);
+        if(random_max_size < 0) {
+            fprintf(stderr,
+                "-R %s: Non-negative value expected\n",
+                optarg);
+            exit(EX_UNAVAILABLE);
+        }
+        srandomdev();
+        break;
 #endif    /* JUNKTEST */
     case 'h':
     default:
@@ -339,6 +371,8 @@
         "  -s <size>    Set the stack usage limit (default is %d)\n"
 #ifdef    JUNKTEST
         "  -J <prob>    Set random junk test bit garbaging probability\n"
+        "  -R <size>    Generate a random value of roughly the given size,\n"
+        "               instead of parsing the value from file.\n"
 #endif
         , (long)suggested_bufsize, ASN__DEFAULT_STACK_MAX);
         exit(EX_USAGE);
@@ -347,7 +381,7 @@
     ac -= optind;
     av += optind;
 
-    if(ac < 1) {
+    if(ac < 1 && isyntax != ATS_RANDOM) {
         fprintf(stderr, "%s: No input files specified. "
                 "Try '-h' for more information\n",
                 av[-optind]);
@@ -378,19 +412,39 @@
       /*
        * Process all files in turn.
        */
-      for(ac_i = 0; ac_i < ac; ac_i++) {
+      for(ac_i = (isyntax == ATS_RANDOM) ? -1 : 0; ac_i < ac; ac_i++) {
         asn_enc_rval_t erv;
         void *structure;    /* Decoded structure */
-        FILE *file = argument_to_file(av, ac_i);
-        char *name = argument_to_name(av, ac_i);
+        FILE *file;
+        char *name;
         int first_pdu;
 
+        if(ac_i == -1) {
+            file = NULL;
+            name = "<random value generator>";
+            opt_onepdu = 1;
+        } else {
+            file = argument_to_file(av, ac_i);
+            name = argument_to_name(av, ac_i);
+        }
+
         for(first_pdu = 1; (first_pdu || !opt_onepdu); first_pdu = 0) {
             /*
              * Decode the encoded structure from file.
              */
-            structure = data_decode_from_file(isyntax, pduType, file, name,
-                                              suggested_bufsize, first_pdu);
+            if(isyntax == ATS_RANDOM) {
+                structure = NULL;
+                if(asn_random_fill(pduType, &structure, random_max_size) != 0) {
+                    fprintf(stderr,
+                            "Cannot generate a random value.\n",
+                            random_max_size);
+                    assert(structure == NULL);
+                    errno = EINVAL;
+                }
+            } else {
+                structure = data_decode_from_file(isyntax, pduType, file, name,
+                                                  suggested_bufsize, first_pdu);
+            }
             if(!structure) {
                 if(errno) {
                     /* Error message is already printed */
@@ -429,6 +483,8 @@
                 if(erv.encoded == -1) {
                     fprintf(stderr, "%s: Cannot convert %s into %s\n", name,
                             pduType->name, ats_simple_name(osyntax));
+                    DEBUG("Conversion failed for %s:\n", pduType->name);
+                    asn_fprint(stderr, pduType, structure);
                     exit(EX_UNAVAILABLE);
                 }
                 DEBUG("Encoded in %zd bytes of %s", erv.encoded,
diff --git a/skeletons/file-dependencies b/skeletons/file-dependencies
index 76c97ea..170dee4 100644
--- a/skeletons/file-dependencies
+++ b/skeletons/file-dependencies
@@ -46,6 +46,7 @@
 asn_system.h			# Platform-dependent types
 asn_codecs.h			# Return types of encoders and decoders
 asn_internal.h			# Internal stuff
+asn_random_fill.h asn_random_fill.c		# Initialize with a random value
 asn_bit_data.h asn_bit_data.c         # Bit streaming support
 OCTET_STRING.h OCTET_STRING.c	# This one is used too widely
 BIT_STRING.h BIT_STRING.c	# This one is necessary for the above one
diff --git a/skeletons/oer_decoder.c b/skeletons/oer_decoder.c
index 52f56de..e803ad2 100644
--- a/skeletons/oer_decoder.c
+++ b/skeletons/oer_decoder.c
@@ -58,9 +58,8 @@
 ssize_t
 oer_open_type_get(const asn_codec_ctx_t *opt_codec_ctx,
                   struct asn_TYPE_descriptor_s *td,
-                  asn_oer_constraints_t *constraints, void **struct_ptr,
+                  const asn_oer_constraints_t *constraints, void **struct_ptr,
                   const void *bufptr, size_t size) {
-
     asn_dec_rval_t dr;
     size_t container_len = 0;
     ssize_t len_len;
diff --git a/skeletons/oer_decoder.h b/skeletons/oer_decoder.h
index db6005f..bf4bc08 100644
--- a/skeletons/oer_decoder.h
+++ b/skeletons/oer_decoder.h
@@ -56,8 +56,8 @@
  */
 ssize_t oer_open_type_get(const asn_codec_ctx_t *opt_codec_ctx,
                           struct asn_TYPE_descriptor_s *td,
-                          asn_oer_constraints_t *constraints, void **struct_ptr,
-                          const void *bufptr, size_t size);
+                          const asn_oer_constraints_t *constraints,
+                          void **struct_ptr, const void *bufptr, size_t size);
 
 
 #ifdef __cplusplus
diff --git a/skeletons/per_opentype.c b/skeletons/per_opentype.c
index c0286ff..9b213d8 100644
--- a/skeletons/per_opentype.c
+++ b/skeletons/per_opentype.c
@@ -26,7 +26,7 @@
  * #10.1, #10.2
  */
 int
-uper_open_type_put(asn_TYPE_descriptor_t *td, asn_per_constraints_t *constraints, void *sptr, asn_per_outp_t *po) {
+uper_open_type_put(asn_TYPE_descriptor_t *td, const asn_per_constraints_t *constraints, void *sptr, asn_per_outp_t *po) {
 	void *buf;
 	void *bptr;
 	ssize_t size;
diff --git a/skeletons/per_opentype.h b/skeletons/per_opentype.h
index 4e3f5fe..31c1832 100644
--- a/skeletons/per_opentype.h
+++ b/skeletons/per_opentype.h
@@ -22,7 +22,7 @@
  * Returns -1 if error is encountered. 0 if all OK.
  */
 int uper_open_type_put(asn_TYPE_descriptor_t *td,
-                       asn_per_constraints_t *constraints, void *sptr,
+                       const asn_per_constraints_t *constraints, void *sptr,
                        asn_per_outp_t *po);
 
 #ifdef __cplusplus