cosmetics
[tomato.git] / release / src / router / openvpn / buffer.c
blobd448e5d7544dbee9c0f2185456448e07cfbbda9f
1 /*
2 * OpenVPN -- An application to securely tunnel IP networks
3 * over a single UDP port, with support for SSL/TLS-based
4 * session authentication and key exchange,
5 * packet encryption, packet authentication, and
6 * packet compression.
8 * Copyright (C) 2002-2009 OpenVPN Technologies, Inc. <sales@openvpn.net>
10 * This program is free software; you can redistribute it and/or modify
11 * it under the terms of the GNU General Public License version 2
12 * as published by the Free Software Foundation.
14 * This program is distributed in the hope that it will be useful,
15 * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 * GNU General Public License for more details.
19 * You should have received a copy of the GNU General Public License
20 * along with this program (see the file COPYING included with this
21 * distribution); if not, write to the Free Software Foundation, Inc.,
22 * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
25 #include "syshead.h"
27 #include "common.h"
28 #include "buffer.h"
29 #include "error.h"
30 #include "mtu.h"
31 #include "thread.h"
33 #include "memdbg.h"
35 size_t
36 array_mult_safe (const size_t m1, const size_t m2, const size_t extra)
38 const size_t limit = 0xFFFFFFFF;
39 unsigned long long res = (unsigned long long)m1 * (unsigned long long)m2 + (unsigned long long)extra;
40 if (unlikely(m1 > limit) || unlikely(m2 > limit) || unlikely(extra > limit) || unlikely(res > (unsigned long long)limit))
41 msg (M_FATAL, "attemped allocation of excessively large array");
42 return (size_t) res;
45 void
46 buf_size_error (size_t size)
48 msg (M_FATAL, "fatal buffer size error, size=%lu", (unsigned long)size);
51 struct buffer
52 #ifdef DMALLOC
53 alloc_buf_debug (size_t size, const char *file, int line)
54 #else
55 alloc_buf (size_t size)
56 #endif
58 #ifdef DMALLOC
59 return alloc_buf_gc_debug (size, NULL, file, line);
60 #else
61 return alloc_buf_gc (size, NULL);
62 #endif
65 struct buffer
66 #ifdef DMALLOC
67 alloc_buf_gc_debug (size_t size, struct gc_arena *gc, const char *file, int line)
68 #else
69 alloc_buf_gc (size_t size, struct gc_arena *gc)
70 #endif
72 struct buffer buf;
73 if (!buf_size_valid (size))
74 buf_size_error (size);
75 buf.capacity = (int)size;
76 buf.offset = 0;
77 buf.len = 0;
78 #ifdef DMALLOC
79 buf.data = (uint8_t *) gc_malloc_debug (size, false, gc, file, line);
80 #else
81 buf.data = (uint8_t *) gc_malloc (size, false, gc);
82 #endif
83 if (size)
84 *buf.data = 0;
85 return buf;
88 struct buffer
89 #ifdef DMALLOC
90 clone_buf_debug (const struct buffer* buf, const char *file, int line)
91 #else
92 clone_buf (const struct buffer* buf)
93 #endif
95 struct buffer ret;
96 ret.capacity = buf->capacity;
97 ret.offset = buf->offset;
98 ret.len = buf->len;
99 #ifdef DMALLOC
100 ret.data = (uint8_t *) openvpn_dmalloc (file, line, buf->capacity);
101 #else
102 ret.data = (uint8_t *) malloc (buf->capacity);
103 #endif
104 check_malloc_return (ret.data);
105 memcpy (BPTR (&ret), BPTR (buf), BLEN (buf));
106 return ret;
109 #ifdef BUF_INIT_TRACKING
111 bool
112 buf_init_debug (struct buffer *buf, int offset, const char *file, int line)
114 buf->debug_file = file;
115 buf->debug_line = line;
116 return buf_init_dowork (buf, offset);
119 static inline int
120 buf_debug_line (const struct buffer *buf)
122 return buf->debug_line;
125 static const char *
126 buf_debug_file (const struct buffer *buf)
128 return buf->debug_file;
131 #else
133 #define buf_debug_line(buf) 0
134 #define buf_debug_file(buf) "[UNDEF]"
136 #endif
138 void
139 buf_clear (struct buffer *buf)
141 if (buf->capacity > 0)
142 memset (buf->data, 0, buf->capacity);
143 buf->len = 0;
144 buf->offset = 0;
147 bool
148 buf_assign (struct buffer *dest, const struct buffer *src)
150 if (!buf_init (dest, src->offset))
151 return false;
152 return buf_write (dest, BPTR (src), BLEN (src));
155 struct buffer
156 clear_buf ()
158 struct buffer buf;
159 CLEAR (buf);
160 return buf;
163 void
164 free_buf (struct buffer *buf)
166 if (buf->data)
167 free (buf->data);
168 CLEAR (*buf);
172 * Return a buffer for write that is a subset of another buffer
174 struct buffer
175 buf_sub (struct buffer *buf, int size, bool prepend)
177 struct buffer ret;
178 uint8_t *data;
180 CLEAR (ret);
181 data = prepend ? buf_prepend (buf, size) : buf_write_alloc (buf, size);
182 if (data)
184 ret.capacity = size;
185 ret.data = data;
187 return ret;
191 * printf append to a buffer with overflow check
193 bool
194 buf_printf (struct buffer *buf, const char *format, ...)
196 int ret = false;
197 if (buf_defined (buf))
199 va_list arglist;
200 uint8_t *ptr = BEND (buf);
201 int cap = buf_forward_capacity (buf);
203 if (cap > 0)
205 int stat;
206 va_start (arglist, format);
207 stat = vsnprintf ((char *)ptr, cap, format, arglist);
208 va_end (arglist);
209 *(buf->data + buf->capacity - 1) = 0; /* windows vsnprintf needs this */
210 buf->len += (int) strlen ((char *)ptr);
211 if (stat >= 0 && stat < cap)
212 ret = true;
215 return ret;
219 * This is necessary due to certain buggy implementations of snprintf,
220 * that don't guarantee null termination for size > 0.
223 int openvpn_snprintf(char *str, size_t size, const char *format, ...)
225 va_list arglist;
226 int ret = 0;
227 if (size > 0)
229 va_start (arglist, format);
230 ret = vsnprintf (str, size, format, arglist);
231 va_end (arglist);
232 str[size - 1] = 0;
234 return ret;
238 * write a string to the end of a buffer that was
239 * truncated by buf_printf
241 void
242 buf_catrunc (struct buffer *buf, const char *str)
244 if (buf_forward_capacity (buf) <= 1)
246 int len = (int) strlen (str) + 1;
247 if (len < buf_forward_capacity_total (buf))
249 strncpynt ((char *)(buf->data + buf->capacity - len), str, len);
255 * convert a multi-line output to one line
257 void
258 convert_to_one_line (struct buffer *buf)
260 uint8_t *cp = BPTR(buf);
261 int len = BLEN(buf);
262 while (len--)
264 if (*cp == '\n')
265 *cp = '|';
266 ++cp;
270 /* NOTE: requires that string be null terminated */
271 void
272 buf_write_string_file (const struct buffer *buf, const char *filename, int fd)
274 const int len = strlen ((char *) BPTR (buf));
275 const int size = write (fd, BPTR (buf), len);
276 if (size != len)
277 msg (M_ERR, "Write error on file '%s'", filename);
281 * Garbage collection
284 void *
285 #ifdef DMALLOC
286 gc_malloc_debug (size_t size, bool clear, struct gc_arena *a, const char *file, int line)
287 #else
288 gc_malloc (size_t size, bool clear, struct gc_arena *a)
289 #endif
291 void *ret;
292 if (a)
294 struct gc_entry *e;
295 #ifdef DMALLOC
296 e = (struct gc_entry *) openvpn_dmalloc (file, line, size + sizeof (struct gc_entry));
297 #else
298 e = (struct gc_entry *) malloc (size + sizeof (struct gc_entry));
299 #endif
300 check_malloc_return (e);
301 ret = (char *) e + sizeof (struct gc_entry);
302 /*mutex_lock_static (L_GC_MALLOC);*/
303 e->next = a->list;
304 a->list = e;
305 /*mutex_unlock_static (L_GC_MALLOC);*/
307 else
309 #ifdef DMALLOC
310 ret = openvpn_dmalloc (file, line, size);
311 #else
312 ret = malloc (size);
313 #endif
314 check_malloc_return (ret);
316 #ifndef ZERO_BUFFER_ON_ALLOC
317 if (clear)
318 #endif
319 memset (ret, 0, size);
320 return ret;
323 void
324 x_gc_free (struct gc_arena *a)
326 struct gc_entry *e;
327 /*mutex_lock_static (L_GC_MALLOC);*/
328 e = a->list;
329 a->list = NULL;
330 /*mutex_unlock_static (L_GC_MALLOC);*/
332 while (e != NULL)
334 struct gc_entry *next = e->next;
335 free (e);
336 e = next;
341 * Transfer src arena to dest, resetting src to an empty arena.
343 void
344 gc_transfer (struct gc_arena *dest, struct gc_arena *src)
346 if (dest && src)
348 struct gc_entry *e = src->list;
349 if (e)
351 while (e->next != NULL)
352 e = e->next;
353 e->next = dest->list;
354 dest->list = src->list;
355 src->list = NULL;
361 * Hex dump -- Output a binary buffer to a hex string and return it.
364 char *
365 format_hex_ex (const uint8_t *data, int size, int maxoutput,
366 int space_break, const char* separator,
367 struct gc_arena *gc)
369 struct buffer out = alloc_buf_gc (maxoutput ? maxoutput :
370 ((size * 2) + (size / space_break) * (int) strlen (separator) + 2),
371 gc);
372 int i;
373 for (i = 0; i < size; ++i)
375 if (separator && i && !(i % space_break))
376 buf_printf (&out, "%s", separator);
377 buf_printf (&out, "%02x", data[i]);
379 buf_catrunc (&out, "[more...]");
380 return (char *)out.data;
384 * remove specific trailing character
387 void
388 buf_rmtail (struct buffer *buf, uint8_t remove)
390 uint8_t *cp = BLAST(buf);
391 if (cp && *cp == remove)
393 *cp = '\0';
394 --buf->len;
399 * force a null termination even it requires
400 * truncation of the last char.
402 void
403 buf_null_terminate (struct buffer *buf)
405 char *last = (char *) BLAST (buf);
406 if (last && *last == '\0') /* already terminated? */
407 return;
409 if (!buf_safe (buf, 1)) /* make space for trailing null */
410 buf_inc_len (buf, -1);
412 buf_write_u8 (buf, 0);
416 * Remove trailing \r and \n chars and ensure
417 * null termination.
419 void
420 buf_chomp (struct buffer *buf)
422 while (true)
424 char *last = (char *) BLAST (buf);
425 if (!last)
426 break;
427 if (char_class (*last, CC_CRLF|CC_NULL))
429 if (!buf_inc_len (buf, -1))
430 break;
432 else
433 break;
435 buf_null_terminate (buf);
438 const char *
439 skip_leading_whitespace (const char *str)
441 while (*str)
443 const char c = *str;
444 if (!(c == ' ' || c == '\t'))
445 break;
446 ++str;
448 return str;
452 * like buf_null_terminate, but operate on strings
454 void
455 string_null_terminate (char *str, int len, int capacity)
457 ASSERT (len >= 0 && len <= capacity && capacity > 0);
458 if (len < capacity)
459 *(str + len) = '\0';
460 else if (len == capacity)
461 *(str + len - 1) = '\0';
465 * Remove trailing \r and \n chars.
467 void
468 chomp (char *str)
470 rm_trailing_chars (str, "\r\n");
474 * Remove trailing chars
476 void
477 rm_trailing_chars (char *str, const char *what_to_delete)
479 bool modified;
480 do {
481 const int len = strlen (str);
482 modified = false;
483 if (len > 0)
485 char *cp = str + (len - 1);
486 if (strchr (what_to_delete, *cp) != NULL)
488 *cp = '\0';
489 modified = true;
492 } while (modified);
496 * Allocate a string
498 char *
499 #ifdef DMALLOC
500 string_alloc_debug (const char *str, struct gc_arena *gc, const char *file, int line)
501 #else
502 string_alloc (const char *str, struct gc_arena *gc)
503 #endif
505 if (str)
507 const int n = strlen (str) + 1;
508 char *ret;
510 #ifdef DMALLOC
511 ret = (char *) gc_malloc_debug (n, false, gc, file, line);
512 #else
513 ret = (char *) gc_malloc (n, false, gc);
514 #endif
515 memcpy (ret, str, n);
516 return ret;
518 else
519 return NULL;
523 * Erase all characters in a string
525 void
526 string_clear (char *str)
528 if (str)
530 const int len = strlen (str);
531 if (len > 0)
532 memset (str, 0, len);
537 * Return the length of a string array
540 string_array_len (const char **array)
542 int i = 0;
543 if (array)
545 while (array[i])
546 ++i;
548 return i;
551 char *
552 print_argv (const char **p, struct gc_arena *gc, const unsigned int flags)
554 struct buffer out = alloc_buf_gc (256, gc);
555 int i = 0;
556 for (;;)
558 const char *cp = *p++;
559 if (!cp)
560 break;
561 if (i)
562 buf_printf (&out, " ");
563 if (flags & PA_BRACKET)
564 buf_printf (&out, "[%s]", cp);
565 else
566 buf_printf (&out, "%s", cp);
567 ++i;
569 return BSTR (&out);
573 * Allocate a string inside a buffer
575 struct buffer
576 #ifdef DMALLOC
577 string_alloc_buf_debug (const char *str, struct gc_arena *gc, const char *file, int line)
578 #else
579 string_alloc_buf (const char *str, struct gc_arena *gc)
580 #endif
582 struct buffer buf;
584 ASSERT (str);
586 #ifdef DMALLOC
587 buf_set_read (&buf, (uint8_t*) string_alloc_debug (str, gc, file, line), strlen (str) + 1);
588 #else
589 buf_set_read (&buf, (uint8_t*) string_alloc (str, gc), strlen (str) + 1);
590 #endif
592 if (buf.len > 0) /* Don't count trailing '\0' as part of length */
593 --buf.len;
595 return buf;
599 * String comparison
602 bool
603 buf_string_match_head_str (const struct buffer *src, const char *match)
605 const int size = strlen (match);
606 if (size < 0 || size > src->len)
607 return false;
608 return memcmp (BPTR (src), match, size) == 0;
611 bool
612 buf_string_compare_advance (struct buffer *src, const char *match)
614 if (buf_string_match_head_str (src, match))
616 buf_advance (src, strlen (match));
617 return true;
619 else
620 return false;
624 buf_substring_len (const struct buffer *buf, int delim)
626 int i = 0;
627 struct buffer tmp = *buf;
628 int c;
630 while ((c = buf_read_u8 (&tmp)) >= 0)
632 ++i;
633 if (c == delim)
634 return i;
636 return -1;
640 * String parsing
643 bool
644 buf_parse (struct buffer *buf, const int delim, char *line, const int size)
646 bool eol = false;
647 int n = 0;
648 int c;
650 ASSERT (size > 0);
654 c = buf_read_u8 (buf);
655 if (c < 0)
656 eol = true;
657 if (c <= 0 || c == delim)
658 c = 0;
659 if (n >= size)
660 break;
661 line[n++] = c;
663 while (c);
665 line[size-1] = '\0';
666 return !(eol && !strlen (line));
670 * Print a string which might be NULL
672 const char *
673 np (const char *str)
675 if (str)
676 return str;
677 else
678 return "[NULL]";
682 * Classify and mutate strings based on character types.
685 bool
686 char_class (const unsigned char c, const unsigned int flags)
688 if (!flags)
689 return false;
690 if (flags & CC_ANY)
691 return true;
693 if ((flags & CC_NULL) && c == '\0')
694 return true;
696 if ((flags & CC_ALNUM) && isalnum (c))
697 return true;
698 if ((flags & CC_ALPHA) && isalpha (c))
699 return true;
700 if ((flags & CC_ASCII) && isascii (c))
701 return true;
702 if ((flags & CC_CNTRL) && iscntrl (c))
703 return true;
704 if ((flags & CC_DIGIT) && isdigit (c))
705 return true;
706 if ((flags & CC_PRINT) && isprint (c))
707 return true;
708 if ((flags & CC_PUNCT) && ispunct (c))
709 return true;
710 if ((flags & CC_SPACE) && isspace (c))
711 return true;
712 if ((flags & CC_XDIGIT) && isxdigit (c))
713 return true;
715 if ((flags & CC_BLANK) && (c == ' ' || c == '\t'))
716 return true;
717 if ((flags & CC_NEWLINE) && c == '\n')
718 return true;
719 if ((flags & CC_CR) && c == '\r')
720 return true;
722 if ((flags & CC_BACKSLASH) && c == '\\')
723 return true;
724 if ((flags & CC_UNDERBAR) && c == '_')
725 return true;
726 if ((flags & CC_DASH) && c == '-')
727 return true;
728 if ((flags & CC_DOT) && c == '.')
729 return true;
730 if ((flags & CC_COMMA) && c == ',')
731 return true;
732 if ((flags & CC_COLON) && c == ':')
733 return true;
734 if ((flags & CC_SLASH) && c == '/')
735 return true;
736 if ((flags & CC_SINGLE_QUOTE) && c == '\'')
737 return true;
738 if ((flags & CC_DOUBLE_QUOTE) && c == '\"')
739 return true;
740 if ((flags & CC_REVERSE_QUOTE) && c == '`')
741 return true;
742 if ((flags & CC_AT) && c == '@')
743 return true;
744 if ((flags & CC_EQUAL) && c == '=')
745 return true;
747 return false;
750 static inline bool
751 char_inc_exc (const char c, const unsigned int inclusive, const unsigned int exclusive)
753 return char_class (c, inclusive) && !char_class (c, exclusive);
756 bool
757 string_class (const char *str, const unsigned int inclusive, const unsigned int exclusive)
759 char c;
760 ASSERT (str);
761 while ((c = *str++))
763 if (!char_inc_exc (c, inclusive, exclusive))
764 return false;
766 return true;
770 * Modify string in place.
771 * Guaranteed to not increase string length.
773 bool
774 string_mod (char *str, const unsigned int inclusive, const unsigned int exclusive, const char replace)
776 const char *in = str;
777 bool ret = true;
779 ASSERT (str);
781 while (true)
783 char c = *in++;
784 if (c)
786 if (!char_inc_exc (c, inclusive, exclusive))
788 c = replace;
789 ret = false;
791 if (c)
792 *str++ = c;
794 else
796 *str = '\0';
797 break;
800 return ret;
803 const char *
804 string_mod_const (const char *str,
805 const unsigned int inclusive,
806 const unsigned int exclusive,
807 const char replace,
808 struct gc_arena *gc)
810 if (str)
812 char *buf = string_alloc (str, gc);
813 string_mod (buf, inclusive, exclusive, replace);
814 return buf;
816 else
817 return NULL;
820 void
821 string_replace_leading (char *str, const char match, const char replace)
823 ASSERT (match != '\0');
824 while (*str)
826 if (*str == match)
827 *str = replace;
828 else
829 break;
830 ++str;
834 #ifdef CHARACTER_CLASS_DEBUG
836 #define CC_INCLUDE (CC_PRINT)
837 #define CC_EXCLUDE (0)
838 #define CC_REPLACE ('.')
840 void
841 character_class_debug (void)
843 char buf[256];
845 while (fgets (buf, sizeof (buf), stdin) != NULL)
847 string_mod (buf, CC_INCLUDE, CC_EXCLUDE, CC_REPLACE);
848 printf ("%s", buf);
852 #endif
854 #ifdef VERIFY_ALIGNMENT
855 void
856 valign4 (const struct buffer *buf, const char *file, const int line)
858 if (buf && buf->len)
860 int msglevel = D_ALIGN_DEBUG;
861 const unsigned int u = (unsigned int) BPTR (buf);
863 if (u & (PAYLOAD_ALIGN-1))
864 msglevel = D_ALIGN_ERRORS;
866 msg (msglevel, "%sAlignment at %s/%d ptr=" ptr_format " OLC=%d/%d/%d I=%s/%d",
867 (msglevel == D_ALIGN_ERRORS) ? "ERROR: " : "",
868 file,
869 line,
870 (ptr_type)buf->data,
871 buf->offset,
872 buf->len,
873 buf->capacity,
874 buf_debug_file (buf),
875 buf_debug_line (buf));
878 #endif
881 * struct buffer_list
884 #ifdef ENABLE_BUFFER_LIST
886 struct buffer_list *
887 buffer_list_new (const int max_size)
889 struct buffer_list *ret;
890 ALLOC_OBJ_CLEAR (ret, struct buffer_list);
891 ret->max_size = max_size;
892 ret->size = 0;
893 return ret;
896 void
897 buffer_list_free (struct buffer_list *ol)
899 buffer_list_reset (ol);
900 free (ol);
903 bool
904 buffer_list_defined (const struct buffer_list *ol)
906 return ol->head != NULL;
909 void
910 buffer_list_reset (struct buffer_list *ol)
912 struct buffer_entry *e = ol->head;
913 while (e)
915 struct buffer_entry *next = e->next;
916 free_buf (&e->buf);
917 free (e);
918 e = next;
920 ol->head = ol->tail = NULL;
921 ol->size = 0;
924 void
925 buffer_list_push (struct buffer_list *ol, const unsigned char *str)
927 if (!ol->max_size || ol->size < ol->max_size)
929 struct buffer_entry *e;
930 ALLOC_OBJ_CLEAR (e, struct buffer_entry);
932 ++ol->size;
933 if (ol->tail)
935 ASSERT (ol->head);
936 ol->tail->next = e;
938 else
940 ASSERT (!ol->head);
941 ol->head = e;
943 e->buf = string_alloc_buf ((const char *) str, NULL);
944 ol->tail = e;
948 const struct buffer *
949 buffer_list_peek (struct buffer_list *ol)
951 if (ol->head)
952 return &ol->head->buf;
953 else
954 return NULL;
957 static void
958 buffer_list_pop (struct buffer_list *ol)
960 if (ol->head)
962 struct buffer_entry *e = ol->head->next;
963 free_buf (&ol->head->buf);
964 free (ol->head);
965 ol->head = e;
966 --ol->size;
967 if (!e)
968 ol->tail = NULL;
972 void
973 buffer_list_advance (struct buffer_list *ol, int n)
975 if (ol->head)
977 struct buffer *buf = &ol->head->buf;
978 ASSERT (buf_advance (buf, n));
979 if (!BLEN (buf))
980 buffer_list_pop (ol);
984 struct buffer_list *
985 buffer_list_file (const char *fn, int max_line_len)
987 FILE *fp = fopen (fn, "r");
988 struct buffer_list *bl = NULL;
990 if (fp)
992 char *line = (char *) malloc (max_line_len);
993 if (line)
995 bl = buffer_list_new (0);
996 while (fgets (line, max_line_len, fp) != NULL)
997 buffer_list_push (bl, (unsigned char *)line);
998 free (line);
1000 fclose (fp);
1002 return bl;
1005 #endif