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