1 /* -*- Mode: C; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2
3 /* Fluent Bit
4 * ==========
5 * Copyright (C) 2019-2021 The Fluent Bit Authors
6 * Copyright (C) 2015-2018 Treasure Data Inc.
7 *
8 * Licensed under the Apache License, Version 2.0 (the "License");
9 * you may not use this file except in compliance with the License.
10 * You may obtain a copy of the License at
11 *
12 * http://www.apache.org/licenses/LICENSE-2.0
13 *
14 * Unless required by applicable law or agreed to in writing, software
15 * distributed under the License is distributed on an "AS IS" BASIS,
16 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
17 * See the License for the specific language governing permissions and
18 * limitations under the License.
19 */
20
21 #include <stdio.h>
22 #include <stdlib.h>
23 #include <string.h>
24 #include <time.h>
25 #include <ctype.h>
26
27 #include <sys/types.h>
28 #include <sys/stat.h>
29 #include <msgpack.h>
30
31 #include <monkey/mk_core.h>
32 #include <fluent-bit/flb_macros.h>
33 #include <fluent-bit/flb_config.h>
34 #include <fluent-bit/flb_error.h>
35 #include <fluent-bit/flb_input.h>
36 #include <fluent-bit/flb_output.h>
37 #include <fluent-bit/flb_utils.h>
38 #include <fluent-bit/flb_utf8.h>
39
40 #ifdef FLB_HAVE_AWS_ERROR_REPORTER
41 #include <fluent-bit/aws/flb_aws_error_reporter.h>
42
43 extern struct flb_aws_error_reporter *error_reporter;
44 #endif
45
46 #ifdef FLB_HAVE_OPENSSL
47 #include <openssl/rand.h>
48 #endif
49
50 /*
51 * The following block descriptor describes the private use unicode character range
52 * used for denoting invalid utf-8 fragments. Invalid fragment 0xCE would become
53 * utf-8 codepoint U+E0CE if FLB_UTILS_FRAGMENT_PRIVATE_BLOCK_DESCRIPTOR is set to
54 * E0 since U+E0CE = U+<FLB_UTILS_FRAGMENT_PRIVATE_BLOCK_DESCRIPTOR><HEX_FRAGMENT>
55 */
56 #define FLB_UTILS_FRAGMENT_PRIVATE_BLOCK_DESCRIPTOR 0xE0
57
flb_utils_error(int err)58 void flb_utils_error(int err)
59 {
60 char *msg = NULL;
61
62 switch (err) {
63 case FLB_ERR_CFG_FILE:
64 msg = "Could not open configuration file";
65 break;
66 case FLB_ERR_CFG_FILE_FORMAT:
67 msg = "Configuration file contains format errors";
68 break;
69 case FLB_ERR_CFG_FILE_STOP:
70 msg = "Configuration file contains errors";
71 break;
72 case FLB_ERR_CFG_FLUSH:
73 msg = "Invalid flush value";
74 break;
75 case FLB_ERR_CFG_FLUSH_CREATE:
76 msg = "Could not create timer for flushing";
77 break;
78 case FLB_ERR_CFG_FLUSH_REGISTER:
79 msg = "Could not register timer for flushing";
80 break;
81 case FLB_ERR_INPUT_INVALID:
82 msg = "Invalid input type";
83 break;
84 case FLB_ERR_INPUT_UNDEF:
85 msg = "No Input(s) have been defined";
86 break;
87 case FLB_ERR_INPUT_UNSUP:
88 msg = "Unsupported Input";
89 break;
90 case FLB_ERR_OUTPUT_UNDEF:
91 msg = "You must specify an output target";
92 break;
93 case FLB_ERR_OUTPUT_INVALID:
94 msg = "Invalid output target";
95 break;
96 case FLB_ERR_OUTPUT_UNIQ:
97 msg = "Just one output type is supported";
98 break;
99 case FLB_ERR_FILTER_INVALID:
100 msg = "Invalid filter plugin";
101 break;
102 case FLB_ERR_CFG_PARSER_FILE:
103 msg = "Could not open parser configuration file";
104 break;
105 case FLB_ERR_JSON_INVAL:
106 msg = "Invalid JSON string";
107 break;
108 case FLB_ERR_JSON_PART:
109 msg = "Truncated JSON string";
110 break;
111 case FLB_ERR_CORO_STACK_SIZE:
112 msg = "Invalid coroutine stack size";
113 break;
114 }
115
116 if (!msg) {
117 fprintf(stderr,
118 "%sError%s: undefined. Aborting",
119 ANSI_BOLD ANSI_RED, ANSI_RESET);
120 #ifdef FLB_HAVE_AWS_ERROR_REPORTER
121 if (is_error_reporting_enabled()) {
122 flb_aws_error_reporter_write(error_reporter, "Error: undefined. Aborting\n");
123 }
124 #endif
125
126 }
127 else {
128 fprintf(stderr,
129 "%sError%s: %s. Aborting\n\n",
130 ANSI_BOLD ANSI_RED, ANSI_RESET, msg);
131
132 #ifdef FLB_HAVE_AWS_ERROR_REPORTER
133 if (is_error_reporting_enabled()) {
134 flb_aws_error_reporter_write(error_reporter, msg);
135 }
136 #endif
137 }
138
139 if (err <= FLB_ERR_FILTER_INVALID) {
140 exit(EXIT_FAILURE);
141 }
142 }
143
144 /* Custom error */
flb_utils_error_c(const char * msg)145 void flb_utils_error_c(const char *msg)
146 {
147 fprintf(stderr,
148 "%sError%s: %s. Aborting\n\n",
149 ANSI_BOLD ANSI_RED, ANSI_RESET, msg);
150 exit(EXIT_FAILURE);
151 }
152
flb_utils_warn_c(const char * msg)153 void flb_utils_warn_c(const char *msg)
154 {
155 fprintf(stderr,
156 "%sWarning%s: %s",
157 ANSI_BOLD ANSI_YELLOW, ANSI_RESET, msg);
158 }
159
160 #ifdef FLB_HAVE_FORK
161 /* Run current process in background mode */
flb_utils_set_daemon(struct flb_config * config)162 int flb_utils_set_daemon(struct flb_config *config)
163 {
164 pid_t pid;
165
166 if ((pid = fork()) < 0){
167 flb_error("Failed creating to switch to daemon mode (fork failed)");
168 exit(EXIT_FAILURE);
169 }
170
171 if (pid > 0) { /* parent */
172 exit(EXIT_SUCCESS);
173 }
174
175 /* set files mask */
176 umask(0);
177
178 /* Create new session */
179 setsid();
180
181 if (chdir("/") < 0) { /* make sure we can unmount the inherited filesystem */
182 flb_error("Unable to unmount the inherited filesystem");
183 exit(EXIT_FAILURE);
184 }
185
186 /* Our last STDOUT messages */
187 flb_info("switching to background mode (PID=%ld)", (long) getpid());
188
189 fclose(stderr);
190 fclose(stdout);
191
192 return 0;
193 }
194 #endif
195
flb_utils_print_setup(struct flb_config * config)196 void flb_utils_print_setup(struct flb_config *config)
197 {
198 struct mk_list *head;
199 struct flb_input_plugin *plugin;
200 struct flb_input_collector *collector;
201 struct flb_input_instance *in;
202 struct flb_filter_instance *f;
203 struct flb_output_instance *out;
204
205 flb_info("Configuration:");
206
207 /* general */
208 flb_info(" flush time | %f seconds", config->flush);
209 flb_info(" grace | %i seconds", config->grace);
210 flb_info(" daemon | %i", config->daemon);
211
212 /* Inputs */
213 flb_info("___________");
214 flb_info(" inputs:");
215 mk_list_foreach(head, &config->inputs) {
216 in = mk_list_entry(head, struct flb_input_instance, _head);
217 flb_info(" %s", in->p->name);
218 }
219
220 /* Filters */
221 flb_info("___________");
222 flb_info(" filters:");
223 mk_list_foreach(head, &config->filters) {
224 f = mk_list_entry(head, struct flb_filter_instance, _head);
225 flb_info(" %s", f->name);
226 }
227
228 /* Outputs */
229 flb_info("___________");
230 flb_info(" outputs:");
231 mk_list_foreach(head, &config->outputs) {
232 out = mk_list_entry(head, struct flb_output_instance, _head);
233 flb_info(" %s", out->name);
234 }
235
236 /* Collectors */
237 flb_info("___________");
238 flb_info(" collectors:");
239 mk_list_foreach(head, &config->collectors) {
240 collector = mk_list_entry(head, struct flb_input_collector, _head);
241 plugin = collector->instance->p;
242
243 if (collector->seconds > 0) {
244 flb_info("[%s %lus,%luns] ",
245 plugin->name,
246 collector->seconds,
247 collector->nanoseconds);
248 }
249 else {
250 flb_info(" [%s] ", plugin->name);
251 }
252
253 }
254 }
255
flb_utils_split(const char * line,int separator,int max_split)256 struct mk_list *flb_utils_split(const char *line, int separator, int max_split)
257 {
258 int i = 0;
259 int count = 0;
260 int val_len;
261 int len;
262 int end;
263 char *val;
264 struct mk_list *list;
265 struct flb_split_entry *new;
266
267 if (!line) {
268 return NULL;
269 }
270
271 list = flb_malloc(sizeof(struct mk_list));
272 if (!list) {
273 flb_errno();
274 return NULL;
275 }
276 mk_list_init(list);
277
278 len = strlen(line);
279 while (i < len) {
280 end = mk_string_char_search(line + i, separator, len - i);
281 if (end >= 0 && end + i < len) {
282 end += i;
283
284 if (i == (unsigned int) end) {
285 i++;
286 continue;
287 }
288
289 val = mk_string_copy_substr(line, i, end);
290 val_len = end - i;
291 }
292 else {
293 val = mk_string_copy_substr(line, i, len);
294 val_len = len - i;
295 end = len;
296 }
297
298 /* Update last position */
299 i = end;
300
301 /* Create new entry */
302 new = flb_malloc(sizeof(struct flb_split_entry));
303 if (!new) {
304 flb_errno();
305 flb_free(val);
306 flb_utils_split_free(list);
307 return NULL;
308 }
309 new->value = val;
310 new->len = val_len;
311 new->last_pos = i;
312 mk_list_add(&new->_head, list);
313 count++;
314
315 /* Update index for next loop */
316 i++;
317
318 /*
319 * If the counter exceeded the maximum specified and there
320 * are still remaining bytes, append those bytes in a new
321 * and last entry.
322 */
323 if (count >= max_split && max_split > 0 && i < len) {
324 new = flb_malloc(sizeof(struct flb_split_entry));
325 if (!new) {
326 flb_errno();
327 flb_utils_split_free(list);
328 return NULL;
329 }
330 new->value = mk_string_copy_substr(line, i, len);
331 new->len = len - i;
332 mk_list_add(&new->_head, list);
333 break;
334 }
335 }
336
337 return list;
338 }
339
flb_utils_split_free_entry(struct flb_split_entry * entry)340 void flb_utils_split_free_entry(struct flb_split_entry *entry)
341 {
342 mk_list_del(&entry->_head);
343 flb_free(entry->value);
344 flb_free(entry);
345 }
346
flb_utils_split_free(struct mk_list * list)347 void flb_utils_split_free(struct mk_list *list)
348 {
349 struct mk_list *tmp;
350 struct mk_list *head;
351 struct flb_split_entry *entry;
352
353 mk_list_foreach_safe(head, tmp, list) {
354 entry = mk_list_entry(head, struct flb_split_entry, _head);
355 flb_utils_split_free_entry(entry);
356 }
357
358 flb_free(list);
359 }
360
361 /* When a timer expires, it needs some handling */
flb_utils_timer_consume(flb_pipefd_t fd)362 int flb_utils_timer_consume(flb_pipefd_t fd)
363 {
364 int ret;
365 uint64_t val;
366
367 ret = flb_pipe_r(fd, &val, sizeof(val));
368 if (ret == -1) {
369 flb_errno();
370 return -1;
371 }
372
373 #ifdef __linux__
374 /* A timer on linux must return an unisgned 64 bit number */
375 if (ret == 0) {
376 return -1;
377 }
378 #endif
379
380 return 0;
381 }
382
flb_utils_pipe_byte_consume(flb_pipefd_t fd)383 int flb_utils_pipe_byte_consume(flb_pipefd_t fd)
384 {
385 int ret;
386 uint64_t val;
387
388 ret = flb_pipe_r(fd, &val, sizeof(val));
389 if (ret == -1) {
390 flb_errno();
391 return -1;
392 }
393
394 return 0;
395 }
396
flb_utils_size_to_bytes(const char * size)397 int64_t flb_utils_size_to_bytes(const char *size)
398 {
399 int i;
400 int len;
401 int plen = 0;
402 int64_t val;
403 char c;
404 char tmp[3] = {0};
405 int64_t KB = 1000;
406 int64_t MB = 1000 * KB;
407 int64_t GB = 1000 * MB;
408
409 if (!size) {
410 return -1;
411 }
412
413 if (strcasecmp(size, "false") == 0) {
414 return 0;
415 }
416
417 len = strlen(size);
418 val = atoll(size);
419
420 if (len == 0) {
421 return -1;
422 }
423
424 for (i = len - 1; i > 0; i--) {
425 if (isdigit(size[i])) {
426 break;
427 }
428 else {
429 plen++;
430 }
431 }
432
433 if (plen == 0) {
434 return val;
435 }
436 else if (plen > 2) {
437 return -1;
438 }
439
440 for (i = 0; i < plen; i++) {
441 c = size[(len - plen) + i];
442 tmp[i] = toupper(c);
443 }
444
445 if (plen == 2) {
446 if (tmp[1] != 'B') {
447 return -1;
448 }
449 }
450
451 if (tmp[0] == 'K') {
452 /* set upper bound (2**64/KB)/2 to avoid overflows */
453 if (val >= 9223372036854775 || val <= -9223372036854774)
454 {
455 return -1;
456 }
457 return (val * KB);
458 }
459 else if (tmp[0] == 'M') {
460 /* set upper bound (2**64/MB)/2 to avoid overflows */
461 if (val >= 9223372036854 || val <= -9223372036853) {
462 return -1;
463 }
464 return (val * MB);
465 }
466 else if (tmp[0] == 'G') {
467 /* set upper bound (2**64/GB)/2 to avoid overflows */
468 if (val >= 9223372036 || val <= -9223372035) {
469 return -1;
470 }
471 return (val * GB);
472 }
473 else {
474 return -1;
475 }
476
477 return val;
478 }
479
flb_utils_hex2int(char * hex,int len)480 int64_t flb_utils_hex2int(char *hex, int len)
481 {
482 int i = 0;
483 int64_t res = 0;
484 char c;
485
486 while ((c = *hex++) && i < len) {
487 /* Ensure no overflow */
488 if (res >= (int64_t)((INT64_MAX/0x10) - 0xff)) {
489 return -1;
490 }
491
492 res *= 0x10;
493
494 if (c >= 'a' && c <= 'f') {
495 res += (c - 0x57);
496 }
497 else if (c >= 'A' && c <= 'F') {
498 res += (c - 0x37);
499 }
500 else if (c >= '0' && c <= '9') {
501 res += (c - 0x30);
502 }
503 else {
504 return -1;
505 }
506 i++;
507 }
508
509 if (res < 0) {
510 return -1;
511 }
512
513 return res;
514 }
515
flb_utils_time_to_seconds(const char * time)516 int flb_utils_time_to_seconds(const char *time)
517 {
518 int len;
519 size_t val;
520
521 len = strlen(time);
522 if (len == 0) {
523 return 0;
524 }
525 val = atoi(time);
526
527 /* String time to seconds */
528 if (time[len - 1] == 'D' || time[len - 1] == 'd') {
529 val *= 86400;
530 }
531 if (time[len - 1] == 'H' || time[len - 1] == 'h') {
532 val *= 3600;
533 }
534 else if (time[len - 1] == 'M' || time[len - 1] == 'm') {
535 val *= 60;
536 }
537
538 return val;
539 }
540
flb_utils_bool(const char * val)541 int flb_utils_bool(const char *val)
542 {
543 if (strcasecmp(val, "true") == 0 ||
544 strcasecmp(val, "on") == 0 ||
545 strcasecmp(val, "yes") == 0) {
546 return FLB_TRUE;
547 }
548 else if (strcasecmp(val, "false") == 0 ||
549 strcasecmp(val, "off") == 0 ||
550 strcasecmp(val, "no") == 0) {
551 return FLB_FALSE;
552 }
553
554 return -1;
555 }
556
557 /* Convert a 'string' time seconds.nanoseconds to int and long values */
flb_utils_time_split(const char * time,int * sec,long * nsec)558 int flb_utils_time_split(const char *time, int *sec, long *nsec)
559 {
560 char *p;
561 char *end;
562 long val = 0;
563
564 errno = 0;
565 val = strtol(time, &end, 10);
566 if ((errno == ERANGE && (val == LONG_MAX || val == LONG_MIN))
567 || (errno != 0 && val == 0)) {
568 flb_errno();
569 return -1;
570 }
571 if (end == time) {
572 return -1;
573 }
574 *sec = (int) val;
575
576 /* Try to find subseconds */
577 *nsec = 0;
578 p = strchr(time, '.');
579 if (p) {
580 p += 1;
581 val = strtol(p, &end, 10);
582 if ((errno == ERANGE && (val == LONG_MAX || val == LONG_MIN))
583 || (errno != 0 && val == 0)) {
584 flb_errno();
585 return -1;
586 }
587 if (end == p) {
588 return -1;
589 }
590 *nsec = val;
591 }
592
593 return 0;
594 }
595
flb_utils_bytes_to_human_readable_size(size_t bytes,char * out_buf,size_t size)596 void flb_utils_bytes_to_human_readable_size(size_t bytes,
597 char *out_buf, size_t size)
598 {
599 unsigned long i;
600 unsigned long u = 1024;
601 static const char *__units[] = {
602 "b", "K", "M", "G",
603 "T", "P", "E", "Z", "Y", NULL
604 };
605
606 for (i = 0; __units[i] != NULL; i++) {
607 if ((bytes / u) == 0) {
608 break;
609 }
610 u *= 1024;
611 }
612 if (!i) {
613 snprintf(out_buf, size, "%lu%s", (long unsigned int) bytes, __units[0]);
614 }
615 else {
616 float fsize = (float) ((double) bytes / (u / 1024));
617 snprintf(out_buf, size, "%.1f%s", fsize, __units[i]);
618 }
619 }
620
621
encoded_to_buf(char * out,const char * in,int len)622 static inline void encoded_to_buf(char *out, const char *in, int len)
623 {
624 int i;
625 char *p = out;
626
627 for (i = 0; i < len; i++) {
628 *p++ = in[i];
629 }
630 }
631
632 /*
633 * Write string pointed by 'str' to the destination buffer 'buf'. It's make sure
634 * to escape sepecial characters and convert utf-8 byte characters to string
635 * representation.
636 */
flb_utils_write_str(char * buf,int * off,size_t size,const char * str,size_t str_len)637 int flb_utils_write_str(char *buf, int *off, size_t size,
638 const char *str, size_t str_len)
639 {
640 int i;
641 int b;
642 int ret;
643 int written = 0;
644 int required;
645 int len;
646 int hex_bytes;
647 int is_valid;
648 int utf_sequence_number;
649 int utf_sequence_length;
650 uint32_t codepoint;
651 uint32_t state = 0;
652 char tmp[16];
653 size_t available;
654 uint32_t c;
655 char *p;
656 uint8_t *s;
657
658 available = (size - *off);
659 required = str_len;
660 if (available <= required) {
661 return FLB_FALSE;
662 }
663
664 p = buf + *off;
665 for (i = 0; i < str_len; i++) {
666 if ((available - written) < 2) {
667 return FLB_FALSE;
668 }
669
670 c = (uint32_t) str[i];
671 if (c == '\"') {
672 *p++ = '\\';
673 *p++ = '\"';
674 }
675 else if (c == '\\') {
676 *p++ = '\\';
677 *p++ = '\\';
678 }
679 else if (c == '\n') {
680 *p++ = '\\';
681 *p++ = 'n';
682 }
683 else if (c == '\r') {
684 *p++ = '\\';
685 *p++ = 'r';
686 }
687 else if (c == '\t') {
688 *p++ = '\\';
689 *p++ = 't';
690 }
691 else if (c == '\b') {
692 *p++ = '\\';
693 *p++ = 'b';
694 }
695 else if (c == '\f') {
696 *p++ = '\\';
697 *p++ = 'f';
698 }
699 else if (c < 32 || c == 0x7f) {
700 if ((available - written) < 6) {
701 return FLB_FALSE;
702 }
703 len = snprintf(tmp, sizeof(tmp) - 1, "\\u%.4hhx", (unsigned char) c);
704 if ((available - written) < len) {
705 return FLB_FALSE;
706 }
707 encoded_to_buf(p, tmp, len);
708 p += len;
709 }
710 else if (c >= 0x80 && c <= 0xFFFF) {
711 hex_bytes = flb_utf8_len(str + i);
712 if (available - written < 6) {
713 return FLB_FALSE;
714 }
715
716 if (i + hex_bytes > str_len) {
717 break; /* skip truncated UTF-8 */
718 }
719
720 state = FLB_UTF8_ACCEPT;
721 codepoint = 0;
722
723 for (b = 0; b < hex_bytes; b++) {
724 s = (unsigned char *) str + i + b;
725 ret = flb_utf8_decode(&state, &codepoint, *s);
726 if (ret == 0) {
727 break;
728 }
729 }
730
731 if (state != FLB_UTF8_ACCEPT) {
732 /* Invalid UTF-8 hex, just skip utf-8 bytes */
733 flb_warn("[pack] invalid UTF-8 bytes found, skipping bytes");
734 }
735 else {
736 len = snprintf(tmp, sizeof(tmp) - 1, "\\u%.4x", codepoint);
737 if ((available - written) < len) {
738 return FLB_FALSE;
739 }
740 encoded_to_buf(p, tmp, len);
741 p += len;
742 }
743 i += (hex_bytes - 1);
744 }
745 else if (c > 0xFFFF) {
746 utf_sequence_length = flb_utf8_len(str + i);
747
748 if (i + utf_sequence_length > str_len) {
749 break; /* skip truncated UTF-8 */
750 }
751
752 is_valid = FLB_TRUE;
753 for (utf_sequence_number = 0; utf_sequence_number < utf_sequence_length;
754 utf_sequence_number++) {
755 /* Leading characters must start with bits 11 */
756 if (utf_sequence_number == 0 && ((str[i] & 0xC0) != 0xC0)) {
757 /* Invalid unicode character. replace */
758 flb_debug("[pack] unexpected UTF-8 leading byte, "
759 "substituting character with replacement character");
760 tmp[utf_sequence_number] = str[i];
761 ++i; /* Consume invalid leading byte */
762 utf_sequence_length = utf_sequence_number + 1;
763 is_valid = FLB_FALSE;
764 break;
765 }
766 /* Trailing characters must start with bits 10 */
767 else if (utf_sequence_number > 0 && ((str[i] & 0xC0) != 0x80)) {
768 /* Invalid unicode character. replace */
769 flb_debug("[pack] unexpected UTF-8 continuation byte, "
770 "substituting character with replacement character");
771 /* This byte, i, is the start of the next unicode character */
772 utf_sequence_length = utf_sequence_number;
773 is_valid = FLB_FALSE;
774 break;
775 }
776
777 tmp[utf_sequence_number] = str[i];
778 ++i;
779 }
780 --i;
781
782 if (is_valid) {
783 if (available - written < utf_sequence_length) {
784 return FLB_FALSE;
785 }
786
787 encoded_to_buf(p, tmp, utf_sequence_length);
788 p += utf_sequence_length;
789 }
790 else {
791 if (available - written < utf_sequence_length * 3) {
792 return FLB_FALSE;
793 }
794
795 /*
796 * Utf-8 sequence is invalid. Map fragments to private use area
797 * codepoints in range:
798 * 0x<FLB_UTILS_FRAGMENT_PRIVATE_BLOCK_DESCRIPTOR>00 to
799 * 0x<FLB_UTILS_FRAGMENT_PRIVATE_BLOCK_DESCRIPTOR>FF
800 */
801 for (b = 0; b < utf_sequence_length; ++b) {
802 /*
803 * Utf-8 private block invalid hex mapping. Format unicode charpoint
804 * in the following format:
805 *
806 * +--------+--------+--------+
807 * |1110PPPP|10PPPPHH|10HHHHHH|
808 * +--------+--------+--------+
809 *
810 * Where:
811 * P is FLB_UTILS_FRAGMENT_PRIVATE_BLOCK_DESCRIPTOR bits (1 byte)
812 * H is Utf-8 fragment hex bits (1 byte)
813 * 1 is bit 1
814 * 0 is bit 0
815 */
816
817 /* unicode codepoint start */
818 *p = 0xE0;
819
820 /* print unicode private block header first 4 bits */
821 *p |= FLB_UTILS_FRAGMENT_PRIVATE_BLOCK_DESCRIPTOR >> 4;
822 ++p;
823
824 /* unicode codepoint middle */
825 *p = 0x80;
826
827 /* print end of unicode private block header last 4 bits */
828 *p |= ((FLB_UTILS_FRAGMENT_PRIVATE_BLOCK_DESCRIPTOR << 2) & 0x3f);
829
830 /* print hex fragment first 2 bits */
831 *p |= (tmp[b] >> 6) & 0x03;
832 ++p;
833
834 /* unicode codepoint middle */
835 *p = 0x80;
836
837 /* print hex fragment last 6 bits */
838 *p |= tmp[b] & 0x3f;
839 ++p;
840 }
841 }
842 }
843 else {
844 *p++ = c;
845 }
846 written = (p - (buf + *off));
847 }
848
849 *off += written;
850
851 return FLB_TRUE;
852 }
853
854
flb_utils_write_str_buf(const char * str,size_t str_len,char ** out,size_t * out_size)855 int flb_utils_write_str_buf(const char *str, size_t str_len, char **out, size_t *out_size)
856 {
857 int ret;
858 int off;
859 char *tmp;
860 char *buf;
861 size_t s;
862
863 s = str_len + 1;
864 buf = flb_malloc(s);
865 if (!buf) {
866 flb_errno();
867 return -1;
868 }
869
870 while (1) {
871 off = 0;
872 ret = flb_utils_write_str(buf, &off, s, str, str_len);
873 if (ret == FLB_FALSE) {
874 s += 256;
875 tmp = flb_realloc(buf, s);
876 if (!tmp) {
877 flb_errno();
878 flb_free(buf);
879 return -1;
880 }
881 buf = tmp;
882 }
883 else {
884 /* done */
885 break;
886 }
887 }
888
889 *out = buf;
890 *out_size = off;
891 return 0;
892 }
893
flb_copy_host(const char * string,int pos_init,int pos_end)894 static char *flb_copy_host(const char *string, int pos_init, int pos_end)
895 {
896 if (string[pos_init] == '[') { /* IPv6 */
897 if (string[pos_end-1] != ']')
898 return NULL;
899
900 return mk_string_copy_substr(string, pos_init + 1, pos_end - 1);
901 }
902 else
903 return mk_string_copy_substr(string, pos_init, pos_end);
904 }
905
flb_utils_url_split(const char * in_url,char ** out_protocol,char ** out_host,char ** out_port,char ** out_uri)906 int flb_utils_url_split(const char *in_url, char **out_protocol,
907 char **out_host, char **out_port, char **out_uri)
908 {
909 char *protocol = NULL;
910 char *host = NULL;
911 char *port = NULL;
912 char *uri = NULL;
913 char *p;
914 char *tmp;
915 char *sep;
916
917 /* Protocol */
918 p = strstr(in_url, "://");
919 if (!p) {
920 return -1;
921 }
922 if (p == in_url) {
923 return -1;
924 }
925
926 protocol = mk_string_copy_substr(in_url, 0, p - in_url);
927 if (!protocol) {
928 flb_errno();
929 return -1;
930 }
931
932 /* Advance position after protocol */
933 p += 3;
934
935 /* Check for first '/' */
936 sep = strchr(p, '/');
937 tmp = strchr(p, ':');
938
939 /* Validate port separator is found before the first slash */
940 if (sep && tmp) {
941 if (tmp > sep) {
942 tmp = NULL;
943 }
944 }
945
946 if (tmp) {
947 host = flb_copy_host(p, 0, tmp - p);
948 if (!host) {
949 flb_errno();
950 goto error;
951 }
952 p = tmp + 1;
953
954 /* Look for an optional URI */
955 tmp = strchr(p, '/');
956 if (tmp) {
957 port = mk_string_copy_substr(p, 0, tmp - p);
958 uri = flb_strdup(tmp);
959 }
960 else {
961 port = flb_strdup(p);
962 uri = flb_strdup("/");
963 }
964 }
965 else {
966 tmp = strchr(p, '/');
967 if (tmp) {
968 host = flb_copy_host(p, 0, tmp - p);
969 uri = flb_strdup(tmp);
970 }
971 else {
972 host = flb_copy_host(p, 0, strlen(p));
973 uri = flb_strdup("/");
974 }
975 }
976
977 if (!port) {
978 if (strcmp(protocol, "http") == 0) {
979 port = flb_strdup("80");
980 }
981 else if (strcmp(protocol, "https") == 0) {
982 port = flb_strdup("443");
983 }
984 }
985
986 *out_protocol = protocol;
987 *out_host = host;
988 *out_port = port;
989 *out_uri = uri;
990
991 return 0;
992
993 error:
994 if (protocol) {
995 flb_free(protocol);
996 }
997
998 return -1;
999 }
1000
1001
1002 /*
1003 * flb_utils_proxy_url_split parses a proxy's information from a http_proxy URL.
1004 * The URL is in the form like `http://username:password@myproxy.com:8080`.
1005 * Note: currently only HTTP is supported.
1006 */
flb_utils_proxy_url_split(const char * in_url,char ** out_protocol,char ** out_username,char ** out_password,char ** out_host,char ** out_port)1007 int flb_utils_proxy_url_split(const char *in_url, char **out_protocol,
1008 char **out_username, char **out_password,
1009 char **out_host, char **out_port)
1010 {
1011 char *protocol = NULL;
1012 char *username = NULL;
1013 char *password = NULL;
1014 char *host = NULL;
1015 char *port = NULL;
1016 char *proto_sep;
1017 char *at_sep;
1018 char *tmp;
1019
1020 /* Parse protocol */
1021 proto_sep = strstr(in_url, "://");
1022 if (!proto_sep) {
1023 return -1;
1024 }
1025 if (proto_sep == in_url) {
1026 return -1;
1027 }
1028
1029 protocol = mk_string_copy_substr(in_url, 0, proto_sep - in_url);
1030 if (!protocol) {
1031 flb_errno();
1032 return -1;
1033 }
1034 /* Only HTTP proxy is supported for now. */
1035 if (strcmp(protocol, "http") != 0) {
1036 flb_free(protocol);
1037 return -1;
1038 }
1039
1040 /* Advance position after protocol */
1041 proto_sep += 3;
1042
1043 /* Seperate `username:password` and `host:port` */
1044 at_sep = strchr(proto_sep, '@');
1045 if (at_sep) {
1046 /* Parse username:passwrod part. */
1047 tmp = strchr(proto_sep, ':');
1048 if (!tmp) {
1049 flb_free(protocol);
1050 return -1;
1051 }
1052 username = mk_string_copy_substr(proto_sep, 0, tmp - proto_sep);
1053 tmp += 1;
1054 password = mk_string_copy_substr(tmp, 0, at_sep - tmp);
1055
1056 /* Parse host:port part. */
1057 at_sep += 1;
1058 tmp = strchr(at_sep, ':');
1059 if (tmp) {
1060 host = flb_copy_host(at_sep, 0, tmp - at_sep);
1061 tmp += 1;
1062 port = strdup(tmp);
1063 }
1064 else {
1065 host = flb_copy_host(at_sep, 0, strlen(at_sep));
1066 port = flb_strdup("80");
1067 }
1068 }
1069 else {
1070 /* Parse host:port part. */
1071 tmp = strchr(proto_sep, ':');
1072 if (tmp) {
1073 host = flb_copy_host(proto_sep, 0, tmp - proto_sep);
1074 tmp += 1;
1075 port = strdup(tmp);
1076 }
1077 else {
1078 host = flb_copy_host(proto_sep, 0, strlen(proto_sep));
1079 port = flb_strdup("80");
1080 }
1081 }
1082
1083 *out_protocol = protocol;
1084 *out_host = host;
1085 *out_port = port;
1086 if (username) {
1087 *out_username = username;
1088 }
1089 if (password) {
1090 *out_password = password;
1091 }
1092
1093 return 0;
1094 }
1095
1096
flb_utils_get_os_name()1097 char *flb_utils_get_os_name()
1098 {
1099 #ifdef _WIN64
1100 return "win64";
1101 #elif _WIN32
1102 return "win32";
1103 #elif __APPLE__ || __MACH__
1104 return "macos";
1105 #elif __linux__
1106 return "linux";
1107 #elif __FreeBSD__
1108 return "freebsd";
1109 #elif __unix || __unix__
1110 return "unix";
1111 #else
1112 return "other";
1113 #endif
1114 }
1115
1116 #ifdef FLB_HAVE_OPENSSL
flb_utils_uuid_v4_gen(char * buf)1117 int flb_utils_uuid_v4_gen(char *buf)
1118 {
1119 int ret;
1120 union {
1121 struct {
1122 uint32_t time_low;
1123 uint16_t time_mid;
1124 uint16_t time_hi_and_version;
1125 uint8_t clk_seq_hi_res;
1126 uint8_t clk_seq_low;
1127 uint8_t node[6];
1128 };
1129 uint8_t __rnd[16];
1130 } uuid;
1131
1132 ret = RAND_bytes(uuid.__rnd, sizeof(uuid));
1133
1134 uuid.clk_seq_hi_res = (uint8_t) ((uuid.clk_seq_hi_res & 0x3F) | 0x80);
1135 uuid.time_hi_and_version = (uint16_t) ((uuid.time_hi_and_version & 0x0FFF) | 0x4000);
1136
1137 snprintf(buf, 38, "%08x-%04x-%04x-%02x%02x-%02x%02x%02x%02x%02x%02x",
1138 uuid.time_low, uuid.time_mid, uuid.time_hi_and_version,
1139 uuid.clk_seq_hi_res, uuid.clk_seq_low,
1140 uuid.node[0], uuid.node[1], uuid.node[2],
1141 uuid.node[3], uuid.node[4], uuid.node[5]);
1142
1143 if (ret == 1) {
1144 return 0;
1145 }
1146
1147 return -1;
1148 }
1149 #else
flb_utils_uuid_v4_gen(char * buf)1150 int flb_utils_uuid_v4_gen(char *buf)
1151 {
1152 snprintf(buf, 38, "ddad00f1-3806-46ab-88d1-277a8c863cd6");
1153 return 0;
1154 }
1155 #endif
1156
flb_utils_read_file(char * path,char ** out_buf,size_t * out_size)1157 int flb_utils_read_file(char *path, char **out_buf, size_t *out_size)
1158 {
1159 int fd;
1160 int ret;
1161 size_t bytes;
1162 struct stat st;
1163 flb_sds_t buf;
1164 FILE *fp;
1165
1166 fp = fopen(path, "rb");
1167 if (!fp) {
1168 return -1;
1169 }
1170 fd = fileno(fp);
1171
1172 ret = fstat(fd, &st);
1173 if (ret == -1) {
1174 flb_errno();
1175 close(fd);
1176 return -1;
1177 }
1178
1179 buf = flb_calloc(1, st.st_size + 1);
1180 if (!buf) {
1181 flb_errno();
1182 fclose(fp);
1183 return -1;
1184 }
1185
1186 bytes = fread(buf, st.st_size, 1, fp);
1187 if (bytes < 1) {
1188 flb_errno();
1189 flb_free(buf);
1190 fclose(fp);
1191 return -1;
1192 }
1193 fclose(fp);
1194
1195 *out_buf = buf;
1196 *out_size = st.st_size;
1197 return 0;
1198 }
1199
machine_id_read_and_sanitize(char * path,char ** out_buf,size_t * out_size)1200 static int machine_id_read_and_sanitize(char *path,
1201 char **out_buf, size_t *out_size)
1202 {
1203 int ret;
1204 size_t s;
1205 char *p;
1206 char *buf;
1207 size_t bytes;
1208
1209 ret = flb_utils_read_file(path, &buf, &bytes);
1210 if (ret != 0) {
1211 return -1;
1212 }
1213
1214 p = buf + bytes - 1;
1215 while (*p == ' ' || *p == '\n') {
1216 p--;
1217 }
1218
1219 /* set new size */
1220 s = p - buf + 1;
1221
1222 buf[s] = '\0';
1223 *out_size = s;
1224 *out_buf = buf;
1225
1226 return 0;
1227 }
1228
flb_utils_get_machine_id(char ** out_id,size_t * out_size)1229 int flb_utils_get_machine_id(char **out_id, size_t *out_size)
1230 {
1231 int ret;
1232 char *id;
1233 size_t bytes;
1234 char *uuid;
1235
1236 #ifdef __linux__
1237 char *dbus_var = "/var/lib/dbus/machine-id";
1238 char *dbus_etc = "/etc/machine-id";
1239
1240 /* dbus */
1241 ret = machine_id_read_and_sanitize(dbus_var, &id, &bytes);
1242 if (ret == 0) {
1243 *out_id = id;
1244 *out_size = bytes;
1245 return 0;
1246 }
1247
1248 /* etc */
1249 ret = machine_id_read_and_sanitize(dbus_etc, &id, &bytes);
1250 if (ret == 0) {
1251 *out_id = id;
1252 *out_size = bytes;
1253 return 0;
1254 }
1255 #elif defined(__FreeBSD__) || defined(__NetBSD__) || \
1256 defined(__OpenBSD__) || defined(__DragonFly__)
1257
1258 char *hostid = "/etc/hostid";
1259
1260 /* hostid */
1261 ret = machine_id_read_and_sanitize(hostid, &id, &bytes);
1262 if (ret == 0) {
1263 *out_id = id;
1264 *out_size = bytes;
1265 return 0;
1266 }
1267 #endif
1268
1269 /* generate a random uuid */
1270 uuid = flb_malloc(38);
1271 if (!uuid) {
1272 flb_errno();
1273 return -1;
1274 }
1275 ret = flb_utils_uuid_v4_gen(uuid);
1276 if (ret == 0) {
1277 *out_id = uuid;
1278 *out_size = strlen(uuid);
1279 return 0;
1280 }
1281
1282 return -1;
1283 }
1284