Browse code

nathelper: new nat test (512) based on target addresses

- return true if the target proto is ws or wss
- return true if the target addresses are different
- for requests it compares r-uri with d-uri
- for replies compares 2nd Via host and port with received and rport

Daniel-Constantin Mierla authored on 06/07/2021 09:08:50
Showing 1 changed files
... ...
@@ -101,6 +101,7 @@ MODULE_VERSION
101 101
 #define NAT_UAC_TEST_WS 0x40
102 102
 #define NAT_UAC_TEST_C_PORT 0x80
103 103
 #define NAT_UAC_TEST_SDP_CLINE 0x100
104
+#define NAT_UAC_TEST_DEST 0x200
104 105
 
105 106
 #define DEFAULT_NATPING_STATE 1
106 107
 
... ...
@@ -1540,6 +1541,125 @@ static int via_1918(struct sip_msg *msg)
1540 1541
 	return (is1918addr(&(msg->via1->host)) == 1) ? 1 : 0;
1541 1542
 }
1542 1543
 
1544
+/*
1545
+ * test if destination address is different than R-URI/2nd Via
1546
+ * - ws/wss target is true
1547
+ */
1548
+static int nh_test_destination(sip_msg_t *msg)
1549
+{
1550
+	str rhost = STR_NULL;
1551
+	int rport = 0;
1552
+	str dhost = STR_NULL;
1553
+	int dport = 0;
1554
+	sip_uri_t pduri;
1555
+	ip_addr_t *rhostip = NULL;
1556
+	ip_addr_t *dhostip = NULL;
1557
+
1558
+	if(msg==NULL)
1559
+		return -1;
1560
+
1561
+	if(msg->first_line.type == SIP_REPLY) {
1562
+		if(parse_headers(msg, HDR_VIA2_F, 0)==-1) {
1563
+			LM_DBG("no 2nd via parsed\n");
1564
+			return 0;
1565
+		}
1566
+		if((msg->via2==0) || (msg->via2->error!=PARSE_OK)) {
1567
+			return -1;
1568
+		}
1569
+		if(msg->via2->proto==PROTO_WSS || msg->via2->proto==PROTO_WS) {
1570
+			/* going to ws/wss */
1571
+			return 1;
1572
+		}
1573
+		if(msg->via2->rport && msg->via2->rport->value.s
1574
+				 && msg->via2->rport->value.len>0) {
1575
+			if(str2sint(&msg->via2->rport->value, &dport)<0) {
1576
+				LM_ERR("invalid rport value\n");
1577
+				return -1;
1578
+			}
1579
+		}
1580
+		if(dport!=0) {
1581
+			rport = GET_SIP_PORT(msg->via2->port, msg->via2->proto);
1582
+			if(dport != rport) {
1583
+				/* ports are different */
1584
+				return 1;
1585
+			}
1586
+		}
1587
+		if(!msg->via2->received) {
1588
+			/* no received param - going to Via host */
1589
+			return 0;
1590
+		}
1591
+		dhost = msg->via2->received->value;
1592
+		rhost = msg->via2->host;
1593
+	} else {
1594
+		if(msg->dst_uri.s==NULL || msg->dst_uri.len<=0) {
1595
+			/* no destination uri - target is r-uri */
1596
+			if(msg->parsed_uri_ok==0 /* R-URI not parsed*/
1597
+					&& parse_sip_msg_uri(msg)<0) {
1598
+				LM_ERR("failed to parse the R-URI\n");
1599
+				return -1;
1600
+			}
1601
+			if(msg->parsed_uri.proto==PROTO_WSS
1602
+					|| msg->parsed_uri.proto==PROTO_WS) {
1603
+				/* going to ws/wss */
1604
+				return 1;
1605
+			}
1606
+			return 0;
1607
+		}
1608
+		if(parse_uri(msg->dst_uri.s, msg->dst_uri.len, &pduri)!=0) {
1609
+			LM_ERR("failed to parse dst uri [%.*s]\n",
1610
+					msg->dst_uri.len, msg->dst_uri.s);
1611
+			return -1;
1612
+		}
1613
+		if(pduri.proto==PROTO_WSS || pduri.proto==PROTO_WS) {
1614
+			/* going to ws/wss */
1615
+			return 1;
1616
+		}
1617
+		if(msg->parsed_uri_ok==0 /* R-URI not parsed*/
1618
+				&& parse_sip_msg_uri(msg)<0) {
1619
+			LM_ERR("failed to parse the R-URI\n");
1620
+			return -1;
1621
+		}
1622
+		dport = GET_SIP_PORT(pduri.port_no, pduri.proto);
1623
+		rport = GET_SIP_PORT(msg->parsed_uri.port_no, msg->parsed_uri.proto);
1624
+		if(dport != rport) {
1625
+			/* ports are different */
1626
+			return 1;
1627
+		}
1628
+		dhost = pduri.host;
1629
+		rhost = msg->parsed_uri.host;
1630
+	}
1631
+	if(dhost.s==NULL || dhost.len<=0) {
1632
+		return 0;
1633
+	}
1634
+	dhostip = str2ipx(&dhost);
1635
+	rhostip = str2ipx(&rhost);
1636
+	if(dhostip==NULL && rhostip==NULL) {
1637
+		/* both are hostnames - do str comparison */
1638
+		if(rhost.s==NULL || rhost.len<=0) {
1639
+			return 0;
1640
+		}
1641
+		if(rhost.len != dhost.len) {
1642
+			/* different in length */
1643
+			return 1;
1644
+		}
1645
+		if(memcmp(rhost.s, dhost.s, dhost.len)!=0) {
1646
+			/* different in content */
1647
+			return 1;
1648
+		}
1649
+		return 0;
1650
+	}
1651
+	if(dhostip==NULL || rhostip==NULL) {
1652
+		/* different in content */
1653
+		return 1;
1654
+	}
1655
+	if(ip_addr_cmp(dhostip, rhostip)) {
1656
+		/* same ip addresses */
1657
+		return 0;
1658
+	}
1659
+	/* different ip addresses */
1660
+	return 1;
1661
+}
1662
+
1543 1663
 static int nat_uac_test(struct sip_msg *msg, int tests)
1544 1664
 {
1545 1665
 	/* return true if any of the NAT-UAC tests holds */
... ...
@@ -1599,6 +1719,13 @@ static int nat_uac_test(struct sip_msg *msg, int tests)
1599 1719
 	if((tests & NAT_UAC_TEST_SDP_CLINE) && (test_sdp_cline(msg) > 0))
1600 1720
 		return 1;
1601 1721
 
1722
+	/**
1723
+	* test if destination address is different than R-URI/2ndVia
1724
+	* - ws/wss target is true
1725
+	*/
1726
+	if((tests & NAT_UAC_TEST_DEST) && (nh_test_destination(msg) > 0))
1727
+		return 1;
1728
+
1602 1729
 	/* no test succeeded */
1603 1730
 	return -1;
1604 1731
 }