Line | Count | Source (jump to first uncovered line) |
1 | | /** |
2 | | * Copyright (C) 2010-2020 OpenSIPS Solutions |
3 | | * Copyright (C) 2005-2009 Voice Sistem SRL |
4 | | * Copyright (C) 2001-2003 FhG Fokus |
5 | | * |
6 | | * This file is part of opensips, a free SIP server. |
7 | | * |
8 | | * opensips is free software; you can redistribute it and/or modify |
9 | | * it under the terms of the GNU General Public License as published by |
10 | | * the Free Software Foundation; either version 2 of the License, or |
11 | | * (at your option) any later version |
12 | | * |
13 | | * opensips is distributed in the hope that it will be useful, |
14 | | * but WITHOUT ANY WARRANTY; without even the implied warranty of |
15 | | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
16 | | * GNU General Public License for more details. |
17 | | * |
18 | | * You should have received a copy of the GNU General Public License |
19 | | * along with this program; if not, write to the Free Software |
20 | | * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA |
21 | | * |
22 | | * History: |
23 | | * -------- |
24 | | * 2004-10-20 - added header name specifier (ramona) |
25 | | * 2005-06-14 - added avp name specifier (ramona) |
26 | | * 2005-06-18 - added color printing support via escape sequesnces |
27 | | * contributed by Ingo Flaschberger (daniel) |
28 | | * 2005-06-22 - created this file from modules/xlog/pv_lib.c (daniel) |
29 | | * 2009-04-28 - $ct and $ct.fields() PVs added (bogdan) |
30 | | * 2009-05-02 - $branch() added, $br, $bR, $bf, $bF removed (bogdan) |
31 | | */ |
32 | | |
33 | | #include <stdio.h> |
34 | | #include <string.h> |
35 | | #include <time.h> |
36 | | #include <sys/types.h> |
37 | | #include <unistd.h> |
38 | | |
39 | | #include "dprint.h" |
40 | | #include "mem/mem.h" |
41 | | #include "mem/shm_mem.h" |
42 | | #include "ut.h" |
43 | | #include "trim.h" |
44 | | #include "dset.h" |
45 | | #include "action.h" |
46 | | #include "socket_info.h" |
47 | | #include "route_struct.h" |
48 | | #include "usr_avp.h" |
49 | | #include "errinfo.h" |
50 | | #include "transformations.h" |
51 | | #include "script_var.h" |
52 | | #include "pvar.h" |
53 | | #include "flags.h" |
54 | | #include "xlog.h" |
55 | | |
56 | | #include "parser/parse_from.h" |
57 | | #include "parser/parse_uri.h" |
58 | | #include "parser/parse_hname2.h" |
59 | | #include "parser/parse_content.h" |
60 | | #include "parser/parse_refer_to.h" |
61 | | #include "parser/parse_rpid.h" |
62 | | #include "parser/parse_diversion.h" |
63 | | #include "parser/parse_ppi.h" |
64 | | #include "parser/parse_pai.h" |
65 | | #include "parser/digest/digest.h" |
66 | | #include "parser/contact/parse_contact.h" |
67 | | |
68 | 2.87k | #define is_in_str(p, in) (p<in->s+in->len && *p) |
69 | | |
70 | | extern int curr_action_line; |
71 | | extern char *curr_action_file; |
72 | | |
73 | | typedef struct _pv_extra |
74 | | { |
75 | | pv_export_t pve; |
76 | | struct _pv_extra *next; |
77 | | } pv_extra_t, *pv_extra_p; |
78 | | |
79 | | pv_extra_p *_pv_extra_list=0; |
80 | | |
81 | | static str str_marker = { PV_MARKER_STR, 1 }; |
82 | | |
83 | | /* IMPORTANT : the "const" strings returned by the var functions must |
84 | | be read-write (as they may be changed by the script interpreter), so |
85 | | we need to allocated as array and not as pointing to RO data segment |
86 | | */ |
87 | | static char _str_null_hlp[] = "<null>"; |
88 | | static str str_null = str_init(_str_null_hlp); |
89 | | |
90 | | static char _str_empty_hlp[] = ""; |
91 | | static str str_empty = str_init(_str_empty_hlp); |
92 | | |
93 | | int _pv_pid = 0; |
94 | | |
95 | 0 | #define PV_FIELD_DELIM ", " |
96 | 0 | #define PV_FIELD_DELIM_LEN (sizeof(PV_FIELD_DELIM) - 1) |
97 | | |
98 | 0 | #define PV_LOCAL_BUF_SIZE 511 |
99 | | static char pv_local_buf[PV_LOCAL_BUF_SIZE+1]; |
100 | | |
101 | | /* pv context list */ |
102 | | pv_context_t* pv_context_lst = NULL; |
103 | | |
104 | | static pv_context_t* pv_get_context(const str* name); |
105 | | static pv_context_t* add_pv_context(const str* name, pv_contextf_t get_context); |
106 | | |
107 | | static int pv_parse_argv_name(pv_spec_p sp, const str *in); |
108 | | static int pv_get_argv(struct sip_msg *msg, pv_param_t *param, pv_value_t *res); |
109 | | static int pv_contextlist_check(void); |
110 | | /* always obtain a printable version of the given (pv_value_t *) */ |
111 | | static str pv_value_print(const pv_value_t *val); |
112 | | |
113 | | static int pvc_before_check = 1; |
114 | | |
115 | | int pv_print_buf_size = 20000; |
116 | 0 | #define PV_PRINT_BUF_NO 7 |
117 | | str *pv_print_buf; |
118 | | |
119 | 0 | #define is_pv_print_buf(p) (p >= (char *)pv_print_buf && \ |
120 | 0 | p <= (char *)pv_print_buf + \ |
121 | 0 | PV_PRINT_BUF_NO * (sizeof(*pv_print_buf) + pv_print_buf_size)) |
122 | | |
123 | | int init_pvar_support(void) |
124 | 0 | { |
125 | 0 | int i; |
126 | | |
127 | | /* check pv context list */ |
128 | 0 | if (pv_contextlist_check() != 0) { |
129 | 0 | LM_ERR("used pv context that was not defined\n"); |
130 | 0 | return -1; |
131 | 0 | } |
132 | | |
133 | 0 | pv_print_buf = pkg_malloc(PV_PRINT_BUF_NO * (sizeof(str) |
134 | 0 | + pv_print_buf_size)); |
135 | 0 | if (!pv_print_buf) { |
136 | 0 | LM_ERR("oom\n"); |
137 | 0 | return -1; |
138 | 0 | } |
139 | | |
140 | 0 | for (i = 0; i < PV_PRINT_BUF_NO; i++) { |
141 | 0 | pv_print_buf[i].s = (char *)(pv_print_buf + PV_PRINT_BUF_NO) |
142 | 0 | + i * pv_print_buf_size; |
143 | 0 | pv_print_buf[i].len = pv_print_buf_size; |
144 | 0 | } |
145 | |
|
146 | 0 | return 0; |
147 | 0 | } |
148 | | |
149 | | /* route param variable */ |
150 | | static int pv_get_param(struct sip_msg *msg, pv_param_t *ip, pv_value_t *res); |
151 | | static int pv_parse_param_name(pv_spec_p sp, const str *in); |
152 | | |
153 | | /********** helper functions ********/ |
154 | | /** |
155 | | * convert unsigned int to pv_value_t |
156 | | */ |
157 | | int pv_get_uintval(struct sip_msg *msg, pv_param_t *param, |
158 | | pv_value_t *res, unsigned int uival) |
159 | 68.1k | { |
160 | 68.1k | int l = 0; |
161 | 68.1k | char *ch = NULL; |
162 | | |
163 | 68.1k | if(res==NULL) |
164 | 0 | return -1; |
165 | | |
166 | 68.1k | ch = int2str(uival, &l); |
167 | 68.1k | res->rs.s = ch; |
168 | 68.1k | res->rs.len = l; |
169 | | |
170 | 68.1k | res->ri = (int)uival; |
171 | 68.1k | res->flags = PV_VAL_STR|PV_VAL_INT|PV_TYPE_INT; |
172 | 68.1k | return 0; |
173 | 68.1k | } |
174 | | |
175 | | /** |
176 | | * convert signed int to pv_value_t |
177 | | */ |
178 | | int pv_get_sintval(struct sip_msg *msg, pv_param_t *param, |
179 | | pv_value_t *res, int sival) |
180 | 75.4k | { |
181 | 75.4k | int l = 0; |
182 | 75.4k | char *ch = NULL; |
183 | | |
184 | 75.4k | if(res==NULL) |
185 | 0 | return -1; |
186 | | |
187 | 75.4k | ch = sint2str(sival, &l); |
188 | 75.4k | res->rs.s = ch; |
189 | 75.4k | res->rs.len = l; |
190 | | |
191 | 75.4k | res->ri = sival; |
192 | 75.4k | res->flags = PV_VAL_STR|PV_VAL_INT|PV_TYPE_INT; |
193 | 75.4k | return 0; |
194 | 75.4k | } |
195 | | |
196 | | /** |
197 | | * convert str to pv_value_t |
198 | | */ |
199 | | int pv_get_strval(struct sip_msg *msg, pv_param_t *param, |
200 | | pv_value_t *res, str *sval) |
201 | 104k | { |
202 | 104k | if(res==NULL) |
203 | 0 | return -1; |
204 | | |
205 | 104k | res->rs = *sval; |
206 | 104k | res->flags = PV_VAL_STR; |
207 | 104k | return 0; |
208 | 104k | } |
209 | | |
210 | | /** |
211 | | * convert str-int to pv_value_t (type is str) |
212 | | */ |
213 | | static int pv_get_strintval(struct sip_msg *msg, pv_param_t *param, |
214 | | pv_value_t *res, str *sval, int ival) |
215 | 26.0k | { |
216 | 26.0k | if(res==NULL) |
217 | 0 | return -1; |
218 | | |
219 | 26.0k | res->rs = *sval; |
220 | 26.0k | res->ri = ival; |
221 | 26.0k | res->flags = PV_VAL_STR|PV_VAL_INT; |
222 | 26.0k | return 0; |
223 | 26.0k | } |
224 | | |
225 | | /** |
226 | | * convert int-str to pv_value_t (type is int) |
227 | | */ |
228 | | static int pv_get_intstrval(struct sip_msg *msg, pv_param_t *param, |
229 | | pv_value_t *res, int ival, str *sval) |
230 | 69 | { |
231 | 69 | if(res==NULL) |
232 | 0 | return -1; |
233 | | |
234 | 69 | res->rs = *sval; |
235 | 69 | res->ri = ival; |
236 | 69 | res->flags = PV_VAL_STR|PV_VAL_INT|PV_TYPE_INT; |
237 | 69 | return 0; |
238 | 69 | } |
239 | | |
240 | | /************************************************************/ |
241 | | static int pv_get_marker(struct sip_msg *msg, pv_param_t *param, |
242 | | pv_value_t *res) |
243 | 0 | { |
244 | 0 | return pv_get_strintval(msg, param, res, &str_marker, (int)str_marker.s[0]); |
245 | 0 | } |
246 | | |
247 | | int pv_get_null(struct sip_msg *msg, pv_param_t *param, pv_value_t *res) |
248 | 824k | { |
249 | 824k | if(res==NULL) |
250 | 0 | return -1; |
251 | | |
252 | 824k | res->rs = str_empty; |
253 | 824k | res->ri = 0; |
254 | 824k | res->flags = PV_VAL_NULL; |
255 | 824k | return 0; |
256 | 824k | } |
257 | | |
258 | | /************************************************************/ |
259 | | static int pv_get_pid(struct sip_msg *msg, pv_param_t *param, |
260 | | pv_value_t *res) |
261 | 10.7k | { |
262 | 10.7k | if(_pv_pid == 0) |
263 | 1 | _pv_pid = (int)getpid(); |
264 | 10.7k | return pv_get_sintval(msg, param, res, _pv_pid); |
265 | 10.7k | } |
266 | | |
267 | | |
268 | | extern int return_code; |
269 | | static int pv_get_return_code(struct sip_msg *msg, pv_param_t *param, |
270 | | pv_value_t *res) |
271 | 21.5k | { |
272 | 21.5k | return pv_get_sintval(msg, param, res, return_code); |
273 | 21.5k | } |
274 | | |
275 | | static int pv_get_route(struct sip_msg *msg, pv_param_t *param, |
276 | | pv_value_t *res) |
277 | 10.7k | { |
278 | 10.7k | static str rn_buf; |
279 | | |
280 | 10.7k | str s; |
281 | 10.7k | int i, idx, idx_flags, len, rlen, has_name, route_stack_size_ctx; |
282 | | |
283 | 10.7k | if (pv_get_spec_index(msg, param, &idx, &idx_flags) != 0) { |
284 | 0 | LM_ERR("invalid index\n"); |
285 | 0 | return -1; |
286 | 0 | } |
287 | | |
288 | 10.7k | if (idx_flags == PV_IDX_ALL) { |
289 | 0 | get_top_route_type(&s, &has_name); |
290 | 0 | if (!has_name) |
291 | 0 | goto unnamed_route; |
292 | | |
293 | 0 | len = strlen(route_stack[route_stack_start]); |
294 | 0 | if (pkg_str_extend(&rn_buf, s.len + 2 + len + 1) != 0) { |
295 | 0 | LM_ERR("oom\n"); |
296 | 0 | return pv_get_null(msg, param, res); |
297 | 0 | } |
298 | | |
299 | 0 | len = sprintf(rn_buf.s, "%.*s[%s]", s.len, s.s, route_stack[route_stack_start]); |
300 | 0 | goto print_remaining; |
301 | | |
302 | 0 | unnamed_route: |
303 | 0 | if (pkg_str_extend(&rn_buf, s.len + 1) != 0) { |
304 | 0 | LM_ERR("oom\n"); |
305 | 0 | return pv_get_null(msg, param, res); |
306 | 0 | } |
307 | | |
308 | 0 | len = sprintf(rn_buf.s, "%.*s", s.len, s.s); |
309 | |
|
310 | 0 | print_remaining: |
311 | 0 | s = str_route; |
312 | |
|
313 | 0 | for (i = route_stack_start+1; i < route_stack_size; i++) { |
314 | 0 | if (!route_stack[i]) { |
315 | 0 | if (pkg_str_extend(&rn_buf, len + 3 + s.len + 1) != 0) { |
316 | 0 | LM_ERR("oom\n"); |
317 | 0 | return pv_get_null(msg, param, res); |
318 | 0 | } |
319 | | |
320 | 0 | len += sprintf(rn_buf.s + len, " > %.*s", s.len, s.s); |
321 | 0 | } else if (route_stack[i][0] != '!') { |
322 | 0 | rlen = strlen(route_stack[i]); |
323 | |
|
324 | 0 | if (pkg_str_extend(&rn_buf, len + s.len + 5 + rlen + 1) != 0) { |
325 | 0 | LM_ERR("oom\n"); |
326 | 0 | return pv_get_null(msg, param, res); |
327 | 0 | } |
328 | | |
329 | 0 | len += sprintf(rn_buf.s + len, " > %.*s[%s]", |
330 | 0 | s.len, s.s, route_stack[i]); |
331 | 0 | } else { |
332 | 0 | rlen = strlen(route_stack[i]); |
333 | | |
334 | | /* the "!" marker tells us to print that route name as-is */ |
335 | 0 | if (pkg_str_extend(&rn_buf, len + rlen + 3) != 0) { |
336 | 0 | LM_ERR("oom\n"); |
337 | 0 | return pv_get_null(msg, param, res); |
338 | 0 | } |
339 | | |
340 | 0 | len += sprintf(rn_buf.s + len, " > %s", route_stack[i] + 1); |
341 | 0 | } |
342 | 0 | } |
343 | | |
344 | 0 | s.s = rn_buf.s; |
345 | 0 | s.len = len; |
346 | 0 | return pv_get_strval(msg, param, res, &s); |
347 | 0 | } |
348 | | |
349 | 10.7k | route_stack_size_ctx = route_stack_size - route_stack_start; |
350 | | |
351 | 10.7k | if (idx < 0) |
352 | 0 | idx += route_stack_size_ctx; |
353 | | |
354 | | /* index out of bounds -- play nice and return NULL */ |
355 | 10.7k | if (idx > route_stack_size_ctx - 1 || idx < 0) |
356 | 10.7k | return pv_get_null(msg, param, res); |
357 | | |
358 | | /* reverse the index, since we index the route stack backwards */ |
359 | 0 | idx = route_stack_size_ctx - idx - 1; |
360 | |
|
361 | 0 | if (idx == 0) { |
362 | 0 | get_top_route_type(&s, &has_name); |
363 | 0 | if (!has_name) |
364 | 0 | goto out_ok; |
365 | |
|
366 | 0 | } else { |
367 | 0 | s = str_route; |
368 | 0 | if (!route_stack[route_stack_start + idx]) |
369 | 0 | goto out_ok; |
370 | 0 | } |
371 | | |
372 | 0 | len = strlen(route_stack[route_stack_start + idx]); |
373 | |
|
374 | 0 | if (route_stack[route_stack_start + idx][0] != '!') { |
375 | 0 | if (pkg_str_extend(&rn_buf, s.len + 2 + len + 1) != 0) { |
376 | 0 | LM_ERR("oom\n"); |
377 | 0 | return pv_get_null(msg, param, res); |
378 | 0 | } |
379 | | |
380 | 0 | s.len = sprintf(rn_buf.s, "%.*s[%s]", s.len, s.s, route_stack[route_stack_start + idx]); |
381 | 0 | s.s = rn_buf.s; |
382 | 0 | } else { |
383 | | /* the "!" marker tells us to print that route name as-is */ |
384 | 0 | if (pkg_str_extend(&rn_buf, len) != 0) { |
385 | 0 | LM_ERR("oom\n"); |
386 | 0 | return pv_get_null(msg, param, res); |
387 | 0 | } |
388 | | |
389 | 0 | s.len = sprintf(rn_buf.s, "%s", route_stack[route_stack_start + idx] + 1); |
390 | 0 | s.s = rn_buf.s; |
391 | 0 | } |
392 | | |
393 | 0 | out_ok: |
394 | 0 | return pv_get_strval(msg, param, res, &s); |
395 | 0 | } |
396 | | |
397 | | |
398 | | static int pv_get_route_name(struct sip_msg *msg, pv_param_t *param, |
399 | | pv_value_t *res) |
400 | 10.7k | { |
401 | 10.7k | str rn; |
402 | 10.7k | int idx, idx_flags, route_stack_size_ctx; |
403 | | |
404 | 10.7k | if (pv_get_spec_index(msg, param, &idx, &idx_flags) != 0) { |
405 | 0 | LM_ERR("invalid index\n"); |
406 | 0 | return -1; |
407 | 0 | } |
408 | | |
409 | 10.7k | if (idx_flags == PV_IDX_ALL) { |
410 | 0 | LM_ERR("unsupported index: [*]\n"); |
411 | 0 | return -1; |
412 | 0 | } |
413 | | |
414 | 10.7k | route_stack_size_ctx = route_stack_size - route_stack_start; |
415 | | |
416 | 10.7k | if (idx < 0) |
417 | 0 | idx += route_stack_size_ctx; |
418 | | |
419 | | /* index out of bounds -- play nice and return NULL */ |
420 | 10.7k | if (idx > route_stack_size_ctx - 1 || idx < 0) |
421 | 10.7k | return pv_get_null(msg, param, res); |
422 | | |
423 | | /* reverse the index, since we index the route stack backwards */ |
424 | 0 | idx = route_stack_size_ctx - idx - 1; |
425 | |
|
426 | 0 | get_route_name(idx, &rn); |
427 | 0 | return pv_get_strval(msg, param, res, &rn); |
428 | 10.7k | } |
429 | | |
430 | | |
431 | | static int pv_get_route_type(struct sip_msg *msg, pv_param_t *param, |
432 | | pv_value_t *res) |
433 | 10.7k | { |
434 | 10.7k | str rt; |
435 | 10.7k | int idx, idx_flags, route_stack_size_ctx; |
436 | | |
437 | 10.7k | if (pv_get_spec_index(msg, param, &idx, &idx_flags) != 0) { |
438 | 0 | LM_ERR("invalid index\n"); |
439 | 0 | return -1; |
440 | 0 | } |
441 | | |
442 | 10.7k | if (idx_flags == PV_IDX_ALL) { |
443 | 0 | LM_ERR("unsupported index: [*]\n"); |
444 | 0 | return -1; |
445 | 0 | } |
446 | | |
447 | 10.7k | route_stack_size_ctx = route_stack_size - route_stack_start; |
448 | | |
449 | 10.7k | if (idx < 0) |
450 | 0 | idx += route_stack_size_ctx; |
451 | | |
452 | | /* index out of bounds -- play nice and return NULL */ |
453 | 10.7k | if (idx > route_stack_size_ctx - 1 || idx < 0) |
454 | 10.7k | return pv_get_null(msg, param, res); |
455 | | |
456 | | /* reverse the index, since we index the route stack backwards */ |
457 | 0 | idx = route_stack_size_ctx - idx - 1; |
458 | |
|
459 | 0 | get_route_type(idx, &rt); |
460 | 0 | return pv_get_strval(msg, param, res, &rt); |
461 | 10.7k | } |
462 | | |
463 | | |
464 | | static int pv_get_times(struct sip_msg *msg, pv_param_t *param, |
465 | | pv_value_t *res) |
466 | 10.7k | { |
467 | 10.7k | if(msg==NULL) |
468 | 0 | return -1; |
469 | | |
470 | 10.7k | return pv_get_uintval(msg, param, res, (unsigned int)time(NULL)); |
471 | 10.7k | } |
472 | | |
473 | | static int pv_get_timem(struct sip_msg *msg, pv_param_t *param, |
474 | | pv_value_t *res) |
475 | 10.7k | { |
476 | 10.7k | struct timeval TP; |
477 | | |
478 | 10.7k | if(msg==NULL) |
479 | 0 | return -1; |
480 | | |
481 | 10.7k | gettimeofday(&TP, NULL); |
482 | 10.7k | return pv_get_uintval(msg, param, res, (unsigned int)TP.tv_usec); |
483 | 10.7k | } |
484 | | |
485 | | static int pv_get_start_times(struct sip_msg *msg, pv_param_t *param, |
486 | | pv_value_t *res) |
487 | 10.7k | { |
488 | 10.7k | if(msg==NULL) |
489 | 0 | return -1; |
490 | | |
491 | 10.7k | return pv_get_uintval(msg, param, res, (unsigned int)startup_time); |
492 | 10.7k | } |
493 | | |
494 | | static int pv_parse_time_name(pv_spec_p sp, const str *in) |
495 | 0 | { |
496 | 0 | sp->pvp.pvn.type = PV_NAME_INTSTR; |
497 | 0 | sp->pvp.pvn.u.isname.type = AVP_NAME_STR; |
498 | 0 | sp->pvp.pvn.u.isname.name.s.s = pkg_malloc(in->len + 1); |
499 | 0 | if (sp->pvp.pvn.u.isname.name.s.s==NULL) { |
500 | 0 | LM_ERR("failed to allocated private mem\n"); |
501 | 0 | return -1; |
502 | 0 | } |
503 | 0 | memcpy(sp->pvp.pvn.u.isname.name.s.s, in->s, in->len); |
504 | 0 | sp->pvp.pvn.u.isname.name.s.s[in->len] = 0; |
505 | 0 | sp->pvp.pvn.u.isname.name.s.len = in->len; |
506 | 0 | return 0; |
507 | 0 | } |
508 | | |
509 | | static int pv_get_formated_time(struct sip_msg *msg, pv_param_t *param, |
510 | | pv_value_t *res) |
511 | 0 | { |
512 | 0 | static char buf[128]; |
513 | 0 | struct tm ltime; |
514 | 0 | time_t t; |
515 | |
|
516 | 0 | if(msg==NULL) |
517 | 0 | return -1; |
518 | | |
519 | 0 | time( &t ); |
520 | 0 | localtime_r(&t, <ime); |
521 | 0 | res->rs.len = strftime( buf, 127, param->pvn.u.isname.name.s.s, <ime); |
522 | |
|
523 | 0 | if (res->rs.len<=0) |
524 | 0 | return pv_get_null(msg, param, res); |
525 | | |
526 | 0 | res->rs.s = buf; |
527 | 0 | res->flags = PV_VAL_STR; |
528 | 0 | return 0; |
529 | 0 | } |
530 | | |
531 | 10.7k | #define CTIME_BUFFER_NO 5 |
532 | | #define CTIME_BUFFER_SIZE 26 |
533 | | |
534 | | static int pv_get_timef(struct sip_msg *msg, pv_param_t *param, |
535 | | pv_value_t *res) |
536 | 10.7k | { |
537 | 10.7k | static char ctime_bufs[CTIME_BUFFER_NO][CTIME_BUFFER_SIZE]; |
538 | 10.7k | static char *buf; |
539 | 10.7k | static int ctime_buf_no = 0; |
540 | 10.7k | time_t t; |
541 | 10.7k | str s; |
542 | | |
543 | 10.7k | if(msg==NULL) |
544 | 0 | return -1; |
545 | | |
546 | 10.7k | t = time(NULL); |
547 | 10.7k | buf = ctime_bufs[ctime_buf_no]; |
548 | 10.7k | ctime_buf_no = (ctime_buf_no + 1) % CTIME_BUFFER_NO; |
549 | 10.7k | s.s = ctime_r(&t, buf); |
550 | 10.7k | s.len = strlen(s.s)-1; |
551 | 10.7k | return pv_get_strintval(msg, param, res, &s, (int)t); |
552 | 10.7k | } |
553 | | |
554 | | static int pv_get_msgid(struct sip_msg *msg, pv_param_t *param, |
555 | | pv_value_t *res) |
556 | 10.7k | { |
557 | 10.7k | if(msg==NULL) |
558 | 0 | return -1; |
559 | 10.7k | return pv_get_uintval(msg, param, res, msg->id); |
560 | 10.7k | } |
561 | | |
562 | | static int pv_get_method(struct sip_msg *msg, pv_param_t *param, |
563 | | pv_value_t *res) |
564 | 10.7k | { |
565 | 10.7k | if(msg==NULL) |
566 | 0 | return -1; |
567 | | |
568 | 10.7k | if(msg->first_line.type == SIP_REQUEST) |
569 | 10.7k | { |
570 | 10.7k | return pv_get_strintval(msg, param, res, |
571 | 10.7k | &msg->first_line.u.request.method, |
572 | 10.7k | (int)msg->first_line.u.request.method_value); |
573 | 10.7k | } |
574 | | |
575 | 4 | if(msg->cseq==NULL && ((parse_headers(msg, HDR_CSEQ_F, 0)==-1) || |
576 | 3 | (msg->cseq==NULL))) |
577 | 3 | { |
578 | 3 | LM_ERR("no CSEQ header\n"); |
579 | 3 | return pv_get_null(msg, param, res); |
580 | 3 | } |
581 | | |
582 | 1 | return pv_get_strintval(msg, param, res, |
583 | 1 | &get_cseq(msg)->method, |
584 | 1 | get_cseq(msg)->method_id); |
585 | 4 | } |
586 | | |
587 | | static int pv_get_status(struct sip_msg *msg, pv_param_t *param, |
588 | | pv_value_t *res) |
589 | 10.7k | { |
590 | 10.7k | if(msg==NULL) |
591 | 0 | return -1; |
592 | | |
593 | 10.7k | if(msg->first_line.type != SIP_REPLY) |
594 | 10.7k | return pv_get_null(msg, param, res); |
595 | | |
596 | 4 | return pv_get_intstrval(msg, param, res, |
597 | 4 | (int)msg->first_line.u.reply.statuscode, |
598 | 4 | &msg->first_line.u.reply.status); |
599 | 10.7k | } |
600 | | |
601 | | static int pv_get_reason(struct sip_msg *msg, pv_param_t *param, |
602 | | pv_value_t *res) |
603 | 10.7k | { |
604 | 10.7k | if(msg==NULL) |
605 | 0 | return -1; |
606 | | |
607 | 10.7k | if(msg->first_line.type != SIP_REPLY) |
608 | 10.7k | return pv_get_null(msg, param, res); |
609 | | |
610 | 4 | return pv_get_strval(msg, param, res, &msg->first_line.u.reply.reason); |
611 | 10.7k | } |
612 | | |
613 | | static int pv_get_ruri(struct sip_msg *msg, pv_param_t *param, |
614 | | pv_value_t *res) |
615 | 21.5k | { |
616 | 21.5k | if(msg==NULL || res==NULL) |
617 | 0 | return -1; |
618 | | |
619 | 21.5k | if(msg->first_line.type == SIP_REPLY) /* REPLY doesn't have a ruri */ |
620 | 8 | return pv_get_null(msg, param, res); |
621 | | |
622 | 21.5k | if(msg->parsed_uri_ok==0 /* R-URI not parsed*/ && parse_sip_msg_uri(msg)<0) |
623 | 17.5k | { |
624 | 17.5k | LM_ERR("failed to parse the R-URI\n"); |
625 | 17.5k | return pv_get_null(msg, param, res); |
626 | 17.5k | } |
627 | | |
628 | 3.95k | if (msg->new_uri.s!=NULL) |
629 | 0 | return pv_get_strval(msg, param, res, &msg->new_uri); |
630 | 3.95k | return pv_get_strval(msg, param, res, &msg->first_line.u.request.uri); |
631 | 3.95k | } |
632 | | |
633 | | static int pv_get_ru_q(struct sip_msg *msg, pv_param_t *param, |
634 | | pv_value_t *res) |
635 | 10.7k | { |
636 | 10.7k | if(msg==NULL || res==NULL) |
637 | 0 | return -1; |
638 | | |
639 | 10.7k | if(msg->first_line.type == SIP_REPLY) |
640 | 4 | return pv_get_null(msg, param, res); |
641 | | |
642 | 10.7k | return pv_get_sintval(msg, param, res, get_ruri_q(msg)); |
643 | 10.7k | } |
644 | | |
645 | | static int pv_get_ouri(struct sip_msg *msg, pv_param_t *param, |
646 | | pv_value_t *res) |
647 | 21.5k | { |
648 | 21.5k | if(msg==NULL || res==NULL) |
649 | 0 | return -1; |
650 | | |
651 | 21.5k | if(msg->first_line.type == SIP_REPLY) /* REPLY doesn't have a ruri */ |
652 | 8 | return pv_get_null(msg, param, res); |
653 | | |
654 | 21.5k | if(msg->parsed_orig_ruri_ok==0 |
655 | 21.5k | /* orig R-URI not parsed*/ && parse_orig_ruri(msg)<0) |
656 | 17.5k | { |
657 | 17.5k | LM_ERR("failed to parse the R-URI\n"); |
658 | 17.5k | return pv_get_null(msg, param, res); |
659 | 17.5k | } |
660 | 3.95k | return pv_get_strval(msg, param, res, &msg->first_line.u.request.uri); |
661 | 21.5k | } |
662 | | |
663 | | static int pv_get_xuri_attr(struct sip_msg *msg, struct sip_uri *parsed_uri, |
664 | | pv_param_t *param, pv_value_t *res) |
665 | 19.7k | { |
666 | 19.7k | unsigned short proto; |
667 | 19.7k | str proto_s; |
668 | | |
669 | 19.7k | if(param->pvn.u.isname.name.n==1) /* username */ |
670 | 5.93k | { |
671 | 5.93k | if(parsed_uri->user.s==NULL || parsed_uri->user.len<=0) |
672 | 4.03k | return pv_get_null(msg, param, res); |
673 | 1.90k | return pv_get_strval(msg, param, res, &parsed_uri->user); |
674 | 13.8k | } else if(param->pvn.u.isname.name.n==2) /* domain */ { |
675 | 5.93k | if(parsed_uri->host.s==NULL || parsed_uri->host.len<=0) |
676 | 18 | return pv_get_null(msg, param, res); |
677 | 5.91k | return pv_get_strval(msg, param, res, &parsed_uri->host); |
678 | 7.91k | } else if(param->pvn.u.isname.name.n==3) /* port */ { |
679 | 3.95k | if(parsed_uri->port.s==NULL) |
680 | 3.44k | return pv_get_uintval(msg, param, res, |
681 | 3.44k | get_uri_port( parsed_uri, &proto)); |
682 | 510 | return pv_get_strintval(msg, param, res, &parsed_uri->port, |
683 | 510 | (int)parsed_uri->port_no); |
684 | 3.95k | } else if(param->pvn.u.isname.name.n==4) /* protocol */ { |
685 | 3.95k | if(parsed_uri->transport_val.s==NULL) { |
686 | 3.43k | get_uri_port(parsed_uri, &proto); |
687 | 3.43k | proto_s.s = protos[proto].name; |
688 | 3.43k | proto_s.len = proto_s.s ? strlen(proto_s.s) : 0; |
689 | 3.43k | return pv_get_strintval(msg, param, res, &proto_s, (int)proto); |
690 | 3.43k | } |
691 | 522 | return pv_get_strintval(msg, param, res, &parsed_uri->transport_val, |
692 | 522 | (int)parsed_uri->proto); |
693 | 3.95k | } |
694 | 0 | LM_ERR("unknown specifier\n"); |
695 | 0 | return pv_get_null(msg, param, res); |
696 | 19.7k | } |
697 | | |
698 | | static int pv_get_ruri_attr(struct sip_msg *msg, pv_param_t *param, |
699 | | pv_value_t *res) |
700 | 64.6k | { |
701 | 64.6k | if(msg==NULL) |
702 | 0 | return -1; |
703 | | |
704 | 64.6k | if(msg->first_line.type == SIP_REPLY) /* REPLY doesn't have a ruri */ |
705 | 24 | return pv_get_null(msg, param, res); |
706 | | |
707 | 64.6k | if(msg->parsed_uri_ok==0 /* R-URI not parsed*/ && parse_sip_msg_uri(msg)<0) |
708 | 52.7k | { |
709 | 52.7k | LM_ERR("failed to parse the R-URI\n"); |
710 | 52.7k | return pv_get_null(msg, param, res); |
711 | 52.7k | } |
712 | 11.8k | return pv_get_xuri_attr(msg, &(msg->parsed_uri), param, res); |
713 | 64.6k | } |
714 | | |
715 | | static int pv_get_ouri_attr(struct sip_msg *msg, pv_param_t *param, |
716 | | pv_value_t *res) |
717 | 43.1k | { |
718 | 43.1k | if(msg==NULL) |
719 | 0 | return -1; |
720 | | |
721 | 43.1k | if(msg->first_line.type == SIP_REPLY) /* REPLY doesn't have a ruri */ |
722 | 16 | return pv_get_null(msg, param, res); |
723 | | |
724 | 43.0k | if(msg->parsed_orig_ruri_ok==0 |
725 | 43.0k | /* orig R-URI not parsed*/ && parse_orig_ruri(msg)<0) |
726 | 35.1k | { |
727 | 35.1k | LM_ERR("failed to parse the R-URI\n"); |
728 | 35.1k | return pv_get_null(msg, param, res); |
729 | 35.1k | } |
730 | 7.91k | return pv_get_xuri_attr(msg, &(msg->parsed_orig_ruri), param, res); |
731 | 43.0k | } |
732 | | |
733 | | static int pv_get_path(struct sip_msg *msg, pv_param_t *param, |
734 | | pv_value_t *res) |
735 | 10.7k | { |
736 | 10.7k | if(msg==NULL) |
737 | 0 | return -1; |
738 | | |
739 | 10.7k | if(!msg->path_vec.s) |
740 | 10.7k | { |
741 | 10.7k | return pv_get_null(msg, param, res); |
742 | 10.7k | } |
743 | 0 | return pv_get_strval(msg, param, res, &msg->path_vec); |
744 | 10.7k | } |
745 | | |
746 | 0 | #define CT_NAME_S "name" |
747 | 0 | #define CT_NAME_LEN (sizeof(CT_NAME_S)-1) |
748 | 0 | #define CT_NAME_ID 1 |
749 | 0 | #define CT_URI_S "uri" |
750 | 0 | #define CT_URI_LEN (sizeof(CT_URI_S)-1) |
751 | 0 | #define CT_URI_ID 2 |
752 | 0 | #define CT_Q_S "q" |
753 | 0 | #define CT_Q_LEN (sizeof(CT_Q_S)-1) |
754 | 0 | #define CT_Q_ID 3 |
755 | 0 | #define CT_EXPIRES_S "expires" |
756 | 0 | #define CT_EXPIRES_LEN (sizeof(CT_EXPIRES_S)-1) |
757 | 0 | #define CT_EXPIRES_ID 4 |
758 | 0 | #define CT_METHODS_S "methods" |
759 | 0 | #define CT_METHODS_LEN (sizeof(CT_METHODS_S)-1) |
760 | 0 | #define CT_METHODS_ID 5 |
761 | 0 | #define CT_RECEIVED_S "received" |
762 | 0 | #define CT_RECEIVED_LEN (sizeof(CT_RECEIVED_S)-1) |
763 | 0 | #define CT_RECEIVED_ID 6 |
764 | 0 | #define CT_PARAMS_S "params" |
765 | 0 | #define CT_PARAMS_LEN (sizeof(CT_PARAMS_S)-1) |
766 | 0 | #define CT_PARAMS_ID 7 |
767 | | |
768 | | static int pv_parse_ct_name(pv_spec_p sp, const str *in) |
769 | 0 | { |
770 | 0 | if (sp==NULL) |
771 | 0 | return -1; |
772 | | |
773 | 0 | sp->pvp.pvn.type = PV_NAME_INTSTR; |
774 | 0 | sp->pvp.pvn.u.isname.type = 0; |
775 | |
|
776 | 0 | if (in==NULL || in->s==NULL || in->len==0) { |
777 | 0 | sp->pvp.pvn.u.isname.name.n = 0; |
778 | 0 | } else |
779 | 0 | if (in->len==CT_NAME_LEN && |
780 | 0 | strncasecmp(in->s, CT_NAME_S, CT_NAME_LEN)==0 ) { |
781 | 0 | sp->pvp.pvn.u.isname.name.n = CT_NAME_ID; |
782 | 0 | } else |
783 | 0 | if (in->len==CT_URI_LEN && |
784 | 0 | strncasecmp(in->s, CT_URI_S, CT_URI_LEN)==0 ) { |
785 | 0 | sp->pvp.pvn.u.isname.name.n = CT_URI_ID; |
786 | 0 | } else |
787 | 0 | if (in->len==CT_Q_LEN && |
788 | 0 | strncasecmp(in->s, CT_Q_S, CT_Q_LEN)==0 ) { |
789 | 0 | sp->pvp.pvn.u.isname.name.n = CT_Q_ID; |
790 | 0 | } else |
791 | 0 | if (in->len==CT_EXPIRES_LEN && |
792 | 0 | strncasecmp(in->s, CT_EXPIRES_S, CT_EXPIRES_LEN)==0 ) { |
793 | 0 | sp->pvp.pvn.u.isname.name.n = CT_EXPIRES_ID; |
794 | 0 | } else |
795 | 0 | if (in->len==CT_METHODS_LEN && |
796 | 0 | strncasecmp(in->s, CT_METHODS_S, CT_METHODS_LEN)==0 ) { |
797 | 0 | sp->pvp.pvn.u.isname.name.n = CT_METHODS_ID; |
798 | 0 | } else |
799 | 0 | if (in->len==CT_RECEIVED_LEN && |
800 | 0 | strncasecmp(in->s, CT_RECEIVED_S, CT_RECEIVED_LEN)==0 ) { |
801 | 0 | sp->pvp.pvn.u.isname.name.n = CT_RECEIVED_ID; |
802 | 0 | } else |
803 | 0 | if (in->len==CT_PARAMS_LEN && |
804 | 0 | strncasecmp(in->s, CT_PARAMS_S, CT_PARAMS_LEN)==0 ) { |
805 | 0 | sp->pvp.pvn.u.isname.name.n = CT_PARAMS_ID; |
806 | 0 | } else { |
807 | 0 | LM_ERR("unsupported CT field <%.*s>\n",in->len,in->s); |
808 | 0 | return -1; |
809 | 0 | } |
810 | | |
811 | 0 | return 0; |
812 | 0 | } |
813 | | |
814 | | |
815 | | static inline int get_contact_body_field(pv_value_t *res,struct hdr_field *cth, |
816 | | contact_t *ct, pv_name_t *pvn) |
817 | 557 | { |
818 | 557 | param_t *p; |
819 | | |
820 | 557 | if (ct==NULL) { |
821 | | /* star contact hdr */ |
822 | 1 | if (pvn->u.isname.name.n==0) { |
823 | 1 | res->rs = cth->body; |
824 | 1 | res->flags = PV_VAL_STR; |
825 | 1 | return 0; |
826 | 1 | } |
827 | 0 | return pv_get_null(NULL, NULL, res); |
828 | 1 | } |
829 | | |
830 | 556 | switch (pvn->u.isname.name.n) { |
831 | 556 | case 0: /* all body */ |
832 | 556 | res->rs.s = ct->name.s?ct->name.s:ct->uri.s; |
833 | 556 | res->rs.len = ct->len; |
834 | 556 | break; |
835 | 0 | case CT_NAME_ID: /* name only */ |
836 | 0 | if (ct->name.s==NULL || ct->name.len==0) |
837 | 0 | return pv_get_null(NULL, NULL, res); |
838 | 0 | res->rs = ct->name; |
839 | 0 | break; |
840 | 0 | case CT_URI_ID: /* uri only */ |
841 | 0 | res->rs = ct->uri; |
842 | 0 | break; |
843 | 0 | case CT_Q_ID: /* Q param only */ |
844 | 0 | if ( !ct->q || !ct->q->body.s || !ct->q->body.len) |
845 | 0 | return pv_get_null(NULL, NULL, res); |
846 | 0 | res->rs = ct->q->body; |
847 | 0 | break; |
848 | 0 | case CT_EXPIRES_ID: /* EXPIRES param only */ |
849 | 0 | if (!ct->expires||!ct->expires->body.s||!ct->expires->body.len) |
850 | 0 | return pv_get_null(NULL, NULL, res); |
851 | 0 | res->rs = ct->expires->body; |
852 | 0 | break; |
853 | 0 | case CT_METHODS_ID: /* METHODS param only */ |
854 | 0 | if (!ct->methods||!ct->methods->body.s||!ct->methods->body.len) |
855 | 0 | return pv_get_null(NULL, NULL, res); |
856 | 0 | res->rs = ct->methods->body; |
857 | 0 | break; |
858 | 0 | case CT_RECEIVED_ID: /* RECEIVED param only */ |
859 | 0 | if(!ct->received||!ct->received->body.s||!ct->received->body.len) |
860 | 0 | return pv_get_null(NULL, NULL, res); |
861 | 0 | res->rs = ct->received->body; |
862 | 0 | break; |
863 | 0 | case CT_PARAMS_ID: /* all param */ |
864 | 0 | if (!ct->params) |
865 | 0 | return pv_get_null(NULL, NULL, res); |
866 | 0 | res->rs.s = ct->params->name.s; |
867 | 0 | for( p=ct->params ; p->next ; p=p->next); |
868 | 0 | res->rs.len = p->name.s + p->len - res->rs.s; |
869 | 0 | break; |
870 | 0 | default: |
871 | 0 | LM_CRIT("BUG - unsupported ID %d\n",pvn->u.isname.type); |
872 | 0 | return pv_get_null(NULL, NULL, res); |
873 | 556 | } |
874 | | |
875 | 556 | res->flags = PV_VAL_STR; |
876 | 556 | return 0; |
877 | 556 | } |
878 | | |
879 | | |
880 | | static int pv_get_contact_body(struct sip_msg *msg, pv_param_t *param, |
881 | | pv_value_t *res) |
882 | 10.7k | { |
883 | 10.7k | struct hdr_field *ct_h; |
884 | 10.7k | contact_body_t *ct_b; |
885 | 10.7k | contact_t *ct; |
886 | 10.7k | int idx; |
887 | 10.7k | int idxf; |
888 | 10.7k | char *p; |
889 | | |
890 | 10.7k | if(msg==NULL) |
891 | 0 | return -1; |
892 | | |
893 | | /* get all CONTACT headers */ |
894 | 10.7k | if(parse_headers(msg, HDR_EOH_F, 0)==-1 || msg->contact==NULL || |
895 | 10.7k | !msg->contact->body.s || msg->contact->body.len<=0) |
896 | 9.68k | { |
897 | 9.68k | LM_DBG("no contact header!\n"); |
898 | 9.68k | return pv_get_null(msg, param, res); |
899 | 9.68k | } |
900 | | |
901 | 1.09k | ct_h = msg->contact; |
902 | 1.09k | if (parse_contact( ct_h )!=0) { |
903 | 538 | LM_ERR("failed to parse contact hdr\n"); |
904 | 538 | return -1; |
905 | 538 | } |
906 | 557 | ct_b = (contact_body_t*)ct_h->parsed; |
907 | 557 | if (ct_b==NULL) |
908 | 0 | return pv_get_null(msg, param, res); |
909 | 557 | ct = ct_b->contacts; |
910 | | |
911 | | /* get the index */ |
912 | 557 | if(pv_get_spec_index(msg, param, &idx, &idxf)!=0) { |
913 | 0 | LM_ERR("invalid index\n"); |
914 | 0 | return -1; |
915 | 0 | } |
916 | | |
917 | 557 | if( idxf!=PV_IDX_ALL && idx==0) { |
918 | | /* no index specified -> return the first contact body */ |
919 | 557 | return get_contact_body_field( res , ct_h, ct, ¶m->pvn); |
920 | 557 | } |
921 | | |
922 | 0 | if(idxf==PV_IDX_ALL) { |
923 | | /* return all contact bodies */ |
924 | 0 | p = pv_local_buf; |
925 | 0 | do { |
926 | 0 | if(p!=pv_local_buf) { |
927 | 0 | if (p-pv_local_buf+PV_FIELD_DELIM_LEN+1>PV_LOCAL_BUF_SIZE){ |
928 | 0 | LM_ERR("local buffer length exceeded\n"); |
929 | 0 | return pv_get_null(msg, param, res); |
930 | 0 | } |
931 | 0 | memcpy(p, PV_FIELD_DELIM, PV_FIELD_DELIM_LEN); |
932 | 0 | p += PV_FIELD_DELIM_LEN; |
933 | 0 | } |
934 | | |
935 | 0 | get_contact_body_field( res , ct_h, ct, ¶m->pvn); |
936 | 0 | if (p-pv_local_buf+res->rs.len+1>PV_LOCAL_BUF_SIZE) { |
937 | 0 | LM_ERR("local buffer length exceeded!\n"); |
938 | 0 | return pv_get_null(msg, param, res); |
939 | 0 | } |
940 | 0 | memcpy(p, res->rs.s, res->rs.len); |
941 | 0 | p += res->rs.len; |
942 | |
|
943 | 0 | ct = ct?ct->next:NULL; |
944 | 0 | while (ct==NULL && ct_h!=NULL) { |
945 | 0 | ct_h = ct_h->sibling; |
946 | 0 | if (ct_h) { |
947 | 0 | if (parse_contact( ct_h )!=0) { |
948 | 0 | LM_ERR("failed to parse contact hdr\n"); |
949 | 0 | return -1; |
950 | 0 | } |
951 | 0 | ct_b = (contact_body_t*)ct_h->parsed; |
952 | 0 | ct = ct_b->contacts; |
953 | 0 | } |
954 | 0 | } |
955 | 0 | } while (ct_h); |
956 | | |
957 | 0 | res->rs.s = pv_local_buf; |
958 | 0 | res->rs.len = p - pv_local_buf; |
959 | 0 | res->flags = PV_VAL_STR; |
960 | 0 | return 0; |
961 | 0 | } |
962 | | |
963 | | /* numerical index */ |
964 | 0 | if (idx<0) { |
965 | | /* index from the end */ |
966 | 0 | idxf=0; |
967 | 0 | while(ct_h) { |
968 | 0 | idxf++; |
969 | 0 | ct = ct?ct->next:NULL; |
970 | 0 | while (ct==NULL && ct_h!=NULL) { |
971 | 0 | ct_h = ct_h->sibling; |
972 | 0 | if (ct_h) { |
973 | 0 | if (parse_contact( ct_h)!=0) { |
974 | 0 | LM_ERR("failed to parse contact hdr\n"); |
975 | 0 | return -1; |
976 | 0 | } |
977 | 0 | ct_b = (contact_body_t*)ct_h->parsed; |
978 | 0 | ct = ct_b->contacts; |
979 | 0 | } |
980 | 0 | } |
981 | 0 | } |
982 | 0 | if (-idx>idxf) |
983 | 0 | return pv_get_null(msg, param, res); |
984 | | |
985 | 0 | idx = idxf +idx; |
986 | 0 | ct_h = msg->contact; |
987 | 0 | ct_b = (contact_body_t*)ct_h->parsed; |
988 | 0 | ct = ct_b->contacts; |
989 | 0 | } |
990 | | |
991 | 0 | while (idx!=0 && ct_h) { |
992 | | /* get to the next contact body */ |
993 | 0 | idx--; |
994 | 0 | ct = ct?ct->next:NULL; |
995 | 0 | while (ct==NULL && ct_h!=NULL) { |
996 | 0 | ct_h = ct_h->sibling; |
997 | 0 | if (ct_h) { |
998 | 0 | if (parse_contact( ct_h )!=0) { |
999 | 0 | LM_ERR("failed to parse contact hdr\n"); |
1000 | 0 | return -1; |
1001 | 0 | } |
1002 | 0 | ct_b = (contact_body_t*)ct_h->parsed; |
1003 | 0 | ct = ct_b->contacts; |
1004 | 0 | } |
1005 | 0 | } |
1006 | 0 | } |
1007 | | |
1008 | | /* nothing found ?*/ |
1009 | 0 | if (ct==NULL) |
1010 | 0 | return pv_get_null(msg, param, res); |
1011 | | |
1012 | | /* take the current body */ |
1013 | 0 | return get_contact_body_field( res , ct_h, ct, ¶m->pvn); |
1014 | 0 | } |
1015 | | |
1016 | | extern err_info_t _oser_err_info; |
1017 | | static int pv_get_errinfo_attr(struct sip_msg *msg, pv_param_t *param, |
1018 | | pv_value_t *res) |
1019 | 53.8k | { |
1020 | 53.8k | if(msg==NULL) |
1021 | 0 | return -1; |
1022 | | |
1023 | 53.8k | if(param->pvn.u.isname.name.n==0) /* class */ { |
1024 | 10.7k | return pv_get_sintval(msg, param, res, _oser_err_info.eclass); |
1025 | 43.1k | } else if(param->pvn.u.isname.name.n==1) /* level */ { |
1026 | 10.7k | return pv_get_sintval(msg, param, res, _oser_err_info.level); |
1027 | 32.3k | } else if(param->pvn.u.isname.name.n==2) /* info */ { |
1028 | 10.7k | if(_oser_err_info.info.s==NULL) |
1029 | 0 | pv_get_null(msg, param, res); |
1030 | 10.7k | return pv_get_strval(msg, param, res, &_oser_err_info.info); |
1031 | 21.5k | } else if(param->pvn.u.isname.name.n==3) /* rcode */ { |
1032 | 10.7k | return pv_get_sintval(msg, param, res, _oser_err_info.rcode); |
1033 | 10.7k | } else if(param->pvn.u.isname.name.n==4) /* rreason */ { |
1034 | 10.7k | if(_oser_err_info.rreason.s==NULL) |
1035 | 0 | pv_get_null(msg, param, res); |
1036 | 10.7k | return pv_get_strval(msg, param, res, &_oser_err_info.rreason); |
1037 | 10.7k | } else { |
1038 | 0 | LM_DBG("invalid attribute!\n"); |
1039 | 0 | return pv_get_null(msg, param, res); |
1040 | 0 | } |
1041 | 53.8k | } |
1042 | | |
1043 | | static int pv_get_xto_attr(struct sip_msg *msg, pv_param_t *param, |
1044 | | pv_value_t *res, struct to_body *xto, int type) |
1045 | 27.1k | { |
1046 | 27.1k | struct sip_uri *uri; |
1047 | 27.1k | if(xto==NULL) |
1048 | 0 | return -1; |
1049 | | |
1050 | 27.1k | if(param->pvn.u.isname.name.n==1) /* uri */ |
1051 | 6.77k | return pv_get_strval(msg, param, res, &xto->uri); |
1052 | | |
1053 | 20.3k | if(param->pvn.u.isname.name.n==4) /* tag */ |
1054 | 3.38k | { |
1055 | 3.38k | if (xto->tag_value.s==NULL || xto->tag_value.len<=0) |
1056 | 3.38k | { |
1057 | 3.38k | LM_DBG("no Tag parameter\n"); |
1058 | 3.38k | return pv_get_null(msg, param, res); |
1059 | 3.38k | } |
1060 | 8 | return pv_get_strval(msg, param, res, &xto->tag_value); |
1061 | 3.38k | } |
1062 | | |
1063 | 16.9k | if(param->pvn.u.isname.name.n==5) /* display name */ |
1064 | 3.38k | { |
1065 | 3.38k | if(xto->display.s==NULL || xto->display.len<=0) |
1066 | 3.19k | { |
1067 | 3.19k | LM_DBG("no Display name\n"); |
1068 | 3.19k | return pv_get_null(msg, param, res); |
1069 | 3.19k | } |
1070 | 194 | return pv_get_strval(msg, param, res, &xto->display); |
1071 | 3.38k | } |
1072 | | |
1073 | 13.5k | if(type==0) |
1074 | 12.9k | { |
1075 | 12.9k | if((uri=parse_to_uri(msg))==NULL) |
1076 | 5.83k | { |
1077 | 5.83k | LM_ERR("cannot parse To URI\n"); |
1078 | 5.83k | return pv_get_null(msg, param, res); |
1079 | 5.83k | } |
1080 | 12.9k | } else { |
1081 | 612 | if((uri=parse_from_uri(msg))==NULL) |
1082 | 184 | { |
1083 | 184 | LM_ERR("cannot parse From URI\n"); |
1084 | 184 | return pv_get_null(msg, param, res); |
1085 | 184 | } |
1086 | 612 | } |
1087 | | |
1088 | 7.53k | if(param->pvn.u.isname.name.n==2) /* username */ |
1089 | 3.76k | { |
1090 | 3.76k | if(uri->user.s==NULL || uri->user.len<=0) |
1091 | 2.61k | { |
1092 | 2.61k | LM_DBG("no username\n"); |
1093 | 2.61k | return pv_get_null(msg, param, res); |
1094 | 2.61k | } |
1095 | 1.15k | return pv_get_strval(msg, param, res, &uri->user); |
1096 | 3.76k | } else if(param->pvn.u.isname.name.n==3) /* domain */ { |
1097 | 3.76k | if(uri->host.s==NULL || uri->host.len<=0) |
1098 | 16 | { |
1099 | 16 | LM_DBG("no domain\n"); |
1100 | 16 | return pv_get_null(msg, param, res); |
1101 | 16 | } |
1102 | 3.75k | return pv_get_strval(msg, param, res, &uri->host); |
1103 | 3.76k | } |
1104 | | |
1105 | 0 | LM_ERR("unknown specifier\n"); |
1106 | 0 | return pv_get_null(msg, param, res); |
1107 | 7.53k | } |
1108 | | |
1109 | | static int pv_get_to_attr(struct sip_msg *msg, pv_param_t *param, |
1110 | | pv_value_t *res) |
1111 | 86.2k | { |
1112 | 86.2k | if(msg==NULL) |
1113 | 0 | return -1; |
1114 | | |
1115 | 86.2k | if(msg->to==NULL && parse_headers(msg, HDR_TO_F, 0)==-1) |
1116 | 0 | { |
1117 | 0 | LM_ERR("cannot parse To header\n"); |
1118 | 0 | return pv_get_null(msg, param, res); |
1119 | 0 | } |
1120 | 86.2k | if(msg->to==NULL || get_to(msg)==NULL) { |
1121 | 60.3k | LM_DBG("no To header\n"); |
1122 | 60.3k | return pv_get_null(msg, param, res); |
1123 | 60.3k | } |
1124 | 25.8k | return pv_get_xto_attr(msg, param, res, get_to(msg), 0); |
1125 | 86.2k | } |
1126 | | |
1127 | | static int pv_get_from_attr(struct sip_msg *msg, pv_param_t *param, |
1128 | | pv_value_t *res) |
1129 | 86.2k | { |
1130 | 86.2k | if(msg==NULL) |
1131 | 0 | return -1; |
1132 | | |
1133 | 86.2k | if(parse_from_header(msg)<0) |
1134 | 84.9k | { |
1135 | 84.9k | LM_ERR("cannot parse From header\n"); |
1136 | 84.9k | return pv_get_null(msg, param, res); |
1137 | 84.9k | } |
1138 | | |
1139 | 1.22k | if(msg->from==NULL || get_from(msg)==NULL) { |
1140 | 0 | LM_DBG("no From header\n"); |
1141 | 0 | return pv_get_null(msg, param, res); |
1142 | 0 | } |
1143 | 1.22k | return pv_get_xto_attr(msg, param, res, get_from(msg), 1); |
1144 | 1.22k | } |
1145 | | |
1146 | | static int pv_get_cseq(struct sip_msg *msg, pv_param_t *param, |
1147 | | pv_value_t *res) |
1148 | 10.7k | { |
1149 | 10.7k | if(msg==NULL) |
1150 | 0 | return -1; |
1151 | | |
1152 | 10.7k | if(msg->cseq==NULL && ((parse_headers(msg, HDR_CSEQ_F, 0)==-1) |
1153 | 10.7k | || (msg->cseq==NULL)) ) |
1154 | 10.7k | { |
1155 | 10.7k | LM_ERR("cannot parse CSEQ header\n"); |
1156 | 10.7k | return pv_get_null(msg, param, res); |
1157 | 10.7k | } |
1158 | 26 | return pv_get_strval(msg, param, res, &(get_cseq(msg)->number)); |
1159 | 10.7k | } |
1160 | | |
1161 | | static int pv_get_msg_buf(struct sip_msg *msg, pv_param_t *param, |
1162 | | pv_value_t *res) |
1163 | 10.7k | { |
1164 | 10.7k | str s; |
1165 | 10.7k | if(msg==NULL) |
1166 | 0 | return -1; |
1167 | | |
1168 | 10.7k | s.s = msg->buf; |
1169 | 10.7k | s.len = msg->len; |
1170 | 10.7k | return pv_get_strval(msg, param, res, &s); |
1171 | 10.7k | } |
1172 | | |
1173 | | static int pv_get_msg_len(struct sip_msg *msg, pv_param_t *param, |
1174 | | pv_value_t *res) |
1175 | 10.7k | { |
1176 | 10.7k | if(msg==NULL) |
1177 | 0 | return -1; |
1178 | | |
1179 | 10.7k | return pv_get_uintval(msg, param, res, msg->len); |
1180 | 10.7k | } |
1181 | | |
1182 | | static int pv_get_flags(struct sip_msg *msg, pv_param_t *param, |
1183 | | pv_value_t *res) |
1184 | 10.7k | { |
1185 | 10.7k | str buf; |
1186 | | |
1187 | 10.7k | if (!msg) |
1188 | 0 | return -1; |
1189 | | |
1190 | 10.7k | buf = bitmask_to_flag_list(FLAG_TYPE_MSG, msg->flags); |
1191 | | |
1192 | 10.7k | return pv_get_strval(msg, param, res, &buf); |
1193 | 10.7k | } |
1194 | | |
1195 | | static int pv_get_bflags(struct sip_msg *msg, pv_param_t *param, |
1196 | | pv_value_t *res) |
1197 | 10.7k | { |
1198 | 10.7k | str buf; |
1199 | | |
1200 | 10.7k | if (!msg) |
1201 | 0 | return -1; |
1202 | | |
1203 | 10.7k | buf = bitmask_to_flag_list(FLAG_TYPE_BRANCH, getb0flags(msg)); |
1204 | | |
1205 | 10.7k | return pv_get_strval(msg, param, res, &buf); |
1206 | 10.7k | } |
1207 | | |
1208 | | static int pv_get_callid(struct sip_msg *msg, pv_param_t *param, |
1209 | | pv_value_t *res) |
1210 | 10.7k | { |
1211 | 10.7k | if(msg==NULL) |
1212 | 0 | return -1; |
1213 | | |
1214 | 10.7k | if(msg->callid==NULL && ((parse_headers(msg, HDR_CALLID_F, 0)==-1) || |
1215 | 10.7k | (msg->callid==NULL)) ) |
1216 | 10.7k | { |
1217 | 10.7k | LM_ERR("cannot parse Call-Id header\n"); |
1218 | 10.7k | return pv_get_null(msg, param, res); |
1219 | 10.7k | } |
1220 | | |
1221 | 25 | return pv_get_strval(msg, param, res, &msg->callid->body); |
1222 | 10.7k | } |
1223 | | |
1224 | | static int pv_get_srcip(struct sip_msg *msg, pv_param_t *param, |
1225 | | pv_value_t *res) |
1226 | 21.5k | { |
1227 | 21.5k | str s; |
1228 | 21.5k | if(msg==NULL) |
1229 | 0 | return -1; |
1230 | | |
1231 | 21.5k | if ( (s.s=ip_addr2a(&msg->rcv.src_ip))==NULL) |
1232 | 0 | return pv_get_null(msg, param, res); |
1233 | 21.5k | s.len = strlen(s.s); |
1234 | 21.5k | return pv_get_strval(msg, param, res, &s); |
1235 | 21.5k | } |
1236 | | |
1237 | | static int pv_get_srcport(struct sip_msg *msg, pv_param_t *param, |
1238 | | pv_value_t *res) |
1239 | 10.7k | { |
1240 | 10.7k | if(msg==NULL) |
1241 | 0 | return -1; |
1242 | 10.7k | return pv_get_uintval(msg, param, res, msg->rcv.src_port); |
1243 | 10.7k | } |
1244 | | |
1245 | | static int pv_get_useragent(struct sip_msg *msg, pv_param_t *param, |
1246 | | pv_value_t *res) |
1247 | 10.7k | { |
1248 | 10.7k | if(msg==NULL) |
1249 | 0 | return -1; |
1250 | 10.7k | if(msg->user_agent==NULL && ((parse_headers(msg, HDR_USERAGENT_F, 0)==-1) |
1251 | 10.7k | || (msg->user_agent==NULL))) |
1252 | 10.7k | { |
1253 | 10.7k | LM_DBG("no User-Agent header\n"); |
1254 | 10.7k | return pv_get_null(msg, param, res); |
1255 | 10.7k | } |
1256 | | |
1257 | 12 | return pv_get_strval(msg, param, res, &msg->user_agent->body); |
1258 | 10.7k | } |
1259 | | |
1260 | | static int pv_get_refer_to(struct sip_msg *msg, pv_param_t *param, |
1261 | | pv_value_t *res) |
1262 | 10.7k | { |
1263 | 10.7k | if(msg==NULL) |
1264 | 0 | return -1; |
1265 | | |
1266 | 10.7k | if(parse_refer_to_header(msg)==-1) |
1267 | 10.7k | { |
1268 | 10.7k | LM_DBG("no Refer-To header\n"); |
1269 | 10.7k | return pv_get_null(msg, param, res); |
1270 | 10.7k | } |
1271 | | |
1272 | 3 | if(msg->refer_to==NULL || get_refer_to(msg)==NULL) |
1273 | 0 | return pv_get_null(msg, param, res); |
1274 | | |
1275 | 3 | return pv_get_strval(msg, param, res, &(get_refer_to(msg)->uri)); |
1276 | 3 | } |
1277 | | |
1278 | | static int pv_get_diversion(struct sip_msg *msg, pv_param_t *param, |
1279 | | pv_value_t *res) |
1280 | 32.3k | { |
1281 | 32.3k | str *val; |
1282 | 32.3k | str name; |
1283 | | |
1284 | 32.3k | if(msg == NULL) |
1285 | 0 | return -1; |
1286 | | |
1287 | 32.3k | if(parse_diversion_header(msg) == -1) |
1288 | 31.9k | { |
1289 | 31.9k | LM_DBG("no Diversion header\n"); |
1290 | 31.9k | return pv_get_null(msg, param, res); |
1291 | 31.9k | } |
1292 | | |
1293 | 363 | if(msg->diversion == NULL || get_diversion(msg) == NULL) |
1294 | 0 | { |
1295 | 0 | LM_DBG("no Diversion header\n"); |
1296 | 0 | return pv_get_null(msg, param, res); |
1297 | 0 | } |
1298 | | |
1299 | 363 | if(param->pvn.u.isname.name.n == 1) { /* uri */ |
1300 | 121 | return pv_get_strval(msg, param, res, &(get_diversion(msg)->uri)); |
1301 | 121 | } |
1302 | | |
1303 | 242 | if(param->pvn.u.isname.name.n == 2) { /* reason param */ |
1304 | 121 | name.s = "reason"; |
1305 | 121 | name.len = 6; |
1306 | 121 | val = diversion_param(msg, name); |
1307 | 121 | if (val) { |
1308 | 3 | return pv_get_strval(msg, param, res, val); |
1309 | 118 | } else { |
1310 | 118 | return pv_get_null(msg, param, res); |
1311 | 118 | } |
1312 | 121 | } |
1313 | | |
1314 | 121 | if(param->pvn.u.isname.name.n == 3) { /* privacy param */ |
1315 | 121 | name.s = "privacy"; |
1316 | 121 | name.len = 7; |
1317 | 121 | val = diversion_param(msg, name); |
1318 | 121 | if (val) { |
1319 | 2 | return pv_get_strval(msg, param, res, val); |
1320 | 119 | } else { |
1321 | 119 | return pv_get_null(msg, param, res); |
1322 | 119 | } |
1323 | 121 | } |
1324 | | |
1325 | 0 | LM_ERR("unknown diversion specifier\n"); |
1326 | 0 | return pv_get_null(msg, param, res); |
1327 | 121 | } |
1328 | | |
1329 | | static int pv_get_rpid(struct sip_msg *msg, pv_param_t *param, |
1330 | | pv_value_t *res) |
1331 | 10.7k | { |
1332 | 10.7k | if(msg==NULL) |
1333 | 0 | return -1; |
1334 | | |
1335 | 10.7k | if(parse_rpid_header(msg)==-1) |
1336 | 10.7k | { |
1337 | 10.7k | LM_DBG("no RPID header\n"); |
1338 | 10.7k | return pv_get_null(msg, param, res); |
1339 | 10.7k | } |
1340 | | |
1341 | 1 | if(msg->rpid==NULL || get_rpid(msg)==NULL) |
1342 | 0 | return pv_get_null(msg, param, res); |
1343 | | |
1344 | 1 | return pv_get_strval(msg, param, res, &(get_rpid(msg)->uri)); |
1345 | 1 | } |
1346 | | |
1347 | | static int pv_get_ppi_attr(struct sip_msg *msg, pv_param_t *param, |
1348 | | pv_value_t *res) |
1349 | 43.1k | { |
1350 | 43.1k | struct sip_uri *uri; |
1351 | | |
1352 | 43.1k | if(msg==NULL) |
1353 | 0 | return -1; |
1354 | | |
1355 | 43.1k | if(parse_ppi_header(msg) < 0) { |
1356 | 42.4k | LM_DBG("no P-Preferred-Identity header\n"); |
1357 | 42.4k | return pv_get_null(msg, param, res); |
1358 | 42.4k | } |
1359 | | |
1360 | 660 | if(msg->ppi == NULL || get_ppi(msg) == NULL) { |
1361 | 0 | LM_DBG("no P-Preferred-Identity header\n"); |
1362 | 0 | return pv_get_null(msg, param, res); |
1363 | 0 | } |
1364 | | |
1365 | 660 | if(param->pvn.u.isname.name.n == 1) { /* uri */ |
1366 | 165 | return pv_get_strval(msg, param, res, &(get_ppi(msg)->uri)); |
1367 | 165 | } |
1368 | | |
1369 | 495 | if(param->pvn.u.isname.name.n==4) { /* display name */ |
1370 | 165 | if(get_ppi(msg)->display.s == NULL || |
1371 | 165 | get_ppi(msg)->display.len <= 0) { |
1372 | 128 | LM_DBG("no P-Preferred-Identity display name\n"); |
1373 | 128 | return pv_get_null(msg, param, res); |
1374 | 128 | } |
1375 | 37 | return pv_get_strval(msg, param, res, &(get_ppi(msg)->display)); |
1376 | 165 | } |
1377 | | |
1378 | 330 | if((uri=parse_ppi_uri(msg))==NULL) { |
1379 | 316 | LM_ERR("cannot parse P-Preferred-Identity URI\n"); |
1380 | 316 | return pv_get_null(msg, param, res); |
1381 | 316 | } |
1382 | | |
1383 | 14 | if(param->pvn.u.isname.name.n==2) { /* username */ |
1384 | 7 | if(uri->user.s==NULL || uri->user.len<=0) { |
1385 | 1 | LM_DBG("no P-Preferred-Identity username\n"); |
1386 | 1 | return pv_get_null(msg, param, res); |
1387 | 1 | } |
1388 | 6 | return pv_get_strval(msg, param, res, &uri->user); |
1389 | 7 | } else if(param->pvn.u.isname.name.n==3) { /* domain */ |
1390 | 7 | if(uri->host.s==NULL || uri->host.len<=0) { |
1391 | 2 | LM_DBG("no P-Preferred-Identity domain\n"); |
1392 | 2 | return pv_get_null(msg, param, res); |
1393 | 2 | } |
1394 | 5 | return pv_get_strval(msg, param, res, &uri->host); |
1395 | 7 | } |
1396 | | |
1397 | 0 | LM_ERR("unknown specifier\n"); |
1398 | 0 | return pv_get_null(msg, param, res); |
1399 | 14 | } |
1400 | | |
1401 | | static int pv_get_pai(struct sip_msg *msg, pv_param_t *param, |
1402 | | pv_value_t *res) |
1403 | 10.7k | { |
1404 | 10.7k | if(msg==NULL) |
1405 | 0 | return -1; |
1406 | | |
1407 | 10.7k | if(parse_pai_header(msg)==-1) |
1408 | 10.7k | { |
1409 | 10.7k | LM_DBG("no P-Asserted-Identity header\n"); |
1410 | 10.7k | return pv_get_null(msg, param, res); |
1411 | 10.7k | } |
1412 | | |
1413 | 16 | if(msg->pai==NULL || get_pai(msg)==NULL) { |
1414 | 0 | LM_DBG("no P-Asserted-Identity header\n"); |
1415 | 0 | return pv_get_null(msg, param, res); |
1416 | 0 | } |
1417 | | |
1418 | 16 | return pv_get_strval(msg, param, res, &(get_pai(msg)->uri)); |
1419 | 16 | } |
1420 | | |
1421 | | static int pv_get_dset(struct sip_msg *msg, pv_param_t *param, |
1422 | | pv_value_t *res) |
1423 | 10.7k | { |
1424 | 10.7k | str s; |
1425 | | |
1426 | 10.7k | if(msg==NULL) |
1427 | 0 | return -1; |
1428 | | |
1429 | 10.7k | s.s = print_dset(msg, &s.len); |
1430 | 10.7k | if (s.s == NULL) |
1431 | 10.7k | return pv_get_null(msg, param, res); |
1432 | 0 | s.len -= CRLF_LEN; |
1433 | |
|
1434 | 0 | return pv_get_strval(msg, param, res, &s); |
1435 | 10.7k | } |
1436 | | |
1437 | | |
1438 | | static int pv_get_dsturi(struct sip_msg *msg, pv_param_t *param, |
1439 | | pv_value_t *res) |
1440 | 21.5k | { |
1441 | 21.5k | if(msg==NULL) |
1442 | 0 | return -1; |
1443 | | |
1444 | 21.5k | if (msg->dst_uri.s == NULL) { |
1445 | 21.5k | LM_DBG("no destination URI\n"); |
1446 | 21.5k | return pv_get_null(msg, param, res); |
1447 | 21.5k | } |
1448 | | |
1449 | 0 | return pv_get_strval(msg, param, res, &msg->dst_uri); |
1450 | 21.5k | } |
1451 | | |
1452 | | static int pv_get_dsturi_attr(struct sip_msg *msg, pv_param_t *param, |
1453 | | pv_value_t *res) |
1454 | 32.3k | { |
1455 | 32.3k | struct sip_uri uri; |
1456 | 32.3k | unsigned short proto; |
1457 | 32.3k | str proto_s; |
1458 | | |
1459 | 32.3k | if(msg==NULL) |
1460 | 0 | return -1; |
1461 | | |
1462 | 32.3k | if (msg->dst_uri.s == NULL) { |
1463 | 32.3k | LM_DBG("no destination URI\n"); |
1464 | 32.3k | return pv_get_null(msg, param, res); |
1465 | 32.3k | } |
1466 | | |
1467 | 0 | if(parse_uri(msg->dst_uri.s, msg->dst_uri.len, &uri)!=0) |
1468 | 0 | { |
1469 | 0 | LM_ERR("failed to parse dst uri\n"); |
1470 | 0 | return pv_get_null(msg, param, res); |
1471 | 0 | } |
1472 | | |
1473 | 0 | if(param->pvn.u.isname.name.n==1) /* domain */ |
1474 | 0 | { |
1475 | 0 | if(uri.host.s==NULL || uri.host.len<=0) |
1476 | 0 | return pv_get_null(msg, param, res); |
1477 | 0 | return pv_get_strval(msg, param, res, &uri.host); |
1478 | 0 | } else if(param->pvn.u.isname.name.n==2) /* port */ { |
1479 | 0 | if(uri.port.s==NULL) |
1480 | 0 | return pv_get_uintval(msg, param, res, get_uri_port(&uri, &proto)); |
1481 | 0 | return pv_get_strintval(msg, param, res, &uri.port, (int)uri.port_no); |
1482 | 0 | } else if(param->pvn.u.isname.name.n==3) /* proto */ { |
1483 | 0 | if(uri.transport_val.s==NULL) { |
1484 | 0 | get_uri_port(&uri, &proto); |
1485 | 0 | proto_s.s = protos[proto].name; |
1486 | 0 | proto_s.len = proto_s.s ? strlen(proto_s.s) : 0; |
1487 | 0 | return pv_get_strintval(msg, param, res, &proto_s, (int)proto); |
1488 | 0 | } |
1489 | 0 | return pv_get_strintval(msg, param, res, &uri.transport_val, |
1490 | 0 | (int)uri.proto); |
1491 | 0 | } |
1492 | | |
1493 | 0 | LM_ERR("invalid specifier\n"); |
1494 | 0 | return pv_get_null(msg, param, res); |
1495 | 0 | } |
1496 | | |
1497 | | static int pv_get_content_type(struct sip_msg *msg, pv_param_t *param, |
1498 | | pv_value_t *res) |
1499 | 10.7k | { |
1500 | 10.7k | #define BUFLEN 1024 |
1501 | | |
1502 | 10.7k | str s; |
1503 | 10.7k | int idx=-1; |
1504 | 10.7k | int idxf=-1; |
1505 | 10.7k | int distance=0; |
1506 | 10.7k | char buf[BUFLEN]; |
1507 | 10.7k | struct sip_msg_body* sbody; |
1508 | 10.7k | struct body_part* body_part; |
1509 | 10.7k | struct body_part* neg_index[2]; |
1510 | | |
1511 | 10.7k | if(msg==NULL) |
1512 | 0 | return -1; |
1513 | | |
1514 | 10.7k | if (pv_get_spec_index(msg, param, &idx, &idxf)!=0) { |
1515 | 0 | LM_ERR("invalid index\n"); |
1516 | 0 | return -1; |
1517 | 0 | } |
1518 | | |
1519 | | /* no index or all contenttypes */ |
1520 | 10.7k | if (param->pvi.type==0 || idxf == PV_IDX_ALL) { |
1521 | 10.7k | if(msg->content_type==NULL |
1522 | 10.7k | && ((parse_headers(msg, HDR_CONTENTTYPE_F, 0)==-1) |
1523 | 10.7k | || (msg->content_type==NULL))) |
1524 | 10.7k | { |
1525 | 10.7k | LM_DBG("no Content-Type header\n"); |
1526 | 10.7k | return pv_get_null(msg, param, res); |
1527 | 10.7k | } |
1528 | | |
1529 | | /* only the main contenttype requested*/ |
1530 | 17 | if (param->pvi.type==0) |
1531 | 17 | return pv_get_strval(msg, param, res, &msg->content_type->body); |
1532 | 17 | } |
1533 | | |
1534 | 0 | if ( parse_sip_body(msg)<0 || (sbody=msg->body)==NULL ) { |
1535 | 0 | LM_DBG("no body found\n"); |
1536 | 0 | return pv_get_null(msg, param, res); |
1537 | 0 | } |
1538 | | |
1539 | | /* one contenttype request */ |
1540 | 0 | if (idxf != PV_IDX_ALL) { |
1541 | 0 | if (idx< 0) { |
1542 | 0 | neg_index[0] = neg_index[1] = &sbody->first; |
1543 | | /*distance=last_body_postition-searched_body_position*/ |
1544 | 0 | distance -= idx+1; |
1545 | 0 | while (neg_index[1]->next) { |
1546 | 0 | if (distance == 0) { |
1547 | 0 | neg_index[0] = neg_index[0]->next; |
1548 | 0 | } else { |
1549 | 0 | distance--; |
1550 | 0 | } |
1551 | 0 | neg_index[1] = neg_index[1]->next; |
1552 | 0 | } |
1553 | |
|
1554 | 0 | if (distance>0) { |
1555 | 0 | LM_ERR("Index too low [%d]\n", idx); |
1556 | 0 | return pv_get_null(msg, param, res); |
1557 | 0 | } |
1558 | | |
1559 | 0 | s.s = convert_mime2string_CT(neg_index[0]->mime); |
1560 | 0 | s.len = strlen(s.s); |
1561 | 0 | } else { |
1562 | 0 | body_part = &sbody->first; |
1563 | 0 | distance = idx; |
1564 | 0 | while (distance && body_part->next) { |
1565 | 0 | distance--; |
1566 | 0 | body_part=body_part->next; |
1567 | 0 | } |
1568 | |
|
1569 | 0 | if (distance > 0) { |
1570 | 0 | LM_ERR("Index too big [%d]\n", idx); |
1571 | 0 | return pv_get_null(msg, param, res); |
1572 | 0 | } |
1573 | | |
1574 | 0 | s.s = convert_mime2string_CT(body_part->mime); |
1575 | 0 | s.len = strlen(s.s); |
1576 | 0 | } |
1577 | 0 | } else { |
1578 | | /* copy main content type */ |
1579 | 0 | memcpy(buf, msg->content_type->body.s, msg->content_type->body.len); |
1580 | 0 | buf[msg->content_type->body.len] = ','; |
1581 | 0 | s.len = msg->content_type->body.len+1; |
1582 | | |
1583 | | /* copy all the other contenttypes */ |
1584 | 0 | body_part = &sbody->first; |
1585 | 0 | while (body_part) { |
1586 | 0 | s.s = convert_mime2string_CT(body_part->mime); |
1587 | 0 | if (s.len + strlen(s.s) >= BUFLEN) { |
1588 | 0 | LM_CRIT("buffer overflow! Too many contenttypes!\n"); |
1589 | 0 | return pv_get_null(msg, param, res); |
1590 | 0 | } |
1591 | | |
1592 | 0 | memcpy( buf+s.len, s.s, strlen(s.s)); |
1593 | 0 | s.len += strlen(s.s); |
1594 | | |
1595 | | /* delimiter only if something follows */ |
1596 | 0 | if(body_part->next) |
1597 | 0 | buf[s.len++] = ','; |
1598 | |
|
1599 | 0 | body_part = body_part->next; |
1600 | 0 | } |
1601 | 0 | s.s = buf; |
1602 | 0 | } |
1603 | | |
1604 | 0 | return pv_get_strval(msg, param, res, &s); |
1605 | |
|
1606 | 0 | #undef BUFLEN |
1607 | 0 | } |
1608 | | |
1609 | | static int pv_get_content_length(struct sip_msg *msg, pv_param_t *param, |
1610 | | pv_value_t *res) |
1611 | 10.7k | { |
1612 | 10.7k | if(msg==NULL) |
1613 | 0 | return -1; |
1614 | 10.7k | if(msg->content_length==NULL |
1615 | 10.7k | && ((parse_headers(msg, HDR_CONTENTLENGTH_F, 0)==-1) |
1616 | 10.7k | || (msg->content_length==NULL))) |
1617 | 10.7k | { |
1618 | 10.7k | LM_DBG("no Content-Length header\n"); |
1619 | 10.7k | return pv_get_null(msg, param, res); |
1620 | 10.7k | } |
1621 | | |
1622 | 65 | return pv_get_intstrval(msg, param, res, |
1623 | 65 | (int)(long)msg->content_length->parsed, |
1624 | 65 | &msg->content_length->body); |
1625 | 10.7k | } |
1626 | | |
1627 | | static int pv_parse_rb_name(pv_spec_p sp, const str *in) |
1628 | 0 | { |
1629 | 0 | if(in==NULL || in->s==NULL || sp==NULL) |
1630 | 0 | return -1; |
1631 | | |
1632 | 0 | if (decode_mime_type( in->s, in->s+in->len , |
1633 | 0 | (unsigned int *)&sp->pvp.pvn.u.isname.name.n , NULL) == 0) { |
1634 | 0 | LM_ERR("unsupported mime <%.*s>\n",in->len,in->s); |
1635 | 0 | return -1; |
1636 | 0 | } |
1637 | | |
1638 | 0 | sp->pvp.pvn.type = PV_NAME_INTSTR; /* INT/STR for var name type */ |
1639 | 0 | sp->pvp.pvn.u.isname.type = 0; /* name is INT */ |
1640 | |
|
1641 | 0 | return 0; |
1642 | 0 | } |
1643 | | |
1644 | | static int pv_get_msg_body(struct sip_msg *msg, pv_param_t *param, |
1645 | | pv_value_t *res) |
1646 | 21.5k | { |
1647 | 21.5k | str s; |
1648 | 21.5k | int idx=-1; |
1649 | 21.5k | int idxf=-1; |
1650 | 21.5k | int distance=0; |
1651 | 21.5k | struct sip_msg_body* sbody; |
1652 | 21.5k | struct body_part* body_part; |
1653 | 21.5k | struct body_part* neg_index[2]; |
1654 | 21.5k | unsigned int mime; |
1655 | | |
1656 | 21.5k | if(msg==NULL) |
1657 | 0 | return -1; |
1658 | | |
1659 | 21.5k | if (pv_get_spec_index(msg, param, &idx, &idxf)!=0) { |
1660 | 0 | LM_ERR("invalid index\n"); |
1661 | 0 | return -1; |
1662 | 0 | } |
1663 | | |
1664 | | /* any index specified */ |
1665 | 21.5k | if (param->pvi.type==0 || idxf==PV_IDX_ALL) { |
1666 | 21.5k | if (param->pvn.u.isname.name.n==0) { |
1667 | | /* no name/mime -> requests all bodies */ |
1668 | 21.5k | if (get_body( msg, &s)!=0 || s.len==0 ) { |
1669 | 21.4k | LM_DBG("no message body\n"); |
1670 | 21.4k | return pv_get_null(msg, param, res); |
1671 | 21.4k | } |
1672 | 92 | goto end; |
1673 | 21.5k | } else { |
1674 | | /* return first part with the requested mime */ |
1675 | 0 | idx = 0; |
1676 | 0 | } |
1677 | 21.5k | } |
1678 | | |
1679 | 0 | if ( parse_sip_body(msg)<0 || (sbody=msg->body)==NULL ) { |
1680 | 0 | LM_DBG("no body found\n"); |
1681 | 0 | return pv_get_null(msg, param, res); |
1682 | 0 | } |
1683 | | |
1684 | 0 | mime = param->pvn.u.isname.name.n; |
1685 | 0 | LM_DBG("--------mime is <%d>, idx=%d\n",mime, idx); |
1686 | |
|
1687 | 0 | #define first_part_by_mime( _part_start, _part_end, _mime) \ |
1688 | 0 | do {\ |
1689 | 0 | _part_end = _part_start;\ |
1690 | 0 | while( (_part_end) && \ |
1691 | 0 | !(is_body_part_received(_part_end) && ((_mime)==0 || \ |
1692 | 0 | (_mime)==(_part_end)->mime )) ) { \ |
1693 | 0 | _part_end = (_part_end)->next; \ |
1694 | 0 | } \ |
1695 | 0 | }while(0) |
1696 | |
|
1697 | 0 | if (idx<0) { |
1698 | 0 | first_part_by_mime( &sbody->first, neg_index[1], mime ); |
1699 | 0 | neg_index[0] = neg_index[1]; |
1700 | |
|
1701 | 0 | if (neg_index[0]==NULL) { |
1702 | 0 | LM_DBG("Body part not found for <%d>\n", mime); |
1703 | 0 | return pv_get_null(msg, param, res); |
1704 | 0 | } |
1705 | | |
1706 | | /*distance=last_body_postition-searched_body_position*/ |
1707 | 0 | distance -= idx+1; |
1708 | 0 | first_part_by_mime(neg_index[1]->next, neg_index[1], mime); |
1709 | 0 | while (neg_index[1]) { |
1710 | 0 | if (distance == 0) { |
1711 | 0 | first_part_by_mime( neg_index[0]->next, neg_index[0], mime ); |
1712 | 0 | } else { |
1713 | 0 | distance--; |
1714 | 0 | } |
1715 | 0 | first_part_by_mime( neg_index[1]->next, neg_index[1], mime ); |
1716 | 0 | } |
1717 | |
|
1718 | 0 | if (distance>0) { |
1719 | 0 | LM_DBG("Index too low [%d]\n", idx); |
1720 | 0 | return pv_get_null(msg, param, res); |
1721 | 0 | } |
1722 | | |
1723 | 0 | s.s = neg_index[0]->body.s; |
1724 | 0 | s.len = neg_index[0]->body.len; |
1725 | 0 | } else { |
1726 | 0 | first_part_by_mime( &sbody->first, body_part, mime ); |
1727 | 0 | distance = idx; |
1728 | 0 | while (distance && body_part ) { |
1729 | 0 | distance--; |
1730 | 0 | first_part_by_mime( body_part->next, body_part, mime ); |
1731 | 0 | } |
1732 | |
|
1733 | 0 | if (distance>0 || body_part==NULL) { |
1734 | 0 | LM_DBG("Index too big [%d], body_part=%p\n", idx,body_part); |
1735 | 0 | return pv_get_null(msg, param, res); |
1736 | 0 | } |
1737 | | |
1738 | 0 | s.s = body_part->body.s; |
1739 | 0 | s.len = body_part->body.len; |
1740 | 0 | } |
1741 | | |
1742 | 92 | end: |
1743 | 92 | return pv_get_strval(msg, param, res, &s); |
1744 | 0 | } |
1745 | | |
1746 | | static int pv_get_authattr(struct sip_msg *msg, pv_param_t *param, |
1747 | | pv_value_t *res) |
1748 | 140k | { |
1749 | 140k | struct hdr_field *hdr; |
1750 | 140k | str *s; |
1751 | | |
1752 | 140k | if(msg==NULL) |
1753 | 0 | return -1; |
1754 | | |
1755 | 140k | if ((msg->REQ_METHOD==METHOD_ACK) || (msg->REQ_METHOD==METHOD_CANCEL)) { |
1756 | 91 | LM_DBG("no [Proxy-]Authorization header\n"); |
1757 | 91 | return pv_get_null(msg, param, res); |
1758 | 91 | } |
1759 | | |
1760 | 140k | if ((parse_headers(msg, HDR_PROXYAUTH_F|HDR_AUTHORIZATION_F, 0)==-1) |
1761 | 140k | || (msg->proxy_auth==0 && msg->authorization==0)) |
1762 | 125k | { |
1763 | 125k | LM_DBG("no [Proxy-]Authorization header\n"); |
1764 | 125k | return pv_get_null(msg, param, res); |
1765 | 125k | } |
1766 | | |
1767 | 14.9k | hdr = (msg->proxy_auth==0)?msg->authorization:msg->proxy_auth; |
1768 | 14.9k | if(parse_credentials(hdr)!=0) { |
1769 | 8.00k | LM_ERR("failed to parse credentials\n"); |
1770 | 8.00k | return pv_get_null(msg, param, res); |
1771 | 8.00k | } |
1772 | | |
1773 | 6.98k | switch(param->pvn.u.isname.name.n) |
1774 | 6.98k | { |
1775 | 537 | case 11: |
1776 | 537 | s = &((auth_body_t*)(hdr->parsed))->digest.nc; |
1777 | 537 | break; |
1778 | 537 | case 10: |
1779 | 537 | s = &((auth_body_t*)(hdr->parsed))->digest.qop.qop_str; |
1780 | 537 | break; |
1781 | 537 | case 9: |
1782 | 537 | s = &((auth_body_t*)(hdr->parsed))->digest.alg.alg_str; |
1783 | 537 | break; |
1784 | 537 | case 8: |
1785 | 537 | s = &((auth_body_t*)(hdr->parsed))->digest.opaque; |
1786 | 537 | break; |
1787 | 537 | case 7: |
1788 | 537 | s = &((auth_body_t*)(hdr->parsed))->digest.cnonce; |
1789 | 537 | break; |
1790 | 537 | case 6: |
1791 | 537 | s = &((auth_body_t*)(hdr->parsed))->digest.response; |
1792 | 537 | break; |
1793 | 1.07k | case 5: |
1794 | 1.07k | s = &((auth_body_t*)(hdr->parsed))->digest.nonce; |
1795 | 1.07k | break; |
1796 | 537 | case 4: |
1797 | 537 | s = &((auth_body_t*)(hdr->parsed))->digest.username.domain; |
1798 | 537 | break; |
1799 | 537 | case 3: |
1800 | 537 | s = &((auth_body_t*)(hdr->parsed))->digest.uri; |
1801 | 537 | break; |
1802 | 537 | case 2: |
1803 | 537 | s = &((auth_body_t*)(hdr->parsed))->digest.realm; |
1804 | 537 | break; |
1805 | 537 | case 1: |
1806 | 537 | s = &((auth_body_t*)(hdr->parsed))->digest.username.user; |
1807 | 537 | break; |
1808 | 537 | default: |
1809 | 537 | s = &((auth_body_t*)(hdr->parsed))->digest.username.whole; |
1810 | 6.98k | } |
1811 | | |
1812 | 6.98k | if (s->len==0) |
1813 | 6.30k | return pv_get_null(msg, param, res); |
1814 | 681 | return pv_get_strval(msg, param, res, s); |
1815 | 6.98k | } |
1816 | | |
1817 | | |
1818 | | static inline str *cred_user(struct sip_msg *rq) |
1819 | 10.7k | { |
1820 | 10.7k | struct hdr_field* h; |
1821 | 10.7k | auth_body_t* cred; |
1822 | | |
1823 | 10.7k | get_authorized_cred(rq->proxy_auth, &h); |
1824 | 10.7k | if (!h) get_authorized_cred(rq->authorization, &h); |
1825 | 10.7k | if (!h) return 0; |
1826 | 0 | cred=(auth_body_t*)(h->parsed); |
1827 | 0 | if (!cred || !cred->digest.username.user.len) |
1828 | 0 | return 0; |
1829 | 0 | return &cred->digest.username.user; |
1830 | 0 | } |
1831 | | |
1832 | | |
1833 | | static inline str *cred_realm(struct sip_msg *rq) |
1834 | 0 | { |
1835 | 0 | str* realm; |
1836 | 0 | struct hdr_field* h; |
1837 | 0 | auth_body_t* cred; |
1838 | |
|
1839 | 0 | get_authorized_cred(rq->proxy_auth, &h); |
1840 | 0 | if (!h) get_authorized_cred(rq->authorization, &h); |
1841 | 0 | if (!h) return 0; |
1842 | 0 | cred=(auth_body_t*)(h->parsed); |
1843 | 0 | if (!cred) return 0; |
1844 | 0 | realm = GET_REALM(&cred->digest); |
1845 | 0 | if (!realm->len || !realm->s) { |
1846 | 0 | return 0; |
1847 | 0 | } |
1848 | 0 | return realm; |
1849 | 0 | } |
1850 | | |
1851 | | static int pv_get_acc_username(struct sip_msg *msg, pv_param_t *param, |
1852 | | pv_value_t *res) |
1853 | 10.7k | { |
1854 | 10.7k | static char buf[MAX_URI_SIZE]; |
1855 | 10.7k | str* user; |
1856 | 10.7k | str* realm; |
1857 | 10.7k | struct sip_uri puri; |
1858 | 10.7k | struct to_body* from; |
1859 | 10.7k | str s; |
1860 | | |
1861 | | /* try to take it from credentials */ |
1862 | 10.7k | user = cred_user(msg); |
1863 | 10.7k | if (user) { |
1864 | 0 | realm = cred_realm(msg); |
1865 | 0 | if (realm) { |
1866 | 0 | s.len = user->len+1+realm->len; |
1867 | 0 | if (s.len > MAX_URI_SIZE) { |
1868 | 0 | LM_ERR("uri too long\n"); |
1869 | 0 | return pv_get_null(msg, param, res); |
1870 | 0 | } |
1871 | 0 | s.s = buf; |
1872 | 0 | memcpy(s.s, user->s, user->len); |
1873 | 0 | (s.s)[user->len] = '@'; |
1874 | 0 | memcpy(s.s+user->len+1, realm->s, realm->len); |
1875 | 0 | return pv_get_strval(msg, param, res, &s); |
1876 | 0 | } |
1877 | 0 | return pv_get_strval(msg, param, res, user); |
1878 | 0 | } |
1879 | | |
1880 | | /* from from uri */ |
1881 | 10.7k | if(parse_from_header(msg)<0) |
1882 | 10.6k | { |
1883 | 10.6k | LM_ERR("cannot parse FROM header\n"); |
1884 | 10.6k | return pv_get_null(msg, param, res); |
1885 | 10.6k | } |
1886 | 153 | if (msg->from && (from=get_from(msg)) && from->uri.len) { |
1887 | 153 | if (parse_uri(from->uri.s, from->uri.len, &puri) < 0 ) { |
1888 | 46 | LM_ERR("bad From URI\n"); |
1889 | 46 | return pv_get_null(msg, param, res); |
1890 | 46 | } |
1891 | 107 | s.len = puri.user.len + 1 + puri.host.len; |
1892 | 107 | if (s.len > MAX_URI_SIZE) { |
1893 | 1 | LM_ERR("from URI too long\n"); |
1894 | 1 | return pv_get_null(msg, param, res); |
1895 | 1 | } |
1896 | 106 | s.s = buf; |
1897 | 106 | memcpy(s.s, puri.user.s, puri.user.len); |
1898 | 106 | (s.s)[puri.user.len] = '@'; |
1899 | 106 | memcpy(s.s + puri.user.len + 1, puri.host.s, puri.host.len); |
1900 | 106 | } else { |
1901 | 0 | s.len = 0; |
1902 | 0 | s.s = 0; |
1903 | 0 | } |
1904 | 106 | return pv_get_strval(msg, param, res, &s); |
1905 | 153 | } |
1906 | | |
1907 | | |
1908 | 0 | #define BR_URI_S "uri" |
1909 | 0 | #define BR_URI_LEN (sizeof(BR_URI_S)-1) |
1910 | 0 | #define BR_URI_ID 1 |
1911 | 0 | #define BR_DURI_S "duri" |
1912 | 0 | #define BR_DURI_LEN (sizeof(BR_DURI_S)-1) |
1913 | 0 | #define BR_DURI_ID 2 |
1914 | 0 | #define BR_Q_S "q" |
1915 | 0 | #define BR_Q_LEN (sizeof(BR_Q_S)-1) |
1916 | 0 | #define BR_Q_ID 3 |
1917 | 0 | #define BR_PATH_S "path" |
1918 | 0 | #define BR_PATH_LEN (sizeof(BR_PATH_S)-1) |
1919 | 0 | #define BR_PATH_ID 4 |
1920 | 0 | #define BR_FLAGS_S "flags" |
1921 | 0 | #define BR_FLAGS_LEN (sizeof(BR_FLAGS_S)-1) |
1922 | 0 | #define BR_FLAGS_ID 5 |
1923 | 0 | #define BR_SOCKET_S "socket" |
1924 | 0 | #define BR_SOCKET_LEN (sizeof(BR_SOCKET_S)-1) |
1925 | 0 | #define BR_SOCKET_ID 6 |
1926 | | |
1927 | | static int pv_parse_branch_name(pv_spec_p sp, const str *in) |
1928 | 0 | { |
1929 | 0 | if (sp==NULL || in==NULL || in->s==NULL || in->len==0) |
1930 | 0 | return -1; |
1931 | | |
1932 | 0 | sp->pvp.pvn.type = PV_NAME_INTSTR; |
1933 | 0 | sp->pvp.pvn.u.isname.type = 0; |
1934 | |
|
1935 | 0 | if (in->len==BR_URI_LEN && |
1936 | 0 | strncasecmp(in->s, BR_URI_S, BR_URI_LEN)==0 ) { |
1937 | 0 | sp->pvp.pvn.u.isname.name.n = BR_URI_ID; |
1938 | 0 | } else |
1939 | 0 | if (in->len==BR_DURI_LEN && |
1940 | 0 | strncasecmp(in->s, BR_DURI_S, BR_DURI_LEN)==0 ) { |
1941 | 0 | sp->pvp.pvn.u.isname.name.n = BR_DURI_ID; |
1942 | 0 | } else |
1943 | 0 | if (in->len==BR_Q_LEN && |
1944 | 0 | strncasecmp(in->s, BR_Q_S, BR_Q_LEN)==0 ) { |
1945 | 0 | sp->pvp.pvn.u.isname.name.n = BR_Q_ID; |
1946 | 0 | } else |
1947 | 0 | if (in->len==BR_PATH_LEN && |
1948 | 0 | strncasecmp(in->s, BR_PATH_S, BR_PATH_LEN)==0 ) { |
1949 | 0 | sp->pvp.pvn.u.isname.name.n = BR_PATH_ID; |
1950 | 0 | } else |
1951 | 0 | if (in->len==BR_FLAGS_LEN && |
1952 | 0 | strncasecmp(in->s, BR_FLAGS_S, BR_FLAGS_LEN)==0 ) { |
1953 | 0 | sp->pvp.pvn.u.isname.name.n = BR_FLAGS_ID; |
1954 | 0 | } else |
1955 | 0 | if (in->len==BR_SOCKET_LEN && |
1956 | 0 | strncasecmp(in->s, BR_SOCKET_S, BR_SOCKET_LEN)==0 ) { |
1957 | 0 | sp->pvp.pvn.u.isname.name.n = BR_SOCKET_ID; |
1958 | 0 | } else { |
1959 | 0 | LM_ERR("unsupported BRANCH field <%.*s>\n",in->len,in->s); |
1960 | 0 | return -1; |
1961 | 0 | } |
1962 | | |
1963 | 0 | return 0; |
1964 | 0 | } |
1965 | | |
1966 | | static inline int get_branch_field( int idx, pv_name_t *pvn, pv_value_t *res) |
1967 | 0 | { |
1968 | 0 | str uri; |
1969 | 0 | qvalue_t q; |
1970 | 0 | str duri; |
1971 | 0 | str path; |
1972 | 0 | unsigned int flags; |
1973 | 0 | const struct socket_info *si; |
1974 | |
|
1975 | 0 | uri.s = get_branch(idx, &uri.len, &q, &duri, &path, &flags, &si); |
1976 | 0 | if (!uri.s) |
1977 | 0 | return pv_get_null( NULL, NULL, res); |
1978 | | |
1979 | | /* got a valid branch, return the field */ |
1980 | 0 | switch (pvn->u.isname.name.n) { |
1981 | 0 | case 0: |
1982 | 0 | case BR_URI_ID: /* return URI */ |
1983 | 0 | res->rs = uri; |
1984 | 0 | res->flags = PV_VAL_STR; |
1985 | 0 | break; |
1986 | 0 | case BR_Q_ID: /* return Q */ |
1987 | 0 | res->rs.s = q2str(q, (unsigned int*)&res->rs.len); |
1988 | 0 | res->flags = PV_VAL_STR; |
1989 | 0 | break; |
1990 | 0 | case BR_DURI_ID: /* return DURI */ |
1991 | 0 | if ( !duri.s || !duri.len) |
1992 | 0 | return pv_get_null(NULL, NULL, res); |
1993 | 0 | res->rs = duri; |
1994 | 0 | res->flags = PV_VAL_STR; |
1995 | 0 | break; |
1996 | 0 | case BR_PATH_ID: /* return PATH */ |
1997 | 0 | if ( !path.s || !path.len) |
1998 | 0 | return pv_get_null(NULL, NULL, res); |
1999 | 0 | res->rs = path; |
2000 | 0 | res->flags = PV_VAL_STR; |
2001 | 0 | break; |
2002 | 0 | case BR_FLAGS_ID: /* return FLAGS */ |
2003 | 0 | res->rs = bitmask_to_flag_list(FLAG_TYPE_BRANCH, flags); |
2004 | 0 | res->flags = PV_VAL_STR; |
2005 | 0 | break; |
2006 | 0 | case BR_SOCKET_ID: /* return SOCKET */ |
2007 | 0 | if ( !si ) |
2008 | 0 | return pv_get_null(NULL, NULL, res); |
2009 | 0 | res->rs = si->sock_str; |
2010 | 0 | res->flags = PV_VAL_STR; |
2011 | 0 | break; |
2012 | 0 | default: |
2013 | 0 | LM_CRIT("BUG - unsupported ID %d\n",pvn->u.isname.name.n); |
2014 | 0 | return pv_get_null(NULL, NULL, res); |
2015 | 0 | } |
2016 | 0 | return 0; |
2017 | 0 | } |
2018 | | |
2019 | | |
2020 | | static int pv_get_branch_fields(struct sip_msg *msg, pv_param_t *param, |
2021 | | pv_value_t *res) |
2022 | 21.5k | { |
2023 | 21.5k | int idx; |
2024 | 21.5k | int idxf; |
2025 | 21.5k | char *p; |
2026 | | |
2027 | 21.5k | if(msg==NULL || res==NULL) |
2028 | 0 | return -1; |
2029 | | |
2030 | 21.5k | if (get_nr_branches() == 0) |
2031 | 21.5k | return pv_get_null(msg, param, res); |
2032 | | |
2033 | | /* get the index */ |
2034 | 0 | if(pv_get_spec_index(msg, param, &idx, &idxf)!=0) { |
2035 | 0 | LM_ERR("invalid index\n"); |
2036 | 0 | return -1; |
2037 | 0 | } |
2038 | | |
2039 | 0 | if (idxf!=PV_IDX_ALL && idx==0) { |
2040 | | /* no index specified -> return the first branch */ |
2041 | 0 | return get_branch_field( 0, ¶m->pvn, res); |
2042 | 0 | } |
2043 | | |
2044 | 0 | if(idxf==PV_IDX_ALL) { |
2045 | | /* return all branches */ |
2046 | 0 | p = pv_local_buf; |
2047 | 0 | idx = 0; |
2048 | |
|
2049 | 0 | while ( idx<get_nr_branches() ) { |
2050 | |
|
2051 | 0 | get_branch_field( idx, ¶m->pvn, res); |
2052 | |
|
2053 | 0 | if ( pv_local_buf + PV_LOCAL_BUF_SIZE <= |
2054 | 0 | p + res->rs.len + PV_FIELD_DELIM_LEN ) { |
2055 | 0 | LM_ERR("local buffer length exceeded\n"); |
2056 | 0 | return pv_get_null(msg, param, res); |
2057 | 0 | } |
2058 | | |
2059 | 0 | if (idx) { |
2060 | 0 | memcpy(p, PV_FIELD_DELIM, PV_FIELD_DELIM_LEN); |
2061 | 0 | p += PV_FIELD_DELIM_LEN; |
2062 | 0 | } |
2063 | |
|
2064 | 0 | memcpy(p, res->rs.s, res->rs.len); |
2065 | 0 | p += res->rs.len; |
2066 | 0 | idx++; |
2067 | 0 | } |
2068 | | |
2069 | 0 | res->rs.s = pv_local_buf; |
2070 | 0 | res->rs.len = p - pv_local_buf; |
2071 | 0 | res->flags = PV_VAL_STR; |
2072 | 0 | return 0; |
2073 | 0 | } |
2074 | | |
2075 | | /* numerical index */ |
2076 | 0 | if (idx<0) { |
2077 | | /* index from the end */ |
2078 | 0 | if (-idx > get_nr_branches()) |
2079 | 0 | return pv_get_null(msg, param, res); |
2080 | 0 | idx = get_nr_branches() + idx; |
2081 | 0 | } |
2082 | | |
2083 | | /* return the request branch info */ |
2084 | 0 | return get_branch_field( idx, ¶m->pvn, res); |
2085 | 0 | } |
2086 | | |
2087 | | |
2088 | | /******** LISTENING SOCKETS related vars & functions **********/ |
2089 | | |
2090 | 0 | #define SOCK_IP_S "ip" |
2091 | 0 | #define SOCK_IP_LEN (sizeof(SOCK_IP_S)-1) |
2092 | 0 | #define SOCK_IP_ID 1 |
2093 | 0 | #define SOCK_PORT_S "port" |
2094 | 0 | #define SOCK_PORT_LEN (sizeof(SOCK_PORT_S)-1) |
2095 | 0 | #define SOCK_PORT_ID 2 |
2096 | 0 | #define SOCK_PROTO_S "proto" |
2097 | 0 | #define SOCK_PROTO_LEN (sizeof(SOCK_PROTO_S)-1) |
2098 | 0 | #define SOCK_PROTO_ID 3 |
2099 | 0 | #define SOCK_ADV_IP_S "advertised_ip" |
2100 | 0 | #define SOCK_ADV_IP_LEN (sizeof(SOCK_ADV_IP_S)-1) |
2101 | 0 | #define SOCK_ADV_IP_ID 4 |
2102 | 0 | #define SOCK_ADV_PORT_S "advertised_port" |
2103 | 0 | #define SOCK_ADV_PORT_LEN (sizeof(SOCK_ADV_PORT_S)-1) |
2104 | 0 | #define SOCK_ADV_PORT_ID 5 |
2105 | 0 | #define SOCK_TAG_S "tag" |
2106 | 0 | #define SOCK_TAG_LEN (sizeof(SOCK_TAG_S)-1) |
2107 | 0 | #define SOCK_TAG_ID 6 |
2108 | 0 | #define SOCK_ANYCAST_S "anycast" |
2109 | 0 | #define SOCK_ANYCAST_LEN (sizeof(SOCK_ANYCAST_S)-1) |
2110 | 0 | #define SOCK_ANYCAST_ID 7 |
2111 | 0 | #define SOCK_AF_S "af" |
2112 | 0 | #define SOCK_AF_LEN (sizeof(SOCK_AF_S)-1) |
2113 | 0 | #define SOCK_AF_ID 8 |
2114 | | |
2115 | | static int pv_parse_socket_name(pv_spec_p sp, const str *in) |
2116 | 0 | { |
2117 | 0 | if (sp==NULL || in==NULL || in->s==NULL || in->len==0) |
2118 | 0 | return -1; |
2119 | | |
2120 | 0 | sp->pvp.pvn.type = PV_NAME_INTSTR; |
2121 | 0 | sp->pvp.pvn.u.isname.type = 0; |
2122 | |
|
2123 | 0 | if (in->len==SOCK_IP_LEN && |
2124 | 0 | strncasecmp(in->s, SOCK_IP_S, SOCK_IP_LEN)==0 ) { |
2125 | 0 | sp->pvp.pvn.u.isname.name.n = SOCK_IP_ID; |
2126 | 0 | } else |
2127 | 0 | if (in->len==SOCK_PORT_LEN && |
2128 | 0 | strncasecmp(in->s, SOCK_PORT_S, SOCK_PORT_LEN)==0 ) { |
2129 | 0 | sp->pvp.pvn.u.isname.name.n = SOCK_PORT_ID; |
2130 | 0 | } else |
2131 | 0 | if (in->len==SOCK_PROTO_LEN && |
2132 | 0 | strncasecmp(in->s, SOCK_PROTO_S, SOCK_PROTO_LEN)==0 ) { |
2133 | 0 | sp->pvp.pvn.u.isname.name.n = SOCK_PROTO_ID; |
2134 | 0 | } else |
2135 | 0 | if (in->len==SOCK_ADV_IP_LEN && |
2136 | 0 | strncasecmp(in->s, SOCK_ADV_IP_S, SOCK_ADV_IP_LEN)==0 ) { |
2137 | 0 | sp->pvp.pvn.u.isname.name.n = SOCK_ADV_IP_ID; |
2138 | 0 | } else |
2139 | 0 | if (in->len==SOCK_ADV_PORT_LEN && |
2140 | 0 | strncasecmp(in->s, SOCK_ADV_PORT_S, SOCK_ADV_PORT_LEN)==0 ) { |
2141 | 0 | sp->pvp.pvn.u.isname.name.n = SOCK_ADV_PORT_ID; |
2142 | 0 | } else |
2143 | 0 | if (in->len==SOCK_TAG_LEN && |
2144 | 0 | strncasecmp(in->s, SOCK_TAG_S, SOCK_TAG_LEN)==0 ) { |
2145 | 0 | sp->pvp.pvn.u.isname.name.n = SOCK_TAG_ID; |
2146 | 0 | } else |
2147 | 0 | if (in->len==SOCK_ANYCAST_LEN && |
2148 | 0 | strncasecmp(in->s, SOCK_ANYCAST_S, SOCK_ANYCAST_LEN)==0 ) { |
2149 | 0 | sp->pvp.pvn.u.isname.name.n = SOCK_ANYCAST_ID; |
2150 | 0 | } else |
2151 | 0 | if (in->len==SOCK_AF_LEN && |
2152 | 0 | strncasecmp(in->s, SOCK_AF_S, SOCK_AF_LEN)==0 ) { |
2153 | 0 | sp->pvp.pvn.u.isname.name.n = SOCK_AF_ID; |
2154 | 0 | } else { |
2155 | 0 | LM_ERR("unsupported SOCKET_IN/OUT field <%.*s>\n",in->len,in->s); |
2156 | 0 | return -1; |
2157 | 0 | } |
2158 | | |
2159 | 0 | return 0; |
2160 | 0 | } |
2161 | | |
2162 | | |
2163 | | static inline int get_socket_field( const struct socket_info *si, |
2164 | | pv_name_t *pvn, pv_value_t *res) |
2165 | 43.1k | { |
2166 | 43.1k | if (si==NULL) |
2167 | 43.1k | return pv_get_null( NULL, NULL, res); |
2168 | | |
2169 | | /* return the field */ |
2170 | 0 | switch (pvn->u.isname.name.n) { |
2171 | 0 | case 0: /* return full socket description */ |
2172 | 0 | res->rs = si->sock_str; |
2173 | 0 | res->flags = PV_VAL_STR; |
2174 | 0 | break; |
2175 | 0 | case SOCK_IP_ID: /* return IP address */ |
2176 | 0 | res->rs = si->address_str; |
2177 | 0 | res->flags = PV_VAL_STR; |
2178 | 0 | break; |
2179 | 0 | case SOCK_PORT_ID: /* return PORT */ |
2180 | 0 | res->rs = si->port_no_str; |
2181 | 0 | res->ri = si->port_no; |
2182 | 0 | res->flags = PV_VAL_STR|PV_VAL_INT|PV_TYPE_INT; |
2183 | 0 | break; |
2184 | 0 | case SOCK_PROTO_ID: /* return PROTOCOL */ |
2185 | 0 | if ( si->proto>=PROTO_FIRST && si->proto<PROTO_LAST && |
2186 | 0 | protos[si->proto].id ) { |
2187 | 0 | res->rs.s = protos[si->proto].name; |
2188 | 0 | res->rs.len = strlen(res->rs.s); |
2189 | 0 | res->flags = PV_VAL_STR; |
2190 | 0 | } else { |
2191 | 0 | return pv_get_null( NULL, NULL, res); |
2192 | 0 | } |
2193 | 0 | break; |
2194 | 0 | case SOCK_ADV_IP_ID: /* return advertised IP address */ |
2195 | 0 | if (si->adv_name_str.s) { |
2196 | 0 | res->rs = si->adv_name_str; |
2197 | 0 | res->flags = PV_VAL_STR; |
2198 | 0 | } else { |
2199 | 0 | return pv_get_null( NULL, NULL, res); |
2200 | 0 | } |
2201 | 0 | break; |
2202 | 0 | case SOCK_ADV_PORT_ID: /* return advertised PORT */ |
2203 | 0 | if (si->adv_port_str.s) { |
2204 | 0 | res->rs = si->adv_port_str; |
2205 | 0 | res->ri = si->adv_port; |
2206 | 0 | res->flags = PV_VAL_STR|PV_VAL_INT|PV_TYPE_INT; |
2207 | 0 | } else { |
2208 | 0 | return pv_get_null( NULL, NULL, res); |
2209 | 0 | } |
2210 | 0 | break; |
2211 | 0 | case SOCK_TAG_ID: /* return internal TAG */ |
2212 | 0 | if (si->tag.s) { |
2213 | 0 | res->rs = si->tag; |
2214 | 0 | res->flags = PV_VAL_STR; |
2215 | 0 | } else { |
2216 | 0 | return pv_get_null( NULL, NULL, res); |
2217 | 0 | } |
2218 | 0 | break; |
2219 | 0 | case SOCK_ANYCAST_ID: /* return ANYCAST */ |
2220 | 0 | if (si->flags&SI_IS_ANYCAST) |
2221 | 0 | res->ri = 1; |
2222 | 0 | else |
2223 | 0 | res->ri = 0; |
2224 | 0 | res->flags = PV_VAL_INT|PV_TYPE_INT; |
2225 | 0 | break; |
2226 | 0 | case SOCK_AF_ID: /* returns Address Family */ |
2227 | 0 | if (si->address.af == AF_INET) { |
2228 | 0 | res->rs.s = "INET"; |
2229 | 0 | res->rs.len = 4; |
2230 | 0 | } else if (si->address.af == AF_INET6) { |
2231 | 0 | res->rs.s = "INET6"; |
2232 | 0 | res->rs.len = 5; |
2233 | 0 | } else |
2234 | 0 | return pv_get_null( NULL, NULL, res); |
2235 | 0 | res->flags = PV_VAL_STR; |
2236 | 0 | break; |
2237 | 0 | default: |
2238 | 0 | LM_CRIT("BUG - unsupported ID %d\n",pvn->u.isname.name.n); |
2239 | 0 | return pv_get_null(NULL, NULL, res); |
2240 | 0 | } |
2241 | 0 | return 0; |
2242 | 0 | } |
2243 | | |
2244 | | |
2245 | | static int pv_get_socket_in_fields(struct sip_msg *msg, pv_param_t *param, |
2246 | | pv_value_t *res) |
2247 | 21.5k | { |
2248 | | |
2249 | 21.5k | if(msg==NULL || res==NULL) |
2250 | 0 | return -1; |
2251 | | |
2252 | 21.5k | return get_socket_field( msg->rcv.bind_address, ¶m->pvn, res); |
2253 | 21.5k | } |
2254 | | |
2255 | | |
2256 | | static int pv_get_socket_out_fields(struct sip_msg *msg, pv_param_t *param, |
2257 | | pv_value_t *res) |
2258 | 21.5k | { |
2259 | 21.5k | const struct socket_info *si; |
2260 | | |
2261 | 21.5k | if(msg==NULL || res==NULL) |
2262 | 0 | return -1; |
2263 | | |
2264 | 21.5k | si = (msg->force_send_socket) ? |
2265 | 21.5k | msg->force_send_socket : msg->rcv.bind_address; |
2266 | | |
2267 | 21.5k | return get_socket_field( si, ¶m->pvn, res); |
2268 | 21.5k | } |
2269 | | |
2270 | | |
2271 | | |
2272 | | |
2273 | | /************************************************************/ |
2274 | | |
2275 | | /** |
2276 | | * |
2277 | | */ |
2278 | | static int pv_get_avp(struct sip_msg *msg, pv_param_t *param, pv_value_t *res) |
2279 | 0 | { |
2280 | 0 | unsigned short name_type; |
2281 | 0 | int avp_name; |
2282 | 0 | int_str avp_value; |
2283 | 0 | struct usr_avp *avp; |
2284 | 0 | int_str avp_value0; |
2285 | 0 | struct usr_avp *avp0; |
2286 | 0 | int idx; |
2287 | 0 | int idxf; |
2288 | 0 | char *p; |
2289 | 0 | int n=0; |
2290 | |
|
2291 | 0 | if(msg==NULL || res==NULL || param==NULL) |
2292 | 0 | return -1; |
2293 | | |
2294 | | /* get the name */ |
2295 | 0 | if(pv_get_avp_name(msg, param, &avp_name, &name_type)!=0) |
2296 | 0 | { |
2297 | 0 | LM_ERR("invalid name\n"); |
2298 | 0 | return -1; |
2299 | 0 | } |
2300 | | /* get the index */ |
2301 | 0 | if(pv_get_spec_index(msg, param, &idx, &idxf)!=0) |
2302 | 0 | { |
2303 | 0 | LM_ERR("invalid index\n"); |
2304 | 0 | return -1; |
2305 | 0 | } |
2306 | 0 | if (idxf==PV_IDX_APPEND) |
2307 | 0 | return pv_get_null(msg, param, res); |
2308 | | |
2309 | 0 | if ((avp=search_first_avp(name_type, avp_name, &avp_value, 0))==0) |
2310 | 0 | return pv_get_null(msg, param, res); |
2311 | 0 | res->flags = PV_VAL_STR; |
2312 | |
|
2313 | 0 | if (idxf!=PV_IDX_ALL && idx==0) |
2314 | 0 | { |
2315 | 0 | if(avp->flags & AVP_VAL_STR) { |
2316 | 0 | res->rs = avp_value.s; |
2317 | 0 | } else if(avp->flags & AVP_VAL_NULL) { |
2318 | 0 | res->flags |= PV_VAL_NULL; |
2319 | 0 | } else { |
2320 | 0 | res->rs.s = sint2str(avp_value.n, &res->rs.len); |
2321 | 0 | res->ri = avp_value.n; |
2322 | 0 | res->flags |= PV_VAL_INT|PV_TYPE_INT; |
2323 | 0 | } |
2324 | 0 | return 0; |
2325 | 0 | } |
2326 | | |
2327 | | /* print the entire AVP array */ |
2328 | 0 | if(idxf==PV_IDX_ALL) |
2329 | 0 | { |
2330 | 0 | p = pv_local_buf; |
2331 | | |
2332 | | /* separately handle the first AVP */ |
2333 | 0 | if(avp->flags & AVP_VAL_STR) { |
2334 | 0 | res->rs = avp_value.s; |
2335 | 0 | } else if(avp->flags & AVP_VAL_NULL) { |
2336 | 0 | memset(&res->rs, 0, sizeof res->rs); |
2337 | 0 | } else { |
2338 | 0 | res->rs.s = sint2str(avp_value.n, &res->rs.len); |
2339 | 0 | } |
2340 | |
|
2341 | 0 | if(p-pv_local_buf+res->rs.len+1>PV_LOCAL_BUF_SIZE) |
2342 | 0 | { |
2343 | 0 | LM_ERR("local buffer length exceeded!\n"); |
2344 | 0 | return pv_get_null(msg, param, res); |
2345 | 0 | } |
2346 | 0 | memcpy(p, res->rs.s, res->rs.len); |
2347 | 0 | p += res->rs.len; |
2348 | | |
2349 | | /* print subsequent AVPs as [DELIM AVP]* */ |
2350 | 0 | while ((avp = search_first_avp(name_type, avp_name, &avp_value, avp))) |
2351 | 0 | { |
2352 | 0 | if(avp->flags & AVP_VAL_STR) { |
2353 | 0 | res->rs = avp_value.s; |
2354 | 0 | } else if(avp->flags & AVP_VAL_NULL) { |
2355 | 0 | memset(&res->rs, 0, sizeof res->rs); |
2356 | 0 | } else { |
2357 | 0 | res->rs.s = sint2str(avp_value.n, &res->rs.len); |
2358 | 0 | } |
2359 | |
|
2360 | 0 | if(p-pv_local_buf+PV_FIELD_DELIM_LEN+1>PV_LOCAL_BUF_SIZE) |
2361 | 0 | { |
2362 | 0 | LM_ERR("local buffer length exceeded\n"); |
2363 | 0 | return pv_get_null(msg, param, res); |
2364 | 0 | } |
2365 | 0 | memcpy(p, PV_FIELD_DELIM, PV_FIELD_DELIM_LEN); |
2366 | 0 | p += PV_FIELD_DELIM_LEN; |
2367 | |
|
2368 | 0 | if(p-pv_local_buf+res->rs.len+1>PV_LOCAL_BUF_SIZE) |
2369 | 0 | { |
2370 | 0 | LM_ERR("local buffer length exceeded!\n"); |
2371 | 0 | return pv_get_null(msg, param, res); |
2372 | 0 | } |
2373 | 0 | memcpy(p, res->rs.s, res->rs.len); |
2374 | 0 | p += res->rs.len; |
2375 | 0 | } |
2376 | | |
2377 | 0 | *p = 0; |
2378 | 0 | res->rs.s = pv_local_buf; |
2379 | 0 | res->rs.len = p - pv_local_buf; |
2380 | 0 | return 0; |
2381 | 0 | } |
2382 | | |
2383 | | /* we have a numeric index */ |
2384 | 0 | if(idx<0) |
2385 | 0 | { |
2386 | 0 | n = 1; |
2387 | 0 | avp0 = avp; |
2388 | 0 | while ((avp0=search_first_avp(name_type, avp_name, |
2389 | 0 | &avp_value0, avp0))!=0) n++; |
2390 | 0 | idx = -idx; |
2391 | 0 | if(idx>n) |
2392 | 0 | { |
2393 | 0 | LM_DBG("index out of range\n"); |
2394 | 0 | return pv_get_null(msg, param, res); |
2395 | 0 | } |
2396 | 0 | idx = n - idx; |
2397 | 0 | if(idx==0) |
2398 | 0 | { |
2399 | 0 | if(avp->flags & AVP_VAL_STR) { |
2400 | 0 | res->rs = avp_value.s; |
2401 | 0 | } else if(avp->flags & AVP_VAL_NULL) { |
2402 | 0 | res->flags |= PV_VAL_NULL; |
2403 | 0 | } else { |
2404 | 0 | res->rs.s = sint2str(avp_value.n, &res->rs.len); |
2405 | 0 | res->ri = avp_value.n; |
2406 | 0 | res->flags |= PV_VAL_INT|PV_TYPE_INT; |
2407 | 0 | } |
2408 | 0 | return 0; |
2409 | 0 | } |
2410 | 0 | } |
2411 | 0 | n=0; |
2412 | 0 | while(n<idx |
2413 | 0 | && (avp=search_first_avp(name_type, avp_name, &avp_value, avp))!=0) |
2414 | 0 | n++; |
2415 | |
|
2416 | 0 | if(avp!=0) |
2417 | 0 | { |
2418 | 0 | if(avp->flags & AVP_VAL_STR) { |
2419 | 0 | res->rs = avp_value.s; |
2420 | 0 | } else if(avp->flags & AVP_VAL_NULL) { |
2421 | 0 | res->flags |= PV_VAL_NULL; |
2422 | 0 | } else { |
2423 | 0 | res->rs.s = sint2str(avp_value.n, &res->rs.len); |
2424 | 0 | res->ri = avp_value.n; |
2425 | 0 | res->flags |= PV_VAL_INT|PV_TYPE_INT; |
2426 | 0 | } |
2427 | 0 | return 0; |
2428 | 0 | } |
2429 | | |
2430 | 0 | LM_DBG("index out of range\n"); |
2431 | 0 | return pv_get_null(msg, param, res); |
2432 | 0 | } |
2433 | | |
2434 | | |
2435 | | static int pv_resolve_hdr_name(const str *in, pv_value_t *tv) |
2436 | 0 | { |
2437 | 0 | struct hdr_field hdr; |
2438 | 0 | str s; |
2439 | 0 | if(in->len>=PV_LOCAL_BUF_SIZE-1) |
2440 | 0 | { |
2441 | 0 | LM_ERR("name too long\n"); |
2442 | 0 | return -1; |
2443 | 0 | } |
2444 | 0 | memcpy(pv_local_buf, in->s, in->len); |
2445 | 0 | pv_local_buf[in->len] = ':'; |
2446 | 0 | s.s = pv_local_buf; |
2447 | 0 | s.len = in->len+1; |
2448 | |
|
2449 | 0 | if (parse_hname2(s.s, s.s + ((s.len<4)?4:s.len), &hdr)==0) |
2450 | 0 | { |
2451 | 0 | LM_ERR("error parsing header name [%.*s]\n", s.len, s.s); |
2452 | 0 | return -1; |
2453 | 0 | } |
2454 | 0 | if (hdr.type!=HDR_OTHER_T && hdr.type!=HDR_ERROR_T) |
2455 | 0 | { |
2456 | 0 | LM_DBG("using hdr type (%d) instead of <%.*s>\n", |
2457 | 0 | hdr.type, in->len, in->s); |
2458 | 0 | tv->flags = 0; |
2459 | 0 | tv->ri = hdr.type; |
2460 | 0 | } else { |
2461 | 0 | tv->flags = PV_VAL_STR; |
2462 | 0 | tv->rs = *in; |
2463 | 0 | } |
2464 | 0 | return 0; |
2465 | 0 | } |
2466 | | |
2467 | | static int pv_get_hdr_prolog(struct sip_msg *msg, pv_param_t *param, pv_value_t *res, pv_value_t* tv) |
2468 | 0 | { |
2469 | 0 | if(msg==NULL || res==NULL || param==NULL) |
2470 | 0 | return -1; |
2471 | | |
2472 | | /* get the name */ |
2473 | 0 | if(param->pvn.type == PV_NAME_PVAR) |
2474 | 0 | { |
2475 | 0 | if(pv_get_spec_name(msg, param, tv)!=0 || (!(tv->flags&PV_VAL_STR))) |
2476 | 0 | { |
2477 | 0 | LM_ERR("invalid name\n"); |
2478 | 0 | return -1; |
2479 | 0 | } |
2480 | 0 | if (pv_resolve_hdr_name(&tv->rs, tv) < 0) |
2481 | 0 | return -1; |
2482 | 0 | } else { |
2483 | 0 | if(param->pvn.u.isname.type == AVP_NAME_STR) |
2484 | 0 | { |
2485 | 0 | tv->flags = PV_VAL_STR; |
2486 | 0 | tv->rs = param->pvn.u.isname.name.s; |
2487 | 0 | } else { |
2488 | 0 | tv->flags = 0; |
2489 | 0 | tv->ri = param->pvn.u.isname.name.n; |
2490 | 0 | } |
2491 | 0 | } |
2492 | | /* we need to be sure we have parsed all headers */ |
2493 | 0 | if(parse_headers(msg, HDR_EOH_F, 0)<0) |
2494 | 0 | { |
2495 | 0 | LM_ERR("error parsing headers\n"); |
2496 | 0 | return pv_get_null(msg, param, res); |
2497 | 0 | } |
2498 | 0 | return 1; |
2499 | 0 | } |
2500 | | |
2501 | | static int pv_get_hdrcnt(struct sip_msg *msg, pv_param_t *param, pv_value_t *res) |
2502 | 0 | { |
2503 | 0 | pv_value_t tv; |
2504 | 0 | struct hdr_field *hf; |
2505 | 0 | unsigned int n; |
2506 | 0 | int ret; |
2507 | |
|
2508 | 0 | if ( (ret=pv_get_hdr_prolog(msg, param, res, &tv)) <= 0 ) |
2509 | 0 | return ret; |
2510 | | |
2511 | 0 | n = 0; |
2512 | 0 | if (tv.flags==0) { |
2513 | | /* it is a known header -> use type to find it */ |
2514 | 0 | for (hf=msg->headers; hf; hf=hf->next) { |
2515 | 0 | if (tv.ri==hf->type) |
2516 | 0 | ++n; |
2517 | 0 | } |
2518 | 0 | } else { |
2519 | | /* it is an un-known header -> use name to find it */ |
2520 | 0 | for (hf=msg->headers; hf; hf=hf->next) { |
2521 | 0 | if (hf->type==HDR_OTHER_T && hf->name.len==tv.rs.len |
2522 | 0 | && strncasecmp(hf->name.s, tv.rs.s, hf->name.len)==0) |
2523 | 0 | ++n; |
2524 | 0 | } |
2525 | 0 | } |
2526 | 0 | return pv_get_uintval(msg, param, res, n); |
2527 | 0 | } |
2528 | | |
2529 | | static int pv_get_hdr(struct sip_msg *msg, pv_param_t *param, pv_value_t *res) |
2530 | 0 | { |
2531 | 0 | int idx; |
2532 | 0 | int idxf; |
2533 | 0 | pv_value_t tv; |
2534 | 0 | struct hdr_field *hf; |
2535 | 0 | struct hdr_field *hf0; |
2536 | 0 | char *p; |
2537 | 0 | int n; |
2538 | 0 | int ret; |
2539 | |
|
2540 | 0 | if ( (ret=pv_get_hdr_prolog(msg, param, res, &tv)) <= 0 ) |
2541 | 0 | return ret; |
2542 | | |
2543 | 0 | if (tv.flags==0) { |
2544 | | /* it is a known header -> use type to find it */ |
2545 | 0 | for (hf=msg->headers; hf; hf=hf->next) { |
2546 | 0 | if (tv.ri==hf->type) |
2547 | 0 | break; |
2548 | 0 | } |
2549 | 0 | } else { |
2550 | | /* it is an un-known header -> use name to find it */ |
2551 | 0 | for (hf=msg->headers; hf; hf=hf->next) { |
2552 | 0 | if (hf->type==HDR_OTHER_T && hf->name.len==tv.rs.len |
2553 | 0 | && strncasecmp(hf->name.s, tv.rs.s, hf->name.len)==0) |
2554 | 0 | break; |
2555 | 0 | } |
2556 | 0 | } |
2557 | |
|
2558 | 0 | if(hf==NULL) |
2559 | 0 | return pv_get_null(msg, param, res); |
2560 | | /* get the index */ |
2561 | 0 | if(pv_get_spec_index(msg, param, &idx, &idxf)!=0) |
2562 | 0 | { |
2563 | 0 | LM_ERR("invalid index\n"); |
2564 | 0 | return -1; |
2565 | 0 | } |
2566 | | |
2567 | | /* get the value */ |
2568 | 0 | res->flags = PV_VAL_STR; |
2569 | 0 | if(idxf!=PV_IDX_ALL && idx==0) |
2570 | 0 | { |
2571 | 0 | res->rs = hf->body; |
2572 | 0 | return 0; |
2573 | 0 | } |
2574 | 0 | if(idxf==PV_IDX_ALL) |
2575 | 0 | { |
2576 | 0 | p = pv_local_buf; |
2577 | 0 | do { |
2578 | 0 | if(p!=pv_local_buf) |
2579 | 0 | { |
2580 | 0 | if(p-pv_local_buf+PV_FIELD_DELIM_LEN+1>PV_LOCAL_BUF_SIZE) |
2581 | 0 | { |
2582 | 0 | LM_ERR("local buffer length exceeded\n"); |
2583 | 0 | return pv_get_null(msg, param, res); |
2584 | 0 | } |
2585 | 0 | memcpy(p, PV_FIELD_DELIM, PV_FIELD_DELIM_LEN); |
2586 | 0 | p += PV_FIELD_DELIM_LEN; |
2587 | 0 | } |
2588 | | |
2589 | 0 | if(p-pv_local_buf+hf->body.len+1>PV_LOCAL_BUF_SIZE) |
2590 | 0 | { |
2591 | 0 | LM_ERR("local buffer length exceeded!\n"); |
2592 | 0 | return pv_get_null(msg, param, res); |
2593 | 0 | } |
2594 | 0 | memcpy(p, hf->body.s, hf->body.len); |
2595 | 0 | p += hf->body.len; |
2596 | | /* next hf */ |
2597 | 0 | if (tv.flags==0) { |
2598 | | /* it is a known header -> use type to find it */ |
2599 | 0 | for (hf=hf->next ; hf; hf=hf->next) { |
2600 | 0 | if (tv.ri==hf->type) |
2601 | 0 | break; |
2602 | 0 | } |
2603 | 0 | } else { |
2604 | | /* it is an un-known header -> use name to find it */ |
2605 | 0 | for (hf=hf->next ; hf; hf=hf->next) { |
2606 | 0 | if (hf->type==HDR_OTHER_T && hf->name.len==tv.rs.len |
2607 | 0 | && strncasecmp(hf->name.s, tv.rs.s, hf->name.len)==0) |
2608 | 0 | break; |
2609 | 0 | } |
2610 | 0 | } |
2611 | 0 | } while (hf); |
2612 | 0 | *p = 0; |
2613 | 0 | res->rs.s = pv_local_buf; |
2614 | 0 | res->rs.len = p - pv_local_buf; |
2615 | 0 | return 0; |
2616 | 0 | } |
2617 | | |
2618 | | /* we have a numeric index */ |
2619 | 0 | hf0 = 0; |
2620 | 0 | if(idx<0) |
2621 | 0 | { |
2622 | 0 | n = 1; |
2623 | | /* count headers */ |
2624 | 0 | if (tv.flags==0 ) { |
2625 | | /* it is a known header -> use type to find it */ |
2626 | 0 | for (hf0=hf->next; hf0; hf0=hf0->next) { |
2627 | 0 | if (tv.ri==hf0->type) |
2628 | 0 | n++; |
2629 | 0 | } |
2630 | 0 | } else { |
2631 | | /* it is an un-known header -> use name to find it */ |
2632 | 0 | for (hf0=hf->next; hf0; hf0=hf0->next) { |
2633 | 0 | if (hf0->type==HDR_OTHER_T && hf0->name.len==tv.rs.len |
2634 | 0 | && strncasecmp(hf0->name.s, tv.rs.s, hf0->name.len)==0) |
2635 | 0 | n++; |
2636 | 0 | } |
2637 | 0 | } |
2638 | |
|
2639 | 0 | idx = -idx; |
2640 | 0 | if(idx>n) |
2641 | 0 | { |
2642 | 0 | LM_DBG("index out of range\n"); |
2643 | 0 | return pv_get_null(msg, param, res); |
2644 | 0 | } |
2645 | 0 | idx = n - idx; |
2646 | 0 | if(idx==0) |
2647 | 0 | { |
2648 | 0 | res->rs = hf->body; |
2649 | 0 | return 0; |
2650 | 0 | } |
2651 | 0 | } |
2652 | 0 | n=0; |
2653 | 0 | while(n<idx) |
2654 | 0 | { |
2655 | 0 | if (tv.flags==0) { |
2656 | | /* it is a known header -> use type to find it */ |
2657 | 0 | for (hf0=hf->next; hf0; hf0=hf0->next) { |
2658 | 0 | if (tv.ri==hf0->type) { |
2659 | 0 | n++; |
2660 | 0 | if(n==idx) break; |
2661 | 0 | } |
2662 | 0 | } |
2663 | 0 | } else { |
2664 | | /* it is an un-known header -> use name to find it */ |
2665 | 0 | for (hf0=hf->next; hf0; hf0=hf0->next) { |
2666 | 0 | if (hf0->type==HDR_OTHER_T && hf0->name.len==tv.rs.len |
2667 | 0 | && strncasecmp(hf0->name.s, tv.rs.s, hf0->name.len)==0) { |
2668 | 0 | n++; |
2669 | 0 | if(n==idx) break; |
2670 | 0 | } |
2671 | 0 | } |
2672 | 0 | } |
2673 | 0 | if(hf0==NULL) |
2674 | 0 | break; |
2675 | 0 | } |
2676 | |
|
2677 | 0 | if(hf0!=0) |
2678 | 0 | { |
2679 | 0 | res->rs = hf0->body; |
2680 | 0 | return 0; |
2681 | 0 | } |
2682 | | |
2683 | 0 | LM_DBG("index out of range\n"); |
2684 | 0 | return pv_get_null(msg, param, res); |
2685 | |
|
2686 | 0 | } |
2687 | | |
2688 | | static int pv_get_hdr_name(struct sip_msg *msg, pv_param_t *param, pv_value_t *res) |
2689 | 10.7k | { |
2690 | 10.7k | int idx, idx_f; |
2691 | 10.7k | struct hdr_field *hf; |
2692 | 10.7k | char *p; |
2693 | 10.7k | int n; |
2694 | | |
2695 | 10.7k | if(msg==NULL || res==NULL || param==NULL) |
2696 | 0 | return -1; |
2697 | | |
2698 | | /* get the index */ |
2699 | 10.7k | if (pv_get_spec_index(msg, param, &idx, &idx_f) != 0) { |
2700 | 0 | LM_ERR("invalid index\n"); |
2701 | 0 | return -1; |
2702 | 0 | } |
2703 | | |
2704 | | /* make sure we have parsed all the headers */ |
2705 | 10.7k | if (parse_headers(msg, HDR_EOH_F, 0) <0 ) { |
2706 | 0 | LM_ERR("error parsing headers\n"); |
2707 | 0 | return pv_get_null(msg, param, res); |
2708 | 0 | } |
2709 | | |
2710 | 10.7k | res->flags = PV_VAL_STR; |
2711 | | |
2712 | 10.7k | if (idx_f == PV_IDX_ALL) { |
2713 | | /* return all header names, separated by ',' */ |
2714 | |
|
2715 | 0 | p = pv_local_buf; |
2716 | 0 | hf = msg->headers; |
2717 | 0 | do { |
2718 | 0 | if (p != pv_local_buf) { |
2719 | 0 | if (p - pv_local_buf + PV_FIELD_DELIM_LEN + 1 > PV_LOCAL_BUF_SIZE) { |
2720 | 0 | LM_ERR("local buffer length exceeded\n"); |
2721 | 0 | return pv_get_null(msg, param, res); |
2722 | 0 | } |
2723 | 0 | memcpy(p, PV_FIELD_DELIM, PV_FIELD_DELIM_LEN); |
2724 | 0 | p += PV_FIELD_DELIM_LEN; |
2725 | 0 | } |
2726 | | |
2727 | 0 | if (p - pv_local_buf + hf->name.len + 1 > PV_LOCAL_BUF_SIZE) { |
2728 | 0 | LM_ERR("local buffer length exceeded!\n"); |
2729 | 0 | return pv_get_null(msg, param, res); |
2730 | 0 | } |
2731 | 0 | memcpy(p, hf->name.s, hf->name.len); |
2732 | 0 | p += hf->name.len; |
2733 | |
|
2734 | 0 | hf = hf->next; |
2735 | 0 | } while (hf); |
2736 | | |
2737 | 0 | *p = 0; |
2738 | 0 | res->rs.s = pv_local_buf; |
2739 | 0 | res->rs.len = p - pv_local_buf; |
2740 | 0 | return 0; |
2741 | 0 | } |
2742 | | |
2743 | 10.7k | if (idx < 0) { |
2744 | | /* negative index, translate it to a positive one */ |
2745 | |
|
2746 | 0 | n = 0; |
2747 | 0 | for (hf = msg->headers; hf; hf = hf->next, n++) ; |
2748 | 0 | idx = -idx; |
2749 | 0 | if(idx > n) { |
2750 | 0 | LM_DBG("index [%d] out of range\n", -idx); |
2751 | 0 | return pv_get_null(msg, param, res); |
2752 | 0 | } |
2753 | 0 | idx = n - idx; |
2754 | 0 | } |
2755 | | |
2756 | 10.7k | for (hf = msg->headers, n = 0; hf && n != idx; hf = hf->next, n++) ; |
2757 | | |
2758 | 10.7k | if (!hf) { |
2759 | 0 | LM_DBG("index [%d] out of range\n", idx); |
2760 | 0 | return pv_get_null(msg, param, res); |
2761 | 0 | } |
2762 | | |
2763 | 10.7k | res->rs = hf->name; |
2764 | 10.7k | return 0; |
2765 | 10.7k | } |
2766 | | |
2767 | | static int pv_get_scriptvar(struct sip_msg *msg, pv_param_t *param, |
2768 | | pv_value_t *res) |
2769 | 0 | { |
2770 | 0 | int ival = 0; |
2771 | 0 | char *sval = NULL; |
2772 | 0 | script_var_t *sv=NULL; |
2773 | |
|
2774 | 0 | if(msg==NULL || res==NULL) |
2775 | 0 | return -1; |
2776 | | |
2777 | 0 | if(param==NULL || param->pvn.u.dname==0) |
2778 | 0 | return pv_get_null(msg, param, res); |
2779 | | |
2780 | 0 | sv= (script_var_t*)param->pvn.u.dname; |
2781 | |
|
2782 | 0 | if (sv->v.flags&VAR_VAL_NULL) |
2783 | 0 | return pv_get_null(msg, param, res); |
2784 | | |
2785 | 0 | if(sv->v.flags&VAR_VAL_STR) |
2786 | 0 | { |
2787 | 0 | res->rs = sv->v.value.s; |
2788 | 0 | res->flags = PV_VAL_STR; |
2789 | 0 | } else { |
2790 | 0 | sval = sint2str(sv->v.value.n, &ival); |
2791 | |
|
2792 | 0 | res->rs.s = sval; |
2793 | 0 | res->rs.len = ival; |
2794 | |
|
2795 | 0 | res->ri = sv->v.value.n; |
2796 | 0 | res->flags = PV_VAL_STR|PV_VAL_INT|PV_TYPE_INT; |
2797 | 0 | } |
2798 | 0 | return 0; |
2799 | 0 | } |
2800 | | |
2801 | | /********* end PV get functions *********/ |
2802 | | |
2803 | | /********* start PV set functions *********/ |
2804 | | static int pv_set_avp(struct sip_msg* msg, pv_param_t *param, |
2805 | | int op, pv_value_t *val) |
2806 | 0 | { |
2807 | 0 | int avp_name; |
2808 | 0 | int_str avp_val; |
2809 | 0 | int flags; |
2810 | 0 | unsigned short name_type; |
2811 | 0 | int idx, idxf; |
2812 | |
|
2813 | 0 | if(param==NULL) |
2814 | 0 | { |
2815 | 0 | LM_ERR("bad parameters\n"); |
2816 | 0 | return -1; |
2817 | 0 | } |
2818 | | |
2819 | 0 | if(pv_get_avp_name(msg, param, &avp_name, &name_type)!=0) |
2820 | 0 | { |
2821 | 0 | LM_ALERT("BUG in getting dst AVP name\n"); |
2822 | 0 | goto error; |
2823 | 0 | } |
2824 | | |
2825 | | /* get the index */ |
2826 | 0 | if(pv_get_spec_index(msg, param, &idx, &idxf)!=0) |
2827 | 0 | { |
2828 | 0 | LM_ERR("invalid index\n"); |
2829 | 0 | return -1; |
2830 | 0 | } |
2831 | | |
2832 | 0 | if(val == NULL) |
2833 | 0 | { |
2834 | 0 | if(op == COLONEQ_T || idxf == PV_IDX_ALL) |
2835 | 0 | destroy_avps(name_type, avp_name, 1); |
2836 | 0 | else |
2837 | 0 | { |
2838 | 0 | destroy_index_avp(name_type, avp_name, idx); |
2839 | 0 | } |
2840 | 0 | return 0; |
2841 | 0 | } |
2842 | | |
2843 | 0 | if(op == COLONEQ_T || idxf == PV_IDX_ALL) |
2844 | 0 | destroy_avps(name_type, avp_name, 1); |
2845 | |
|
2846 | 0 | flags = name_type; |
2847 | 0 | if(val->flags&PV_TYPE_INT) |
2848 | 0 | { |
2849 | 0 | avp_val.n = val->ri; |
2850 | 0 | } else { |
2851 | 0 | avp_val.s = val->rs; |
2852 | 0 | flags |= AVP_VAL_STR; |
2853 | 0 | } |
2854 | |
|
2855 | 0 | if(idxf == PV_IDX_INT || idxf == PV_IDX_PVAR) /* if the avp is indexed */ |
2856 | 0 | { |
2857 | 0 | if(replace_avp(flags, avp_name, avp_val, idx)< 0) |
2858 | 0 | { |
2859 | 0 | LM_ERR("Failed to replace avp\n"); |
2860 | 0 | goto error; |
2861 | 0 | } |
2862 | 0 | } |
2863 | 0 | else if (idxf == PV_IDX_APPEND) /* add AVP at the end */ |
2864 | 0 | { |
2865 | 0 | if (add_avp_last(flags, avp_name, avp_val)<0) |
2866 | 0 | { |
2867 | 0 | LM_ERR("error - cannot add AVP\n"); |
2868 | 0 | goto error; |
2869 | 0 | } |
2870 | 0 | } |
2871 | 0 | else { |
2872 | 0 | if (add_avp(flags, avp_name, avp_val)<0) |
2873 | 0 | { |
2874 | 0 | LM_ERR("error - cannot add AVP\n"); |
2875 | 0 | goto error; |
2876 | 0 | } |
2877 | 0 | } |
2878 | | |
2879 | 0 | return 0; |
2880 | 0 | error: |
2881 | 0 | return -1; |
2882 | 0 | } |
2883 | | |
2884 | | static int pv_set_scriptvar(struct sip_msg* msg, pv_param_t *param, |
2885 | | int op, pv_value_t *val) |
2886 | 0 | { |
2887 | 0 | int_str avp_val; |
2888 | 0 | int flags; |
2889 | |
|
2890 | 0 | if(param==NULL) |
2891 | 0 | { |
2892 | 0 | LM_ERR("bad parameters\n"); |
2893 | 0 | return -1; |
2894 | 0 | } |
2895 | | |
2896 | 0 | if(param->pvn.u.dname==0) |
2897 | 0 | { |
2898 | 0 | LM_ERR("error - cannot find svar\n"); |
2899 | 0 | goto error; |
2900 | 0 | } |
2901 | 0 | if(val == NULL) |
2902 | 0 | { |
2903 | 0 | set_var_value((script_var_t*)param->pvn.u.dname, NULL, VAR_VAL_NULL); |
2904 | 0 | return 0; |
2905 | 0 | } |
2906 | 0 | if(val->flags&PV_TYPE_INT) |
2907 | 0 | { |
2908 | 0 | avp_val.n = val->ri; |
2909 | 0 | flags = 0; |
2910 | 0 | } else { |
2911 | 0 | avp_val.s = val->rs; |
2912 | 0 | flags = VAR_VAL_STR; |
2913 | 0 | } |
2914 | 0 | if(set_var_value((script_var_t*)param->pvn.u.dname, &avp_val, flags)==NULL) |
2915 | 0 | { |
2916 | 0 | LM_ERR("error - cannot set svar [%.*s] \n", |
2917 | 0 | ((script_var_t*)param->pvn.u.dname)->name.len, |
2918 | 0 | ((script_var_t*)param->pvn.u.dname)->name.s); |
2919 | 0 | goto error; |
2920 | 0 | } |
2921 | 0 | return 0; |
2922 | 0 | error: |
2923 | 0 | return -1; |
2924 | 0 | } |
2925 | | |
2926 | | static int pv_set_dsturi(struct sip_msg* msg, pv_param_t *param, |
2927 | | int op, pv_value_t *val) |
2928 | 0 | { |
2929 | 0 | if(msg==NULL || param==NULL) |
2930 | 0 | { |
2931 | 0 | LM_ERR("bad parameters\n"); |
2932 | 0 | return -1; |
2933 | 0 | } |
2934 | | |
2935 | 0 | if(val == NULL) |
2936 | 0 | { |
2937 | 0 | reset_dst_uri(msg); |
2938 | |
|
2939 | 0 | return 1; |
2940 | 0 | } |
2941 | 0 | if(!(val->flags&PV_VAL_STR)) |
2942 | 0 | { |
2943 | 0 | LM_ERR("error - str value required to set dst uri\n"); |
2944 | 0 | goto error; |
2945 | 0 | } |
2946 | | |
2947 | 0 | if(set_dst_uri(msg, &val->rs)!=0) |
2948 | 0 | goto error; |
2949 | | |
2950 | 0 | return 0; |
2951 | 0 | error: |
2952 | 0 | return -1; |
2953 | 0 | } |
2954 | | |
2955 | | static int pv_set_ruri(struct sip_msg* msg, pv_param_t *param, |
2956 | | int op, pv_value_t *val) |
2957 | 0 | { |
2958 | 0 | if(msg==NULL || param==NULL || val==NULL) |
2959 | 0 | { |
2960 | 0 | LM_ERR("bad parameters\n"); |
2961 | 0 | return -1; |
2962 | 0 | } |
2963 | | |
2964 | 0 | if(!(val->flags&PV_VAL_STR)) |
2965 | 0 | { |
2966 | 0 | LM_ERR("str value required to set R-URI\n"); |
2967 | 0 | goto error; |
2968 | 0 | } |
2969 | | |
2970 | 0 | if (set_ruri( msg, &val->rs)!=0) { |
2971 | 0 | LM_ERR("failed to set RURI\n"); |
2972 | 0 | goto error; |
2973 | 0 | } |
2974 | | |
2975 | 0 | return 0; |
2976 | 0 | error: |
2977 | 0 | return -1; |
2978 | 0 | } |
2979 | | |
2980 | | static int pv_set_ru_q(struct sip_msg* msg, pv_param_t *param, |
2981 | | int op, pv_value_t *val) |
2982 | 0 | { |
2983 | 0 | if(msg==NULL || param==NULL || val==NULL) |
2984 | 0 | { |
2985 | 0 | LM_ERR("bad parameters\n"); |
2986 | 0 | return -1; |
2987 | 0 | } |
2988 | | |
2989 | 0 | if(!(val->flags&PV_VAL_INT)) |
2990 | 0 | { |
2991 | 0 | LM_ERR("int value required to set r-uri queue value\n"); |
2992 | 0 | return -1; |
2993 | 0 | } |
2994 | | |
2995 | 0 | if (val->ri > 1000) { |
2996 | 0 | LM_WARN("queue value too big %d - setting queue to " |
2997 | 0 | "maximum value (1000)\n", val->ri); |
2998 | 0 | set_ruri_q(msg, 1000); |
2999 | 0 | } else |
3000 | 0 | set_ruri_q(msg, val->ri); |
3001 | |
|
3002 | 0 | return 0; |
3003 | 0 | } |
3004 | | |
3005 | | static int pv_set_ruri_user(struct sip_msg* msg, pv_param_t *param, |
3006 | | int op, pv_value_t *val) |
3007 | 0 | { |
3008 | 0 | str sval; |
3009 | |
|
3010 | 0 | if(msg==NULL || param==NULL) |
3011 | 0 | { |
3012 | 0 | LM_ERR("bad parameters\n"); |
3013 | 0 | return -1; |
3014 | 0 | } |
3015 | | |
3016 | 0 | if(val == NULL) |
3017 | 0 | sval = str_empty; |
3018 | 0 | else if(!(val->flags&PV_VAL_STR)) { |
3019 | 0 | LM_ERR("str value required to set R-URI user\n"); |
3020 | 0 | return -1; |
3021 | 0 | } else |
3022 | 0 | sval = val->rs; |
3023 | | |
3024 | 0 | if (rewrite_ruri(msg, &sval, 0, RW_RURI_USER) < 0) { |
3025 | 0 | LM_ERR("Failed to set R-URI user\n"); |
3026 | 0 | return -1; |
3027 | 0 | } |
3028 | | |
3029 | 0 | return 0; |
3030 | 0 | } |
3031 | | |
3032 | | static int pv_set_ruri_host(struct sip_msg* msg, pv_param_t *param, |
3033 | | int op, pv_value_t *val) |
3034 | 0 | { |
3035 | 0 | if(msg==NULL || param==NULL || val==NULL) |
3036 | 0 | { |
3037 | 0 | LM_ERR("bad parameters\n"); |
3038 | 0 | return -1; |
3039 | 0 | } |
3040 | | |
3041 | 0 | if(!(val->flags&PV_VAL_STR)) |
3042 | 0 | { |
3043 | 0 | LM_ERR("str value required to set R-URI hostname\n"); |
3044 | 0 | return -1; |
3045 | 0 | } |
3046 | | |
3047 | 0 | if (rewrite_ruri(msg, &val->rs, 0, RW_RURI_HOST) < 0) { |
3048 | 0 | LM_ERR("Failed to set R-URI hostname\n"); |
3049 | 0 | return -1; |
3050 | 0 | } |
3051 | | |
3052 | 0 | return 0; |
3053 | 0 | } |
3054 | | |
3055 | | static int pv_set_dsturi_host(struct sip_msg* msg, pv_param_t *param, |
3056 | | int op, pv_value_t *val) |
3057 | 0 | { |
3058 | 0 | if(msg==NULL || param==NULL || val==NULL) |
3059 | 0 | { |
3060 | 0 | LM_ERR("bad parameters\n"); |
3061 | 0 | return -1; |
3062 | 0 | } |
3063 | | |
3064 | 0 | if(!(val->flags&PV_VAL_STR)) |
3065 | 0 | { |
3066 | 0 | LM_ERR("str value required to set DST-URI hostname\n"); |
3067 | 0 | return -1; |
3068 | 0 | } |
3069 | | |
3070 | 0 | if (set_dst_host_port(msg, &val->rs, NULL) < 0) { |
3071 | 0 | LM_ERR("Failed to set DST-URI host\n"); |
3072 | 0 | return -1; |
3073 | 0 | } |
3074 | | |
3075 | 0 | return 0; |
3076 | 0 | } |
3077 | | |
3078 | | static int pv_set_dsturi_port(struct sip_msg* msg, pv_param_t *param, |
3079 | | int op, pv_value_t *val) |
3080 | 0 | { |
3081 | 0 | str sval; |
3082 | |
|
3083 | 0 | if(msg==NULL || param==NULL) |
3084 | 0 | { |
3085 | 0 | LM_ERR("bad parameters\n"); |
3086 | 0 | return -1; |
3087 | 0 | } |
3088 | | |
3089 | 0 | if(val == NULL) |
3090 | 0 | sval = str_empty; |
3091 | 0 | else if(!(val->flags&PV_VAL_STR)) |
3092 | 0 | sval.s = int2str(val->ri, &sval.len); |
3093 | 0 | else |
3094 | 0 | sval = val->rs; |
3095 | |
|
3096 | 0 | if (set_dst_host_port(msg, NULL, &sval) < 0) { |
3097 | 0 | LM_ERR("Failed to set DST-URI port\n"); |
3098 | 0 | return -1; |
3099 | 0 | } |
3100 | | |
3101 | 0 | return 0; |
3102 | 0 | } |
3103 | | |
3104 | | |
3105 | | |
3106 | | |
3107 | | static int pv_set_ruri_port(struct sip_msg* msg, pv_param_t *param, |
3108 | | int op, pv_value_t *val) |
3109 | 0 | { |
3110 | 0 | str sval; |
3111 | |
|
3112 | 0 | if(msg==NULL || param==NULL) |
3113 | 0 | { |
3114 | 0 | LM_ERR("bad parameters\n"); |
3115 | 0 | return -1; |
3116 | 0 | } |
3117 | | |
3118 | 0 | if(val == NULL) |
3119 | 0 | sval = str_empty; |
3120 | 0 | else if(!(val->flags&PV_VAL_STR)) |
3121 | 0 | sval.s = int2str(val->ri, &sval.len); |
3122 | 0 | else |
3123 | 0 | sval = val->rs; |
3124 | |
|
3125 | 0 | if (rewrite_ruri(msg, &sval, 0, RW_RURI_PORT) < 0) { |
3126 | 0 | LM_ERR("Failed to set R-URI hostname\n"); |
3127 | 0 | return -1; |
3128 | 0 | } |
3129 | | |
3130 | 0 | return 0; |
3131 | 0 | } |
3132 | | |
3133 | | |
3134 | | static int pv_set_branch(struct sip_msg* msg, pv_param_t *param, |
3135 | | int op, pv_value_t *val) |
3136 | 0 | { |
3137 | 0 | if (msg==NULL || param==NULL) { |
3138 | 0 | LM_ERR("bad parameters\n"); |
3139 | 0 | return -1; |
3140 | 0 | } |
3141 | | |
3142 | 0 | if (!val || !(val->flags&PV_VAL_STR) || val->flags&(PV_VAL_NULL) || |
3143 | 0 | val->rs.len==0 ) { |
3144 | 0 | LM_ERR("str value required to create a new branch\n"); |
3145 | 0 | return -1; |
3146 | 0 | } |
3147 | | |
3148 | 0 | if (append_branch( msg, &val->rs, NULL, NULL, Q_UNSPECIFIED, 0, NULL)!=1){ |
3149 | 0 | LM_ERR("failed to append new branch\n"); |
3150 | 0 | return -1; |
3151 | 0 | } |
3152 | | |
3153 | 0 | return 0; |
3154 | 0 | } |
3155 | | |
3156 | | |
3157 | | static int pv_set_branch_fields(struct sip_msg* msg, pv_param_t *param, |
3158 | | int op, pv_value_t *val) |
3159 | 0 | { |
3160 | 0 | int idx; |
3161 | 0 | int idxf; |
3162 | 0 | str *s; |
3163 | 0 | qvalue_t q; |
3164 | 0 | unsigned int flags; |
3165 | 0 | const struct socket_info *si; |
3166 | |
|
3167 | 0 | if (msg==NULL || param==NULL) { |
3168 | 0 | LM_ERR("bad parameters\n"); |
3169 | 0 | return -1; |
3170 | 0 | } |
3171 | | |
3172 | 0 | if (msg->first_line.type == SIP_REPLY) |
3173 | 0 | return -1; |
3174 | | |
3175 | | /* get the index */ |
3176 | 0 | if (pv_get_spec_index(msg, param, &idx, &idxf)!=0) { |
3177 | 0 | LM_ERR("invalid index\n"); |
3178 | 0 | return -1; |
3179 | 0 | } |
3180 | | |
3181 | 0 | if(idxf==PV_IDX_ALL) { |
3182 | 0 | LM_ERR("SCRIPT BUG - * not allowed in branch assignment\n"); |
3183 | 0 | return -1; |
3184 | 0 | } |
3185 | | |
3186 | 0 | if (idx<0) { |
3187 | 0 | idx = get_nr_branches() + idx; |
3188 | 0 | } |
3189 | |
|
3190 | 0 | if (idx<0 || idx>=get_nr_branches()) { |
3191 | 0 | LM_ERR("SCRIPT BUG - inexisting branch assignment [%d/%d]\n", |
3192 | 0 | get_nr_branches(), idx); |
3193 | 0 | return -1; |
3194 | 0 | } |
3195 | | |
3196 | 0 | switch (param->pvn.u.isname.name.n) { |
3197 | 0 | case BR_URI_ID: /* set URI */ |
3198 | 0 | if (!val || !(val->flags&PV_VAL_STR) || val->flags&(PV_VAL_NULL) || |
3199 | 0 | val->rs.len==0 ) { |
3200 | 0 | LM_ERR("str value required to set the branch URI\n"); |
3201 | 0 | return -1; |
3202 | 0 | } |
3203 | 0 | s = &val->rs; |
3204 | 0 | return update_branch( idx, &s, NULL, |
3205 | 0 | NULL, NULL, NULL, NULL); |
3206 | 0 | case BR_Q_ID: /* set Q */ |
3207 | 0 | if ( val && !(val->flags&PV_VAL_INT) ) { |
3208 | 0 | LM_ERR("INT value required to set the branch Q\n"); |
3209 | 0 | return -1; |
3210 | 0 | } |
3211 | 0 | q = (!val||val->flags&PV_VAL_NULL)? Q_UNSPECIFIED : val->ri; |
3212 | 0 | return update_branch( idx, NULL, NULL, |
3213 | 0 | NULL, &q, NULL, NULL); |
3214 | 0 | case BR_DURI_ID: /* set DURI */ |
3215 | 0 | if ( val && !(val->flags&PV_VAL_STR) ) { |
3216 | 0 | LM_ERR("STR value required to set the branch DURI\n"); |
3217 | 0 | return -1; |
3218 | 0 | } |
3219 | 0 | s = (!val||val->flags&PV_VAL_NULL)? NULL : &val->rs; |
3220 | 0 | return update_branch( idx, NULL, &s, |
3221 | 0 | NULL, NULL, NULL, NULL); |
3222 | 0 | case BR_PATH_ID: /* set PATH */ |
3223 | 0 | if ( val && !(val->flags&PV_VAL_STR) ) { |
3224 | 0 | LM_ERR("STR value required to set the branch PATH\n"); |
3225 | 0 | return -1; |
3226 | 0 | } |
3227 | 0 | s = (!val||val->flags&PV_VAL_NULL)? NULL : &val->rs; |
3228 | 0 | return update_branch( idx, NULL, NULL, |
3229 | 0 | &s, NULL, NULL, NULL); |
3230 | 0 | case BR_FLAGS_ID: /* set FLAGS */ |
3231 | 0 | if ( val && !(val->flags&PV_VAL_STR) ) { |
3232 | 0 | LM_ERR("string value required to set the branch FLAGS\n"); |
3233 | 0 | return -1; |
3234 | 0 | } |
3235 | 0 | flags = (!val||val->flags&PV_VAL_NULL)? |
3236 | 0 | 0 : flag_list_to_bitmask(str2const(&val->rs), FLAG_TYPE_BRANCH, FLAG_DELIM, 0); |
3237 | 0 | return update_branch( idx, NULL, NULL, |
3238 | 0 | NULL, NULL, &flags, NULL); |
3239 | 0 | case BR_SOCKET_ID: /* set SOCKET */ |
3240 | 0 | if ( val && !(val->flags&PV_VAL_STR) ) { |
3241 | 0 | LM_ERR("STR value required to set the branch SOCKET\n"); |
3242 | 0 | return -1; |
3243 | 0 | } |
3244 | 0 | if (!val || val->flags&PV_VAL_NULL) { |
3245 | 0 | si = NULL; |
3246 | 0 | } else { |
3247 | 0 | si = parse_sock_info(&val->rs); |
3248 | 0 | if (si==NULL) |
3249 | 0 | return -1; |
3250 | 0 | } |
3251 | 0 | return update_branch( idx, NULL, NULL, |
3252 | 0 | NULL, NULL, NULL, &si); |
3253 | 0 | default: |
3254 | 0 | LM_CRIT("BUG - unsupported ID %d\n",param->pvn.u.isname.type); |
3255 | 0 | return -1; |
3256 | 0 | } |
3257 | 0 | } |
3258 | | |
3259 | | static int pv_set_force_sock(struct sip_msg* msg, pv_param_t *param, |
3260 | | int op, pv_value_t *val) |
3261 | 0 | { |
3262 | 0 | const struct socket_info *si; |
3263 | |
|
3264 | 0 | if(msg==NULL || param==NULL) |
3265 | 0 | { |
3266 | 0 | LM_ERR("bad parameters\n"); |
3267 | 0 | return -1; |
3268 | 0 | } |
3269 | | |
3270 | 0 | if(val==NULL) |
3271 | 0 | { |
3272 | 0 | msg->force_send_socket = NULL; |
3273 | 0 | return 0; |
3274 | 0 | } |
3275 | | |
3276 | 0 | if(!(val->flags&PV_VAL_STR) || val->rs.len<=0) |
3277 | 0 | { |
3278 | 0 | LM_ERR("str value required to set the force send sock\n"); |
3279 | 0 | goto error; |
3280 | 0 | } |
3281 | | |
3282 | 0 | si = parse_sock_info(&val->rs); |
3283 | 0 | if (si!=NULL) |
3284 | 0 | { |
3285 | 0 | msg->force_send_socket = si; |
3286 | 0 | } else { |
3287 | 0 | LM_WARN("no socket found to match [%.*s]\n", |
3288 | 0 | val->rs.len, val->rs.s); |
3289 | 0 | } |
3290 | |
|
3291 | 0 | return 0; |
3292 | 0 | error: |
3293 | 0 | return -1; |
3294 | 0 | } |
3295 | | |
3296 | | |
3297 | | /********* end PV set functions *********/ |
3298 | | |
3299 | | static int pv_parse_scriptvar_name(pv_spec_p sp, const str *in) |
3300 | 0 | { |
3301 | 0 | if(in==NULL || in->s==NULL || sp==NULL) |
3302 | 0 | return -1; |
3303 | | |
3304 | 0 | sp->pvp.pvn.type = PV_NAME_PVAR; |
3305 | 0 | sp->pvp.pvn.u.dname = (void*)add_var(in); |
3306 | 0 | if(sp->pvp.pvn.u.dname==NULL) |
3307 | 0 | { |
3308 | 0 | LM_ERR("cannot register var [%.*s]\n", in->len, in->s); |
3309 | 0 | return -1; |
3310 | 0 | } |
3311 | 0 | return 0; |
3312 | 0 | } |
3313 | | |
3314 | | static int pv_parse_hdr_name(pv_spec_p sp, const str *in) |
3315 | 0 | { |
3316 | 0 | char *p; |
3317 | 0 | pv_spec_p nsp = 0; |
3318 | 0 | pv_value_t tv; |
3319 | |
|
3320 | 0 | if(in==NULL || in->s==NULL || sp==NULL) |
3321 | 0 | return -1; |
3322 | | |
3323 | 0 | p = in->s; |
3324 | 0 | if(*p==PV_MARKER) |
3325 | 0 | { |
3326 | 0 | nsp = (pv_spec_p)pkg_malloc(sizeof(pv_spec_t)); |
3327 | 0 | if(nsp==NULL) |
3328 | 0 | { |
3329 | 0 | LM_ERR("no more memory\n"); |
3330 | 0 | return -1; |
3331 | 0 | } |
3332 | 0 | p = pv_parse_spec(in, nsp); |
3333 | 0 | if(p==NULL) |
3334 | 0 | { |
3335 | 0 | LM_ERR("invalid name [%.*s]\n", in->len, in->s); |
3336 | 0 | pv_spec_free(nsp); |
3337 | 0 | return -1; |
3338 | 0 | } |
3339 | | //LM_ERR("dynamic name [%.*s]\n", in->len, in->s); |
3340 | | //pv_print_spec(nsp); |
3341 | 0 | sp->pvp.pvn.type = PV_NAME_PVAR; |
3342 | 0 | sp->pvp.pvn.u.dname = (void*)nsp; |
3343 | 0 | return 0; |
3344 | 0 | } |
3345 | | |
3346 | 0 | if (pv_resolve_hdr_name(in, &tv) < 0) |
3347 | 0 | return -1; |
3348 | | |
3349 | 0 | sp->pvp.pvn.type = PV_NAME_INTSTR; |
3350 | 0 | if (!tv.flags) |
3351 | 0 | { |
3352 | 0 | LM_DBG("using hdr type (%d) instead of <%.*s>\n", |
3353 | 0 | tv.ri, in->len, in->s); |
3354 | 0 | sp->pvp.pvn.u.isname.type = 0; |
3355 | 0 | sp->pvp.pvn.u.isname.name.n = tv.ri; |
3356 | 0 | } else { |
3357 | 0 | sp->pvp.pvn.u.isname.type = AVP_NAME_STR; |
3358 | 0 | sp->pvp.pvn.u.isname.name.s = *in; |
3359 | 0 | } |
3360 | 0 | return 0; |
3361 | 0 | } |
3362 | | |
3363 | | int pv_parse_avp_name(pv_spec_p sp, const str *in) |
3364 | 0 | { |
3365 | 0 | char *p; |
3366 | 0 | char *s; |
3367 | 0 | pv_spec_p nsp = 0; |
3368 | |
|
3369 | 0 | if(in==NULL || in->s==NULL || sp==NULL) |
3370 | 0 | return -1; |
3371 | 0 | p = in->s; |
3372 | 0 | if(*p==PV_MARKER) |
3373 | 0 | { |
3374 | 0 | nsp = (pv_spec_p)pkg_malloc(sizeof(pv_spec_t)); |
3375 | 0 | if(nsp==NULL) |
3376 | 0 | { |
3377 | 0 | LM_ERR("no more memory\n"); |
3378 | 0 | return -1; |
3379 | 0 | } |
3380 | 0 | s = pv_parse_spec(in, nsp); |
3381 | 0 | if(s==NULL) |
3382 | 0 | { |
3383 | 0 | LM_ERR("invalid name [%.*s]\n", in->len, in->s); |
3384 | 0 | pv_spec_free(nsp); |
3385 | 0 | return -1; |
3386 | 0 | } |
3387 | | //LM_ERR("dynamic name [%.*s]\n", in->len, in->s); |
3388 | | //pv_print_spec(nsp); |
3389 | 0 | sp->pvp.pvn.type = PV_NAME_PVAR; |
3390 | 0 | sp->pvp.pvn.u.dname = (void*)nsp; |
3391 | 0 | return 0; |
3392 | 0 | } |
3393 | | /*LM_DBG("static name [%.*s]\n", in->len, in->s);*/ |
3394 | | /* always an int type from now */ |
3395 | 0 | sp->pvp.pvn.u.isname.type = 0; |
3396 | 0 | if(parse_avp_spec(in, &sp->pvp.pvn.u.isname.name.n)!=0) |
3397 | 0 | { |
3398 | 0 | LM_ERR("bad avp name [%.*s]\n", in->len, in->s); |
3399 | 0 | return -1; |
3400 | 0 | } |
3401 | 0 | sp->pvp.pvn.type = PV_NAME_INTSTR; |
3402 | 0 | return 0; |
3403 | 0 | } |
3404 | | |
3405 | | static int pv_parse_avp_index(pv_spec_p sp, const str *in) |
3406 | 0 | { |
3407 | 0 | #define AVP_APPEND_IDX "append" |
3408 | |
|
3409 | 0 | if(in==NULL || in->s==NULL || sp==NULL) |
3410 | 0 | return -1; |
3411 | | |
3412 | 0 | if ( (in->len==(sizeof(AVP_APPEND_IDX)-1)) && |
3413 | 0 | strncasecmp(in->s,AVP_APPEND_IDX,in->len)==0) { |
3414 | 0 | sp->pvp.pvi.type = PV_IDX_APPEND; |
3415 | 0 | return 0; |
3416 | 0 | } |
3417 | 0 | return pv_parse_index(sp,in); |
3418 | 0 | } |
3419 | | |
3420 | | int pv_parse_index(pv_spec_p sp, const str *in) |
3421 | 0 | { |
3422 | 0 | char *p; |
3423 | 0 | char *s; |
3424 | 0 | int sign; |
3425 | 0 | pv_spec_p nsp = 0; |
3426 | |
|
3427 | 0 | if(in==NULL || in->s==NULL || sp==NULL) |
3428 | 0 | return -1; |
3429 | 0 | p = in->s; |
3430 | 0 | if(*p==PV_MARKER) |
3431 | 0 | { |
3432 | 0 | nsp = (pv_spec_p)pkg_malloc(sizeof(pv_spec_t)); |
3433 | 0 | if(nsp==NULL) |
3434 | 0 | { |
3435 | 0 | LM_ERR("no more memory\n"); |
3436 | 0 | return -1; |
3437 | 0 | } |
3438 | 0 | memset(nsp, 0, sizeof(pv_spec_t)); |
3439 | 0 | s = pv_parse_spec(in, nsp); |
3440 | 0 | if(s==NULL) |
3441 | 0 | { |
3442 | 0 | LM_ERR("invalid index [%.*s]\n", in->len, in->s); |
3443 | 0 | pv_spec_free(nsp); |
3444 | 0 | return -1; |
3445 | 0 | } |
3446 | 0 | sp->pvp.pvi.type = PV_IDX_PVAR; |
3447 | 0 | sp->pvp.pvi.u.dval = (void*)nsp; |
3448 | 0 | return 0; |
3449 | 0 | } |
3450 | 0 | if(*p=='*' && in->len==1) |
3451 | 0 | { |
3452 | 0 | sp->pvp.pvi.type = PV_IDX_ALL; |
3453 | 0 | return 0; |
3454 | 0 | } |
3455 | 0 | sign = 1; |
3456 | 0 | if(*p=='-') |
3457 | 0 | { |
3458 | 0 | sign = -1; |
3459 | 0 | p++; |
3460 | 0 | } |
3461 | 0 | sp->pvp.pvi.u.ival = 0; |
3462 | 0 | while(p<in->s+in->len && *p>='0' && *p<='9') |
3463 | 0 | { |
3464 | 0 | sp->pvp.pvi.u.ival = sp->pvp.pvi.u.ival * 10 + *p - '0'; |
3465 | 0 | p++; |
3466 | 0 | } |
3467 | 0 | if(p!=in->s+in->len) |
3468 | 0 | { |
3469 | 0 | LM_ERR("invalid index [%.*s]\n", in->len, in->s); |
3470 | 0 | return -1; |
3471 | 0 | } |
3472 | 0 | sp->pvp.pvi.u.ival *= sign; |
3473 | 0 | sp->pvp.pvi.type = PV_IDX_INT; |
3474 | |
|
3475 | 0 | return 0; |
3476 | 0 | } |
3477 | | |
3478 | | int pv_init_iname(pv_spec_p sp, int param) |
3479 | 108 | { |
3480 | 108 | if(sp==NULL) |
3481 | 0 | return -1; |
3482 | 108 | sp->pvp.pvn.type = PV_NAME_INTSTR; |
3483 | 108 | sp->pvp.pvn.u.isname.name.n = param; |
3484 | 108 | return 0; |
3485 | 108 | } |
3486 | | |
3487 | 10.7k | static int pv_get_line_number(struct sip_msg *msg, pv_param_t *param, pv_value_t *res){ |
3488 | 10.7k | int l; |
3489 | 10.7k | char *ch; |
3490 | | |
3491 | 10.7k | if (param==NULL) { |
3492 | 0 | LM_CRIT("BUG - bad parameters\n"); |
3493 | 0 | return -1; |
3494 | 0 | } |
3495 | | |
3496 | 10.7k | if(res == NULL) { |
3497 | 0 | return -1; |
3498 | 0 | } |
3499 | | |
3500 | 10.7k | res->ri = curr_action_line; |
3501 | 10.7k | ch = int2str( (unsigned long)res->ri, &l); |
3502 | | |
3503 | 10.7k | res->rs.s = ch; |
3504 | 10.7k | res->rs.len = l; |
3505 | | |
3506 | 10.7k | res->flags = PV_VAL_STR|PV_VAL_INT|PV_TYPE_INT; |
3507 | | |
3508 | 10.7k | return 0; |
3509 | 10.7k | } |
3510 | | |
3511 | 10.7k | static int pv_get_cfg_file_name(struct sip_msg *msg, pv_param_t *param, pv_value_t *res){ |
3512 | | |
3513 | 10.7k | if (param==NULL) { |
3514 | 0 | LM_CRIT("BUG - bad parameters\n"); |
3515 | 0 | return -1; |
3516 | 0 | } |
3517 | | |
3518 | 10.7k | if(res == NULL) { |
3519 | 0 | return -1; |
3520 | 0 | } |
3521 | | |
3522 | 10.7k | res->rs.s = curr_action_file; |
3523 | 10.7k | res->rs.len = (res->rs.s)?(strlen(res->rs.s)):(0); |
3524 | | |
3525 | 10.7k | res->flags = PV_VAL_STR; |
3526 | | |
3527 | 10.7k | return 0; |
3528 | 10.7k | } |
3529 | | |
3530 | | |
3531 | | static int pv_set_log_level(struct sip_msg* msg, pv_param_t *param, int op, |
3532 | | pv_value_t *val) |
3533 | 0 | { |
3534 | 0 | if(param==NULL) |
3535 | 0 | { |
3536 | 0 | LM_ERR("bad parameters\n"); |
3537 | 0 | return -1; |
3538 | 0 | } |
3539 | | |
3540 | 0 | if(val==NULL || (val->flags&(PV_VAL_NULL|PV_VAL_NONE))!=0) { |
3541 | | /* reset the value to default */ |
3542 | 0 | reset_proc_log_level(); |
3543 | 0 | } else { |
3544 | 0 | if ((val->flags&PV_TYPE_INT)==0) { |
3545 | 0 | LM_ERR("input for $log_level found not to be an integer\n"); |
3546 | 0 | return -1; |
3547 | 0 | } |
3548 | 0 | set_proc_log_level(val->ri); |
3549 | 0 | } |
3550 | | |
3551 | 0 | return 0; |
3552 | 0 | } |
3553 | | |
3554 | | static int pv_get_log_level(struct sip_msg *msg, pv_param_t *param, pv_value_t *res) |
3555 | 10.7k | { |
3556 | 10.7k | int l; |
3557 | | |
3558 | 10.7k | if (param==NULL) { |
3559 | 0 | LM_CRIT("BUG - bad parameters\n"); |
3560 | 0 | return -1; |
3561 | 0 | } |
3562 | | |
3563 | 10.7k | if(res == NULL) { |
3564 | 0 | return -1; |
3565 | 0 | } |
3566 | | |
3567 | 10.7k | res->ri = *log_level; |
3568 | 10.7k | res->rs.s = sint2str( (long)res->ri, &l); |
3569 | 10.7k | res->rs.len = l; |
3570 | | |
3571 | 10.7k | res->flags = PV_VAL_STR|PV_VAL_INT|PV_TYPE_INT; |
3572 | | |
3573 | 10.7k | return 0; |
3574 | 10.7k | } |
3575 | | |
3576 | | static int pv_set_xlog_level(struct sip_msg* msg, pv_param_t *param, int op, |
3577 | | pv_value_t *val) |
3578 | 0 | { |
3579 | 0 | if(param==NULL) |
3580 | 0 | { |
3581 | 0 | LM_ERR("bad parameters\n"); |
3582 | 0 | return -1; |
3583 | 0 | } |
3584 | | |
3585 | 0 | if(val==NULL || (val->flags&(PV_VAL_NULL|PV_VAL_NONE))!=0) { |
3586 | | /* reset the value to default */ |
3587 | 0 | reset_xlog_level(); |
3588 | 0 | } else { |
3589 | 0 | if ((val->flags&PV_TYPE_INT)==0) { |
3590 | 0 | LM_ERR("input for $xlog_level found not to be an integer\n"); |
3591 | 0 | return -1; |
3592 | 0 | } |
3593 | 0 | set_local_xlog_level( val->ri ); |
3594 | 0 | } |
3595 | | |
3596 | 0 | return 0; |
3597 | 0 | } |
3598 | | |
3599 | | static int pv_get_xlog_level(struct sip_msg *msg, pv_param_t *param, pv_value_t *res) |
3600 | 10.7k | { |
3601 | 10.7k | int l; |
3602 | | |
3603 | 10.7k | if (param==NULL) { |
3604 | 0 | LM_CRIT("BUG - bad parameters\n"); |
3605 | 0 | return -1; |
3606 | 0 | } |
3607 | | |
3608 | 10.7k | if(res == NULL) { |
3609 | 0 | return -1; |
3610 | 0 | } |
3611 | | |
3612 | 10.7k | res->ri = *xlog_level; |
3613 | 10.7k | res->rs.s = sint2str( (long)res->ri, &l); |
3614 | 10.7k | res->rs.len = l; |
3615 | | |
3616 | 10.7k | res->flags = PV_VAL_STR|PV_VAL_INT|PV_TYPE_INT; |
3617 | | |
3618 | 10.7k | return 0; |
3619 | 10.7k | } |
3620 | | |
3621 | | /************** Boolean consts *****************/ |
3622 | | |
3623 | | static const pv_value_t pv_true = { |
3624 | | .ri = 1, |
3625 | | .rs = str_init("true"), |
3626 | | .flags = PV_VAL_STR|PV_VAL_INT|PV_TYPE_INT, |
3627 | | }; |
3628 | | |
3629 | | |
3630 | | static const pv_value_t pv_false = { |
3631 | | .ri = 0, |
3632 | | .rs = str_init("false"), |
3633 | | .flags = PV_VAL_STR|PV_VAL_INT|PV_TYPE_INT, |
3634 | | }; |
3635 | | |
3636 | | |
3637 | | /************** MSG FLAGS function *****************/ |
3638 | | |
3639 | | static int msg_flag_parse_name(pv_spec_p sp, const str *in) |
3640 | 0 | { |
3641 | 0 | unsigned int idx; |
3642 | 0 | if (sp==NULL || in==NULL || in->s==NULL || in->len==0) |
3643 | 0 | return -1; |
3644 | | |
3645 | 0 | if ( (idx=fixup_flag(FLAG_TYPE_MSG, in))==NAMED_FLAG_ERROR) { |
3646 | 0 | LM_ERR("failed to fix the flag <%.*s>\n",in->len,in->s); |
3647 | 0 | return -1; |
3648 | 0 | } |
3649 | | |
3650 | 0 | sp->pvp.pvn.type = PV_NAME_INTSTR; |
3651 | 0 | sp->pvp.pvn.u.isname.type = 0; |
3652 | |
|
3653 | 0 | sp->pvp.pvn.u.isname.name.n = idx; |
3654 | |
|
3655 | 0 | return 0; |
3656 | 0 | } |
3657 | | |
3658 | | |
3659 | | static int msg_flag_set(struct sip_msg* msg, pv_param_t *param, int op, |
3660 | | pv_value_t *val) |
3661 | 0 | { |
3662 | 0 | if(param==NULL) { |
3663 | 0 | LM_ERR("bad parameters\n"); |
3664 | 0 | return -1; |
3665 | 0 | } |
3666 | | |
3667 | 0 | if (val==NULL || (val->flags&(PV_VAL_NULL|PV_VAL_NONE))!=0 || |
3668 | 0 | (val->flags&PV_TYPE_INT)==0 ) { |
3669 | 0 | LM_ERR("input for $msg.flag() found not to be an integer\n"); |
3670 | 0 | return -1; |
3671 | 0 | } |
3672 | | |
3673 | 0 | if (val->ri==0) |
3674 | 0 | resetflag (msg, (unsigned int)param->pvn.u.isname.name.n); |
3675 | 0 | else |
3676 | 0 | setflag( msg, (unsigned int)param->pvn.u.isname.name.n); |
3677 | |
|
3678 | 0 | return 0; |
3679 | 0 | } |
3680 | | |
3681 | | |
3682 | | static int msg_flag_get(struct sip_msg *msg, pv_param_t *param, pv_value_t *res) |
3683 | 0 | { |
3684 | 0 | if (param==NULL||res==NULL) { |
3685 | 0 | LM_CRIT("BUG - bad parameters\n"); |
3686 | 0 | return -1; |
3687 | 0 | } |
3688 | | |
3689 | 0 | if ( isflagset( msg, (unsigned int)param->pvn.u.isname.name.n)==1 ) { |
3690 | 0 | *res = pv_true; |
3691 | 0 | } else { |
3692 | 0 | *res = pv_false; |
3693 | 0 | } |
3694 | 0 | return 0; |
3695 | 0 | } |
3696 | | |
3697 | | |
3698 | | /************** MSG TYPE function *****************/ |
3699 | | |
3700 | | static int msg_is_request_get(struct sip_msg *msg, pv_param_t *param, pv_value_t *res) |
3701 | 10.7k | { |
3702 | 10.7k | if (param==NULL||res==NULL) { |
3703 | 0 | LM_CRIT("BUG - bad parameters\n"); |
3704 | 0 | return -1; |
3705 | 0 | } |
3706 | | |
3707 | 10.7k | if ( msg->first_line.type==SIP_REQUEST ) { |
3708 | 10.7k | *res = pv_true; |
3709 | 10.7k | } else { |
3710 | 4 | *res = pv_false; |
3711 | 4 | } |
3712 | 10.7k | return 0; |
3713 | 10.7k | } |
3714 | | |
3715 | | |
3716 | | static int msg_type_get(struct sip_msg *msg, pv_param_t *param, pv_value_t *res) |
3717 | 10.7k | { |
3718 | 10.7k | if (param==NULL||res==NULL) { |
3719 | 0 | LM_CRIT("BUG - bad parameters\n"); |
3720 | 0 | return -1; |
3721 | 0 | } |
3722 | | |
3723 | 10.7k | if ( msg->first_line.type==SIP_REQUEST ) { |
3724 | 10.7k | res->rs.s = "request"; |
3725 | 10.7k | res->rs.len = 7; |
3726 | 10.7k | } else { |
3727 | 4 | res->rs.s = "reply"; |
3728 | 4 | res->rs.len = 5; |
3729 | 4 | } |
3730 | | |
3731 | 10.7k | res->flags = PV_VAL_STR; |
3732 | | |
3733 | 10.7k | return 0; |
3734 | 10.7k | } |
3735 | | |
3736 | | |
3737 | | |
3738 | | /************** BRANCH FLAGS function *****************/ |
3739 | | |
3740 | | static int branch_flag_parse_name(pv_spec_p sp, const str *in) |
3741 | 0 | { |
3742 | 0 | unsigned int idx; |
3743 | 0 | if (sp==NULL || in==NULL || in->s==NULL || in->len==0) |
3744 | 0 | return -1; |
3745 | | |
3746 | 0 | if ( (idx=fixup_flag(FLAG_TYPE_BRANCH, in))==NAMED_FLAG_ERROR) { |
3747 | 0 | LM_ERR("failed to fix the flag <%.*s>\n",in->len,in->s); |
3748 | 0 | return -1; |
3749 | 0 | } |
3750 | | |
3751 | 0 | sp->pvp.pvn.type = PV_NAME_INTSTR; |
3752 | 0 | sp->pvp.pvn.u.isname.type = 0; |
3753 | |
|
3754 | 0 | sp->pvp.pvn.u.isname.name.n = idx; |
3755 | |
|
3756 | 0 | return 0; |
3757 | 0 | } |
3758 | | |
3759 | | |
3760 | | static int branch_flag_set(struct sip_msg* msg, pv_param_t *param, int op, |
3761 | | pv_value_t *val) |
3762 | 0 | { |
3763 | 0 | int idx; |
3764 | 0 | int idxf; |
3765 | |
|
3766 | 0 | if(param==NULL) { |
3767 | 0 | LM_ERR("bad parameters\n"); |
3768 | 0 | return -1; |
3769 | 0 | } |
3770 | | |
3771 | 0 | if (val==NULL || (val->flags&(PV_VAL_NULL|PV_VAL_NONE))!=0 || |
3772 | 0 | (val->flags&PV_TYPE_INT)==0 ) { |
3773 | 0 | LM_ERR("input for $branch.flag() found not to be an integer\n"); |
3774 | 0 | return -1; |
3775 | 0 | } |
3776 | | |
3777 | | /* get the index */ |
3778 | 0 | if (pv_get_spec_index(msg, param, &idx, &idxf)!=0) { |
3779 | 0 | LM_ERR("invalid index\n"); |
3780 | 0 | return -1; |
3781 | 0 | } |
3782 | | |
3783 | 0 | if(idxf==PV_IDX_ALL) { |
3784 | 0 | LM_ERR("SCRIPT BUG - * not allowed in branch flag assignment\n"); |
3785 | 0 | return -1; |
3786 | 0 | } |
3787 | | |
3788 | 0 | if (idx<0) { |
3789 | 0 | idx = get_nr_branches() + idx; |
3790 | 0 | } |
3791 | |
|
3792 | 0 | if (idx<0 || idx>=get_nr_branches()) { |
3793 | 0 | LM_DBG("inexisting branch flag assignment [%d/%d]\n", |
3794 | 0 | get_nr_branches(), idx); |
3795 | 0 | return -1; |
3796 | 0 | } |
3797 | | |
3798 | 0 | if (val->ri==0) |
3799 | 0 | resetbflag (msg, idx, param->pvn.u.isname.name.n); |
3800 | 0 | else |
3801 | 0 | setbflag( msg, idx, param->pvn.u.isname.name.n); |
3802 | |
|
3803 | 0 | return 0; |
3804 | 0 | } |
3805 | | |
3806 | | |
3807 | | static int branch_flag_get(struct sip_msg *msg, pv_param_t *param, pv_value_t *res) |
3808 | 0 | { |
3809 | 0 | int idx; |
3810 | 0 | int idxf; |
3811 | |
|
3812 | 0 | if (param==NULL||res==NULL) { |
3813 | 0 | LM_CRIT("BUG - bad parameters\n"); |
3814 | 0 | return -1; |
3815 | 0 | } |
3816 | | |
3817 | | /* get the index */ |
3818 | 0 | if (pv_get_spec_index(msg, param, &idx, &idxf)!=0) { |
3819 | 0 | LM_ERR("invalid index\n"); |
3820 | 0 | return -1; |
3821 | 0 | } |
3822 | | |
3823 | 0 | if(idxf==PV_IDX_ALL) { |
3824 | 0 | LM_ERR("SCRIPT BUG - * not allowed in branch flag reading\n"); |
3825 | 0 | return -1; |
3826 | 0 | } |
3827 | | |
3828 | 0 | if (idx<0) { |
3829 | 0 | idx = get_nr_branches() + idx; |
3830 | 0 | } |
3831 | |
|
3832 | 0 | if (idx<0 || idx>=get_nr_branches()) { |
3833 | 0 | LM_DBG("inexisting branch flag reading [%d/%d]\n", |
3834 | 0 | get_nr_branches(), idx); |
3835 | 0 | return -1; |
3836 | 0 | } |
3837 | | |
3838 | 0 | if ( isbflagset( msg, idx, param->pvn.u.isname.name.n)==1 ) { |
3839 | 0 | *res = pv_true; |
3840 | 0 | } else { |
3841 | 0 | *res = pv_false; |
3842 | 0 | } |
3843 | 0 | return 0; |
3844 | 0 | } |
3845 | | |
3846 | | |
3847 | | /********** generic helper functions ***************/ |
3848 | | |
3849 | | /** |
3850 | | * the table with core pseudo-variables |
3851 | | */ |
3852 | | #ifndef FUZZ_BUILD |
3853 | | static |
3854 | | #endif |
3855 | | const pv_export_t _pv_names_table[] = { |
3856 | | {str_const_init("avp"), PVT_AVP, pv_get_avp, pv_set_avp, |
3857 | | pv_parse_avp_name, pv_parse_avp_index, 0, 0}, |
3858 | | {str_const_init("hdr"), PVT_HDR, pv_get_hdr, 0, pv_parse_hdr_name, |
3859 | | pv_parse_index, 0, 0}, |
3860 | | {str_const_init("hdr_name"), PVT_HDR_NAME, pv_get_hdr_name, 0, 0, |
3861 | | pv_parse_index, 0, 0}, |
3862 | | {str_const_init("hdrcnt"), PVT_HDRCNT, pv_get_hdrcnt, 0, pv_parse_hdr_name, 0, 0, 0}, |
3863 | | {str_const_init("var"), PVT_SCRIPTVAR, pv_get_scriptvar, |
3864 | | pv_set_scriptvar, pv_parse_scriptvar_name, 0, 0, 0}, |
3865 | | {str_const_init("ai"), /* */ |
3866 | | PVT_PAI_URI, pv_get_pai, 0, |
3867 | | 0, 0, 0, 0}, |
3868 | | {str_const_init("au"), /* */ |
3869 | | PVT_AUTH_USERNAME, pv_get_authattr, 0, |
3870 | | 0, 0, pv_init_iname, 1}, |
3871 | | {str_const_init("ar"), /* auth realm */ |
3872 | | PVT_AUTH_REALM, pv_get_authattr, 0, |
3873 | | 0, 0, pv_init_iname, 2}, |
3874 | | {str_const_init("adu"), /* auth digest uri */ |
3875 | | PVT_AUTH_DURI, pv_get_authattr, 0, |
3876 | | 0, 0, pv_init_iname, 3}, |
3877 | | {str_const_init("ad"), /* */ |
3878 | | PVT_AUTH_DOMAIN, pv_get_authattr, 0, |
3879 | | 0, 0, pv_init_iname, 4}, |
3880 | | {str_const_init("an"), /* */ |
3881 | | PVT_AUTH_NONCE, pv_get_authattr, 0, |
3882 | | 0, 0, pv_init_iname, 5}, |
3883 | | {str_const_init("auth.nonce"), /* */ |
3884 | | PVT_AUTH_NONCE, pv_get_authattr, 0, |
3885 | | 0, 0, pv_init_iname, 5}, |
3886 | | {str_const_init("auth.resp"), /* */ |
3887 | | PVT_AUTH_RESPONSE, pv_get_authattr, 0, |
3888 | | 0, 0, pv_init_iname, 6}, |
3889 | | {str_const_init("auth.cnonce"), /* */ |
3890 | | PVT_AUTH_CNONCE, pv_get_authattr, 0, |
3891 | | 0, 0, pv_init_iname, 7}, |
3892 | | {str_const_init("auth.opaque"), /* */ |
3893 | | PVT_AUTH_OPAQUE, pv_get_authattr, 0, |
3894 | | 0, 0, pv_init_iname, 8}, |
3895 | | {str_const_init("auth.alg"), /* */ |
3896 | | PVT_AUTH_ALGORITHM, pv_get_authattr, 0, |
3897 | | 0, 0, pv_init_iname, 9}, |
3898 | | {str_const_init("auth.qop"), /* */ |
3899 | | PVT_AUTH_QOP, pv_get_authattr, 0, |
3900 | | 0, 0, pv_init_iname, 10}, |
3901 | | {str_const_init("auth.nc"), /* */ |
3902 | | PVT_AUTH_NONCE_COUNT, pv_get_authattr, 0, |
3903 | | 0, 0, pv_init_iname, 11}, |
3904 | | {str_const_init("aU"), /* */ |
3905 | | PVT_AUTH_USERNAME_WHOLE, pv_get_authattr, 0, |
3906 | | 0, 0, pv_init_iname, 99}, |
3907 | | {str_const_init("Au"), /* */ |
3908 | | PVT_ACC_USERNAME, pv_get_acc_username, 0, |
3909 | | 0, 0, pv_init_iname, 1}, |
3910 | | {str_const_init("bf"), /* */ |
3911 | | PVT_BFLAGS, pv_get_bflags, 0, |
3912 | | 0, 0, 0, 0}, |
3913 | | {str_const_init("branch"), /* */ |
3914 | | PVT_BRANCH, pv_get_branch_fields, pv_set_branch, |
3915 | | 0, 0, 0, 0}, |
3916 | | {str_const_init("branch"), /* */ |
3917 | | PVT_BRANCH, pv_get_branch_fields, pv_set_branch_fields, |
3918 | | pv_parse_branch_name, pv_parse_index, 0, 0}, |
3919 | | {str_const_init("branch.flag"), /* */ |
3920 | | PVT_BRANCH_FLAG, branch_flag_get, branch_flag_set, |
3921 | | branch_flag_parse_name, pv_parse_index, 0, 0}, |
3922 | | {str_const_init("ci"), /* */ |
3923 | | PVT_CALLID, pv_get_callid, 0, |
3924 | | 0, 0, 0, 0}, |
3925 | | {str_const_init("cl"), /* */ |
3926 | | PVT_CONTENT_LENGTH, pv_get_content_length, 0, |
3927 | | 0, 0, 0, 0}, |
3928 | | {str_const_init("cs"), /* */ |
3929 | | PVT_CSEQ, pv_get_cseq, 0, |
3930 | | 0, 0, 0, 0}, |
3931 | | {str_const_init("ct"), /* */ |
3932 | | PVT_CONTACT, pv_get_contact_body, 0, |
3933 | | 0, pv_parse_index, 0, 0}, |
3934 | | {str_const_init("ct.fields"), /* */ |
3935 | | PVT_CONTACT, pv_get_contact_body, 0, |
3936 | | pv_parse_ct_name, pv_parse_index, 0, 0}, |
3937 | | {str_const_init("cT"), /* */ |
3938 | | PVT_CONTENT_TYPE, pv_get_content_type, 0, |
3939 | | 0, pv_parse_index, 0, 0}, |
3940 | | {str_const_init("dd"), /* */ |
3941 | | PVT_DSTURI_DOMAIN, pv_get_dsturi_attr, pv_set_dsturi_host, |
3942 | | 0, 0, pv_init_iname, 1}, |
3943 | | {str_const_init("di"), /* */ |
3944 | | PVT_DIVERSION_URI, pv_get_diversion, 0, |
3945 | | 0, 0, pv_init_iname, 1}, |
3946 | | {str_const_init("dir"), /* */ |
3947 | | PVT_DIV_REASON, pv_get_diversion, 0, |
3948 | | 0, 0, pv_init_iname, 2}, |
3949 | | {str_const_init("dip"), /* */ |
3950 | | PVT_DIV_PRIVACY, pv_get_diversion, 0, |
3951 | | 0, 0, pv_init_iname, 3}, |
3952 | | {str_const_init("dp"), /* */ |
3953 | | PVT_DSTURI_PORT, pv_get_dsturi_attr, pv_set_dsturi_port, |
3954 | | 0, 0, pv_init_iname, 2}, |
3955 | | {str_const_init("dP"), /* */ |
3956 | | PVT_DSTURI_PROTOCOL, pv_get_dsturi_attr, 0, |
3957 | | 0, 0, pv_init_iname, 3}, |
3958 | | {str_const_init("ds"), /* */ |
3959 | | PVT_DSET, pv_get_dset, 0, |
3960 | | 0, 0, 0, 0}, |
3961 | | {str_const_init("du"), /* */ |
3962 | | PVT_DSTURI, pv_get_dsturi, pv_set_dsturi, |
3963 | | 0, 0, 0, 0}, |
3964 | | {str_const_init("duri"), /* */ |
3965 | | PVT_DSTURI, pv_get_dsturi, pv_set_dsturi, |
3966 | | 0, 0, 0, 0}, |
3967 | | {str_const_init("err.class"), /* */ |
3968 | | PVT_ERR_CLASS, pv_get_errinfo_attr, 0, |
3969 | | 0, 0, 0, 0}, |
3970 | | {str_const_init("err.level"), /* */ |
3971 | | PVT_ERR_LEVEL, pv_get_errinfo_attr, 0, |
3972 | | 0, 0, pv_init_iname, 1}, |
3973 | | {str_const_init("err.info"), /* */ |
3974 | | PVT_ERR_INFO, pv_get_errinfo_attr, 0, |
3975 | | 0, 0, pv_init_iname, 2}, |
3976 | | {str_const_init("err.rcode"), /* */ |
3977 | | PVT_ERR_RCODE, pv_get_errinfo_attr, 0, |
3978 | | 0, 0, pv_init_iname, 3}, |
3979 | | {str_const_init("err.rreason"), /* */ |
3980 | | PVT_ERR_RREASON, pv_get_errinfo_attr, 0, |
3981 | | 0, 0, pv_init_iname, 4}, |
3982 | | {str_const_init("fd"), /* */ |
3983 | | PVT_FROM_DOMAIN, pv_get_from_attr, 0, |
3984 | | 0, 0, pv_init_iname, 3}, |
3985 | | {str_const_init("from.domain"), /* */ |
3986 | | PVT_FROM_DOMAIN, pv_get_from_attr, 0, |
3987 | | 0, 0, pv_init_iname, 3}, |
3988 | | {str_const_init("fn"), /* */ |
3989 | | PVT_FROM_DISPLAYNAME, pv_get_from_attr, 0, |
3990 | | 0, 0, pv_init_iname, 5}, |
3991 | | {str_const_init("ft"), /* */ |
3992 | | PVT_FROM_TAG, pv_get_from_attr, 0, |
3993 | | 0, 0, pv_init_iname, 4}, |
3994 | | {str_const_init("fu"), /* */ |
3995 | | PVT_FROM, pv_get_from_attr, 0, |
3996 | | 0, 0, pv_init_iname, 1}, |
3997 | | {str_const_init("from"), /* */ |
3998 | | PVT_FROM, pv_get_from_attr, 0, |
3999 | | 0, 0, pv_init_iname, 1}, |
4000 | | {str_const_init("fU"), /* */ |
4001 | | PVT_FROM_USERNAME, pv_get_from_attr, 0, |
4002 | | 0, 0, pv_init_iname, 2}, |
4003 | | {str_const_init("from.user"), /* */ |
4004 | | PVT_FROM_USERNAME, pv_get_from_attr, 0, |
4005 | | 0, 0, pv_init_iname, 2}, |
4006 | | {str_const_init("log_level"), /* per process log level*/ |
4007 | | PVT_LOG_LEVEL, pv_get_log_level, pv_set_log_level, |
4008 | | 0, 0, 0, 0}, |
4009 | | {str_const_init("mb"), /* */ |
4010 | | PVT_MSG_BUF, pv_get_msg_buf, 0, |
4011 | | 0, 0, 0, 0}, |
4012 | | {str_const_init("mf"), /* */ |
4013 | | PVT_FLAGS, pv_get_flags, 0, |
4014 | | 0, 0, 0, 0}, |
4015 | | {str_const_init("msg.flag"), /* */ |
4016 | | PVT_MSG_FLAG, msg_flag_get, msg_flag_set, |
4017 | | msg_flag_parse_name, 0, 0, 0}, |
4018 | | {str_const_init("msg.is_request"), /* */ |
4019 | | PVT_MSG_FLAG, msg_is_request_get, 0, |
4020 | | 0, 0, 0, 0}, |
4021 | | {str_const_init("msg.type"), /* */ |
4022 | | PVT_MSG_FLAG, msg_type_get, 0, |
4023 | | 0, 0, 0, 0}, |
4024 | | {str_const_init("mi"), /* */ |
4025 | | PVT_MSGID, pv_get_msgid, 0, |
4026 | | 0, 0, 0, 0}, |
4027 | | {str_const_init("ml"), /* */ |
4028 | | PVT_MSG_LEN, pv_get_msg_len, 0, |
4029 | | 0, 0, 0, 0}, |
4030 | | {str_const_init("od"), /* */ |
4031 | | PVT_OURI_DOMAIN, pv_get_ouri_attr, 0, |
4032 | | 0, 0, pv_init_iname, 2}, |
4033 | | {str_const_init("op"), /* */ |
4034 | | PVT_OURI_PORT, pv_get_ouri_attr, 0, |
4035 | | 0, 0, pv_init_iname, 3}, |
4036 | | {str_const_init("oP"), /* */ |
4037 | | PVT_OURI_PROTOCOL, pv_get_ouri_attr, 0, |
4038 | | 0, 0, pv_init_iname, 4}, |
4039 | | {str_const_init("ou"), /* */ |
4040 | | PVT_OURI, pv_get_ouri, 0, |
4041 | | 0, 0, 0, 0}, |
4042 | | {str_const_init("ouri"), /* */ |
4043 | | PVT_OURI, pv_get_ouri, 0, |
4044 | | 0, 0, 0, 0}, |
4045 | | {str_const_init("oU"), /* */ |
4046 | | PVT_OURI_USERNAME, pv_get_ouri_attr, 0, |
4047 | | 0, 0, pv_init_iname, 1}, |
4048 | | {str_const_init("path"), /* */ |
4049 | | PVT_PATH, pv_get_path, 0, |
4050 | | 0, 0, 0, 0}, |
4051 | | {str_const_init("pd"), /* */ |
4052 | | PVT_PPI_DOMAIN, pv_get_ppi_attr, 0, |
4053 | | 0, 0, pv_init_iname, 3}, |
4054 | | {str_const_init("pn"), /* */ |
4055 | | PVT_PPI_DISPLAYNAME, pv_get_ppi_attr, 0, |
4056 | | 0, 0, pv_init_iname, 4}, |
4057 | | {str_const_init("pp"), /* */ |
4058 | | PVT_PID, pv_get_pid, 0, |
4059 | | 0, 0, 0, 0}, |
4060 | | {str_const_init("pu"), /* */ |
4061 | | PVT_PPI, pv_get_ppi_attr, 0, |
4062 | | 0, 0, pv_init_iname, 1}, |
4063 | | {str_const_init("pU"), /* */ |
4064 | | PVT_PPI_USERNAME, pv_get_ppi_attr, 0, |
4065 | | 0, 0, pv_init_iname, 2}, |
4066 | | {str_const_init("rb"), /* */ |
4067 | | PVT_MSG_BODY, pv_get_msg_body, 0, |
4068 | | 0, pv_parse_index, 0, 0}, |
4069 | | {str_const_init("rb"), /* */ |
4070 | | PVT_MSG_BODY, pv_get_msg_body, 0, |
4071 | | pv_parse_rb_name, pv_parse_index, 0, 0}, |
4072 | | {str_const_init("rc"), /* */ |
4073 | | PVT_RETURN_CODE, pv_get_return_code, 0, |
4074 | | 0, 0, 0, 0}, |
4075 | | {str_const_init("retcode"), /* */ |
4076 | | PVT_RETURN_CODE, pv_get_return_code, 0, |
4077 | | 0, 0, 0, 0}, |
4078 | | {str_const_init("rd"), /* */ |
4079 | | PVT_RURI_DOMAIN, pv_get_ruri_attr, pv_set_ruri_host, |
4080 | | 0, 0, pv_init_iname, 2}, |
4081 | | {str_const_init("ruri.domain"), /* */ |
4082 | | PVT_RURI_DOMAIN, pv_get_ruri_attr, pv_set_ruri_host, |
4083 | | 0, 0, pv_init_iname, 2}, |
4084 | | {str_const_init("re"), /* */ |
4085 | | PVT_RPID_URI, pv_get_rpid, 0, |
4086 | | 0, 0, 0, 0}, |
4087 | | {str_const_init("rm"), /* */ |
4088 | | PVT_METHOD, pv_get_method, 0, |
4089 | | 0, 0, 0, 0}, |
4090 | | {str_const_init("route"), /* */ |
4091 | | PVT_ROUTE, pv_get_route, 0, |
4092 | | 0, pv_parse_index, 0, 0}, |
4093 | | {str_const_init("route.name"), /* */ |
4094 | | PVT_ROUTE_NAME, pv_get_route_name, 0, |
4095 | | 0, pv_parse_index, 0, 0}, |
4096 | | {str_const_init("route.type"), /* */ |
4097 | | PVT_ROUTE_TYPE, pv_get_route_type, 0, |
4098 | | 0, pv_parse_index, 0, 0}, |
4099 | | {str_const_init("rp"), /* */ |
4100 | | PVT_RURI_PORT, pv_get_ruri_attr, pv_set_ruri_port, |
4101 | | 0, 0, pv_init_iname, 3}, |
4102 | | {str_const_init("rP"), /* */ |
4103 | | PVT_RURI_PROTOCOL, pv_get_ruri_attr, 0, |
4104 | | 0, 0, pv_init_iname, 4}, |
4105 | | {str_const_init("rr"), /* */ |
4106 | | PVT_REASON, pv_get_reason, 0, |
4107 | | 0, 0, 0, 0}, |
4108 | | {str_const_init("rs"), /* */ |
4109 | | PVT_STATUS, pv_get_status, 0, |
4110 | | 0, 0, 0, 0}, |
4111 | | {str_const_init("rt"), /* */ |
4112 | | PVT_REFER_TO, pv_get_refer_to, 0, |
4113 | | 0, 0, 0, 0}, |
4114 | | {str_const_init("ru"), /* */ |
4115 | | PVT_RURI, pv_get_ruri, pv_set_ruri, |
4116 | | 0, 0, 0, 0}, |
4117 | | {str_const_init("ruri"), /* */ |
4118 | | PVT_RURI, pv_get_ruri, pv_set_ruri, |
4119 | | 0, 0, 0, 0}, |
4120 | | {str_const_init("ru_q"), /* */ |
4121 | | PVT_RU_Q, pv_get_ru_q, pv_set_ru_q, |
4122 | | 0, 0, 0, 0}, |
4123 | | {str_const_init("rU"), /* */ |
4124 | | PVT_RURI_USERNAME, pv_get_ruri_attr, pv_set_ruri_user, |
4125 | | 0, 0, pv_init_iname, 1}, |
4126 | | {str_const_init("ruri.user"), /* */ |
4127 | | PVT_RURI_USERNAME, pv_get_ruri_attr, pv_set_ruri_user, |
4128 | | 0, 0, pv_init_iname, 1}, |
4129 | | {str_const_init("src_ip"), /* */ |
4130 | | PVT_SRCIP, pv_get_srcip, 0, |
4131 | | 0, 0, 0, 0}, |
4132 | | {str_const_init("socket_in"), /* */ |
4133 | | PVT_SOCKET_IN, pv_get_socket_in_fields, NULL, |
4134 | | 0, 0, 0, 0}, |
4135 | | {str_const_init("socket_in"), /* */ |
4136 | | PVT_SOCKET_IN, pv_get_socket_in_fields, NULL, |
4137 | | pv_parse_socket_name, 0, 0, 0}, |
4138 | | {str_const_init("socket_out"), /* */ |
4139 | | PVT_SOCKET_OUT, pv_get_socket_out_fields, pv_set_force_sock, |
4140 | | 0, 0, 0, 0}, |
4141 | | {str_const_init("socket_out"), /* */ |
4142 | | PVT_SOCKET_OUT, pv_get_socket_out_fields, NULL, |
4143 | | pv_parse_socket_name, 0, 0, 0}, |
4144 | | {str_const_init("si"), /* */ |
4145 | | PVT_SRCIP, pv_get_srcip, 0, |
4146 | | 0, 0, 0, 0}, |
4147 | | {str_const_init("sp"), /* */ |
4148 | | PVT_SRCPORT, pv_get_srcport, 0, |
4149 | | 0, 0, 0, 0}, |
4150 | | {str_const_init("td"), /* */ |
4151 | | PVT_TO_DOMAIN, pv_get_to_attr, 0, |
4152 | | 0, 0, pv_init_iname, 3}, |
4153 | | {str_const_init("to.domain"), /* */ |
4154 | | PVT_TO_DOMAIN, pv_get_to_attr, 0, |
4155 | | 0, 0, pv_init_iname, 3}, |
4156 | | {str_const_init("time"), /* */ |
4157 | | PVT_TIME, pv_get_formated_time, 0, |
4158 | | pv_parse_time_name, 0, 0, 0}, |
4159 | | {str_const_init("tn"), /* */ |
4160 | | PVT_TO_DISPLAYNAME, pv_get_to_attr, 0, |
4161 | | 0, 0, pv_init_iname, 5}, |
4162 | | {str_const_init("tt"), /* */ |
4163 | | PVT_TO_TAG, pv_get_to_attr, 0, |
4164 | | 0, 0, pv_init_iname, 4}, |
4165 | | {str_const_init("tu"), /* */ |
4166 | | PVT_TO, pv_get_to_attr, 0, |
4167 | | 0, 0, pv_init_iname, 1}, |
4168 | | {str_const_init("to"), /* */ |
4169 | | PVT_TO, pv_get_to_attr, 0, |
4170 | | 0, 0, pv_init_iname, 1}, |
4171 | | {str_const_init("tU"), /* */ |
4172 | | PVT_TO_USERNAME, pv_get_to_attr, 0, |
4173 | | 0, 0, pv_init_iname, 2}, |
4174 | | {str_const_init("to.user"), /* */ |
4175 | | PVT_TO_USERNAME, pv_get_to_attr, 0, |
4176 | | 0, 0, pv_init_iname, 2}, |
4177 | | {str_const_init("Tf"), /* */ |
4178 | | PVT_TIMEF, pv_get_timef, 0, |
4179 | | 0, 0, 0, 0}, |
4180 | | {str_const_init("Ts"), /* */ |
4181 | | PVT_TIMES, pv_get_times, 0, |
4182 | | 0, 0, 0, 0}, |
4183 | | {str_const_init("Tsm"), /* */ |
4184 | | PVT_TIMES, pv_get_timem, 0, |
4185 | | 0, 0, 0, 0}, |
4186 | | {str_const_init("TS"), /* */ |
4187 | | PVT_TIMES, pv_get_start_times, 0, |
4188 | | 0, 0, 0, 0}, |
4189 | | {str_const_init("ua"), /* */ |
4190 | | PVT_USERAGENT, pv_get_useragent, 0, |
4191 | | 0, 0, 0, 0}, |
4192 | | {str_const_init("C"), PVT_COLOR, pv_get_color, 0, |
4193 | | pv_parse_color_name, 0, 0, 0 }, |
4194 | | {str_const_init("argv"), PVT_ARGV, pv_get_argv, 0, |
4195 | | pv_parse_argv_name, 0, 0, 0 }, |
4196 | | {str_const_init("param"), PVT_ROUTE_PARAM, pv_get_param, 0, |
4197 | | pv_parse_param_name, 0, 0, 0 }, |
4198 | | {str_const_init("cfg_line"), PVT_LINE_NUMBER, pv_get_line_number, 0, |
4199 | | 0, 0, 0, 0 }, |
4200 | | {str_const_init("cfg_file"), PVT_CFG_FILE_NAME, pv_get_cfg_file_name, 0, |
4201 | | 0, 0, 0, 0 }, |
4202 | | {str_const_init("xlog_level"), PVT_XLOG_LEVEL, pv_get_xlog_level, |
4203 | | pv_set_xlog_level, 0, 0, 0, 0 }, |
4204 | | {{0,0}, 0, 0, 0, 0, 0, 0, 0} |
4205 | | }; |
4206 | | |
4207 | | static const pv_export_t* pv_lookup_spec_name(str *pvname, pv_spec_p e, int has_name) |
4208 | 240 | { |
4209 | 240 | int i; |
4210 | 240 | pv_extra_p pvi; |
4211 | 240 | int found; |
4212 | | |
4213 | 240 | if(pvname==0 || e==0) |
4214 | 0 | { |
4215 | 0 | LM_ERR("bad parameters\n"); |
4216 | 0 | return NULL; |
4217 | 0 | } |
4218 | | /* search in main table */ |
4219 | 16.0k | for(i=0; _pv_names_table[i].name.s!=0; i++) |
4220 | 16.0k | { |
4221 | 16.0k | if(_pv_names_table[i].name.len==pvname->len |
4222 | 16.0k | && !((has_name?1:0) ^ (_pv_names_table[i].parse_name?1:0)) |
4223 | 16.0k | && memcmp(_pv_names_table[i].name.s, pvname->s, pvname->len)==0) |
4224 | 218 | { |
4225 | | /*LM_DBG("found [%.*s] [%d]\n", pvname->len, pvname->s, |
4226 | | _pv_names_table[i].type);*/ |
4227 | | /* copy data from table to spec */ |
4228 | 218 | e->type = _pv_names_table[i].type; |
4229 | 218 | e->getf = _pv_names_table[i].getf; |
4230 | 218 | e->setf = _pv_names_table[i].setf; |
4231 | 218 | return &_pv_names_table[i]; |
4232 | 218 | } |
4233 | 16.0k | } |
4234 | | /* search in extra list */ |
4235 | 22 | if(_pv_extra_list==0) |
4236 | 22 | { |
4237 | 22 | LM_DBG("extra items list is empty\n"); |
4238 | 22 | return NULL; |
4239 | 22 | } |
4240 | 0 | pvi = *_pv_extra_list; |
4241 | 0 | while(pvi) |
4242 | 0 | { |
4243 | 0 | if(pvi->pve.name.len>pvname->len) |
4244 | 0 | break; |
4245 | 0 | if(pvi->pve.name.len==pvname->len) |
4246 | 0 | { |
4247 | 0 | found = strncmp(pvi->pve.name.s, pvname->s, pvname->len); |
4248 | 0 | if(found>0) |
4249 | 0 | break; |
4250 | 0 | if(found==0) |
4251 | 0 | { |
4252 | 0 | LM_DBG("found in extra list [%.*s]\n", pvname->len, pvname->s); |
4253 | | /* copy data from export to spec */ |
4254 | 0 | e->type = pvi->pve.type; |
4255 | 0 | e->getf = pvi->pve.getf; |
4256 | 0 | e->setf = pvi->pve.setf; |
4257 | 0 | return &(pvi->pve); |
4258 | 0 | } |
4259 | 0 | } |
4260 | 0 | pvi = pvi->next; |
4261 | 0 | } |
4262 | | |
4263 | 0 | return NULL; |
4264 | 0 | } |
4265 | | |
4266 | | static int is_pv_valid_char(char c) |
4267 | 1.07k | { |
4268 | 1.07k | if((c>='0' && c<='9') || (c>='a' && c<='z') || (c>='A' && c<='Z') |
4269 | 1.07k | || (c=='_') || (c=='.')) |
4270 | 1.07k | return 1; |
4271 | 0 | return 0; |
4272 | 1.07k | } |
4273 | | |
4274 | | char* pv_parse_spec(const str *in, const pv_spec_p e) |
4275 | 240 | { |
4276 | 240 | char *p; |
4277 | 240 | str s; |
4278 | 240 | str pvname; |
4279 | 240 | str pvcontext; |
4280 | 240 | int pvstate; |
4281 | 240 | int has_inner_name; |
4282 | 240 | trans_t *tr = NULL; |
4283 | 240 | const pv_export_t *pte = NULL; |
4284 | 240 | int n=0; |
4285 | | |
4286 | 240 | if(in==NULL || in->s==NULL || e==NULL || *in->s!=PV_MARKER) |
4287 | 0 | { |
4288 | 0 | LM_ERR("bad parameters\n"); |
4289 | 0 | return NULL; |
4290 | 0 | } |
4291 | | |
4292 | | // LM_DBG("***** input [%.*s] (%d)\n", in->len, in->s, in->len); |
4293 | 240 | tr = 0; |
4294 | 240 | pvstate = 0; |
4295 | 240 | memset(e, 0, sizeof(pv_spec_t)); |
4296 | 240 | p = in->s; |
4297 | 240 | p++; |
4298 | 240 | if(*p==PV_LNBRACKET) |
4299 | 0 | { |
4300 | 0 | p++; |
4301 | 0 | pvstate = 1; |
4302 | 0 | } |
4303 | 240 | pvname.s = p; |
4304 | 240 | if(*p == PV_MARKER) { |
4305 | 0 | p++; |
4306 | 0 | if(pvstate==1) |
4307 | 0 | { |
4308 | 0 | if(*p!=PV_RNBRACKET) |
4309 | 0 | goto error; |
4310 | 0 | p++; |
4311 | 0 | } |
4312 | 0 | e->getf = pv_get_marker; |
4313 | 0 | e->type = PVT_MARKER; |
4314 | 0 | pvname.len = 1; |
4315 | 0 | goto done_all; |
4316 | 0 | } |
4317 | | |
4318 | 240 | if (*p==PV_LCBRACKET) |
4319 | 0 | { /* context definition*/ |
4320 | 0 | p++; |
4321 | 0 | pvcontext.s = p; |
4322 | |
|
4323 | 0 | while(is_in_str(p,in) && is_pv_valid_char(*p)) |
4324 | 0 | p++; |
4325 | |
|
4326 | 0 | if(*p != PV_RCBRACKET) |
4327 | 0 | { |
4328 | 0 | LM_ERR("Expected to find the end of the context\n"); |
4329 | 0 | return 0; |
4330 | 0 | } |
4331 | 0 | pvcontext.len = p - pvcontext.s; |
4332 | 0 | LM_DBG("Context name is %.*s\n", pvcontext.len, pvcontext.s); |
4333 | 0 | p++; |
4334 | 0 | e->pvc = pv_get_context(&pvcontext); |
4335 | 0 | if(e->pvc == NULL) |
4336 | 0 | { |
4337 | 0 | if(!pvc_before_check) |
4338 | 0 | { |
4339 | 0 | LM_ERR("Requested a non existing pv context\n"); |
4340 | 0 | return 0; |
4341 | 0 | } |
4342 | 0 | LM_DBG("No context definition found for [%.*s]\n", pvcontext.len, pvcontext.s); |
4343 | | /* create a dummy context strcuture to be filled by the register functions */ |
4344 | 0 | e->pvc = add_pv_context(&pvcontext, 0); |
4345 | 0 | if(e->pvc == NULL ) |
4346 | 0 | { |
4347 | 0 | LM_ERR("Failed to new context\n"); |
4348 | 0 | return 0; |
4349 | 0 | } |
4350 | 0 | } |
4351 | 0 | } |
4352 | | |
4353 | 240 | pvname.s = p; |
4354 | 1.31k | while(is_in_str(p,in) && is_pv_valid_char(*p)) |
4355 | 1.07k | p++; |
4356 | 240 | pvname.len = p - pvname.s; |
4357 | | |
4358 | 240 | if(pvstate==1) |
4359 | 0 | { |
4360 | 0 | if(*p==PV_RNBRACKET) |
4361 | 0 | { /* full pv name ended here*/ |
4362 | 0 | goto done_inm; |
4363 | 0 | } else if(*p==PV_LNBRACKET) { |
4364 | 0 | p++; |
4365 | 0 | pvstate = 2; |
4366 | 0 | } else if(*p==PV_LIBRACKET) { |
4367 | 0 | p++; |
4368 | 0 | pvstate = 3; |
4369 | 0 | } else if(*p==TR_LBRACKET) { |
4370 | 0 | p++; |
4371 | 0 | pvstate = 4; |
4372 | 0 | } |
4373 | 0 | else { |
4374 | 0 | LM_ERR("invalid char '%c' in [%.*s] (%d)\n", *p, in->len, in->s, |
4375 | 0 | pvstate); |
4376 | 0 | goto error; |
4377 | 0 | } |
4378 | 240 | } else { |
4379 | 240 | if(!is_in_str(p, in)) { |
4380 | 240 | p--; |
4381 | 240 | goto done_inm; |
4382 | 240 | } else if(*p==PV_LNBRACKET) { |
4383 | 0 | p++; |
4384 | 0 | pvstate = 5; |
4385 | 0 | } else { |
4386 | | /* still in input str, but end of PV */ |
4387 | | /* p is increased at the end, so decrement here */ |
4388 | 0 | p--; |
4389 | 0 | goto done_inm; |
4390 | 0 | } |
4391 | 240 | } |
4392 | | |
4393 | 240 | done_inm: |
4394 | 240 | has_inner_name = (pvstate==2||pvstate==5)?1:0; |
4395 | 240 | if((pte = pv_lookup_spec_name(&pvname, e, has_inner_name))==NULL) |
4396 | 22 | { |
4397 | 22 | LM_ERR("unknown script var $%.*s%s, maybe a 'loadmodule' statement " |
4398 | 22 | "is missing?\n", pvname.len, pvname.s,has_inner_name ? "()":""); |
4399 | 22 | goto error; |
4400 | 22 | } |
4401 | 218 | if(pvstate==2 || pvstate==5) |
4402 | 0 | { |
4403 | 0 | s.s = p; |
4404 | 0 | n = 0; |
4405 | 0 | while(is_in_str(p, in)) |
4406 | 0 | { |
4407 | 0 | if(*p==PV_RNBRACKET) |
4408 | 0 | { |
4409 | 0 | if(n==0) |
4410 | 0 | break; |
4411 | 0 | n--; |
4412 | 0 | } |
4413 | 0 | if(*p == PV_LNBRACKET) |
4414 | 0 | n++; |
4415 | 0 | p++; |
4416 | 0 | } |
4417 | |
|
4418 | 0 | if(!is_in_str(p, in)) |
4419 | 0 | goto error; |
4420 | | |
4421 | 0 | if(p==s.s) |
4422 | 0 | { |
4423 | 0 | LM_ERR("pvar \"%.*s\" does not get empty name param\n", |
4424 | 0 | pvname.len, pvname.s); |
4425 | 0 | goto error; |
4426 | 0 | } |
4427 | 0 | s.len = p - s.s; |
4428 | 0 | if(pte->parse_name == NULL || pte->parse_name(e, &s)!=0) |
4429 | 0 | { |
4430 | 0 | LM_ERR("pvar \"%.*s\" has an invalid name param [%.*s]\n", |
4431 | 0 | pvname.len, pvname.s, s.len, s.s); |
4432 | 0 | goto error; |
4433 | 0 | } |
4434 | 0 | if(pvstate==2) |
4435 | 0 | { |
4436 | 0 | p++; |
4437 | 0 | if(*p==PV_RNBRACKET) |
4438 | 0 | { /* full pv name ended here*/ |
4439 | 0 | goto done_vnm; |
4440 | 0 | } else if(*p==PV_LIBRACKET) { |
4441 | 0 | p++; |
4442 | 0 | pvstate = 3; |
4443 | 0 | } else if(*p==TR_LBRACKET) { |
4444 | 0 | p++; |
4445 | 0 | pvstate = 4; |
4446 | 0 | } else { |
4447 | 0 | LM_ERR("invalid char '%c' in [%.*s] (%d)\n", *p, in->len, in->s, |
4448 | 0 | pvstate); |
4449 | 0 | goto error; |
4450 | 0 | } |
4451 | 0 | } else { |
4452 | 0 | if(*p==PV_RNBRACKET) |
4453 | 0 | { /* full pv name ended here*/ |
4454 | 0 | p++; |
4455 | 0 | goto done_all; |
4456 | 0 | } else { |
4457 | 0 | LM_ERR("invalid char '%c' in [%.*s] (%d)\n", *p, in->len, in->s, |
4458 | 0 | pvstate); |
4459 | 0 | goto error; |
4460 | 0 | } |
4461 | 0 | } |
4462 | 0 | } |
4463 | 218 | done_vnm: |
4464 | 218 | if(pvstate==3) |
4465 | 0 | { |
4466 | 0 | if(pte->parse_index==NULL) |
4467 | 0 | { |
4468 | 0 | LM_ERR("pvar \"%.*s\" does not get index param\n", |
4469 | 0 | pvname.len, pvname.s); |
4470 | 0 | goto error; |
4471 | 0 | } |
4472 | 0 | s.s = p; |
4473 | 0 | n = 0; |
4474 | 0 | while(is_in_str(p, in)) |
4475 | 0 | { |
4476 | 0 | if(*p==PV_RIBRACKET) |
4477 | 0 | { |
4478 | 0 | if(n==0) |
4479 | 0 | break; |
4480 | 0 | n--; |
4481 | 0 | } |
4482 | 0 | if(*p == PV_LIBRACKET) |
4483 | 0 | n++; |
4484 | 0 | p++; |
4485 | 0 | } |
4486 | 0 | if(!is_in_str(p, in)) |
4487 | 0 | goto error; |
4488 | | |
4489 | 0 | if(p==s.s) |
4490 | 0 | { |
4491 | 0 | LM_ERR("pvar \"%.*s\" does not get empty index param\n", |
4492 | 0 | pvname.len, pvname.s); |
4493 | 0 | goto error; |
4494 | 0 | } |
4495 | 0 | s.len = p - s.s; |
4496 | 0 | if(pte->parse_index(e, &s)!=0) |
4497 | 0 | { |
4498 | 0 | LM_ERR("pvar \"%.*s\" has an invalid index param [%.*s]\n", |
4499 | 0 | pvname.len, pvname.s, s.len, s.s); |
4500 | 0 | goto error; |
4501 | 0 | } |
4502 | 0 | p++; |
4503 | 0 | if(*p==PV_RNBRACKET) |
4504 | 0 | { /* full pv name ended here*/ |
4505 | 0 | goto done_idx; |
4506 | 0 | } else if(*p==TR_LBRACKET) { |
4507 | 0 | p++; |
4508 | 0 | pvstate = 4; |
4509 | 0 | } else { |
4510 | 0 | LM_ERR("invalid char '%c' in [%.*s] (%d)\n", *p, in->len, in->s, |
4511 | 0 | pvstate); |
4512 | 0 | goto error; |
4513 | 0 | } |
4514 | 0 | } |
4515 | 218 | done_idx: |
4516 | 218 | if(pvstate==4) |
4517 | 0 | { |
4518 | 0 | s.s = p-1; |
4519 | 0 | n = 0; |
4520 | 0 | while(is_in_str(p, in)) |
4521 | 0 | { |
4522 | 0 | if(*p==TR_RBRACKET) |
4523 | 0 | { |
4524 | 0 | if(n==0) |
4525 | 0 | { |
4526 | | /* yet another transformation */ |
4527 | 0 | p++; |
4528 | 0 | while(is_in_str(p, in) && (*p==' ' || *p=='\t')) p++; |
4529 | |
|
4530 | 0 | if(!is_in_str(p, in) || *p != TR_LBRACKET) |
4531 | 0 | { |
4532 | 0 | p--; |
4533 | 0 | break; |
4534 | 0 | } |
4535 | 0 | } |
4536 | 0 | n--; |
4537 | 0 | } |
4538 | 0 | if(*p == TR_LBRACKET) |
4539 | 0 | n++; |
4540 | 0 | p++; |
4541 | 0 | } |
4542 | 0 | if(!is_in_str(p, in)) |
4543 | 0 | goto error; |
4544 | | |
4545 | 0 | if(p==s.s) |
4546 | 0 | { |
4547 | 0 | LM_ERR("pvar \"%.*s\" does not get empty index param\n", |
4548 | 0 | pvname.len, pvname.s); |
4549 | 0 | goto error; |
4550 | 0 | } |
4551 | 0 | s.len = p - s.s + 1; |
4552 | |
|
4553 | 0 | p = parse_transformation(&s, &tr); |
4554 | 0 | if(p==NULL) |
4555 | 0 | { |
4556 | 0 | LM_ERR("ERROR:bad tr in pvar name \"%.*s\"\n", |
4557 | 0 | pvname.len, pvname.s); |
4558 | 0 | goto error; |
4559 | 0 | } |
4560 | 0 | if(*p!=PV_RNBRACKET) |
4561 | 0 | { |
4562 | 0 | LM_ERR("bad pvar name \"%.*s\" (%c)!\n", in->len, in->s, *p); |
4563 | 0 | goto error; |
4564 | 0 | } |
4565 | 0 | e->trans = (void*)tr; |
4566 | 0 | } |
4567 | 218 | p++; |
4568 | | |
4569 | 218 | done_all: |
4570 | 218 | if(pte!=NULL && pte->init_param) |
4571 | 108 | pte->init_param(e, pte->iparam); |
4572 | 218 | return p; |
4573 | | |
4574 | 22 | error: |
4575 | 22 | if(p!=NULL) |
4576 | 22 | LM_ERR("wrong char [%c/%d] in [%.*s] at [%d (%d)]\n", *p, (int)*p, |
4577 | 22 | in->len, in->s, (int)(p-in->s), pvstate); |
4578 | 0 | else |
4579 | 0 | LM_ERR("invalid parsing in [%.*s] at (%d)\n", in->len, in->s, pvstate); |
4580 | 22 | return NULL; |
4581 | | |
4582 | 218 | } /* end: pv_parse_spec */ |
4583 | | |
4584 | | /** |
4585 | | * |
4586 | | */ |
4587 | | int pv_parse_format(const str *in, pv_elem_p *el) |
4588 | 0 | { |
4589 | 0 | char *p, *p0; |
4590 | | /*int n = 0;*/ |
4591 | 0 | pv_elem_p e, e0; |
4592 | 0 | str s; |
4593 | |
|
4594 | 0 | if(in==NULL || in->s==NULL || el==NULL) |
4595 | 0 | return -1; |
4596 | | |
4597 | | /*LM_DBG("parsing [%.*s]\n", in->len, in->s);*/ |
4598 | | |
4599 | 0 | if(in->len == 0) |
4600 | 0 | { |
4601 | 0 | *el = pkg_malloc(sizeof(pv_elem_t)); |
4602 | 0 | if(*el == NULL) { |
4603 | 0 | LM_ERR("not enough pkg memory for PV element (1)\n"); |
4604 | 0 | goto error; |
4605 | 0 | } |
4606 | 0 | memset(*el, 0, sizeof(pv_elem_t)); |
4607 | 0 | (*el)->text = *in; |
4608 | 0 | return 0; |
4609 | 0 | } |
4610 | | |
4611 | 0 | p = in->s; |
4612 | 0 | *el = NULL; |
4613 | 0 | e = e0 = NULL; |
4614 | |
|
4615 | 0 | while(is_in_str(p,in)) |
4616 | 0 | { |
4617 | 0 | e0 = e; |
4618 | 0 | e = pkg_malloc(sizeof(pv_elem_t)); |
4619 | 0 | if(!e) { |
4620 | 0 | LM_ERR("not enough pkg memory for PV element (2)\n"); |
4621 | 0 | goto error; |
4622 | 0 | } |
4623 | 0 | memset(e, 0, sizeof(pv_elem_t)); |
4624 | | /*n++;*/ |
4625 | 0 | if(*el == NULL) |
4626 | 0 | *el = e; |
4627 | 0 | if(e0) |
4628 | 0 | e0->next = e; |
4629 | |
|
4630 | 0 | e->text.s = p; |
4631 | 0 | while(is_in_str(p,in) && *p!=PV_MARKER) |
4632 | 0 | p++; |
4633 | 0 | e->text.len = p - e->text.s; |
4634 | |
|
4635 | 0 | if(!is_in_str(p,in)) |
4636 | 0 | break; |
4637 | 0 | s.s = p; |
4638 | 0 | s.len = in->s+in->len-p; |
4639 | 0 | p0 = pv_parse_spec(&s, &e->spec); |
4640 | |
|
4641 | 0 | if(p0==NULL) { |
4642 | 0 | LM_ERR("parsing PV spec failed\n"); |
4643 | 0 | goto error; |
4644 | 0 | } |
4645 | 0 | if(!is_in_str(p0,in)) |
4646 | 0 | break; |
4647 | 0 | p = p0; |
4648 | 0 | } |
4649 | | /*LM_DBG("format parsed OK: [%d] items\n", n);*/ |
4650 | | |
4651 | 0 | if(*el == NULL) |
4652 | 0 | return -1; |
4653 | | |
4654 | 0 | return 0; |
4655 | | |
4656 | 0 | error: |
4657 | 0 | pv_elem_free_all(*el); |
4658 | 0 | *el = NULL; |
4659 | 0 | return -1; |
4660 | 0 | } |
4661 | | |
4662 | | int pv_get_spec_name(struct sip_msg* msg, pv_param_p ip, pv_value_t *name) |
4663 | 0 | { |
4664 | 0 | if(msg==NULL || ip==NULL || name==NULL) |
4665 | 0 | return -1; |
4666 | 0 | memset(name, 0, sizeof(pv_value_t)); |
4667 | |
|
4668 | 0 | if(ip->pvn.type==PV_NAME_INTSTR) |
4669 | 0 | { |
4670 | 0 | if(ip->pvn.u.isname.type&AVP_NAME_STR) |
4671 | 0 | { |
4672 | 0 | name->rs = ip->pvn.u.isname.name.s; |
4673 | 0 | name->flags = PV_VAL_STR; |
4674 | 0 | } else { |
4675 | 0 | name->ri = ip->pvn.u.isname.name.n; |
4676 | 0 | name->flags = PV_VAL_INT|PV_TYPE_INT; |
4677 | 0 | } |
4678 | 0 | return 0; |
4679 | 0 | } |
4680 | | /* pvar */ |
4681 | 0 | if(pv_get_spec_value(msg, (const pv_spec_p)(ip->pvn.u.dname), name)!=0) |
4682 | 0 | { |
4683 | 0 | LM_ERR("cannot get name value\n"); |
4684 | 0 | return -1; |
4685 | 0 | } |
4686 | 0 | if(name->flags&PV_VAL_NULL || name->flags&PV_VAL_EMPTY) |
4687 | 0 | { |
4688 | 0 | LM_ERR("null or empty name\n"); |
4689 | 0 | return -1; |
4690 | 0 | } |
4691 | 0 | return 0; |
4692 | 0 | } |
4693 | | |
4694 | | int pv_get_avp_name(struct sip_msg* msg, pv_param_p ip, int *avp_name, |
4695 | | unsigned short *name_type) |
4696 | 0 | { |
4697 | 0 | pv_value_t tv; |
4698 | 0 | if(ip==NULL || avp_name==NULL || name_type==NULL) |
4699 | 0 | return -1; |
4700 | 0 | *avp_name = 0; |
4701 | 0 | *name_type = 0; |
4702 | |
|
4703 | 0 | if(ip->pvn.type==PV_NAME_INTSTR) |
4704 | 0 | { |
4705 | 0 | *name_type = ip->pvn.u.isname.type; |
4706 | 0 | *avp_name = ip->pvn.u.isname.name.n; |
4707 | 0 | *name_type &= AVP_SCRIPT_MASK; |
4708 | 0 | return 0; |
4709 | 0 | } |
4710 | | /* pvar */ |
4711 | 0 | if(pv_get_spec_value(msg, (const pv_spec_p)(ip->pvn.u.dname), &tv)!=0) |
4712 | 0 | { |
4713 | 0 | LM_ERR("cannot get avp value\n"); |
4714 | 0 | return -1; |
4715 | 0 | } |
4716 | 0 | if(tv.flags&PV_VAL_NULL || tv.flags&PV_VAL_EMPTY) |
4717 | 0 | { |
4718 | 0 | LM_ERR("null or empty name\n"); |
4719 | 0 | return -1; |
4720 | 0 | } |
4721 | | |
4722 | 0 | if(!(tv.flags&PV_VAL_STR)) |
4723 | 0 | tv.rs.s = int2str(tv.ri, &tv.rs.len); |
4724 | | |
4725 | | /* search the name here */ |
4726 | 0 | *avp_name = get_avp_id(&tv.rs); |
4727 | 0 | if (*avp_name == 0) { |
4728 | 0 | LM_ERR("cannot find avp %.*s\n", tv.rs.len, tv.rs.s); |
4729 | 0 | return -1; |
4730 | 0 | } |
4731 | 0 | return 0; |
4732 | 0 | } |
4733 | | |
4734 | | |
4735 | | int pv_get_spec_index(struct sip_msg* msg, pv_param_p ip, int *idx, int *flags) |
4736 | 75.9k | { |
4737 | 75.9k | pv_value_t tv; |
4738 | 75.9k | if(ip==NULL || idx==NULL || flags==NULL) |
4739 | 0 | return -1; |
4740 | | |
4741 | 75.9k | *idx = 0; |
4742 | 75.9k | *flags = ip->pvi.type; |
4743 | | |
4744 | 75.9k | if(ip->pvi.type == 0) |
4745 | 75.9k | return 0; |
4746 | | |
4747 | 0 | if(ip->pvi.type == PV_IDX_ALL || ip->pvi.type == PV_IDX_APPEND) { |
4748 | 0 | return 0; |
4749 | 0 | } |
4750 | | |
4751 | 0 | if(ip->pvi.type == PV_IDX_INT) |
4752 | 0 | { |
4753 | 0 | *idx = ip->pvi.u.ival; |
4754 | 0 | return 0; |
4755 | 0 | } |
4756 | | |
4757 | | /* pvar */ |
4758 | 0 | if(pv_get_spec_value(msg, (const pv_spec_p)ip->pvi.u.dval, &tv)!=0) |
4759 | 0 | { |
4760 | 0 | LM_ERR("cannot get index value\n"); |
4761 | 0 | return -1; |
4762 | 0 | } |
4763 | 0 | if(!(tv.flags & PV_VAL_INT)) |
4764 | 0 | { |
4765 | 0 | LM_ERR("invalid index value\n"); |
4766 | 0 | return -1; |
4767 | 0 | } |
4768 | 0 | *idx = tv.ri; |
4769 | 0 | return 0; |
4770 | 0 | } |
4771 | | |
4772 | | /* function to set pv value */ |
4773 | | int pv_set_value(struct sip_msg* msg, pv_spec_p sp, |
4774 | | int op, pv_value_t *value) |
4775 | 0 | { |
4776 | 0 | struct sip_msg* pv_msg; |
4777 | |
|
4778 | 0 | if(msg==NULL || sp==NULL || sp->setf==NULL || sp->type==PVT_NONE) |
4779 | 0 | { |
4780 | 0 | LM_ERR("bad parameters\n"); |
4781 | 0 | return -1; |
4782 | 0 | } |
4783 | | |
4784 | 0 | if(sp->pvc && sp->pvc->contextf) |
4785 | 0 | { |
4786 | 0 | pv_msg = sp->pvc->contextf(msg); |
4787 | 0 | if(pv_msg == NULL || pv_msg==FAKED_REPLY) |
4788 | 0 | { |
4789 | 0 | LM_DBG("Invalid %p pv context message\n",pv_msg); |
4790 | 0 | return -1; |
4791 | 0 | } |
4792 | 0 | } |
4793 | 0 | else |
4794 | 0 | pv_msg = msg; |
4795 | | |
4796 | 0 | return (*sp->setf)(pv_msg, &(sp->pvp), op, value); |
4797 | 0 | } |
4798 | | |
4799 | | int pv_get_spec_value(struct sip_msg* msg, const pv_spec_p sp, pv_value_t *value) |
4800 | 0 | { |
4801 | 0 | struct sip_msg* pv_msg; |
4802 | |
|
4803 | 0 | if(msg==NULL || sp==NULL || sp->getf==NULL || value==NULL |
4804 | 0 | || sp->type==PVT_NONE) |
4805 | 0 | { |
4806 | 0 | LM_ERR("bad parameters\n"); |
4807 | 0 | return -1; |
4808 | 0 | } |
4809 | | |
4810 | 0 | memset(value, 0, sizeof(pv_value_t)); |
4811 | |
|
4812 | 0 | if(sp->pvc && sp->pvc->contextf) |
4813 | 0 | { |
4814 | 0 | LM_DBG("Found context function %p\n", sp->pvc->contextf); |
4815 | 0 | pv_msg = sp->pvc->contextf(msg); |
4816 | 0 | if(pv_msg == NULL || pv_msg==FAKED_REPLY) |
4817 | 0 | { |
4818 | 0 | LM_DBG("Invalid %p pv context message\n",pv_msg); |
4819 | 0 | return pv_get_null( NULL, NULL, value); |
4820 | 0 | } |
4821 | 0 | } else { |
4822 | 0 | pv_msg = msg; |
4823 | 0 | } |
4824 | 0 | if((*sp->getf)(pv_msg, &(sp->pvp), value)!=0) |
4825 | 0 | return pv_get_null( NULL, NULL, value); |
4826 | 0 | if(sp->trans) |
4827 | 0 | if (run_transformations(pv_msg, (trans_t*)sp->trans, value)!=0) |
4828 | 0 | return pv_get_null( NULL, NULL, value); |
4829 | 0 | return 0; |
4830 | 0 | } |
4831 | | |
4832 | | int pv_print_spec(struct sip_msg* msg, const pv_spec_p sp, char *buf, int *len) |
4833 | 0 | { |
4834 | 0 | pv_value_t tok; |
4835 | 0 | if(msg==NULL || sp==NULL || buf==NULL || len==NULL) |
4836 | 0 | return -1; |
4837 | | |
4838 | 0 | if(*len <= 0) |
4839 | 0 | return -1; |
4840 | | |
4841 | 0 | memset(&tok, 0, sizeof(pv_value_t)); |
4842 | | |
4843 | | /* put the value of the specifier */ |
4844 | 0 | if(pv_get_spec_value(msg, sp, &tok)==0) |
4845 | 0 | { |
4846 | 0 | if(tok.flags&PV_VAL_NULL) |
4847 | 0 | tok.rs = str_null; |
4848 | 0 | if(tok.rs.len < *len) |
4849 | 0 | memcpy(buf, tok.rs.s, tok.rs.len); |
4850 | 0 | else |
4851 | 0 | goto overflow; |
4852 | 0 | } |
4853 | | |
4854 | 0 | *len = tok.rs.len; |
4855 | 0 | buf[tok.rs.len] = '\0'; |
4856 | 0 | return 0; |
4857 | | |
4858 | 0 | overflow: |
4859 | 0 | LM_ERR("buffer overflow -- increase the buffer size...\n"); |
4860 | 0 | return -1; |
4861 | 0 | } |
4862 | | |
4863 | | |
4864 | | int pv_printf(struct sip_msg* msg, pv_elem_p list, char *buf, int *len) |
4865 | 0 | { |
4866 | 0 | int n; |
4867 | 0 | pv_value_t tok; |
4868 | 0 | str print; |
4869 | 0 | pv_elem_p it; |
4870 | 0 | char *cur; |
4871 | |
|
4872 | 0 | if(msg==NULL || list==NULL || buf==NULL || len==NULL) |
4873 | 0 | return -1; |
4874 | | |
4875 | 0 | if(*len <= 0) |
4876 | 0 | return -1; |
4877 | | |
4878 | 0 | *buf = '\0'; |
4879 | 0 | cur = buf; |
4880 | |
|
4881 | 0 | n = 0; |
4882 | 0 | for (it=list; it; it=it->next) |
4883 | 0 | { |
4884 | | /* put the text */ |
4885 | 0 | if(it->text.s && it->text.len>0) |
4886 | 0 | { |
4887 | 0 | if(n+it->text.len < *len) |
4888 | 0 | { |
4889 | 0 | memcpy(cur, it->text.s, it->text.len); |
4890 | 0 | n += it->text.len; |
4891 | 0 | cur += it->text.len; |
4892 | 0 | } else { |
4893 | 0 | LM_ERR("no more space for text [%d][%d]\n", n, it->text.len); |
4894 | 0 | goto overflow; |
4895 | 0 | } |
4896 | 0 | } |
4897 | | /* put the value of the specifier */ |
4898 | 0 | if(it->spec.type!=PVT_NONE |
4899 | 0 | && pv_get_spec_value(msg, &(it->spec), &tok)==0) |
4900 | 0 | { |
4901 | 0 | print = pv_value_print(&tok); |
4902 | 0 | if (n + print.len >= *len) { |
4903 | 0 | LM_ERR("no more space for spec value [%d][%d]\n", |
4904 | 0 | n, print.len); |
4905 | 0 | goto overflow; |
4906 | 0 | } |
4907 | | |
4908 | 0 | memcpy(cur, print.s, print.len); |
4909 | 0 | n += print.len; |
4910 | 0 | cur += print.len; |
4911 | 0 | } |
4912 | 0 | } |
4913 | | |
4914 | 0 | goto done; |
4915 | | |
4916 | 0 | overflow: |
4917 | 0 | if (is_pv_print_buf(buf)) |
4918 | 0 | LM_ERR("buffer too small -- increase 'pv_print_buf_size' from [%d]\n", |
4919 | 0 | *len); |
4920 | 0 | else |
4921 | 0 | LM_ERR("buffer too small -- increase the buffer size " |
4922 | 0 | "from [%d]...\n", *len); |
4923 | 0 | return -1; |
4924 | | |
4925 | 0 | done: |
4926 | | #ifdef EXTRA_DEBUG |
4927 | | LM_DBG("final buffer length %d\n", n); |
4928 | | #endif |
4929 | 0 | *cur = '\0'; |
4930 | 0 | *len = n; |
4931 | 0 | return 0; |
4932 | 0 | } |
4933 | | |
4934 | | |
4935 | | |
4936 | | pvname_list_t* parse_pvname_list(str *in, unsigned int type) |
4937 | 0 | { |
4938 | 0 | pvname_list_t* head = NULL; |
4939 | 0 | pvname_list_t* al = NULL; |
4940 | 0 | pvname_list_t* last = NULL; |
4941 | 0 | char *p; |
4942 | 0 | pv_spec_t spec; |
4943 | 0 | str s; |
4944 | |
|
4945 | 0 | if(in==NULL || in->s==NULL) |
4946 | 0 | { |
4947 | 0 | LM_ERR("bad parameters\n"); |
4948 | 0 | return NULL; |
4949 | 0 | } |
4950 | | |
4951 | 0 | p = in->s; |
4952 | 0 | while(is_in_str(p, in)) |
4953 | 0 | { |
4954 | 0 | while(is_in_str(p, in) && (is_ws(*p)||*p==','||*p==';')) |
4955 | 0 | p++; |
4956 | 0 | if(!is_in_str(p, in)) |
4957 | 0 | { |
4958 | 0 | if(head==NULL) |
4959 | 0 | LM_ERR("wrong item name list [%.*s]\n", in->len, in->s); |
4960 | 0 | return head; |
4961 | 0 | } |
4962 | 0 | s.s=p; |
4963 | 0 | s.len = in->s+in->len-p; |
4964 | 0 | p = pv_parse_spec(&s, &spec); |
4965 | 0 | if(p==NULL || (type && spec.type!=type)) |
4966 | 0 | { |
4967 | 0 | LM_ERR("wrong item name list [%.*s]!\n", in->len, in->s); |
4968 | 0 | goto error; |
4969 | 0 | } |
4970 | 0 | al = (pvname_list_t*)pkg_malloc(sizeof(pvname_list_t)); |
4971 | 0 | if(al==NULL) |
4972 | 0 | { |
4973 | 0 | LM_ERR("no more memory!\n"); |
4974 | 0 | goto error; |
4975 | 0 | } |
4976 | 0 | memset(al, 0, sizeof(pvname_list_t)); |
4977 | 0 | memcpy(&al->sname, &spec, sizeof(pv_spec_t)); |
4978 | |
|
4979 | 0 | if(last==NULL) |
4980 | 0 | { |
4981 | 0 | head = al; |
4982 | 0 | last = al; |
4983 | 0 | } else { |
4984 | 0 | last->next = al; |
4985 | 0 | last = al; |
4986 | 0 | } |
4987 | 0 | } |
4988 | | |
4989 | 0 | return head; |
4990 | | |
4991 | 0 | error: |
4992 | 0 | while(head) |
4993 | 0 | { |
4994 | 0 | al = head; |
4995 | 0 | head=head->next; |
4996 | 0 | pkg_free(al); |
4997 | 0 | } |
4998 | 0 | return NULL; |
4999 | 0 | } |
5000 | | |
5001 | | int pv_elem_free_all(pv_elem_p log) |
5002 | 0 | { |
5003 | 0 | pv_elem_p t; |
5004 | 0 | while(log) |
5005 | 0 | { |
5006 | 0 | t = log; |
5007 | 0 | log = log->next; |
5008 | |
|
5009 | 0 | if (t->spec.trans) |
5010 | 0 | free_transformation((trans_t *)t->spec.trans); |
5011 | 0 | pkg_free(t); |
5012 | 0 | } |
5013 | 0 | return 0; |
5014 | 0 | } |
5015 | | |
5016 | | static str pv_value_print(const pv_value_t *val) |
5017 | 0 | { |
5018 | 0 | str printed = str_init(NULL); |
5019 | |
|
5020 | 0 | if (val->flags & PV_VAL_NULL) |
5021 | 0 | return str_null; |
5022 | | |
5023 | 0 | if (val->flags & PV_VAL_STR) |
5024 | 0 | return val->rs; |
5025 | | |
5026 | 0 | if (val->flags & (PV_VAL_INT|PV_TYPE_INT)) { |
5027 | 0 | printed.s = int2str(val->ri, &printed.len); |
5028 | 0 | return printed; |
5029 | 0 | } |
5030 | | |
5031 | 0 | LM_ERR("unknown type %x\n", val->flags); |
5032 | 0 | return str_empty; |
5033 | 0 | } |
5034 | | |
5035 | | void pv_value_destroy(pv_value_t *val) |
5036 | 0 | { |
5037 | 0 | if(val==0) return; |
5038 | 0 | if(val->flags&PV_VAL_PKG) pkg_free(val->rs.s); |
5039 | 0 | if(val->flags&PV_VAL_SHM) shm_free(val->rs.s); |
5040 | 0 | memset(val, 0, sizeof(pv_value_t)); |
5041 | 0 | } |
5042 | | |
5043 | | /* IMPORTANT NOTE - even if the function prints and returns a static buffer, it |
5044 | | * has built-in support for PV_PRINTF_BUF_NO levels of nesting |
5045 | | * (or concurrent usage). If you think it's not enough for you, either use |
5046 | | * pv_printf() directly, either increase PV_PRINT_BUF_NO --bogdan */ |
5047 | | int pv_printf_s(struct sip_msg* msg, pv_elem_p list, str *s) |
5048 | 0 | { |
5049 | 0 | static int buf_itr = 0; |
5050 | |
|
5051 | 0 | if (list->next==0 && list->spec.getf==0) { |
5052 | 0 | *s = list->text; |
5053 | 0 | return 0; |
5054 | 0 | } else { |
5055 | 0 | *s = pv_print_buf[buf_itr]; |
5056 | 0 | buf_itr = (buf_itr + 1) % PV_PRINT_BUF_NO; |
5057 | 0 | return pv_printf(msg, list, s->s, &s->len); |
5058 | 0 | } |
5059 | 0 | } |
5060 | | |
5061 | | void pv_spec_free(pv_spec_t *spec) |
5062 | 0 | { |
5063 | 0 | if(spec==0) return; |
5064 | | /* TODO: free name if it is PV */ |
5065 | 0 | if(spec->trans) |
5066 | 0 | free_transformation((trans_t*)spec->trans); |
5067 | 0 | pkg_free(spec); |
5068 | 0 | } |
5069 | | |
5070 | | int pv_spec_dbg(const pv_spec_p sp) |
5071 | 0 | { |
5072 | 0 | if(sp==NULL) |
5073 | 0 | { |
5074 | 0 | LM_DBG("spec: <<NULL>>\n"); |
5075 | 0 | return 0; |
5076 | 0 | } |
5077 | 0 | LM_DBG("<spec>\n"); |
5078 | 0 | LM_DBG("type: %d\n", sp->type); |
5079 | 0 | LM_DBG("getf: %p\n", sp->getf); |
5080 | 0 | LM_DBG("setf: %p\n", sp->setf); |
5081 | 0 | LM_DBG("tran: %p\n", sp->trans); |
5082 | 0 | LM_DBG("<param>\n"); |
5083 | 0 | LM_DBG("<name>\n"); |
5084 | 0 | LM_DBG("type: %d\n", sp->pvp.pvn.type); |
5085 | 0 | if(sp->pvp.pvn.type==PV_NAME_INTSTR) |
5086 | 0 | { |
5087 | 0 | LM_DBG("sub-type: %d\n", sp->pvp.pvn.u.isname.type); |
5088 | 0 | if (sp->pvp.pvn.u.isname.type&AVP_NAME_STR) |
5089 | 0 | { |
5090 | 0 | LM_DBG("name str: %.*s\n", |
5091 | 0 | sp->pvp.pvn.u.isname.name.s.len, |
5092 | 0 | sp->pvp.pvn.u.isname.name.s.s); |
5093 | 0 | } else { |
5094 | 0 | LM_DBG("name in: %d\n", |
5095 | 0 | sp->pvp.pvn.u.isname.name.n); |
5096 | 0 | } |
5097 | |
|
5098 | 0 | } else if(sp->pvp.pvn.type==PV_NAME_PVAR) { |
5099 | 0 | pv_spec_dbg((pv_spec_p)sp->pvp.pvn.u.dname); |
5100 | 0 | } else { |
5101 | 0 | LM_DBG("name: unknown\n"); |
5102 | 0 | } |
5103 | 0 | LM_DBG("</name>\n"); |
5104 | 0 | LM_DBG("<index>\n"); |
5105 | 0 | LM_DBG("type: %d\n", sp->pvp.pvi.type); |
5106 | 0 | if(sp->pvp.pvi.type==PV_IDX_INT) |
5107 | 0 | { |
5108 | 0 | LM_DBG("index: %d\n", sp->pvp.pvi.u.ival); |
5109 | 0 | } else if(sp->pvp.pvi.type==PV_IDX_PVAR) { |
5110 | 0 | pv_spec_dbg((pv_spec_p)sp->pvp.pvi.u.dval); |
5111 | 0 | } else if(sp->pvp.pvi.type==PV_IDX_ALL){ |
5112 | 0 | LM_DBG("index: *\n"); |
5113 | 0 | } else { |
5114 | 0 | LM_DBG("index: unknown\n"); |
5115 | 0 | } |
5116 | 0 | LM_DBG("</index>\n"); |
5117 | 0 | LM_DBG("</param>\n"); |
5118 | 0 | LM_DBG("</spec\n"); |
5119 | 0 | return 0; |
5120 | 0 | } |
5121 | | |
5122 | | |
5123 | | /** |
5124 | | * |
5125 | | */ |
5126 | | static int pv_init_extra_list(void) |
5127 | 0 | { |
5128 | 0 | _pv_extra_list = (pv_extra_p*)pkg_malloc(sizeof(pv_extra_p)); |
5129 | 0 | if(_pv_extra_list==0) |
5130 | 0 | { |
5131 | 0 | LM_ERR("cannot alloc extra items list\n"); |
5132 | 0 | return -1; |
5133 | 0 | } |
5134 | 0 | *_pv_extra_list=0; |
5135 | 0 | return 0; |
5136 | 0 | } |
5137 | | |
5138 | | static int pv_add_extra(const pv_export_t *e) |
5139 | 0 | { |
5140 | 0 | const char *p; |
5141 | 0 | const str_const *in; |
5142 | 0 | pv_extra_t *pvi = NULL; |
5143 | 0 | pv_extra_t *pvj = NULL; |
5144 | 0 | pv_extra_t *pvn = NULL; |
5145 | 0 | int found; |
5146 | |
|
5147 | 0 | if(e==NULL || e->name.s==NULL || e->getf==NULL || e->type==PVT_NONE) |
5148 | 0 | { |
5149 | 0 | LM_ERR("invalid parameters\n"); |
5150 | 0 | return -1; |
5151 | 0 | } |
5152 | | |
5153 | 0 | if(_pv_extra_list==0) |
5154 | 0 | { |
5155 | 0 | LM_DBG("extra items list is not initialized\n"); |
5156 | 0 | if(pv_init_extra_list()!=0) |
5157 | 0 | { |
5158 | 0 | LM_ERR("cannot intit extra list\n"); |
5159 | 0 | return -1; |
5160 | 0 | } |
5161 | 0 | } |
5162 | 0 | in = &(e->name); |
5163 | 0 | p = in->s; |
5164 | 0 | while(is_in_str(p,in) && is_pv_valid_char(*p)) |
5165 | 0 | p++; |
5166 | 0 | if(is_in_str(p,in)) |
5167 | 0 | { |
5168 | 0 | LM_ERR("invalid char [%c] in [%.*s]\n", *p, in->len, in->s); |
5169 | 0 | return -1; |
5170 | 0 | } |
5171 | 0 | found = 0; |
5172 | 0 | pvi = *_pv_extra_list; |
5173 | 0 | while(pvi) |
5174 | 0 | { |
5175 | 0 | if(pvi->pve.name.len > in->len) |
5176 | 0 | break; |
5177 | 0 | if(pvi->pve.name.len==in->len) |
5178 | 0 | { |
5179 | 0 | found = strncmp(pvi->pve.name.s, in->s, in->len); |
5180 | 0 | if(found>0) |
5181 | 0 | break; |
5182 | 0 | if(found==0) |
5183 | 0 | { |
5184 | 0 | LM_ERR("pvar [%.*s] already exists\n", in->len, in->s); |
5185 | 0 | return -1; |
5186 | 0 | } |
5187 | 0 | } |
5188 | 0 | pvj = pvi; |
5189 | 0 | pvi = pvi->next; |
5190 | 0 | } |
5191 | | |
5192 | 0 | pvn = (pv_extra_t*)pkg_malloc(sizeof(pv_extra_t)); |
5193 | 0 | if(pvn==0) |
5194 | 0 | { |
5195 | 0 | LM_ERR("no more memory\n"); |
5196 | 0 | return -1; |
5197 | 0 | } |
5198 | 0 | memcpy(&pvn->pve, e, sizeof(*e)); |
5199 | 0 | pvn->pve.type += PVT_EXTRA; |
5200 | |
|
5201 | 0 | if(pvj==0) |
5202 | 0 | { |
5203 | 0 | pvn->next = *_pv_extra_list; |
5204 | 0 | *_pv_extra_list = pvn; |
5205 | 0 | goto done; |
5206 | 0 | } |
5207 | 0 | pvn->next = pvj->next; |
5208 | 0 | pvj->next = pvn; |
5209 | |
|
5210 | 0 | done: |
5211 | 0 | return 0; |
5212 | 0 | } |
5213 | | |
5214 | | int register_pvars_mod(const char *mod_name, const pv_export_t *items) |
5215 | 0 | { |
5216 | 0 | int ret; |
5217 | 0 | int i; |
5218 | |
|
5219 | 0 | if (items==0) |
5220 | 0 | return 0; |
5221 | | |
5222 | 0 | for ( i=0 ; items[i].name.s ; i++ ) { |
5223 | 0 | ret = pv_add_extra(&items[i]); |
5224 | 0 | if (ret!=0) { |
5225 | 0 | LM_ERR("failed to register pseudo-variable <%.*s> for module %s\n", |
5226 | 0 | items[i].name.len, items[i].name.s, mod_name); |
5227 | 0 | } |
5228 | 0 | } |
5229 | 0 | return 0; |
5230 | 0 | } |
5231 | | |
5232 | | /** |
5233 | | * |
5234 | | */ |
5235 | | int pv_free_extra_list(void) |
5236 | 0 | { |
5237 | 0 | pv_extra_p xe; |
5238 | 0 | pv_extra_p xe1; |
5239 | 0 | if(_pv_extra_list!=0) |
5240 | 0 | { |
5241 | 0 | xe = *_pv_extra_list; |
5242 | 0 | while(xe!=0) |
5243 | 0 | { |
5244 | 0 | xe1 = xe; |
5245 | 0 | xe = xe->next; |
5246 | 0 | pkg_free(xe1); |
5247 | 0 | } |
5248 | 0 | pkg_free(_pv_extra_list); |
5249 | 0 | _pv_extra_list = 0; |
5250 | 0 | } |
5251 | |
|
5252 | 0 | return 0; |
5253 | 0 | } |
5254 | | |
5255 | | static pv_context_t* new_pv_context(const str* name, pv_contextf_t get_context) |
5256 | 0 | { |
5257 | 0 | pv_context_t* pvc_new = NULL; |
5258 | 0 | int size; |
5259 | | /* |
5260 | | if(get_context == NULL) |
5261 | | { |
5262 | | LM_ERR("NULL pointer to function\n"); |
5263 | | return 0; |
5264 | | } |
5265 | | */ |
5266 | 0 | size = sizeof(pv_context_t) + name->len; |
5267 | 0 | pvc_new = (pv_context_t*)pkg_malloc(size); |
5268 | 0 | if(pvc_new == NULL) |
5269 | 0 | { |
5270 | 0 | LM_ERR("No more memory\n"); |
5271 | 0 | return 0; |
5272 | 0 | } |
5273 | 0 | memset(pvc_new, 0, size); |
5274 | |
|
5275 | 0 | pvc_new->name.s = (char*)pvc_new + sizeof(pv_context_t); |
5276 | 0 | memcpy(pvc_new->name.s, name->s, name->len); |
5277 | 0 | pvc_new->name.len = name->len; |
5278 | |
|
5279 | 0 | pvc_new->contextf = get_context; |
5280 | |
|
5281 | 0 | return pvc_new; |
5282 | 0 | } |
5283 | | |
5284 | | int register_pv_context(char* cname, pv_contextf_t get_context) |
5285 | 0 | { |
5286 | 0 | pv_context_t* pvc = pv_context_lst; |
5287 | 0 | str name; |
5288 | |
|
5289 | 0 | if(cname == NULL) |
5290 | 0 | { |
5291 | 0 | LM_DBG("NULL parameter\n"); |
5292 | 0 | return -1; |
5293 | 0 | } |
5294 | | |
5295 | 0 | name.s = cname; |
5296 | 0 | name.len = strlen(cname); |
5297 | |
|
5298 | 0 | LM_DBG("Registered new context: %.*s / %p\n", name.len, name.s, get_context); |
5299 | 0 | pvc = pv_get_context(&name); |
5300 | 0 | if(pvc == NULL) |
5301 | 0 | { |
5302 | 0 | LM_DBG("Context not found\n"); |
5303 | 0 | if(add_pv_context(&name, get_context) == NULL) |
5304 | 0 | { |
5305 | 0 | LM_ERR("Failed to add context\n"); |
5306 | 0 | return -1; |
5307 | 0 | } |
5308 | 0 | return 1; |
5309 | 0 | } |
5310 | | |
5311 | 0 | if(pvc->contextf!=NULL) |
5312 | 0 | { |
5313 | 0 | LM_ERR("Context already registered [%s]\n", cname); |
5314 | 0 | return -1; |
5315 | 0 | } |
5316 | 0 | if(get_context == NULL) |
5317 | 0 | { |
5318 | 0 | LM_ERR("NULL context getter function\n"); |
5319 | 0 | return -1; |
5320 | 0 | } |
5321 | 0 | pvc->contextf= get_context; |
5322 | 0 | return 1; |
5323 | 0 | } |
5324 | | |
5325 | | |
5326 | | /* function to register a pv context getter */ |
5327 | | static pv_context_t* add_pv_context(const str* name, pv_contextf_t get_context) |
5328 | 0 | { |
5329 | 0 | pv_context_t* pvc = pv_context_lst; |
5330 | 0 | pv_context_t* pvc_new, *pvc_prev; |
5331 | |
|
5332 | 0 | if(pvc == NULL) |
5333 | 0 | { |
5334 | 0 | pvc_new = new_pv_context(name, get_context); |
5335 | 0 | if(pvc_new == NULL) |
5336 | 0 | { |
5337 | 0 | LM_ERR("Failed to allocate context\n"); |
5338 | 0 | return 0; |
5339 | 0 | } |
5340 | 0 | pv_context_lst = pvc_new; |
5341 | 0 | return pvc_new; |
5342 | 0 | } |
5343 | | |
5344 | 0 | while(pvc) |
5345 | 0 | { |
5346 | 0 | if(pvc->name.len == name->len && strncmp(pvc->name.s, name->s, name->len)==0) |
5347 | 0 | { |
5348 | 0 | LM_ERR("PV Context already registered [%.*s]\n", name->len, name->s); |
5349 | 0 | return 0; |
5350 | 0 | } |
5351 | 0 | pvc_prev = pvc; |
5352 | 0 | pvc = pvc->next; |
5353 | 0 | } |
5354 | | |
5355 | 0 | pvc_new = new_pv_context(name, get_context); |
5356 | 0 | if(pvc_new == NULL) |
5357 | 0 | { |
5358 | 0 | LM_ERR("Failed to allocate context\n"); |
5359 | 0 | return 0; |
5360 | 0 | } |
5361 | | |
5362 | 0 | LM_DBG("Registered new context: %.*s\n", name->len, name->s); |
5363 | |
|
5364 | 0 | pvc_prev->next = pvc_new; |
5365 | |
|
5366 | 0 | return pvc_new; |
5367 | 0 | } |
5368 | | |
5369 | | static pv_context_t* pv_get_context(const str* name) |
5370 | 0 | { |
5371 | 0 | pv_context_t* pvc = pv_context_lst; |
5372 | |
|
5373 | 0 | while(pvc) |
5374 | 0 | { |
5375 | 0 | if(pvc->name.len == name->len && |
5376 | 0 | strncmp(pvc->name.s, name->s, name->len) == 0) |
5377 | 0 | { |
5378 | 0 | return pvc; |
5379 | 0 | } |
5380 | 0 | pvc = pvc->next; |
5381 | 0 | } |
5382 | 0 | return 0; |
5383 | 0 | } |
5384 | | |
5385 | | static int pv_contextlist_check(void) |
5386 | 0 | { |
5387 | 0 | pv_context_t* pvc = pv_context_lst; |
5388 | |
|
5389 | 0 | while(pvc) |
5390 | 0 | { |
5391 | 0 | if(pvc->contextf == NULL) |
5392 | 0 | return -1; |
5393 | | |
5394 | 0 | pvc = pvc->next; |
5395 | 0 | } |
5396 | 0 | pvc_before_check = 0; |
5397 | 0 | return 0; |
5398 | 0 | } |
5399 | | |
5400 | | /* argument options '-o' */ |
5401 | | argv_p argv_vars = NULL; |
5402 | | |
5403 | | static argv_p search_argv(const str *name) |
5404 | 0 | { |
5405 | 0 | argv_p it; |
5406 | |
|
5407 | 0 | for (it = argv_vars; it; it = it->next) { |
5408 | 0 | if (it->name.len == name->len && |
5409 | 0 | !strncmp(it->name.s, name->s, name->len)) |
5410 | 0 | return it; |
5411 | 0 | } |
5412 | 0 | return 0; |
5413 | 0 | } |
5414 | | |
5415 | | int add_arg_var(char *opt) |
5416 | 0 | { |
5417 | 0 | char *eq; |
5418 | 0 | str name; |
5419 | 0 | argv_p new = NULL; |
5420 | |
|
5421 | 0 | if (!opt) { |
5422 | 0 | LM_ERR("cannot receive null option\n"); |
5423 | 0 | return -1; |
5424 | 0 | } |
5425 | | |
5426 | 0 | eq = strchr(opt, '='); |
5427 | 0 | if (!eq) { |
5428 | 0 | LM_ERR("invalid option format - '=' char cannot be found\n"); |
5429 | 0 | return -1; |
5430 | 0 | } |
5431 | 0 | if (eq <= opt) { |
5432 | 0 | LM_ERR("no option name specified\n"); |
5433 | 0 | return -1; |
5434 | 0 | } |
5435 | | |
5436 | 0 | name.s = opt; |
5437 | 0 | name.len = eq - name.s; |
5438 | | |
5439 | | /* check for duplicate option name */ |
5440 | 0 | if (search_argv(&name)) { |
5441 | 0 | LM_ERR("duplicate option name <%.*s>\n", name.len, name.s); |
5442 | 0 | return -1; |
5443 | 0 | } |
5444 | | |
5445 | 0 | new = (argv_p)pkg_malloc(sizeof(argv_t)); |
5446 | 0 | if (!new) { |
5447 | 0 | LM_ERR("no more pkg memory\n"); |
5448 | 0 | return -1; |
5449 | 0 | } |
5450 | 0 | memset(new, 0, sizeof(argv_t)); |
5451 | |
|
5452 | 0 | new->name.s = name.s; |
5453 | 0 | new->name.len = name.len; |
5454 | |
|
5455 | 0 | new->value.s = eq+1; |
5456 | 0 | new->value.len = strlen(opt) + opt - new->value.s; |
5457 | |
|
5458 | 0 | if (!new->value.len) |
5459 | 0 | new->value.s = 0; |
5460 | |
|
5461 | 0 | new->next = argv_vars; |
5462 | 0 | argv_vars = new; |
5463 | |
|
5464 | 0 | LM_DBG("added argument name <%.*s> = <%.*s>\n", |
5465 | 0 | name.len, name.s, new->value.len, new->value.s); |
5466 | 0 | return 0; |
5467 | |
|
5468 | 0 | } |
5469 | | |
5470 | | static int pv_parse_argv_name(pv_spec_p sp, const str *in) |
5471 | 0 | { |
5472 | 0 | argv_p v_arg; |
5473 | |
|
5474 | 0 | if(in==NULL || in->s==NULL || sp==NULL) |
5475 | 0 | return -1; |
5476 | | |
5477 | 0 | v_arg = search_argv(in); |
5478 | 0 | if (!v_arg) { |
5479 | 0 | LM_DBG("$argv(%.*s) not found\n", in->len, in->s); |
5480 | 0 | sp->pvp.pvv.len = 0; |
5481 | 0 | sp->pvp.pvv.s = 0; |
5482 | 0 | } else { |
5483 | 0 | sp->pvp.pvv = v_arg->value; |
5484 | 0 | sp->pvp.pvn.u.isname.name.s = v_arg->name; |
5485 | 0 | } |
5486 | |
|
5487 | 0 | sp->pvp.pvn.type = PV_NAME_PVAR; |
5488 | |
|
5489 | 0 | return 0; |
5490 | 0 | } |
5491 | | |
5492 | | static int pv_get_argv(struct sip_msg *msg, pv_param_t *param, pv_value_t *res) |
5493 | 0 | { |
5494 | 0 | if (!param) { |
5495 | 0 | LM_ERR("null parameter received\n"); |
5496 | 0 | return -1; |
5497 | 0 | } |
5498 | | |
5499 | 0 | if (param->pvv.len == 0 || !param->pvv.s) |
5500 | 0 | return pv_get_null(msg, param, res); |
5501 | | |
5502 | 0 | return pv_get_strval(msg, param, res, ¶m->pvv); |
5503 | 0 | } |
5504 | | |
5505 | | static int pv_parse_param_name(pv_spec_p sp, const str *in) |
5506 | 0 | { |
5507 | 0 | char *p; |
5508 | 0 | char *s; |
5509 | 0 | pv_spec_p nsp = 0; |
5510 | |
|
5511 | 0 | if(in==NULL || in->s==NULL || sp==NULL) |
5512 | 0 | return -1; |
5513 | 0 | p = in->s; |
5514 | 0 | if(*p==PV_MARKER) |
5515 | 0 | { |
5516 | 0 | nsp = (pv_spec_p)pkg_malloc(sizeof(pv_spec_t)); |
5517 | 0 | if(nsp==NULL) |
5518 | 0 | { |
5519 | 0 | LM_ERR("no more memory\n"); |
5520 | 0 | return -1; |
5521 | 0 | } |
5522 | 0 | s = pv_parse_spec(in, nsp); |
5523 | 0 | if(s==NULL) |
5524 | 0 | { |
5525 | 0 | LM_ERR("invalid name [%.*s]\n", in->len, in->s); |
5526 | 0 | pv_spec_free(nsp); |
5527 | 0 | return -1; |
5528 | 0 | } |
5529 | 0 | sp->pvp.pvn.type = PV_NAME_PVAR; |
5530 | 0 | sp->pvp.pvn.u.dname = (void*)nsp; |
5531 | 0 | return 0; |
5532 | 0 | } |
5533 | | /*LM_DBG("static name [%.*s]\n", in->len, in->s);*/ |
5534 | | /* always an int type from now */ |
5535 | 0 | sp->pvp.pvn.u.isname.type = 0; |
5536 | 0 | sp->pvp.pvn.type = PV_NAME_INTSTR; |
5537 | | /* do our best to convert it to an index */ |
5538 | 0 | if (str2int(in, (unsigned int *)&sp->pvp.pvn.u.isname.name.n) < 0) |
5539 | 0 | { |
5540 | | /* remember it was a string, so we can retrieve it later */ |
5541 | 0 | sp->pvp.pvn.u.isname.name.s = *in; |
5542 | 0 | sp->pvp.pvn.u.isname.type = AVP_NAME_STR; |
5543 | 0 | } |
5544 | 0 | return 0; |
5545 | |
|
5546 | 0 | } |
5547 | | |
5548 | | static int pv_get_param(struct sip_msg *msg, pv_param_t *ip, pv_value_t *res) |
5549 | 0 | { |
5550 | 0 | if (!ip) |
5551 | 0 | { |
5552 | 0 | LM_ERR("null parameter received\n"); |
5553 | 0 | return -1; |
5554 | 0 | } |
5555 | 0 | return route_params_run(msg, ip, res); |
5556 | 0 | } |
5557 | | |
5558 | | void destroy_argv_list(void) |
5559 | 0 | { |
5560 | 0 | argv_p arg; |
5561 | |
|
5562 | 0 | while (argv_vars) { |
5563 | 0 | arg = argv_vars; |
5564 | 0 | argv_vars = argv_vars->next; |
5565 | 0 | pkg_free(arg); |
5566 | 0 | } |
5567 | 0 | } |