1 /*
2 * Copyright (C) 2011-2019 Free Software Foundation, Inc.
3 * Copyright (C) 2019 Red Hat, Inc.
4 *
5 * Author: Nikos Mavrogiannopoulos
6 *
7 * This file is part of GnuTLS.
8 *
9 * The GnuTLS is free software; you can redistribute it and/or
10 * modify it under the terms of the GNU Lesser General Public License
11 * as published by the Free Software Foundation; either version 2.1 of
12 * the License, or (at your option) any later version.
13 *
14 * This library is distributed in the hope that it will be useful, but
15 * WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
17 * Lesser General Public License for more details.
18 *
19 * You should have received a copy of the GNU Lesser General Public License
20 * along with this program. If not, see <https://www.gnu.org/licenses/>
21 *
22 */
23
24 #ifndef GNUTLS_NAME_VAL_ARRAY_H
25 #define GNUTLS_NAME_VAL_ARRAY_H
26
27 #include "gnutls_int.h"
28 #include "errors.h"
29
30 /* Functionality to allow an array of strings. Strings
31 * are allowed to be added to the list and matched against it.
32 */
33
34 typedef struct name_val_array_st {
35 char *name;
36 unsigned name_size;
37 char *val;
38 struct name_val_array_st *next;
39 } *name_val_array_t;
40
_name_val_array_init(name_val_array_t * head)41 inline static void _name_val_array_init(name_val_array_t * head)
42 {
43 *head = NULL;
44 }
45
_name_val_array_clear(name_val_array_t * head)46 inline static void _name_val_array_clear(name_val_array_t * head)
47 {
48 name_val_array_t prev, array = *head;
49
50 while (array != NULL) {
51 prev = array;
52 array = prev->next;
53 gnutls_free(prev);
54 }
55 *head = NULL;
56 }
57
_name_val_array_value(name_val_array_t head,const char * name,unsigned name_size)58 inline static const char *_name_val_array_value(name_val_array_t head,
59 const char *name, unsigned name_size)
60 {
61 name_val_array_t array = head;
62
63 while (array != NULL) {
64 if (array->name_size == name_size &&
65 memcmp(array->name, name, name_size) == 0) {
66 return array->val;
67 }
68 array = array->next;
69 }
70
71 return NULL;
72 }
73
append(name_val_array_t array,const char * name,unsigned name_len,const char * val,unsigned val_len)74 inline static void append(name_val_array_t array, const char *name,
75 unsigned name_len, const char *val,
76 unsigned val_len)
77 {
78 array->name = ((char *) array) + sizeof(struct name_val_array_st);
79 memcpy(array->name, name, name_len);
80 array->name[name_len] = 0;
81 array->name_size = name_len;
82
83 array->val = ((char *) array) + name_len + 1 + sizeof(struct name_val_array_st);
84 if (val)
85 memcpy(array->val, val, val_len);
86 array->val[val_len] = 0;
87
88 array->next = NULL;
89 }
90
_name_val_array_append(name_val_array_t * head,const char * name,const char * val)91 inline static int _name_val_array_append(name_val_array_t * head,
92 const char *name,
93 const char *val)
94 {
95 name_val_array_t prev, array;
96 unsigned name_len = strlen(name);
97 unsigned val_len = (val==NULL)?0:strlen(val);
98
99 if (*head == NULL) {
100 *head =
101 gnutls_malloc(val_len + name_len + 2 +
102 sizeof(struct name_val_array_st));
103 if (*head == NULL)
104 return gnutls_assert_val(GNUTLS_E_MEMORY_ERROR);
105
106 array = *head;
107 append(array, name, name_len, val, val_len);
108 } else {
109 array = *head;
110 prev = array;
111
112 while (array != NULL) {
113 prev = array;
114 array = prev->next;
115 }
116 prev->next =
117 gnutls_malloc(name_len + val_len + 2 +
118 sizeof(struct name_val_array_st));
119 array = prev->next;
120
121 if (array == NULL)
122 return gnutls_assert_val(GNUTLS_E_MEMORY_ERROR);
123
124 append(array, name, name_len, val, val_len);
125 }
126
127 return 0;
128 }
129
130 #endif
131