1 /*
2 The oSIP library implements the Session Initiation Protocol (SIP -rfc3261-)
3 Copyright (C) 2001-2020 Aymeric MOIZARD amoizard@antisip.com
4
5 This library is free software; you can redistribute it and/or
6 modify it under the terms of the GNU Lesser General Public
7 License as published by the Free Software Foundation; either
8 version 2.1 of the License, or (at your option) any later version.
9
10 This library is distributed in the hope that it will be useful,
11 but WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 Lesser General Public License for more details.
14
15 You should have received a copy of the GNU Lesser General Public
16 License along with this library; if not, write to the Free Software
17 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
18 */
19
20 #include <osipparser2/internal.h>
21
22 #include <osipparser2/osip_port.h>
23 #include <osipparser2/osip_parser.h>
24 #include "parser.h"
25
26 static __osip_message_config_t pconfig[NUMBER_OF_HEADERS];
27 static __osip_message_config_commaseparated_t pconfig_commasep[NUMBER_OF_HEADERS_COMMASEPARATED];
28
29 /* The size of the hash table seems large for a limited number of possible entries
30 * The 'problem' is that the header name are too much alike for the osip_hash() function
31 * which gives a poor deviation.
32 * Anyway, this mechanism improves the search time (from binary seach (log(n)) to 1).
33 */
34
35 #ifndef HASH_TABLE_SIZE
36 #ifdef __amd64__
37 #define HASH_TABLE_SIZE 150
38 #else
39 #define HASH_TABLE_SIZE \
40 150 /* set this to the hash table size, 150 is the \
41 first size where no conflicts occur */
42 #endif
43
44 static int hdr_ref_table[HASH_TABLE_SIZE]; /* the hashtable contains indices to the pconfig table */
45
46 /*
47 list of compact header:
48 i: Call-ID => ok
49 m: Contact => ok
50 e: Content-Encoding => ok
51 l: Content-Length => ok
52 c: Content-Type => ok
53 f: From => ok
54 s: Subject => NOT A SUPPORTED HEADER! will be
55 available in the list of unknown headers
56 t: To => ok
57 v: Via => ok
58 */
59 /* This method must be called before using the parser */
parser_init(void)60 int parser_init(void) {
61 int i = 0;
62 int hname_length = sizeof(pconfig_commasep[0].hname);
63
64 memset(pconfig_commasep, 0, sizeof(pconfig_commasep));
65 /* rfc3261 */
66 snprintf(pconfig_commasep[i++].hname, hname_length, "%s", "Accept");
67 snprintf(pconfig_commasep[i++].hname, hname_length, "%s", "a");
68 snprintf(pconfig_commasep[i++].hname, hname_length, "%s", "Accept-Encoding");
69 snprintf(pconfig_commasep[i++].hname, hname_length, "%s", "Accept-Language");
70 snprintf(pconfig_commasep[i++].hname, hname_length, "%s", "Alert-Info");
71 snprintf(pconfig_commasep[i++].hname, hname_length, "%s", "Allow");
72 snprintf(pconfig_commasep[i++].hname, hname_length, "%s", "Authentication-Info");
73 snprintf(pconfig_commasep[i++].hname, hname_length, "%s", "Call-Info");
74 snprintf(pconfig_commasep[i++].hname, hname_length, "%s", "Contact");
75 snprintf(pconfig_commasep[i++].hname, hname_length, "%s", "m");
76 snprintf(pconfig_commasep[i++].hname, hname_length, "%s", "Content-Encoding");
77 snprintf(pconfig_commasep[i++].hname, hname_length, "%s", "e");
78 snprintf(pconfig_commasep[i++].hname, hname_length, "%s", "Content-Language");
79 snprintf(pconfig_commasep[i++].hname, hname_length, "%s", "Error-Info");
80 snprintf(pconfig_commasep[i++].hname, hname_length, "%s", "In-Reply-To");
81 snprintf(pconfig_commasep[i++].hname, hname_length, "%s", "Proxy-Require");
82 snprintf(pconfig_commasep[i++].hname, hname_length, "%s", "Record-Route");
83 snprintf(pconfig_commasep[i++].hname, hname_length, "%s", "Require");
84 snprintf(pconfig_commasep[i++].hname, hname_length, "%s", "Route");
85 snprintf(pconfig_commasep[i++].hname, hname_length, "%s", "Supported");
86 snprintf(pconfig_commasep[i++].hname, hname_length, "%s", "k");
87 snprintf(pconfig_commasep[i++].hname, hname_length, "%s", "Unsupported");
88 snprintf(pconfig_commasep[i++].hname, hname_length, "%s", "Via");
89 snprintf(pconfig_commasep[i++].hname, hname_length, "%s", "v");
90 snprintf(pconfig_commasep[i++].hname, hname_length, "%s", "Warning");
91
92 /* rfc3313 */
93 snprintf(pconfig_commasep[i++].hname, hname_length, "%s", "P-Media-Authorization");
94
95 /* rfc3325 */
96 snprintf(pconfig_commasep[i++].hname, hname_length, "%s", "P-Asserted-Identity");
97 snprintf(pconfig_commasep[i++].hname, hname_length, "%s", "P-Preferred-Identity");
98
99 /* rfc3326 */
100 snprintf(pconfig_commasep[i++].hname, hname_length, "%s", "Reason");
101
102 /* rfc3327 */
103 snprintf(pconfig_commasep[i++].hname, hname_length, "%s", "Path");
104
105 /* rfc3329 */
106 snprintf(pconfig_commasep[i++].hname, hname_length, "%s", "Security-Client");
107 snprintf(pconfig_commasep[i++].hname, hname_length, "%s", "Security-Server");
108 snprintf(pconfig_commasep[i++].hname, hname_length, "%s", "Security-Verify");
109
110 /* rfc3608 */
111 snprintf(pconfig_commasep[i++].hname, hname_length, "%s", "Service-Route");
112
113 /* rfc3841 */
114 snprintf(pconfig_commasep[i++].hname, hname_length, "%s", "Request-Disposition");
115 snprintf(pconfig_commasep[i++].hname, hname_length, "%s", "d");
116 snprintf(pconfig_commasep[i++].hname, hname_length, "%s", "Accept-Contact");
117 snprintf(pconfig_commasep[i++].hname, hname_length, "%s", "a");
118 snprintf(pconfig_commasep[i++].hname, hname_length, "%s", "Reject-Contact");
119 snprintf(pconfig_commasep[i++].hname, hname_length, "%s", "j");
120
121 /* rfc4412 */
122 snprintf(pconfig_commasep[i++].hname, hname_length, "%s", "Resource-Priority");
123 snprintf(pconfig_commasep[i++].hname, hname_length, "%s", "Accept-Resource-Priority");
124
125 /* rfc5009 */
126 snprintf(pconfig_commasep[i++].hname, hname_length, "%s", "P-Early-Media");
127
128 /* rfc5318 */
129 snprintf(pconfig_commasep[i++].hname, hname_length, "%s", "P-Refused-URI-List");
130
131 /* rfc5360 */
132 snprintf(pconfig_commasep[i++].hname, hname_length, "%s", "Permission-Missing");
133 snprintf(pconfig_commasep[i++].hname, hname_length, "%s", "Trigger-Consent");
134
135 /* rfc6050 */
136 snprintf(pconfig_commasep[i++].hname, hname_length, "%s", "P-Asserted-Service");
137 snprintf(pconfig_commasep[i++].hname, hname_length, "%s", "P-Preferred-Service");
138
139 /* rfc6086 */
140 snprintf(pconfig_commasep[i++].hname, hname_length, "%s", "Recv-Info");
141
142 /* rfc6665 */
143 snprintf(pconfig_commasep[i++].hname, hname_length, "%s", "Allow-Events");
144 snprintf(pconfig_commasep[i++].hname, hname_length, "%s", "u");
145
146 /* rfc6794 */
147 snprintf(pconfig_commasep[i++].hname, hname_length, "%s", "Policy-ID");
148 snprintf(pconfig_commasep[i++].hname, hname_length, "%s", "Policy-Contact");
149
150 /* rfc6809 */
151 snprintf(pconfig_commasep[i++].hname, hname_length, "%s", "Feature-Caps");
152
153 /* rfc7044 */
154 snprintf(pconfig_commasep[i++].hname, hname_length, "%s", "History-Info");
155 snprintf(pconfig_commasep[i++].hname, hname_length, "%s", "Accept");
156
157 /* rfc7315 */
158 snprintf(pconfig_commasep[i++].hname, hname_length, "%s", "P-Associated-URI");
159 snprintf(pconfig_commasep[i++].hname, hname_length, "%s", "P-Visited-Network-ID");
160 snprintf(pconfig_commasep[i++].hname, hname_length, "%s", "P-Access-Network-Info");
161 snprintf(pconfig_commasep[i++].hname, hname_length, "%s", "P-Charging-Function-Addresses");
162
163 /* rfc7433 */
164 snprintf(pconfig_commasep[i++].hname, hname_length, "%s", "User-to-User");
165
166 i = 0;
167 #ifndef MINISIZE
168 pconfig[i].hname = ACCEPT;
169 pconfig[i].ignored_when_invalid = 1;
170 pconfig[i++].setheader = (&osip_message_set_accept);
171 pconfig[i].hname = ACCEPT_ENCODING;
172 pconfig[i].ignored_when_invalid = 1;
173 pconfig[i++].setheader = (&osip_message_set_accept_encoding);
174 pconfig[i].hname = ACCEPT_LANGUAGE;
175 pconfig[i].ignored_when_invalid = 1;
176 pconfig[i++].setheader = (&osip_message_set_accept_language);
177 pconfig[i].hname = ALERT_INFO;
178 pconfig[i].ignored_when_invalid = 1;
179 pconfig[i++].setheader = (&osip_message_set_alert_info);
180 pconfig[i].hname = ALLOW;
181 pconfig[i].ignored_when_invalid = 1;
182 pconfig[i++].setheader = (&osip_message_set_allow);
183 pconfig[i].hname = AUTHENTICATION_INFO;
184 pconfig[i].ignored_when_invalid = 1;
185 pconfig[i++].setheader = (&osip_message_set_authentication_info);
186 #endif
187 pconfig[i].hname = AUTHORIZATION;
188 pconfig[i].ignored_when_invalid = 1;
189 pconfig[i++].setheader = (&osip_message_set_authorization);
190 pconfig[i].hname = CONTENT_TYPE_SHORT; /* "l" */
191 pconfig[i].ignored_when_invalid = 0;
192 pconfig[i++].setheader = (&osip_message_set_content_type);
193 pconfig[i].hname = CALL_ID;
194 pconfig[i].ignored_when_invalid = 0;
195 pconfig[i++].setheader = (&osip_message_set_call_id);
196 #ifndef MINISIZE
197 pconfig[i].hname = CALL_INFO;
198 pconfig[i].ignored_when_invalid = 1;
199 pconfig[i++].setheader = (&osip_message_set_call_info);
200 #endif
201 pconfig[i].hname = CONTACT;
202 pconfig[i].ignored_when_invalid = 0;
203 pconfig[i++].setheader = (&osip_message_set_contact);
204 #ifndef MINISIZE
205 pconfig[i].hname = CONTENT_ENCODING;
206 pconfig[i].ignored_when_invalid = 1;
207 pconfig[i++].setheader = (&osip_message_set_content_encoding);
208 #endif
209 pconfig[i].hname = CONTENT_LENGTH;
210 pconfig[i].ignored_when_invalid = 0;
211 pconfig[i++].setheader = (&osip_message_set_content_length);
212 pconfig[i].hname = CONTENT_TYPE;
213 pconfig[i].ignored_when_invalid = 0;
214 pconfig[i++].setheader = (&osip_message_set_content_type);
215 pconfig[i].hname = CSEQ;
216 pconfig[i].ignored_when_invalid = 0;
217 pconfig[i++].setheader = (&osip_message_set_cseq);
218 #ifndef MINISIZE
219 pconfig[i].hname = CONTENT_ENCODING_SHORT; /* "e" */
220 pconfig[i].ignored_when_invalid = 1;
221 pconfig[i++].setheader = (&osip_message_set_content_encoding);
222 pconfig[i].hname = ERROR_INFO;
223 pconfig[i].ignored_when_invalid = 1;
224 pconfig[i++].setheader = (&osip_message_set_error_info);
225 #endif
226 pconfig[i].hname = FROM_SHORT; /* "f" */
227 pconfig[i].ignored_when_invalid = 0;
228 pconfig[i++].setheader = (&osip_message_set_from);
229 pconfig[i].hname = FROM;
230 pconfig[i].ignored_when_invalid = 0;
231 pconfig[i++].setheader = (&osip_message_set_from);
232 pconfig[i].hname = CALL_ID_SHORT; /* "i" */
233 pconfig[i].ignored_when_invalid = 0;
234 pconfig[i++].setheader = (&osip_message_set_call_id);
235 pconfig[i].hname = CONTENT_LENGTH_SHORT; /* "l" */
236 pconfig[i].ignored_when_invalid = 0;
237 pconfig[i++].setheader = (&osip_message_set_content_length);
238 pconfig[i].hname = CONTACT_SHORT; /* "m" */
239 pconfig[i].ignored_when_invalid = 0;
240 pconfig[i++].setheader = (&osip_message_set_contact);
241 pconfig[i].hname = MIME_VERSION;
242 pconfig[i].ignored_when_invalid = 1;
243 pconfig[i++].setheader = (&osip_message_set_mime_version);
244 pconfig[i].hname = PROXY_AUTHENTICATE;
245 pconfig[i].ignored_when_invalid = 1;
246 pconfig[i++].setheader = (&osip_message_set_proxy_authenticate);
247 #ifndef MINISIZE
248 pconfig[i].hname = PROXY_AUTHENTICATION_INFO;
249 pconfig[i].ignored_when_invalid = 1;
250 pconfig[i++].setheader = (&osip_message_set_proxy_authentication_info);
251 #endif
252 pconfig[i].hname = PROXY_AUTHORIZATION;
253 pconfig[i].ignored_when_invalid = 1;
254 pconfig[i++].setheader = (&osip_message_set_proxy_authorization);
255 pconfig[i].hname = RECORD_ROUTE;
256 pconfig[i].ignored_when_invalid = 1; /* best effort - but should be 0 */
257 pconfig[i++].setheader = (&osip_message_set_record_route);
258 pconfig[i].hname = ROUTE;
259 pconfig[i].ignored_when_invalid = 1; /* best effort - but should be 0 */
260 pconfig[i++].setheader = (&osip_message_set_route);
261 pconfig[i].hname = TO_SHORT;
262 pconfig[i].ignored_when_invalid = 0;
263 pconfig[i++].setheader = (&osip_message_set_to);
264 pconfig[i].hname = TO;
265 pconfig[i].ignored_when_invalid = 0;
266 pconfig[i++].setheader = (&osip_message_set_to);
267 pconfig[i].hname = VIA_SHORT;
268 pconfig[i].ignored_when_invalid = 0;
269 pconfig[i++].setheader = (&osip_message_set_via);
270 pconfig[i].hname = VIA;
271 pconfig[i].ignored_when_invalid = 0;
272 pconfig[i++].setheader = (&osip_message_set_via);
273 pconfig[i].hname = WWW_AUTHENTICATE;
274 pconfig[i].ignored_when_invalid = 1;
275 pconfig[i++].setheader = (&osip_message_set_www_authenticate);
276
277 /* build up hash table for fast header lookup */
278
279 /* initialize the table */
280 for (i = 0; i < HASH_TABLE_SIZE; i++) {
281 hdr_ref_table[i] = -1; /* -1 -> no entry */
282 }
283
284 for (i = 0; i < NUMBER_OF_HEADERS; i++) {
285 unsigned long hash;
286
287 /* calculate hash value using lower case */
288 /* Fixed: do not lower constant... osip_tolower( pconfig[i].hname ); */
289 hash = osip_hash(pconfig[i].hname);
290 hash = hash % HASH_TABLE_SIZE;
291
292 if (hdr_ref_table[hash] == -1) {
293 /* store reference(index) to pconfig table */
294 hdr_ref_table[hash] = i;
295
296 } else {
297 /* oops, conflict!-> change the hash table or use another hash function size */
298
299 OSIP_TRACE(osip_trace(__FILE__, __LINE__, OSIP_ERROR, NULL, "conflict with current hashtable size\n"));
300 return OSIP_UNDEFINED_ERROR;
301 }
302 }
303
304 return OSIP_SUCCESS;
305 }
306
parser_add_comma_separated_header(const char * hname)307 int parser_add_comma_separated_header(const char *hname) {
308 int i;
309
310 for (i = 0; i < NUMBER_OF_HEADERS_COMMASEPARATED; i++) {
311 if (pconfig_commasep[i].hname[0] == '\0') {
312 snprintf(pconfig_commasep[i].hname, sizeof(pconfig_commasep[i].hname), "%s", hname);
313 return OSIP_SUCCESS;
314 }
315 }
316
317 return OSIP_UNDEFINED_ERROR;
318 }
319
__osip_message_is_header_comma_separated(const char * hname)320 int __osip_message_is_header_comma_separated(const char *hname) {
321 int i;
322
323 for (i = 0; i < NUMBER_OF_HEADERS_COMMASEPARATED; i++) {
324 if (pconfig_commasep[i].hname[0] == '\0')
325 break;
326
327 if (osip_strcasecmp(pconfig_commasep[i].hname, hname) == 0)
328 return OSIP_SUCCESS;
329 }
330
331 return OSIP_UNDEFINED_ERROR;
332 }
333
334 /* improved look-up mechanism
335 precondition: hname is all lowercase */
__osip_message_is_known_header(const char * hname)336 int __osip_message_is_known_header(const char *hname) {
337 unsigned long hash;
338 int result = -1;
339
340 int index;
341
342 hash = osip_hash(hname);
343 hash = hash % HASH_TABLE_SIZE;
344 index = hdr_ref_table[hash];
345
346 if ((index != -1) && (0 == strcmp(pconfig[index].hname, hname))) {
347 result = index;
348 }
349
350 return result;
351 }
352
353 #endif
354
355 /* This method calls the method that is able to parse the header */
__osip_message_call_method(int i,osip_message_t * dest,const char * hvalue)356 int __osip_message_call_method(int i, osip_message_t *dest, const char *hvalue) {
357 int err;
358
359 err = pconfig[i].setheader(dest, hvalue);
360
361 if (err < 0) {
362 OSIP_TRACE(osip_trace(__FILE__, __LINE__, OSIP_WARNING, NULL, "Could not set header: %s: %s\n", pconfig[i].hname, hvalue));
363 }
364
365 if (pconfig[i].ignored_when_invalid == 1)
366 return OSIP_SUCCESS;
367
368 return err;
369 }
370