Browse code

pv: use macro to get port based on proto

Daniel-Constantin Mierla authored on 06/07/2021 09:08:00
Showing 1 changed files
... ...
@@ -704,7 +704,7 @@ int pv_get_nh_reply(struct sip_msg *msg, pv_param_t *param,
704 704
 		host = msg->via2->host;
705 705
 	}
706 706
 	if(port==0) {
707
-		port = (msg->via2->port)?msg->via2->port:SIP_PORT;
707
+		port = GET_SIP_PORT(msg->via2->port, msg->via2->proto);
708 708
 	}
709 709
 
710 710
 	switch(param->pvn.u.isname.name.n) {
Browse code

pv: $nh(i) returns ip address family version

- 4 for ipv4; 6 for ipv6; and 0 if next hop address is not an ip address

Daniel-Constantin Mierla authored on 13/06/2021 14:43:46
Showing 1 changed files
... ...
@@ -23,6 +23,7 @@
23 23
 #include "../../core/dset.h"
24 24
 #include "../../core/onsend.h"
25 25
 #include "../../core/socket_info.h"
26
+#include "../../core/resolve.h"
26 27
 
27 28
 #include "pv_core.h"
28 29
 #include "pv_branch.h"
... ...
@@ -735,6 +736,14 @@ int pv_get_nh_reply(struct sip_msg *msg, pv_param_t *param,
735 736
 			}
736 737
 			return pv_get_strintval(msg, param, res, &sproto,
737 738
 					(int)msg->via2->proto);
739
+		case 5: /* ip family */
740
+			if(str2ip(&host)!=NULL) {
741
+				return pv_get_uintval(msg, param, res, 4);
742
+			}
743
+			if(str2ip6(&host)!=NULL) {
744
+				return pv_get_uintval(msg, param, res, 6);
745
+			}
746
+			return pv_get_uintval(msg, param, res, 0);
738 747
 	}
739 748
 
740 749
 	LM_ERR("unknown specifier\n");
... ...
@@ -797,6 +806,17 @@ int pv_get_nh(struct sip_msg *msg, pv_param_t *param,
797 806
 			return pv_get_udp(msg, param, res);
798 807
 		return pv_get_strintval(msg, param, res, &parsed_uri.transport_val,
799 808
 				(int)parsed_uri.proto);
809
+	} else if(param->pvn.u.isname.name.n==5) /* ip family */ {
810
+		if(parsed_uri.host.s==NULL || parsed_uri.host.len<=0) {
811
+			return pv_get_uintval(msg, param, res, 0);
812
+		}
813
+		if(str2ip(&parsed_uri.host)!=NULL) {
814
+			return pv_get_uintval(msg, param, res, 4);
815
+		}
816
+		if(str2ip6(&parsed_uri.host)!=NULL) {
817
+			return pv_get_uintval(msg, param, res, 6);
818
+		}
819
+		return pv_get_uintval(msg, param, res, 0);
800 820
 	}
801 821
 	LM_ERR("unknown specifier\n");
802 822
 	return pv_get_null(msg, param, res);
... ...
@@ -820,6 +840,8 @@ int pv_parse_nh_name(pv_spec_p sp, str *in)
820 840
 				sp->pvp.pvn.u.isname.name.n = 3;
821 841
 			else if(strncmp(in->s, "P", 1)==0)
822 842
 				sp->pvp.pvn.u.isname.name.n = 4;
843
+			else if(strncmp(in->s, "i", 1)==0)
844
+				sp->pvp.pvn.u.isname.name.n = 5;
823 845
 			else goto error;
824 846
 		break;
825 847
 		default:
Browse code

pv: extended $nh(k) to work for replies using 2nd via

Daniel-Constantin Mierla authored on 09/06/2021 10:02:08
Showing 1 changed files
... ...
@@ -669,6 +669,81 @@ error:
669 669
 	return -1;
670 670
 }
671 671
 
