pv: use safer macros for temporarily making zero-ending strings
[sip-router] / src / modules / pv / pv_branch.c
1 /*
2  * Copyright (C) 2008 Daniel-Constantin Mierla (asipto.com)
3  *
4  * This file is part of Kamailio, a free SIP server.
5  *
6  * Kamailio is free software; you can redistribute it and/or modify
7  * it under the terms of the GNU General Public License as published by
8  * the Free Software Foundation; either version 2 of the License, or
9  * (at your option) any later version
10  *
11  * Kamailio is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14  * GNU General Public License for more details.
15  *
16  * You should have received a copy of the GNU General Public License
17  * along with this program; if not, write to the Free Software
18  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
19  */
20
21
22 #include "../../core/parser/parse_uri.h"
23 #include "../../core/dset.h"
24 #include "../../core/onsend.h"
25 #include "../../core/socket_info.h"
26
27 #include "pv_core.h"
28 #include "pv_branch.h"
29
30 static branch_t _pv_sbranch;
31
32 void pv_init_sbranch(void)
33 {
34         memset(&_pv_sbranch, 0, sizeof(branch_t));
35 }
36
37 int pv_get_branchx_helper(sip_msg_t *msg, pv_param_t *param,
38                 pv_value_t *res, int btype)
39 {
40         int idx = 0;
41         int idxf = 0;
42         branch_t *br;
43
44         if(btype==1) {
45                 br = &_pv_sbranch;
46         } else {
47                 /* get the index */
48                 if(pv_get_spec_index(msg, param, &idx, &idxf)!=0)
49                 {
50                         LM_ERR("invalid index\n");
51                         return pv_get_null(msg, param, res);
52                 }
53                 br = get_sip_branch(idx);
54                 if(br==NULL) {
55                         return pv_get_null(msg, param, res);
56                 }
57         }
58
59         /* branch(count) doesn't need a valid branch, everything else does */
60         if(br->len == 0 && ( param->pvn.u.isname.name.n != 5/* count*/ ))
61         {
62                 LM_ERR("error accessing branch [%d]\n", idx);
63                 return pv_get_null(msg, param, res);
64         }
65
66         switch(param->pvn.u.isname.name.n)
67         {
68                 case 1: /* dst uri */
69                         if(br->dst_uri_len==0)
70                                 return pv_get_null(msg, param, res);
71                         return pv_get_strlval(msg, param, res, br->dst_uri, br->dst_uri_len);
72                 case 2: /* path */
73                         if(br->path_len==0)
74                                 return pv_get_null(msg, param, res);
75                         return pv_get_strlval(msg, param, res, br->path, br->path_len);
76                 case 3: /* Q */
77                         if(br->q == Q_UNSPECIFIED)
78                                 return pv_get_null(msg, param, res);
79                         return pv_get_sintval(msg, param, res, br->q);
80                 case 4: /* send socket */
81                         if(br->force_send_socket!=0)
82                                 return pv_get_strval(msg, param, res, &br->force_send_socket->sock_str);
83                         return pv_get_null(msg, param, res);
84                 case 5: /* count */
85                         return pv_get_uintval(msg, param, res, nr_branches);
86                 case 6: /* flags */
87                         return pv_get_uintval(msg, param, res, br->flags);
88                 case 7: /* ruid */
89                         if(br->ruid_len==0)
90                                 return pv_get_null(msg, param, res);
91                         return pv_get_strlval(msg, param, res, br->ruid, br->ruid_len);
92                 case 8: /* location_ua */
93                         if(br->location_ua_len==0)
94                                 return pv_get_null(msg, param, res);
95                         return pv_get_strlval(msg, param, res, br->location_ua, br->location_ua_len);
96                 default:
97                         /* 0 - uri */
98                         return pv_get_strlval(msg, param, res, br->uri, br->len);
99         }
100
101         return 0;
102 }
103
104 int pv_get_branchx(sip_msg_t *msg, pv_param_t *param,
105                 pv_value_t *res)
106 {
107         return pv_get_branchx_helper(msg, param, res, 0);
108 }
109
110 int pv_set_branchx_helper(sip_msg_t *msg, pv_param_t *param,
111                 int op, pv_value_t *val, int btype)
112 {
113         int idx = 0;
114         int idxf = 0;
115         branch_t *br;
116         struct socket_info *si;
117         int port, proto;
118         str host;
119         char backup;
120
121         if(msg==NULL || param==NULL)
122         {
123                 LM_ERR("bad parameters\n");
124                 return -1;
125         }
126
127         if(btype==1) {
128                 br = &_pv_sbranch;
129         } else {
130                 /* get the index */
131                 if(pv_get_spec_index(msg, param, &idx, &idxf)!=0)
132                 {
133                         LM_ERR("invalid index\n");
134                         return -1;
135                 }
136                 if(idx<0)
137                 {
138                         if((int)nr_branches + idx >= 0) {
139                                 idx += nr_branches;
140                         } else {
141                                 LM_ERR("index too low: %d (%u)\n", idx, nr_branches);
142                                 return -1;
143                         }
144                 }
145                 LM_DBG("managing branch index %d (%u)\n", idx, nr_branches);
146                 br = get_sip_branch(idx);
147         }
148
149         if(br==NULL)
150         {
151                 LM_DBG("no branch to operate on\n");
152                 return -1;
153         }
154
155         switch(param->pvn.u.isname.name.n)
156         {
157                 case 1: /* dst uri */
158                         if(val==NULL || (val->flags&PV_VAL_NULL))
159                         {
160                                 br->dst_uri[0] = '\0';
161                                 br->dst_uri_len = 0;
162                                 break;
163                         }
164                         if(!(val->flags&PV_VAL_STR))
165                         {
166                                 LM_ERR("str value required to set branch dst uri\n");
167                                 return -1;
168                         }
169                         if(val->rs.len<=0)
170                         {
171                                 br->dst_uri[0] = '\0';
172                                 br->dst_uri_len = 0;
173                                 break;
174                         }
175
176                         if (unlikely(val->rs.len > MAX_URI_SIZE - 1))
177                         {
178                                 LM_ERR("too long dst uri: %.*s\n",
179                                                                 val->rs.len, val->rs.s);
180                                 return -1;
181                         }
182                         memcpy(br->dst_uri, val->rs.s, val->rs.len);
183                         br->dst_uri[val->rs.len] = 0;
184                         br->dst_uri_len = val->rs.len;
185                 break;
186                 case 2: /* path */
187                         if(val==NULL || (val->flags&PV_VAL_NULL))
188                         {
189                                 br->path[0] = '\0';
190                                 br->path_len = 0;
191                                 break;
192                         }
193                         if(!(val->flags&PV_VAL_STR))
194                         {
195                                 LM_ERR("str value required to set branch path\n");
196                                 return -1;
197                         }
198                         if(val->rs.len<=0)
199                         {
200                                 br->path[0] = '\0';
201                                 br->path_len = 0;
202                                 break;
203                         }
204
205                         if (unlikely(val->rs.len > MAX_PATH_SIZE - 1))
206                         {
207                                 LM_ERR("path too long: %.*s\n",
208                                                         val->rs.len, val->rs.s);
209                                 return -1;
210                         }
211                         memcpy(br->path, val->rs.s, val->rs.len);
212                         br->path[val->rs.len] = 0;
213                         br->path_len = val->rs.len;
214                 break;
215                 case 3: /* Q */
216                         if(val==NULL || (val->flags&PV_VAL_NULL))
217                         {
218                                 br->q = Q_UNSPECIFIED;
219                                 break;
220                         }
221                         if(!(val->flags&PV_VAL_INT))
222                         {
223                                 LM_ERR("int value required to set branch q\n");
224                                 return -1;
225                         }
226                         br->q = val->ri;
227                 break;
228                 case 4: /* send socket */
229                         if(val==NULL || (val->flags&PV_VAL_NULL))
230                         {
231                                 br->force_send_socket = NULL;
232                                 break;
233                         }
234                         if(!(val->flags&PV_VAL_STR))
235                         {
236                                 LM_ERR("str value required to set branch send sock\n");
237                                 return -1;
238                         }
239                         if(val->rs.len<=0)
240                         {
241                                 br->force_send_socket = NULL;
242                                 break;
243                         }
244                         STR_VTOZ(val->rs.s[val->rs.len], backup);
245                         if (parse_phostport(val->rs.s, &host.s, &host.len, &port,
246                                                 &proto) < 0)
247                         {
248                                 LM_ERR("invalid socket specification\n");
249                                 STR_ZTOV(val->rs.s[val->rs.len], backup);
250                                 return -1;
251                         }
252                         STR_ZTOV(val->rs.s[val->rs.len], backup);
253                         si = grep_sock_info(&host, (unsigned short)port,
254                                         (unsigned short)proto);
255                         if (si!=NULL)
256                         {
257                                 br->force_send_socket = si;
258                         } else {
259                                 LM_WARN("no socket found to match [%.*s]\n",
260                                         val->rs.len, val->rs.s);
261                                 br->force_send_socket = NULL;
262                         }
263                 break;
264                 case 5: /* count */
265                         /* do nothing - cannot set the branch counter */
266                 break;
267                 case 6: /* flags */
268                         if(val==NULL || (val->flags&PV_VAL_NULL))
269                         {
270                                 br->flags = 0;
271                                 break;
272                         }
273                         if(!(val->flags&PV_VAL_INT))
274                         {
275                                 LM_ERR("int value required to set branch flags\n");
276                                 return -1;
277                         }
278                         br->flags = val->ri;
279                 break;
280                 case 7: /* ruid */
281                         /* do nothing - cannot set the ruid */
282                 break;
283                 case 8: /* location_ua */
284                         /* do nothing - cannot set the location_ua */
285                 break;
286                 default:
287                         /* 0 - uri */
288                         if(val==NULL || (val->flags&PV_VAL_NULL))
289                         {
290                                 if(btype==1) {
291                                         memset(br, 0, sizeof(branch_t));
292                                 } else {
293                                         drop_sip_branch(idx);
294                                 }
295                         } else {
296                                 if(!(val->flags&PV_VAL_STR))
297                                 {
298                                         LM_ERR("str value required to set branch uri\n");
299                                         return -1;
300                                 }
301                                 if(val->rs.len<=0)
302                                 {
303                                         if(btype==1) {
304                                                 memset(br, 0, sizeof(branch_t));
305                                         } else {
306                                                 drop_sip_branch(idx);
307                                         }
308                                 } else {
309                                         if (unlikely(val->rs.len > MAX_URI_SIZE - 1))
310                                         {
311                                                 LM_ERR("too long r-uri: %.*s\n",
312                                                                 val->rs.len, val->rs.s);
313                                                 return -1;
314                                         }
315                                         memcpy(br->uri, val->rs.s, val->rs.len);
316                                         br->uri[val->rs.len] = 0;
317                                         br->len = val->rs.len;
318                                 }
319                         }
320         }
321
322         return 0;
323 }
324
325 int pv_set_branchx(sip_msg_t *msg, pv_param_t *param,
326                 int op, pv_value_t *val)
327 {
328         return pv_set_branchx_helper(msg, param, op, val, 0);
329 }
330
331 int pv_parse_branchx_name(pv_spec_p sp, str *in)
332 {
333         if(sp==NULL || in==NULL || in->len<=0)
334                 return -1;
335
336         switch(in->len)
337         {
338                 case 3: 
339                         if(strncmp(in->s, "uri", 3)==0)
340                                 sp->pvp.pvn.u.isname.name.n = 0;
341                         else goto error;
342                 break;
343                 case 7: 
344                         if(strncmp(in->s, "dst_uri", 7)==0)
345                                 sp->pvp.pvn.u.isname.name.n = 1;
346                         else goto error;
347                 break;
348                 case 4: 
349                         if(strncmp(in->s, "path", 4)==0)
350                                 sp->pvp.pvn.u.isname.name.n = 2;
351                         else if (strncmp(in->s, "ruid", 4)==0)
352                                 sp->pvp.pvn.u.isname.name.n = 7;
353                         else goto error;
354                 break;
355                 case 1: 
356                         if(*in->s=='q' || *in->s=='Q')
357                                 sp->pvp.pvn.u.isname.name.n = 3;
358                         else goto error;
359                 break;
360                 case 11: 
361                         if(strncmp(in->s, "send_socket", 11)==0)
362                                 sp->pvp.pvn.u.isname.name.n = 4;
363                         else if(strncmp(in->s, "location_ua", 11)==0)
364                                 sp->pvp.pvn.u.isname.name.n = 8;
365                         else goto error;
366                 break;
367                 case 5: 
368                         if(strncmp(in->s, "count", 5)==0)
369                                 sp->pvp.pvn.u.isname.name.n = 5;
370                         else if(strncmp(in->s, "flags", 5)==0)
371                                 sp->pvp.pvn.u.isname.name.n = 6;
372                         else goto error;
373                 break;
374                 default:
375                         goto error;
376         }
377         sp->pvp.pvn.type = PV_NAME_INTSTR;
378         sp->pvp.pvn.u.isname.type = 0;
379
380         return 0;
381
382 error:
383         LM_ERR("unknown PV branch name %.*s\n", in->len, in->s);
384         return -1;
385 }
386
387 int pv_get_sbranch(sip_msg_t *msg, pv_param_t *param,
388                 pv_value_t *res)
389 {
390         return pv_get_branchx_helper(msg, param, res, 1);
391 }
392
393 int pv_set_sbranch(sip_msg_t *msg, pv_param_t *param,
394                 int op, pv_value_t *val)
395 {
396         return pv_set_branchx_helper(msg, param, op, val, 1);
397 }
398
399 int pv_get_sndfrom(struct sip_msg *msg, pv_param_t *param,
400                 pv_value_t *res)
401 {
402         struct onsend_info* snd_inf;
403         str s;
404
405         snd_inf=get_onsend_info();
406         if (! likely(snd_inf && snd_inf->send_sock))
407                 return pv_get_null(msg, param, res);
408
409         switch(param->pvn.u.isname.name.n)
410         {
411                 case 1: /* af */
412                         return pv_get_uintval(msg, param, res,
413                                         (int)snd_inf->send_sock->address.af);
414                 case 2: /* port */
415                         return pv_get_uintval(msg, param, res,
416                                         (int)snd_inf->send_sock->port_no);
417                 case 3: /* proto */
418                         return pv_get_uintval(msg, param, res,
419                                         (int)snd_inf->send_sock->proto);
420                 case 4: /* buf */
421                         s.s   = snd_inf->buf;
422                         s.len = snd_inf->len;
423                         return pv_get_strval(msg, param, res, &s);
424                 case 5: /* len */
425                         return pv_get_uintval(msg, param, res,
426                                         (int)snd_inf->len);
427                 case 6: /* sproto */
428                         if(get_valid_proto_string((int)snd_inf->send_sock->proto,
429                                                 0, 0, &s)<0)
430                                 return pv_get_null(msg, param, res);
431                         return pv_get_strval(msg, param, res, &s);
432                 default:
433                         /* 0 - ip */
434                         return pv_get_strval(msg, param, res,
435                                         &snd_inf->send_sock->address_str);
436         }
437
438         return 0;
439 }
440
441 int pv_get_sndto(struct sip_msg *msg, pv_param_t *param,
442                 pv_value_t *res)
443 {
444         struct onsend_info* snd_inf;
445         struct ip_addr ip;
446         str s;
447
448         snd_inf=get_onsend_info();
449         if (! likely(snd_inf && snd_inf->send_sock))
450                 return pv_get_null(msg, param, res);
451
452         switch(param->pvn.u.isname.name.n)
453         {
454                 case 1: /* af */
455                         return pv_get_uintval(msg, param, res,
456                                         (int)snd_inf->send_sock->address.af);
457                 case 2: /* port */
458                         return pv_get_uintval(msg, param, res,
459                                         (int)su_getport(snd_inf->to));
460                 case 3: /* proto */
461                         return pv_get_uintval(msg, param, res,
462                                         (int)snd_inf->send_sock->proto);
463                 case 4: /* buf */
464                         s.s   = snd_inf->buf;
465                         s.len = snd_inf->len;
466                         return pv_get_strval(msg, param, res, &s);
467                 case 5: /* len */
468                         return pv_get_uintval(msg, param, res,
469                                         (int)snd_inf->len);
470                 case 6: /* sproto */
471                         if(get_valid_proto_string((int)snd_inf->send_sock->proto,
472                                                 0, 0, &s)<0)
473                                 return pv_get_null(msg, param, res);
474                         return pv_get_strval(msg, param, res, &s);
475                 default:
476                         /* 0 - ip */
477                         su2ip_addr(&ip, snd_inf->to);
478                         s.s = ip_addr2a(&ip);
479                         s.len = strlen(s.s);
480                         return pv_get_strval(msg, param, res, &s);
481         }
482
483         return 0;
484 }
485
486 int pv_parse_snd_name(pv_spec_p sp, str *in)
487 {
488         if(sp==NULL || in==NULL || in->len<=0)
489                 return -1;
490
491         switch(in->len)
492         {
493                 case 2:
494                         if(strncmp(in->s, "ip", 2)==0)
495                                 sp->pvp.pvn.u.isname.name.n = 0;
496                         else if(strncmp(in->s, "af", 2)==0)
497                                 sp->pvp.pvn.u.isname.name.n = 1;
498                         else goto error;
499                 break;
500                 case 3:
501                         if(strncmp(in->s, "buf", 3)==0)
502                                 sp->pvp.pvn.u.isname.name.n = 4;
503                         else if(strncmp(in->s, "len", 3)==0)
504                                 sp->pvp.pvn.u.isname.name.n = 5;
505                         else goto error;
506                 break;
507                 case 4:
508                         if(strncmp(in->s, "port", 4)==0)
509                                 sp->pvp.pvn.u.isname.name.n = 2;
510                         else goto error;
511                 break;
512                 case 5:
513                         if(strncmp(in->s, "proto", 5)==0)
514                                 sp->pvp.pvn.u.isname.name.n = 3;
515                         else goto error;
516                 break;
517                 case 6:
518                         if(strncmp(in->s, "sproto", 6)==0)
519                                 sp->pvp.pvn.u.isname.name.n = 6;
520                         else goto error;
521                 break;
522                 default:
523                         goto error;
524         }
525         sp->pvp.pvn.type = PV_NAME_INTSTR;
526         sp->pvp.pvn.u.isname.type = 0;
527
528         return 0;
529
530 error:
531         LM_ERR("unknown PV snd name %.*s\n", in->len, in->s);
532         return -1;
533 }
534
535 int pv_get_rcv(struct sip_msg *msg, pv_param_t *param,
536                 pv_value_t *res)
537 {
538         sr_net_info_t *neti = NULL;
539         str s;
540
541         neti = ksr_evrt_rcvnetinfo_get();
542
543         if (neti==NULL || neti->rcv==NULL || neti->rcv->bind_address==NULL)
544                 return pv_get_null(msg, param, res);
545
546         switch(param->pvn.u.isname.name.n)
547         {
548                 case 1: /* buf */
549                         s.s   = neti->data.s;
550                         s.len = neti->data.len;
551                         return pv_get_strval(msg, param, res, &s);
552                 case 2: /* len */
553                         return pv_get_uintval(msg, param, res,
554                                         (int)neti->data.len);
555                 case 3: /* proto */
556                         return pv_get_uintval(msg, param, res, (int)neti->rcv->proto);
557                 case 4: /* srcip */
558                         s.s = ip_addr2a(&neti->rcv->src_ip);
559                         s.len = strlen(s.s);
560                         return pv_get_strval(msg, param, res, &s);
561                 case 5: /* rcvip */
562                         s.s = ip_addr2a(&neti->rcv->dst_ip);
563                         s.len = strlen(s.s);
564                         return pv_get_strval(msg, param, res, &s);
565                 case 6: /* sproto */
566                         if(get_valid_proto_string((int)neti->rcv->proto,
567                                                 0, 0, &s)<0) {
568                                 return pv_get_null(msg, param, res);
569                         }
570                         return pv_get_strval(msg, param, res, &s);
571                 case 7: /* srcport */
572                         return pv_get_uintval(msg, param, res,
573                                         (int)neti->rcv->src_port);
574                 case 8: /* rcvport */
575                         return pv_get_uintval(msg, param, res,
576                                         (int)neti->rcv->dst_port);
577                 default:
578                         /* 0 - af */
579                         return pv_get_uintval(msg, param, res,
580                                         (int)neti->rcv->bind_address->address.af);
581         }
582
583         return 0;
584 }
585
586 int pv_parse_rcv_name(pv_spec_p sp, str *in)
587 {
588         if(sp==NULL || in==NULL || in->len<=0)
589                 return -1;
590
591         switch(in->len)
592         {
593                 case 2:
594                         if(strncmp(in->s, "af", 2)==0)
595                                 sp->pvp.pvn.u.isname.name.n = 0;
596                         else goto error;
597                 break;
598                 case 3:
599                         if(strncmp(in->s, "buf", 3)==0)
600                                 sp->pvp.pvn.u.isname.name.n = 1;
601                         else if(strncmp(in->s, "len", 3)==0)
602                                 sp->pvp.pvn.u.isname.name.n = 2;
603                         else goto error;
604                 break;
605                 case 5:
606                         if(strncmp(in->s, "proto", 5)==0)
607                                 sp->pvp.pvn.u.isname.name.n = 3;
608                         else if(strncmp(in->s, "srcip", 5)==0)
609                                 sp->pvp.pvn.u.isname.name.n = 4;
610                         else if(strncmp(in->s, "rcvip", 5)==0)
611                                 sp->pvp.pvn.u.isname.name.n = 5;
612                         else goto error;
613                 break;
614                 case 6:
615                         if(strncmp(in->s, "sproto", 6)==0)
616                                 sp->pvp.pvn.u.isname.name.n = 6;
617                         else goto error;
618                 break;
619                 case 7:
620                         if(strncmp(in->s, "srcport", 7)==0)
621                                 sp->pvp.pvn.u.isname.name.n = 7;
622                         else if(strncmp(in->s, "rcvport", 7)==0)
623                                 sp->pvp.pvn.u.isname.name.n = 8;
624                         else goto error;
625                 break;
626                 default:
627                         goto error;
628         }
629         sp->pvp.pvn.type = PV_NAME_INTSTR;
630         sp->pvp.pvn.u.isname.type = 0;
631
632         return 0;
633
634 error:
635         LM_ERR("unknown PV rcv name %.*s\n", in->len, in->s);
636         return -1;
637 }
638
639 int pv_get_nh(struct sip_msg *msg, pv_param_t *param,
640                 pv_value_t *res)
641 {
642         struct sip_uri parsed_uri;
643         str uri;
644
645         if(msg==NULL || res==NULL)
646                 return -1;
647
648         if(msg->first_line.type == SIP_REPLY)   /* REPLY doesnt have r/d-uri */
649                 return pv_get_null(msg, param, res);
650
651     if (msg->dst_uri.s != NULL && msg->dst_uri.len>0)
652         {
653                 uri = msg->dst_uri;
654         } else {
655                 if (msg->new_uri.s!=NULL && msg->new_uri.len>0)
656                 {
657                         uri = msg->new_uri;
658                 } else {
659                         uri = msg->first_line.u.request.uri;
660                 }
661         }
662         if(param->pvn.u.isname.name.n==0) /* uri */
663         {
664                 return pv_get_strval(msg, param, res, &uri);
665         }
666         if(parse_uri(uri.s, uri.len, &parsed_uri)!=0)
667         {
668                 LM_ERR("failed to parse nh uri [%.*s]\n", uri.len, uri.s);
669                 return pv_get_null(msg, param, res);
670         }
671         if(param->pvn.u.isname.name.n==1) /* username */
672         {
673                 if(parsed_uri.user.s==NULL || parsed_uri.user.len<=0)
674                         return pv_get_null(msg, param, res);
675                 return pv_get_strval(msg, param, res, &parsed_uri.user);
676         } else if(param->pvn.u.isname.name.n==2) /* domain */ {
677                 if(parsed_uri.host.s==NULL || parsed_uri.host.len<=0)
678                         return pv_get_null(msg, param, res);
679                 return pv_get_strval(msg, param, res, &parsed_uri.host);
680         } else if(param->pvn.u.isname.name.n==3) /* port */ {
681                 if(parsed_uri.port.s==NULL)
682                         return pv_get_5060(msg, param, res);
683                 return pv_get_strintval(msg, param, res, &parsed_uri.port,
684                                 (int)parsed_uri.port_no);
685         } else if(param->pvn.u.isname.name.n==4) /* protocol */ {
686                 if(parsed_uri.transport_val.s==NULL)
687                         return pv_get_udp(msg, param, res);
688                 return pv_get_strintval(msg, param, res, &parsed_uri.transport_val,
689                                 (int)parsed_uri.proto);
690         }
691         LM_ERR("unknown specifier\n");
692         return pv_get_null(msg, param, res);
693 }
694
695 int pv_parse_nh_name(pv_spec_p sp, str *in)
696 {
697         if(sp==NULL || in==NULL || in->len<=0)
698                 return -1;
699
700         switch(in->len)
701         {
702                 case 1:
703                         if(strncmp(in->s, "u", 1)==0)
704                                 sp->pvp.pvn.u.isname.name.n = 0;
705                         else if(strncmp(in->s, "U", 1)==0)
706                                 sp->pvp.pvn.u.isname.name.n = 1;
707                         else if(strncmp(in->s, "d", 1)==0)
708                                 sp->pvp.pvn.u.isname.name.n = 2;
709                         else if(strncmp(in->s, "p", 1)==0)
710                                 sp->pvp.pvn.u.isname.name.n = 3;
711                         else if(strncmp(in->s, "P", 1)==0)
712                                 sp->pvp.pvn.u.isname.name.n = 4;
713                         else goto error;
714                 break;
715                 default:
716                         goto error;
717         }
718         sp->pvp.pvn.type = PV_NAME_INTSTR;
719         sp->pvp.pvn.u.isname.type = 0;
720
721         return 0;
722
723 error:
724         LM_ERR("unknown PV nh name %.*s\n", in->len, in->s);
725         return -1;
726 }
727
728 /**
729  *
730  */
731 int sbranch_set_ruri(sip_msg_t *msg)
732 {
733         str sv;
734         flag_t old_bflags;
735         branch_t *br;
736         int ret;
737
738         ret = 0;
739         br = &_pv_sbranch;
740         if(br->len==0)
741                 return -1;
742
743         sv.s = br->uri;
744         sv.len = br->len;
745
746         if (rewrite_uri(msg, &sv) < 0) {
747                 LM_ERR("unable to rewrite Request-URI\n");
748                 ret = -3;
749                 goto error;
750         }
751
752         /* reset next hop address */
753         reset_dst_uri(msg);
754         if(br->dst_uri_len>0) {
755                 sv.s = br->dst_uri;
756                 sv.len = br->dst_uri_len;
757                 if (set_dst_uri(msg, &sv) < 0) {
758                         ret = -3;
759                         goto error;
760                 }
761         }
762
763         reset_path_vector(msg);
764         if(br->path_len==0) {
765                 sv.s = br->path;
766                 sv.len = br->path_len;
767                 if(set_path_vector(msg, &sv) < 0) {
768                         ret = -4;
769                         goto error;
770                 }
771         }
772
773         reset_instance(msg);
774         if (br->instance_len) {
775                 sv.s = br->instance;
776                 sv.len = br->instance_len;
777             if (set_instance(msg, &sv) < 0) {
778                         ret = -5;
779                         goto error;
780             }
781         }
782
783         reset_ruid(msg);
784         if (br->ruid_len) {
785                 sv.s = br->ruid;
786                 sv.len = br->ruid_len;
787             if (set_ruid(msg, &sv) < 0) {
788                         ret = -6;
789                         goto error;
790             }
791         }
792
793         reset_ua(msg);
794         if (br->location_ua_len) {
795                 sv.s = br->location_ua;
796                 sv.len = br->location_ua_len;
797             if (set_ua(msg, &sv) < 0) {
798                         ret = -7;
799                         goto error;
800             }
801         }
802
803         if (br->force_send_socket)
804                 set_force_socket(msg, br->force_send_socket);
805
806         msg->reg_id = br->reg_id;
807         set_ruri_q(br->q);
808         old_bflags = 0;
809         getbflagsval(0, &old_bflags);
810         setbflagsval(0, old_bflags|br->flags);
811
812         return 0;
813 error:
814         return ret;
815 }
816
817 /**
818  *
819  */
820 int sbranch_append(sip_msg_t *msg)
821 {
822         str uri = {0};
823         str duri = {0};
824         str path = {0};
825         str ruid = {0};
826         str location_ua = {0};
827         branch_t *br;
828
829         br = &_pv_sbranch;
830         if(br->len==0)
831                 return -1;
832
833         uri.s = br->uri;
834         uri.len = br->len;
835
836         if(br->dst_uri_len) {
837                 duri.s = br->dst_uri;
838                 duri.len = br->dst_uri_len;
839         }
840         if(br->path_len) {
841                 path.s = br->path;
842                 path.len = br->path_len;
843         }
844         if(br->ruid_len) {
845                 ruid.s = br->ruid;
846                 ruid.len = br->ruid_len;
847         }
848         if(br->location_ua_len) {
849                 location_ua.s = br->location_ua;
850                 location_ua.len = br->location_ua_len;
851         }
852
853         if (append_branch(msg, &uri, &duri, &path, br->q, br->flags,
854                                           br->force_send_socket, 0 /*instance*/, br->reg_id,
855                                           &ruid, &location_ua)
856                             == -1) {
857                 LM_ERR("failed to append static branch\n");
858                 return -1;
859         }
860         return 0;
861 }
862
863 /**
864  *
865  */
866 int sbranch_reset(void)
867 {
868         memset(&_pv_sbranch, 0, sizeof(branch_t));
869         return 0;
870 }