6b1fd6ff81894f4a8cba5fc6a90ffb3f53729f47
[sim/o1-interface.git] / ntsimulator / ntsim-ng / utils / rand_utils.c
1 /*************************************************************************
2 *
3 * Copyright 2020 highstreet technologies GmbH and others
4 *
5 * Licensed under the Apache License, Version 2.0 (the "License");
6 * you may not use this file except in compliance with the License.
7 * You may obtain a copy of the License at
8 *
9 *     http://www.apache.org/licenses/LICENSE-2.0
10 *
11 * Unless required by applicable law or agreed to in writing, software
12 * distributed under the License is distributed on an "AS IS" BASIS,
13 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 * See the License for the specific language governing permissions and
15 * limitations under the License.
16 ***************************************************************************/
17
18 #define _GNU_SOURCE
19
20 #include "rand_utils.h"
21 #include "log_utils.h"
22 #include "sys_utils.h"  //for b64_encode
23 #include <stdio.h>
24 #include <stdlib.h>
25 #include <time.h>
26 #include <inttypes.h>
27 #include <assert.h>
28 #include <math.h>
29
30 #include "core/context.h"       //for context_get_identity_leafs_of_type
31 #include "core/framework.h"     //to check for no_rand
32
33 //private definitions
34 typedef struct __rand_range {
35     union {
36         int64_t num;
37         double dec;
38     } value;
39
40     union {
41         int64_t num;
42         double dec;
43     } min;
44
45     union {
46         int64_t num;
47         double dec;
48     } max;
49 } rand_range_t;
50
51 //private functions
52 static char *rand_string(int min_length, int max_length);
53 static struct lys_ident *rand_identity(struct lys_ident *type);
54
55 //random based on ranges
56 static int64_t rand_range_type_int_min(LY_DATA_TYPE type);
57 static int64_t rand_range_type_int_max(LY_DATA_TYPE type);
58 static rand_range_t rand_range(const char *range, const LY_DATA_TYPE type);
59
60 //for the following functions, the result should be freed by the user
61 static char *rand_date_and_time(void);
62 static char *rand_ipv4_address(void);
63 static char *rand_ipv6_address(void);
64 static char *rand_uuid(void);
65
66
67 void rand_init(void) {
68     unsigned int seed;
69
70     FILE* urandom = fopen("/dev/urandom", "r");
71     if(urandom == 0) {
72         log_error("failed to open /dev/urandom");
73     }
74     else {
75         fread(&seed, sizeof(int), 1, urandom);
76         fclose(urandom);
77     }
78
79     srand(seed);
80     srandom(seed);
81
82     log_message(2, "rand_init() was called and seed was initialized to %u\n", seed);
83     if(RAND_MAX < 65536) {
84         log_error("RAND_MAX is too low: %d", RAND_MAX);
85     }
86 }
87
88 void rand_init_fixed(unsigned int seed) {
89     srand(seed);
90     srandom(seed);
91
92     log_message(2, "rand_init_fixed() was called and seed was initialized to %u\n", seed);
93
94     if(RAND_MAX < 65536) {
95         log_error("RAND_MAX is too low: %d", RAND_MAX);
96     }
97 }
98
99 char *rand_get_populate_value(const struct lys_type *type) {
100     assert(type);
101
102     char *ret = 0;
103
104     if(type->der->module) {
105         char *full_type = 0;
106         
107         asprintf(&full_type, "%s:%s", type->der->module->name, type->der->name);
108         if(full_type == 0) {
109             log_error("bad malloc");
110             return 0;
111         }
112
113         if(strstr(full_type, "ietf-yang-types:date-and-time") != 0) {
114             ret = rand_date_and_time();
115         }
116         else if(strstr(full_type, "ietf-inet-types:ipv4-address") != 0) {
117             ret = rand_ipv4_address();
118         }
119         else if(strstr(full_type, "ietf-inet-types:ipv6-address") != 0) {
120             ret = rand_ipv6_address();
121         }
122         else if((strstr(full_type, "ietf-yang-types:mac-address") != 0) || (strstr(full_type, "ietf-yang-types:phys-address") != 0)) {
123             ret = rand_mac_address();
124         }
125         else if(strstr(full_type, "universal-id") != 0) {
126             ret = rand_uuid();
127         }
128         
129         free(full_type);
130         if(ret) {
131             return ret;
132         }
133     }
134
135     switch(type->base) {
136         case LY_TYPE_EMPTY:
137         case LY_TYPE_BOOL:
138             if(rand_bool()) {
139                 asprintf(&ret, "true");
140                 return ret;
141             }
142             else {
143                 asprintf(&ret, "false");
144                 return ret;
145             }
146             break;
147
148         case LY_TYPE_DER:
149             return rand_get_populate_value(&type->der->type);
150             break;
151
152         case LY_TYPE_ENUM:
153             if(type->info.enums.count) {
154                 int i = rand_uint16() % type->info.enums.count; 
155                 asprintf(&ret, "%s", type->info.enums.enm[i].name);
156                 return ret;
157             }
158             else {
159                 return rand_get_populate_value(&type->der->type);
160             }
161             break;
162
163         case LY_TYPE_IDENT: {
164             while(!type->info.ident.ref) {
165                 type = &type->der->type;
166             }
167             struct lys_ident *ident = rand_identity(type->info.ident.ref[0]);
168             if(ident == 0) {
169                 log_error("rand_identity failed");
170                 return 0;
171             }
172
173             asprintf(&ret, "%s:%s", ident->module->name, ident->name);
174             return ret;    
175         } break;
176
177         case LY_TYPE_STRING: {
178             int min_length = 1;
179             int max_length = 255;
180             char *expression = 0;
181             bool found_length = false;
182
183             do {
184                 if(type->info.str.length && !found_length) {
185                     rand_range_t vals = rand_range(type->info.str.length->expr, LY_TYPE_UINT8);
186                     min_length = vals.min.num;
187                     max_length = vals.max.num;
188                     if(min_length == 0) {
189                         min_length = 1;
190                     }
191
192                     found_length = true;
193                 }
194
195                 if(type->info.str.pat_count) {
196                     //checkAL aici de fapt trebuie sa facem AND si NOT intre toate expresiile, in functie de modifier
197                     // int modifier = type->info.str.patterns[i].expr[0];
198                     if(expression) {
199                         free(expression);
200                         expression = 0;
201                     }
202                     expression = strdup((char*)(type->info.str.patterns[0].expr + 1));
203                 }
204
205                 if(type->der) {
206                     type = &type->der->type;
207                 }
208                 else {
209                     break;
210                 }
211             } while(1);
212
213             if(expression) {
214                 char *ret = rand_regex(expression);
215                 if(ret == 0) {
216                     log_error("rand_regex failed");
217                     free(expression);
218                     return 0;
219                 }
220
221                 while(strlen(ret) < min_length) {
222                     char *add = rand_regex(expression);
223                     if(add == 0) {
224                         log_error("rand_regex failed");
225                         free(expression);
226                         free(ret);
227                         return 0;
228                     }
229
230                     char *newret = 0;
231                     asprintf(&newret, "%s%s", ret, add);
232                     free(add);
233                     free(ret);
234                     ret = newret;
235                 }
236                 free(expression);
237
238                 if(ret == 0) {
239                     log_error("rand_regex failed");
240                     return 0;
241                 }
242
243                 if(max_length && (strlen(ret) > max_length)) {
244                     ret[max_length] = 0;
245                 }
246
247                 return ret;
248             }
249             else {
250                 return rand_string(min_length, max_length);
251             }
252         } break;
253
254         case LY_TYPE_INT8:
255         case LY_TYPE_UINT8:
256         case LY_TYPE_INT16:
257         case LY_TYPE_UINT16:
258         case LY_TYPE_INT32:
259         case LY_TYPE_UINT32:
260         case LY_TYPE_INT64:
261         case LY_TYPE_UINT64: {
262             const char *expr = 0;
263             
264             do {
265                 if(type->info.num.range) {
266                     expr = type->info.num.range->expr;
267                 }    
268
269                 if(type->der) {
270                     type = &type->der->type;
271                 }
272                 else {
273                     break;
274                 }
275             } while(1);
276
277             int64_t r = rand_range(expr, type->base).value.num;
278             if(type->base == LY_TYPE_UINT8) {
279                 asprintf(&ret, "%"PRIu8, (uint8_t)r);
280             }
281             else if(type->base == LY_TYPE_UINT16) {
282                 asprintf(&ret, "%"PRIu16, (uint16_t)r);
283             }
284             else if(type->base == LY_TYPE_UINT32) {
285                 asprintf(&ret, "%"PRIu32, (uint32_t)r);
286             }
287             else if(type->base == LY_TYPE_UINT64) {
288                 asprintf(&ret, "%"PRIu64, (uint64_t)r);
289             }
290             else if(type->base == LY_TYPE_INT8) {
291                 asprintf(&ret, "%"PRId8, (int8_t)r);
292             }
293             else if(type->base == LY_TYPE_INT16) {
294                 asprintf(&ret, "%"PRId16, (int16_t)r);
295             }
296             else if(type->base == LY_TYPE_INT32) {
297                 asprintf(&ret, "%"PRId32, (int32_t)r);
298             }
299             else if(type->base == LY_TYPE_INT64) {
300                 asprintf(&ret, "%"PRId64, (int64_t)r);
301             }
302
303             return ret;
304         } break;
305
306         case LY_TYPE_DEC64: {
307             const char *expr = 0;
308             int digits = -1;
309             char fmt[10];
310             char *ret = 0;
311             
312             do {
313                 if(type->info.dec64.range) {
314                     expr = type->info.dec64.range->expr;
315                 }
316
317                 if(digits == -1) {
318                     digits = type->info.dec64.dig;
319                 }
320
321                 if(type->der) {
322                     type = &type->der->type;
323                 }
324                 else {
325                     break;
326                 }
327             } while(1);
328
329             rand_range_t dr = rand_range(expr, LY_TYPE_DEC64);
330             sprintf(fmt, "%%.%df", digits);
331
332             //19 digits total, including decimal part
333             int intdig = 19 - digits;
334             double max_val = 9.223372036854775807;
335
336             while(fabs(dr.value.dec) > (pow(10, intdig - 1) * max_val)) {
337                 dr.value.dec /= 10;
338             }
339
340             asprintf(&ret, fmt, dr.value.dec);
341             return ret;
342         } break;
343
344         case LY_TYPE_BITS:
345             ret = (char*)malloc(1);
346             if(ret == 0) {
347                 log_error("malloc failed");
348                 return 0;
349             }
350             ret[0] = 0;
351
352             for(int i = 0; i < type->info.bits.count; i++) {
353                 if(rand_bool()) {
354                     const char *val = type->info.bits.bit[i].name;
355                     bool first = (ret == 0);
356                     ret = (char*)realloc(ret, sizeof(char) * (strlen(ret) + 1 + strlen(val) + 1));
357                     if(ret == 0) {
358                         log_error("malloc failed");
359                         return 0;
360                     }
361
362                     if(!first) {
363                         strcat(ret, " ");
364                     }
365                     strcat(ret, val);
366                 }
367             }
368             return ret;
369             break;
370
371         case LY_TYPE_BINARY: {
372             int length = 1;
373             char *ret = 0;
374
375             do {
376                 if(type->info.binary.length) {
377                     rand_range_t vals = rand_range(type->info.binary.length->expr, LY_TYPE_UINT16);
378                     length = vals.min.num;
379                     if(length == 0) {
380                         length = 1;
381                     }
382                 }
383
384                 if(type->der) {
385                     type = &type->der->type;
386                 }
387                 else {
388                     break;
389                 }
390             } while(1);
391
392             uint8_t *data = (uint8_t *)malloc(sizeof(uint8_t) * length);
393             if(!data) {
394                 log_error("bad malloc");
395                 return 0;
396             }
397
398             for(int i = 0; i < length; i++) {
399                 data[i] = rand_uint8();
400             }
401
402             ret = b64_encode(data, length);
403             free(data);
404             return ret;
405         } break;
406
407         case LY_TYPE_LEAFREF:
408         case LY_TYPE_UNION:
409         case LY_TYPE_INST:
410             asprintf(&ret, "{late_resolve_%s}", type->der->name);
411             log_error("needed: %s", ret);
412             assert(0);
413             return ret;
414             break;
415
416         case LY_TYPE_UNKNOWN:
417         default:
418             asprintf(&ret, "{unimplemented_%s}", type->der->name);
419             log_error("can't generate random for: %s", type->der->name);
420             assert(0);
421             return ret;
422             break;
423     }
424 }
425
426 uint8_t rand_uint8(void) {
427     return rand() % 256;
428 }
429
430 int8_t rand_int8(void) {
431     return (int8_t)rand_uint8();
432 }
433
434 uint16_t rand_uint16(void) {
435     return rand() % 65536;
436 }
437
438 int16_t rand_int16(void) {
439     return (int16_t)rand_uint16();
440 }
441
442 uint32_t rand_uint32(void) {
443     uint32_t x = rand_uint16();
444     x <<= 16;
445     x += rand_uint16();
446     return x;
447 }
448
449 int32_t rand_int32(void) {
450     return (int32_t)rand_uint32();
451 }
452
453 uint64_t rand_uint64(void) {
454     uint64_t x = rand_uint32();
455     x <<= 32;
456     x += rand_uint32();
457     return x;
458 }
459
460 int64_t rand_int64(void) {
461     return (int64_t)rand_uint64();
462 }
463
464 bool rand_bool(void) {
465     return ((rand() & 0x01) == 1);
466 }
467
468 char *rand_regex(const char *regexp) {
469     assert(regexp);
470
471     char buffer[8192];
472     char *cmd = 0;
473     static int run_time = 0;
474
475     char *regexp64 = b64_encode((const unsigned char*)regexp, strlen(regexp));
476     if(regexp64 == 0) {
477         log_error("b64_encode failed");
478         return 0;
479     }
480
481     if(framework_arguments.no_rand) {
482         run_time++;
483         asprintf(&cmd, "regxstring %d '%s'", run_time, regexp64);
484     }
485     else {
486         asprintf(&cmd, "regxstring '%s'", regexp64);
487     }
488     free(regexp64);
489
490     if(cmd == 0) {
491         log_error("asprintf failed");
492         return 0;
493     }
494
495     char last_char = ' ';
496     while(last_char == ' ') {
497         FILE* pipe = popen(cmd, "r");
498         if (!pipe) {
499             log_error("popen() failed");
500             free(cmd);
501             return 0;
502         }
503
504         fgets(buffer, sizeof(buffer), pipe);
505         pclose(pipe);
506
507         buffer[strlen(buffer) - 1] = 0;   //remove trailing \n
508         last_char = buffer[strlen(buffer) - 1];
509     }
510         
511     char *ret = strdup(buffer);
512     free(cmd);
513
514     return ret;
515 }
516
517 char *rand_mac_address(void) {
518     char *ret = 0;
519
520     asprintf(&ret, "%02x:%02x:%02x:%02x:%02x:%02x", rand_uint8(), rand_uint8(), rand_uint8(), rand_uint8(), rand_uint8(), rand_uint8());
521     return ret;
522 }
523
524 static char *rand_string(int min_length, int max_length) {
525     assert(min_length >= 0);
526     assert(min_length <= max_length);
527
528     char charset[] = "0123456789"
529                      "abcdefghijklmnopqrstuvwxyz"
530                      "ABCDEFGHIJKLMNOPQRSTUVWXYZ";
531
532     int length = 1;
533     if(min_length == max_length) {
534         length = min_length;
535     }
536     else {
537         if((framework_config.debug_max_string_size) && (framework_config.debug_max_string_size < max_length)) {
538             max_length = framework_config.debug_max_string_size;
539         }
540
541         length = min_length + rand_uint16() % (max_length - min_length);
542     }
543
544     char *ret = (char *)malloc(length + 1);
545     if(!ret) {
546         log_error("bad malloc");
547         return 0;
548     }
549
550     for(int i = 0; i < length; i++) {
551         ret[i] = charset[(rand_uint8() % (sizeof(charset) - 1))];
552     }
553     ret[length] = 0;
554     return ret;
555 }
556
557 static struct lys_ident *rand_identity(struct lys_ident *type) {
558     assert(type);
559
560     struct lys_ident **found_identities;
561     int total = context_get_identity_leafs_of_type(type, &found_identities);
562     if(total == 0) {
563         return 0;
564     }
565
566     int chosen = rand_uint16() % total;
567     struct lys_ident *ret = found_identities[chosen];
568     free(found_identities);
569
570     return ret;
571 }
572
573
574 static int64_t rand_range_type_int_min(LY_DATA_TYPE type) {
575     switch (type) {
576         case LY_TYPE_UINT8:
577             return 0;
578             break;
579
580         case LY_TYPE_INT8:
581             return INT8_MIN;
582             break;
583
584         case LY_TYPE_UINT16:
585             return 0;
586             break;
587
588         case LY_TYPE_INT16:
589             return INT16_MIN;
590             break;
591
592         case LY_TYPE_UINT32:
593             return 0;
594             break;
595
596         case LY_TYPE_INT32:
597             return INT32_MIN;
598             break;
599
600         case LY_TYPE_UINT64:
601             return 0;
602             break;
603
604         case LY_TYPE_INT64:
605             return INT64_MIN;
606             break;
607
608         default:
609             return 0;
610             assert(0);
611             break;
612     }
613 }
614
615 static int64_t rand_range_type_int_max(LY_DATA_TYPE type) {
616     switch (type) {
617         case LY_TYPE_UINT8:
618             return UINT8_MAX;
619             break;
620
621         case LY_TYPE_INT8:
622             return INT8_MAX;
623             break;
624
625         case LY_TYPE_UINT16:
626             return UINT16_MAX;
627             break;
628
629         case LY_TYPE_INT16:
630             return INT16_MAX;
631             break;
632
633         case LY_TYPE_UINT32:
634             return UINT32_MAX;
635             break;
636
637         case LY_TYPE_INT32:
638             return INT32_MAX;
639             break;
640
641         case LY_TYPE_UINT64:
642             return INT64_MAX;   //yes, intended
643             break;
644
645         case LY_TYPE_INT64:
646             return INT64_MAX;
647             break;
648
649         default:
650             return 0;
651             assert(0);
652             break;
653     }
654 }
655
656 static rand_range_t rand_range(const char *range, const LY_DATA_TYPE type) {
657     char *working_range = 0;
658     rand_range_t ret;
659     ret.value.num = 0;
660     ret.min.num = 0;
661     ret.max.num = 0;
662
663     if (range) {
664         //remove spaces
665         char *rrange = (char*)malloc(sizeof(char) * (strlen(range) + 1));
666         if (!rrange) {
667             log_error("bad malloc");
668             return ret;
669         }
670
671         int i = 0;
672         int j = 0;
673         while (range[i]) {
674             if ((range[i] != ' ') && (range[i] != '\r') && (range[i] != '\n')) {
675                 rrange[j] = range[i];
676                 j++;
677             }
678             i++;
679         }
680         rrange[j] = 0;
681  
682         //split the range into OR ranges
683         //first count how many different ranges exist
684         int chosen_range = 1;
685         char *search = strchr(rrange, '|');
686         while (search) {
687             chosen_range++;
688             search = strchr(search + 1, '|');
689         }
690
691         //choose a random one
692         chosen_range = rand_uint16() % chosen_range;
693         int current_range = 0;
694         char *token;
695         token = strtok(rrange, "|");
696         while (token) {
697             if (current_range == chosen_range) {
698                 working_range = strdup(token);
699             }
700             current_range++;
701             token = strtok(0, "|");
702         }
703         free(rrange);
704     }
705
706     //now parse working_range according to type
707     if (type == LY_TYPE_DEC64) {
708         double min = -922337203685477580.8;
709         double max = 922337203685477580.7;
710         bool negative = false;
711
712         if (working_range) {
713             min = 0;
714             max = 0;
715
716             int i = 0;
717             if ((working_range[i] == 'm') || (working_range[i] == 'M')) {
718                 min = -922337203685477580.8;
719                 while (working_range[i] != '.') {
720                     i++;
721                 }
722             }
723             else {
724                 if (working_range[i] == '-') {
725                     negative = true;
726                     i++;
727                 }
728
729                 while ((working_range[i] >= '0') && (working_range[i] <= '9')) {
730                     min *= 10;
731                     min += working_range[i] - '0';
732                     i++;
733                 }
734             }
735
736             //working_range[i...] is either '.', ".." or \0
737             if (working_range[i] == '.') {
738                 if (working_range[i + 1] != '.') {
739                     i++;
740                     int power = 0;
741                     while ((working_range[i] >= '0') && (working_range[i] <= '9')) {
742                         power--;
743                         min += (working_range[i] - '0') * pow(10, power);
744                         i++;
745                     }
746                 }
747                 else {
748                     i += 2;    //skip ".."
749                 }
750             }
751
752             if (negative) {
753                 min *= -1;
754                 negative = false;
755             }
756             
757             if (working_range[i] == 0) {
758                 //single value
759                 max = min;
760             }
761             else {
762                 //there's also an upper value
763                 if ((working_range[i] == 'm') || (working_range[i] == 'M')) {
764                     max = 922337203685477580.7;
765                 }
766                 else {
767                     if (working_range[i] == '-') {
768                         negative = true;
769                         i++;
770                     }
771
772                     while ((working_range[i] >= '0') && (working_range[i] <= '9')) {
773                         max *= 10;
774                         max += working_range[i] - '0';
775                         i++;
776                     }
777                 }
778
779                 //working_range[i...] is either '.', or \0
780                 if (working_range[i] == '.') {
781                     i++;
782                     int power = 0;
783                     while ((working_range[i] >= '0') && (working_range[i] <= '9')) {
784                         power--;
785                         max += (working_range[i] - '0') * pow(10, power);
786                         i++;
787                     }
788                 }
789
790                 if (negative) {
791                     max *= -1;
792                     negative = false;
793                 }
794             }
795         }
796
797         ret.value.dec = rand() / 1.0 / RAND_MAX;
798         ret.value.dec = (max - min) * ret.value.dec + min;
799         ret.min.dec = min;
800         ret.max.dec = max;
801     }
802     else {
803         int64_t min = rand_range_type_int_min(type);
804         int64_t max = rand_range_type_int_max(type);
805         bool negative = false;
806
807         if (working_range) {
808             min = 0;
809             max = 0;
810
811             int i = 0;
812             if ((working_range[i] == 'm') || (working_range[i] == 'M')) {
813                 min = rand_range_type_int_min(type);
814                 while (working_range[i] != '.') {
815                     i++;
816                 }
817             }
818             else {
819                 if (working_range[i] == '-') {
820                     negative = true;
821                     i++;
822                 }
823
824                 while ((working_range[i] >= '0') && (working_range[i] <= '9')) {
825                     min *= 10;
826                     min += working_range[i] - '0';
827                     i++;
828                 }
829             }
830
831             //working_range[i...] is either ".." or \0
832             if (working_range[i] == '.') {
833                 i += 2;    //skip ".."
834             }
835
836             if (negative) {
837                 min *= -1;
838                 negative = false;
839             }
840
841             if (working_range[i] == 0) {
842                 //single value
843                 max = min;
844             }
845             else {
846                 //there's also an upper value
847                 if ((working_range[i] == 'm') || (working_range[i] == 'M')) {
848                     max = rand_range_type_int_max(type);
849                 }
850                 else {
851                     if (working_range[i] == '-') {
852                         negative = true;
853                         i++;
854                     }
855
856                     while ((working_range[i] >= '0') && (working_range[i] <= '9')) {
857                         max *= 10;
858                         max += working_range[i] - '0';
859                         i++;
860                     }
861                 }
862
863                 if (negative) {
864                     max *= -1;
865                     negative = false;
866                 }
867
868             }
869         }
870
871         double ch = rand() / 1.0 / RAND_MAX;
872         ret.value.num = (max - min) * ch + min;
873         ret.min.num = min;
874         ret.max.num = max;
875     }
876
877     free(working_range);
878
879     return ret;
880 }
881
882 static char *rand_date_and_time(void) {
883     time_t t = rand_uint32() / 2;
884     struct tm lt;
885     (void)localtime_r(&t, &lt);
886
887     char *ret = (char *)malloc(21);
888     if(!ret) {
889         log_error("bad malloc");
890         return 0;
891     }
892     strftime(ret, 21, "%Y-%m-%dT%H:%M:%SZ", &lt);
893     return ret;
894 }
895
896 static char *rand_ipv4_address(void) {
897     char *ret = 0;
898     uint8_t ip1 = rand_uint8();
899     uint8_t ip2 = rand_uint8();
900     uint8_t ip3 = rand_uint8();
901     uint8_t ip4 = rand_uint8();
902
903     asprintf(&ret, "%d.%d.%d.%d", ip1, ip2, ip3, ip4);
904     return ret;
905 }
906
907 static char *rand_ipv6_address(void) {
908     char *ret = 0;
909
910     uint16_t ip1 = rand_uint16();
911     uint16_t ip2 = rand_uint16();
912     uint16_t ip3 = rand_uint16();
913     uint16_t ip4 = rand_uint16();
914     uint16_t ip5 = rand_uint16();
915     uint16_t ip6 = rand_uint16();
916     uint16_t ip7 = rand_uint16();
917     uint16_t ip8 = rand_uint16();
918
919     asprintf(&ret, "%04x:%04x:%04x:%04x:%04x:%04x:%04x:%04x", ip1, ip2, ip3, ip4, ip5, ip6, ip7, ip8);
920     return ret;
921 }
922
923 static char *rand_uuid(void) {
924     char *ret = 0;
925
926     //8-4-4-4-12
927     uint32_t v1 = rand_uint32();
928     uint16_t v2 = rand_uint16();
929     uint16_t v3 = rand_uint16();
930     uint16_t v4 = rand_uint16();
931     uint16_t v5 = rand_uint16();
932     uint32_t v6 = rand_uint32();
933
934     asprintf(&ret, "%08x-%04x-%04x-%04x-%04x%08x", v1, v2, v3, v4, v5, v6);
935
936     return ret;
937 }