672
+/**
673
+ *
674
+ */
675
+int pv_get_nh_reply(struct sip_msg *msg, pv_param_t *param,
676
+		pv_value_t *res)
677
+{
678
+	static char rpluribuf[MAX_URI_SIZE];
679
+	str suri = STR_NULL;
680
+	str host = STR_NULL;
681
+	str sproto = STR_NULL;
682
+	unsigned int port = 0;
683
+
684
+	if(parse_headers( msg, HDR_VIA2_F, 0)==-1) {
685
+		LM_DBG("no 2nd via parsed\n");
686
+		return pv_get_null(msg, param, res);
687
+	}
688
+	if((msg->via2==0) || (msg->via2->error!=PARSE_OK)) {
689
+		return pv_get_null(msg, param, res);
690
+	}
691
+	if(msg->via2->rport && msg->via2->rport->value.s) {
692
+		LM_DBG("using 'rport'\n");
693
+		if(str2int(&msg->via2->rport->value, &port)<0) {
694
+			LM_ERR("invalid rport value\n");
695
+			return pv_get_null(msg, param, res);
696
+		}
697
+	}
698
+	if(msg->via2->received) {
699
+		LM_DBG("using 'received'\n");
700
+		host = msg->via2->received->value;
701
+	} else {
702
+		LM_DBG("using via host\n");
703
+		host = msg->via2->host;
704
+	}
705
+	if(port==0) {
706
+		port = (msg->via2->port)?msg->via2->port:SIP_PORT;
707
+	}
708
+
709
+	switch(param->pvn.u.isname.name.n) {
710
+		case 0: /* uri */
711
+			if(get_valid_proto_string(msg->via2->proto, 1, 0, &sproto)<0) {
712
+				sproto.s = "udp";
713
+				sproto.len = 3;
714
+			}
715
+			suri.len = snprintf(rpluribuf, MAX_URI_SIZE, "sip:%.*s:%u;transport=%.*s",
716
+					host.len, host.s, port, sproto.len, sproto.s);
717
+			if(suri.len<=0 || suri.len>=MAX_URI_SIZE) {
718
+				LM_DBG("building the dst uri failed (%d)\n", suri.len);
719
+				return pv_get_null(msg, param, res);
720
+			}
721
+			suri.s = rpluribuf;
722
+			return pv_get_strval(msg, param, res, &suri);
723
+		case 1: /* user - not in Via */
724
+			return pv_get_null(msg, param, res);
725
+		case 2: /* domain/host */
726
+			return pv_get_strval(msg, param, res, &host);
727
+		case 3: /* port */
728
+			return pv_get_uintval(msg, param, res, port);
729
+		case 4: /* proto */
730
+			if(get_valid_proto_string(msg->via2->proto, 0, 0, &sproto)<0) {
731
+				/* default to udp */
732
+				sproto.s = "udp";
733
+				sproto.len = 3;
734
+				return pv_get_strintval(msg, param, res, &sproto, PROTO_UDP);
735
+			}
736
+			return pv_get_strintval(msg, param, res, &sproto,
737
+					(int)msg->via2->proto);
738
+	}
739
+
740
+	LM_ERR("unknown specifier\n");
741
+	return pv_get_null(msg, param, res);
742
+}
743
+
744
+/**
745
+ *
746
+ */
672 747
 int pv_get_nh(struct sip_msg *msg, pv_param_t *param,
673 748
 		pv_value_t *res)
674 749
 {
... ...
@@ -678,8 +753,10 @@ int pv_get_nh(struct sip_msg *msg, pv_param_t *param,
678 753
 	if(msg==NULL || res==NULL)
679 754
 		return -1;
680 755
 
681
-	if(msg->first_line.type == SIP_REPLY)	/* REPLY doesnt have r/d-uri */
682
-		return pv_get_null(msg, param, res);
756
+	if(msg->first_line.type == SIP_REPLY) {
757
+		/* REPLY doesnt have r/d-uri - use second Via */
758
+		return pv_get_nh_reply(msg, param, res);
759
+	}
683 760
 
684 761
     if (msg->dst_uri.s != NULL && msg->dst_uri.len>0)
685 762
 	{
Browse code

pv: handle missing fields (otcid, instance) for $banch() and $sbranch()

Daniel-Constantin Mierla authored on 09/03/2021 10:38:26
Showing 1 changed files
... ...
@@ -93,6 +93,12 @@ int pv_get_branchx_helper(sip_msg_t *msg, pv_param_t *param,
93 93
 			if(br->location_ua_len==0)
94 94
 				return pv_get_null(msg, param, res);
95 95
 			return pv_get_strlval(msg, param, res, br->location_ua, br->location_ua_len);
96
+		case 9: /* otcpid */
97
+			return pv_get_uintval(msg, param, res, br->otcpid);
98
+		case 10: /* instance */
99
+			if(br->instance_len==0)
100
+				return pv_get_null(msg, param, res);
101
+			return pv_get_strlval(msg, param, res, br->instance, br->instance_len);
96 102
 		default:
97 103
 			/* 0 - uri */
98 104
 			return pv_get_strlval(msg, param, res, br->uri, br->len);
... ...
@@ -283,6 +289,22 @@ int pv_set_branchx_helper(sip_msg_t *msg, pv_param_t *param,
283 289
 		case 8: /* location_ua */
284 290
 			/* do nothing - cannot set the location_ua */
285 291
 		break;
292
+		case 9: /* otcpid */
293
+			if(val==NULL || (val->flags&PV_VAL_NULL))
294
+			{
295
+				br->otcpid = 0;
296
+				break;
297
+			}
298
+			if(!(val->flags&PV_VAL_INT))
299
+			{
300
+				LM_ERR("int value required to set branch flags\n");
301
+				return -1;
302
+			}
303
+			br->otcpid = val->ri;
304
+		break;
305
+		case 10: /* instance */
306
+			/* do nothing - cannot set the instance */
307
+		break;
286 308
 		default:
287 309
 			/* 0 - uri */
288 310
 			if(val==NULL || (val->flags&PV_VAL_NULL))
... ...
@@ -335,42 +357,53 @@ int pv_parse_branchx_name(pv_spec_p sp, str *in)
335 357
 
336 358
 	switch(in->len)
337 359
 	{
338
-		case 3: 
339
-			if(strncmp(in->s, "uri", 3)==0)
340
-				sp->pvp.pvn.u.isname.name.n = 0;
360
+		case 1:
361
+			if(*in->s=='q' || *in->s=='Q')
362
+				sp->pvp.pvn.u.isname.name.n = 3;
341 363
 			else goto error;
342 364
 		break;
343
-		case 7: 
344
-			if(strncmp(in->s, "dst_uri", 7)==0)
345
-				sp->pvp.pvn.u.isname.name.n = 1;
365
+		case 3:
366
+			if(strncmp(in->s, "uri", 3)==0)
367
+				sp->pvp.pvn.u.isname.name.n = 0;
346 368
 			else goto error;
347 369
 		break;
348
-		case 4: 
370
+		case 4:
349 371
 			if(strncmp(in->s, "path", 4)==0)
350 372
 				sp->pvp.pvn.u.isname.name.n = 2;
351 373
 			else if (strncmp(in->s, "ruid", 4)==0)
352 374
 				sp->pvp.pvn.u.isname.name.n = 7;
353 375
 			else goto error;
354 376
 		break;
355
-		case 1: 
356
-			if(*in->s=='q' || *in->s=='Q')
357
-				sp->pvp.pvn.u.isname.name.n = 3;
377
+		case 5:
378
+			if(strncmp(in->s, "count", 5)==0)
379
+				sp->pvp.pvn.u.isname.name.n = 5;
380
+			else if(strncmp(in->s, "flags", 5)==0)
381
+				sp->pvp.pvn.u.isname.name.n = 6;
382
+			else goto error;
383
+		break;
384
+		case 6:
385
+			if(strncmp(in->s, "otcpid", 6)==0)
386
+				sp->pvp.pvn.u.isname.name.n = 9;
387
+			else goto error;
388
+		break;
389
+		case 7:
390
+			if(strncmp(in->s, "dst_uri", 7)==0)
391
+				sp->pvp.pvn.u.isname.name.n = 1;
392
+			else goto error;
393
+		break;
394
+		case 8:
395
+			if(strncmp(in->s, "instance", 8)==0)
396
+				sp->pvp.pvn.u.isname.name.n = 10;
358 397
 			else goto error;
359 398
 		break;
360
-		case 11: 
399
+		case 11:
361 400
 			if(strncmp(in->s, "send_socket", 11)==0)
362 401
 				sp->pvp.pvn.u.isname.name.n = 4;
363 402
 			else if(strncmp(in->s, "location_ua", 11)==0)
364 403
 				sp->pvp.pvn.u.isname.name.n = 8;
365 404
 			else goto error;
366 405
 		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;
406
+
374 407
 		default:
375 408
 			goto error;
376 409
 	}
... ...
@@ -804,6 +837,7 @@ int sbranch_set_ruri(sip_msg_t *msg)
804 837
 		set_force_socket(msg, br->force_send_socket);
805 838
 
806 839
 	msg->reg_id = br->reg_id;
840
+	msg->otcpid = br->otcpid;
807 841
 	set_ruri_q(br->q);
808 842
 	old_bflags = 0;
809 843
 	getbflagsval(0, &old_bflags);
... ...
@@ -824,7 +858,9 @@ int sbranch_append(sip_msg_t *msg)
824 858
 	str path = {0};
825 859
 	str ruid = {0};
826 860
 	str location_ua = {0};
861
+	str instance = {0};
827 862
 	branch_t *br;
863
+	branch_t *newbr;
828 864
 
829 865
 	br = &_pv_sbranch;
830 866
 	if(br->len==0)
... ...
@@ -849,14 +885,19 @@ int sbranch_append(sip_msg_t *msg)
849 885
 		location_ua.s = br->location_ua;
850 886
 		location_ua.len = br->location_ua_len;
851 887
 	}
888
+	if(br->instance_len) {
889
+		instance.s = br->instance;
890
+		instance.len = br->instance_len;
891
+	}
852 892
 
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) {
893
+	newbr = ksr_push_branch(msg, &uri, &duri, &path, br->q, br->flags,
894
+					  br->force_send_socket, &instance, br->reg_id,
895
+					  &ruid, &location_ua);
896
+	if(newbr==NULL) {
857 897
 		LM_ERR("failed to append static branch\n");
858 898
 		return -1;
859 899
 	}
900
+	newbr->otcpid = br->otcpid;
860 901
 	return 0;
861 902
 }
862 903
 
Browse code

pv: use safer macros for temporarily making zero-ending strings

Daniel-Constantin Mierla authored on 28/04/2020 07:42:13
Showing 1 changed files
... ...
@@ -13,8 +13,8 @@
13 13
  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14 14
  * GNU General Public License for more details.
15 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 
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 18
  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
19 19
  */
20 20
 
... ...
@@ -241,16 +241,15 @@ int pv_set_branchx_helper(sip_msg_t *msg, pv_param_t *param,
241 241
 				br->force_send_socket = NULL;
242 242
 				break;
243 243
 			}
244
-			backup = val->rs.s[val->rs.len];
245
-			val->rs.s[val->rs.len] = '\0';
244
+			STR_VTOZ(val->rs.s[val->rs.len], backup);
246 245
 			if (parse_phostport(val->rs.s, &host.s, &host.len, &port,
247 246
 						&proto) < 0)
248 247
 			{
249 248
 				LM_ERR("invalid socket specification\n");
250
-				val->rs.s[val->rs.len] = backup;
249
+				STR_ZTOV(val->rs.s[val->rs.len], backup);
251 250
 				return -1;
252 251
 			}
253
-			val->rs.s[val->rs.len] = backup;
252
+			STR_ZTOV(val->rs.s[val->rs.len], backup);
254 253
 			si = grep_sock_info(&host, (unsigned short)port,
255 254
 					(unsigned short)proto);
256 255
 			if (si!=NULL)
Browse code

pv: new variable $rcv(key)

- available inside event_route[core:msg-received]
- get details of the received message - the key can be:
* buf - received message
* len - lenght of received message
* srcip - source ip
* rcvip - local ip where it was received
* scrport - source port
* rcvport - local port where it was received
* proto - protocol as int id
* sproto - protocol as string
* af - address family

Daniel-Constantin Mierla authored on 01/03/2019 14:06:16
Showing 1 changed files
... ...
@@ -533,6 +533,110 @@ error:
533 533
 	return -1;
534 534
 }
535 535
 
536
+int pv_get_rcv(struct sip_msg *msg, pv_param_t *param,
537
+		pv_value_t *res)
538
+{
539
+	sr_net_info_t *neti = NULL;
540
+	str s;
541
+
542
+	neti = ksr_evrt_rcvnetinfo_get();
543
+
544
+	if (neti==NULL || neti->rcv==NULL || neti->rcv->bind_address==NULL)
545
+		return pv_get_null(msg, param, res);
546
+
547
+	switch(param->pvn.u.isname.name.n)
548
+	{
549
+		case 1: /* buf */
550
+			s.s   = neti->data.s;
551
+			s.len = neti->data.len;
552
+			return pv_get_strval(msg, param, res, &s);
553
+		case 2: /* len */
554
+			return pv_get_uintval(msg, param, res,
555
+					(int)neti->data.len);
556
+		case 3: /* proto */
557
+			return pv_get_uintval(msg, param, res, (int)neti->rcv->proto);
558
+		case 4: /* srcip */
559
+			s.s = ip_addr2a(&neti->rcv->src_ip);
560
+			s.len = strlen(s.s);
561
+			return pv_get_strval(msg, param, res, &s);
562
+		case 5: /* rcvip */
563
+			s.s = ip_addr2a(&neti->rcv->dst_ip);
564
+			s.len = strlen(s.s);
565
+			return pv_get_strval(msg, param, res, &s);
566
+		case 6: /* sproto */
567
+			if(get_valid_proto_string((int)neti->rcv->proto,
568
+						0, 0, &s)<0) {
569
+				return pv_get_null(msg, param, res);
570
+			}
571
+			return pv_get_strval(msg, param, res, &s);
572
+		case 7: /* srcport */
573
+			return pv_get_uintval(msg, param, res,
574
+					(int)neti->rcv->src_port);
575
+		case 8: /* rcvport */
576
+			return pv_get_uintval(msg, param, res,
577
+					(int)neti->rcv->dst_port);
578
+		default:
579
+			/* 0 - af */
580
+			return pv_get_uintval(msg, param, res,
581
+					(int)neti->rcv->bind_address->address.af);
582
+	}
583
+
584
+	return 0;
585
+}
586
+
587
+int pv_parse_rcv_name(pv_spec_p sp, str *in)
588
+{
589
+	if(sp==NULL || in==NULL || in->len<=0)
590
+		return -1;
591
+
592
+	switch(in->len)
593
+	{
594
+		case 2:
595
+			if(strncmp(in->s, "af", 2)==0)
596
+				sp->pvp.pvn.u.isname.name.n = 0;
597
+			else goto error;
598
+		break;
599
+		case 3:
600
+			if(strncmp(in->s, "buf", 3)==0)
601
+				sp->pvp.pvn.u.isname.name.n = 1;
602
+			else if(strncmp(in->s, "len", 3)==0)
603
+				sp->pvp.pvn.u.isname.name.n = 2;
604
+			else goto error;
605
+		break;
606
+		case 5:
607
+			if(strncmp(in->s, "proto", 5)==0)
608
+				sp->pvp.pvn.u.isname.name.n = 3;
609
+			else if(strncmp(in->s, "srcip", 5)==0)
610
+				sp->pvp.pvn.u.isname.name.n = 4;
611
+			else if(strncmp(in->s, "rcvip", 5)==0)
612
+				sp->pvp.pvn.u.isname.name.n = 5;
613
+			else goto error;
614
+		break;
615
+		case 6:
616
+			if(strncmp(in->s, "sproto", 6)==0)
617
+				sp->pvp.pvn.u.isname.name.n = 6;
618
+			else goto error;
619
+		break;
620
+		case 7:
621
+			if(strncmp(in->s, "srcport", 7)==0)
622
+				sp->pvp.pvn.u.isname.name.n = 7;
623
+			else if(strncmp(in->s, "rcvport", 7)==0)
624
+				sp->pvp.pvn.u.isname.name.n = 8;
625
+			else goto error;
626
+		break;
627
+		default:
628
+			goto error;
629
+	}
630
+	sp->pvp.pvn.type = PV_NAME_INTSTR;
631
+	sp->pvp.pvn.u.isname.type = 0;
632
+
633
+	return 0;
634
+
635
+error:
636
+	LM_ERR("unknown PV rcv name %.*s\n", in->len, in->s);
637
+	return -1;
638
+}
639
+
536 640
 int pv_get_nh(struct sip_msg *msg, pv_param_t *param,
537 641
 		pv_value_t *res)
538 642
 {
Browse code

pv: correct sbranch params appending

- some params (like dest uri) were not appended to branch
due to a copy-paste typo

Dmitri Savolainen authored on 20/12/2017 10:07:35
Showing 1 changed files
... ...
@@ -730,19 +730,19 @@ int sbranch_append(sip_msg_t *msg)
730 730
 	uri.s = br->uri;
731 731
 	uri.len = br->len;
732 732
 
733
-	if(br->dst_uri_len==0) {
733
+	if(br->dst_uri_len) {
734 734
 		duri.s = br->dst_uri;
735 735
 		duri.len = br->dst_uri_len;
736 736
 	}
737
-	if(br->path_len==0) {
737
+	if(br->path_len) {
738 738
 		path.s = br->path;
739 739
 		path.len = br->path_len;
740 740
 	}
741
-	if(br->ruid_len==0) {
741
+	if(br->ruid_len) {
742 742
 		ruid.s = br->ruid;
743 743
 		ruid.len = br->ruid_len;
744 744
 	}
745
-	if(br->location_ua_len==0) {
745
+	if(br->location_ua_len) {
746 746
 		location_ua.s = br->location_ua;
747 747
 		location_ua.len = br->location_ua_len;
748 748
 	}
Browse code

core, lib, modules: updated include paths for header files

Daniel-Constantin Mierla authored on 07/12/2016 11:07:22
Showing 1 changed files
... ...
@@ -19,10 +19,10 @@
19 19
  */
20 20
 
21 21
 
22
-#include "../../parser/parse_uri.h"
23
-#include "../../dset.h"
24
-#include "../../onsend.h"
25
-#include "../../socket_info.h"
22
+#include "../../core/parser/parse_uri.h"
23
+#include "../../core/dset.h"
24
+#include "../../core/onsend.h"
25
+#include "../../core/socket_info.h"
26 26
 
27 27
 #include "pv_core.h"
28 28
 #include "pv_branch.h"
Browse code

core, lib, modules: restructured source code tree

- new folder src/ to hold the source code for main project applications
- main.c is in src/
- all core files are subfolder are in src/core/
- modules are in src/modules/
- libs are in src/lib/
- application Makefiles are in src/
- application binary is built in src/ (src/kamailio)

Daniel-Constantin Mierla authored on 07/12/2016 11:03:51
Showing 1 changed files
1 1
new file mode 100644
... ...
@@ -0,0 +1,767 @@
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 "../../parser/parse_uri.h"
23
+#include "../../dset.h"
24
+#include "../../onsend.h"
25
+#include "../../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
+			backup = val->rs.s[val->rs.len];
245
+			val->rs.s[val->rs.len] = '\0';
246
+			if (parse_phostport(val->rs.s, &host.s, &host.len, &port,
247
+						&proto) < 0)
248
+			{
249
+				LM_ERR("invalid socket specification\n");
250
+				val->rs.s[val->rs.len] = backup;
251
+				return -1;
252
+			}
253
+			val->rs.s[val->rs.len] = backup;
254
+			si = grep_sock_info(&host, (unsigned short)port,
255
+					(unsigned short)proto);
256
+			if (si!=NULL)
257
+			{
258
+				br->force_send_socket = si;
259
+			} else {
260
+				LM_WARN("no socket found to match [%.*s]\n",
261
+					val->rs.len, val->rs.s);
262
+				br->force_send_socket = NULL;
263
+			}
264
+		break;
265
+		case 5: /* count */
266
+			/* do nothing - cannot set the branch counter */
267
+		break;
268
+		case 6: /* flags */
269
+			if(val==NULL || (val->flags&PV_VAL_NULL))
270
+			{
271
+				br->flags = 0;
272
+				break;
273
+			}
274
+			if(!(val->flags&PV_VAL_INT))
275
+			{
276
+				LM_ERR("int value required to set branch flags\n");
277
+				return -1;
278
+			}
279
+			br->flags = val->ri;
280
+		break;
281
+		case 7: /* ruid */
282
+			/* do nothing - cannot set the ruid */
283
+		break;
284
+		case 8: /* location_ua */
285
+			/* do nothing - cannot set the location_ua */
286
+		break;
287
+		default:
288
+			/* 0 - uri */
289
+			if(val==NULL || (val->flags&PV_VAL_NULL))
290
+			{
291
+				if(btype==1) {
292
+					memset(br, 0, sizeof(branch_t));
293
+				} else {
294
+					drop_sip_branch(idx);
295
+				}
296
+			} else {
297
+				if(!(val->flags&PV_VAL_STR))
298
+				{
299
+					LM_ERR("str value required to set branch uri\n");
300
+					return -1;
301
+				}
302
+				if(val->rs.len<=0)
303
+				{
304
+					if(btype==1) {
305
+						memset(br, 0, sizeof(branch_t));
306
+					} else {
307
+						drop_sip_branch(idx);
308
+					}
309
+				} else {
310
+					if (unlikely(val->rs.len > MAX_URI_SIZE - 1))
311
+					{
312
+						LM_ERR("too long r-uri: %.*s\n",
313
+								val->rs.len, val->rs.s);
314
+						return -1;
315
+					}
316
+					memcpy(br->uri, val->rs.s, val->rs.len);
317
+					br->uri[val->rs.len] = 0;
318
+					br->len = val->rs.len;
319
+				}
320
+			}
321
+	}
322
+
323
+	return 0;
324
+}
325
+
326
+int pv_set_branchx(sip_msg_t *msg, pv_param_t *param,
327
+		int op, pv_value_t *val)
328
+{
329
+	return pv_set_branchx_helper(msg, param, op, val, 0);
330
+}
331
+
332
+int pv_parse_branchx_name(pv_spec_p sp, str *in)
333
+{
334
+	if(sp==NULL || in==NULL || in->len<=0)
335
+		return -1;
336
+
337
+	switch(in->len)
338
+	{
339
+		case 3: 
340
+			if(strncmp(in->s, "uri", 3)==0)
341
+				sp->pvp.pvn.u.isname.name.n = 0;
342
+			else goto error;
343
+		break;
344
+		case 7: 
345
+			if(strncmp(in->s, "dst_uri", 7)==0)
346
+				sp->pvp.pvn.u.isname.name.n = 1;
347
+			else goto error;
348
+		break;
349
+		case 4: 
350
+			if(strncmp(in->s, "path", 4)==0)
351
+				sp->pvp.pvn.u.isname.name.n = 2;
352
+			else if (strncmp(in->s, "ruid", 4)==0)
353
+				sp->pvp.pvn.u.isname.name.n = 7;
354
+			else goto error;
355
+		break;
356
+		case 1: 
357
+			if(*in->s=='q' || *in->s=='Q')
358
+				sp->pvp.pvn.u.isname.name.n = 3;
359
+			else goto error;
360
+		break;
361
+		case 11: 
362
+			if(strncmp(in->s, "send_socket", 11)==0)
363
+				sp->pvp.pvn.u.isname.name.n = 4;
364
+			else if(strncmp(in->s, "location_ua", 11)==0)
365
+				sp->pvp.pvn.u.isname.name.n = 8;
366
+			else goto error;
367
+		break;
368
+		case 5: 
369
+			if(strncmp(in->s, "count", 5)==0)
370
+				sp->pvp.pvn.u.isname.name.n = 5;
371
+			else if(strncmp(in->s, "flags", 5)==0)
372
+				sp->pvp.pvn.u.isname.name.n = 6;
373
+			else goto error;
374
+		break;
375
+		default:
376
+			goto error;
377
+	}
378
+	sp->pvp.pvn.type = PV_NAME_INTSTR;
379
+	sp->pvp.pvn.u.isname.type = 0;
380
+
381
+	return 0;
382
+
383
+error:
384
+	LM_ERR("unknown PV branch name %.*s\n", in->len, in->s);
385
+	return -1;
386
+}
387
+
388
+int pv_get_sbranch(sip_msg_t *msg, pv_param_t *param,
389
+		pv_value_t *res)
390
+{
391
+	return pv_get_branchx_helper(msg, param, res, 1);
392
+}
393
+
394
+int pv_set_sbranch(sip_msg_t *msg, pv_param_t *param,
395
+		int op, pv_value_t *val)
396
+{
397
+	return pv_set_branchx_helper(msg, param, op, val, 1);
398
+}
399
+
400
+int pv_get_sndfrom(struct sip_msg *msg, pv_param_t *param,
401
+		pv_value_t *res)
402
+{
403
+	struct onsend_info* snd_inf;
404
+	str s;
405
+
406
+	snd_inf=get_onsend_info();
407
+	if (! likely(snd_inf && snd_inf->send_sock))
408
+		return pv_get_null(msg, param, res);
409
+
410
+	switch(param->pvn.u.isname.name.n)
411
+	{
412
+		case 1: /* af */
413
+			return pv_get_uintval(msg, param, res,
414
+					(int)snd_inf->send_sock->address.af);
415
+		case 2: /* port */