Browse code

core/dns: dns SRV lookup, if no NAPTR available

- Resolving the first most preferred and available SRV record if no NAPTR found.
It reuse the dns protocol preference scores. Sort protocols based on this preference.

Mihály Mészáros authored on 12/11/2012 15:02:48
Showing 2 changed files
... ...
@@ -2890,7 +2890,7 @@ struct hostent* dns_naptr_sip_resolvehost(str* name, unsigned short* port,
2890 2890
 		dns_hash_put(e);
2891 2891
 	}
2892 2892
 naptr_not_found:
2893
-	return dns_srv_sip_resolvehost(name, port, proto);
2893
+	return no_naptr_srv_sip_resolvehost(name,port,proto);
2894 2894
 }
2895 2895
 #endif /* USE_NAPTR */
2896 2896
 
... ...
@@ -1448,8 +1448,142 @@ end:
1448 1448
 	return 0;
1449 1449
 }
1450 1450
 
1451
+/* Resolves SRV if no naptr found. 
1452
+ * It reuse dns_pref values and according that resolves supported protocols. 
1453
+ * If dns_pref are equal then it use udp,tcp,tls,sctp order.
1454
+ * returns: hostent struct & *port filled with the port from the SRV record;
1455
+ *  0 on error
1456
+ */
1457
+
1458
+struct hostent* no_naptr_srv_sip_resolvehost(str* name, unsigned short* port, char* proto)
1459
+{
1460
+	struct dns_srv_proto_t {
1461
+		char proto;
1462
+		int proto_pref;
1463
+	} srv_proto_list[PROTO_LAST], tmp_srv_element;
1464
+	struct hostent* he;
1465
+	str srv_name;
1466
+	static char tmp_srv[MAX_DNS_NAME]; /* tmp. buff. for SRV lookups */
1467
+	int len;
1468
+	unsigned char i,j,max,default_order=0,list_len=0;
1469
+	/* init variables */
1470
+	he=0;
1471
+	len=0;
1472
+
1473
+	if ((name->len+SRV_MAX_PREFIX_LEN+1)>MAX_DNS_NAME){
1474
+		LOG(L_WARN, "WARNING: no_naptr_srv_sip_resolvehost: domain name too long"
1475
+						" (%d), unable to perform SRV lookup\n", name->len);
1476
+	} else {
1477
+		/* if proto available, then add only the forced protocol to the list */
1478
+		if (proto && *proto==0){
1479
+			srv_proto_list[0].proto=*proto;
1480
+			list_len=1;
1481
+		} else {
1482
+	
1483
+			/*get protocols and preference scores, and add availble protocol(s) and score(s) to the list*/
1484
+			for (i=PROTO_UDP; i<PROTO_LAST;i++) {
1485
+				tmp_srv_element.proto_pref = proto_pref_score(i);
1486
+				/* if -1 so disabled continue with next protocol*/
1487
+				if (naptr_proto_supported(i) == 0 ) {
1488
+					continue;
1489
+				} else {
1490
+					srv_proto_list[i-1].proto_pref=tmp_srv_element.proto_pref;
1491
+					srv_proto_list[i-1].proto=i;
1492
+					list_len++;
1493
+				}
1494
+			};
1495
+
1496
+			/* if all protocol prefence scores equal, then set the perference to default values: udp,tcp,tls,sctp */
1497
+			for (i=1; i<list_len;i++) {
1498
+				if(srv_proto_list[0].proto_pref!=srv_proto_list[i].proto_pref){
1499
+					default_order=0;
1500
+				}
1501
+			}
1502
+			if (default_order){
1503
+				for (i=0; i<list_len;i++) {
1504
+					switch ( srv_proto_list[i].proto) {
1505
+						case PROTO_UDP:
1506
+							srv_proto_list[i].proto_pref=4;
1507
+							break;
1508
+						case PROTO_TCP:
1509
+							srv_proto_list[i].proto_pref=3;
1510
+							break;
1511
+						case PROTO_TLS:
1512
+							srv_proto_list[i].proto_pref=2;
1513
+							break;
1514
+						case PROTO_SCTP:
1515
+							srv_proto_list[i].proto_pref=1;
1516
+							break;
1517
+					}
1518
+				}
1519
+			}
1520
+
1521
+			/* sorting the list */
1522
+			for (i=0;i<list_len-1;i++) {
1523
+				max=i;
1524
+				for (j=i+1;j<list_len;j++) {
1525
+					if (srv_proto_list[j].proto_pref>srv_proto_list[max].proto_pref) { 
1526
+						max=j; 
1527
+					}
1528
+				}
1529
+				if (i!=max) {
1530
+					tmp_srv_element=srv_proto_list[i];
1531
+					srv_proto_list[i]=srv_proto_list[max];
1532
+					srv_proto_list[max]=tmp_srv_element;
1533
+				}
1534
+			}
1451 1535
 
1536
+		}
1537
+		/* looping on the ordered list until we found a protocol what has srv record */
1538
+		for (i=0; i<list_len;i++) {	
1539
+			switch (srv_proto_list[i].proto) {
1540
+				case PROTO_NONE: /* no proto specified, use udp */
1541
+					if (proto)
1542
+						*proto=PROTO_UDP;
1543
+					/* no break */
1544
+				case PROTO_UDP:
1545
+					memcpy(tmp_srv, SRV_UDP_PREFIX, SRV_UDP_PREFIX_LEN);
1546
+					memcpy(tmp_srv+SRV_UDP_PREFIX_LEN, name->s, name->len);
1547
+					tmp_srv[SRV_UDP_PREFIX_LEN + name->len] = '\0';
1548
+					len=SRV_UDP_PREFIX_LEN + name->len;
1549
+					break;
1550
+				case PROTO_TCP:
1551
+					memcpy(tmp_srv, SRV_TCP_PREFIX, SRV_TCP_PREFIX_LEN);
1552
+					memcpy(tmp_srv+SRV_TCP_PREFIX_LEN, name->s, name->len);
1553
+					tmp_srv[SRV_TCP_PREFIX_LEN + name->len] = '\0';
1554
+					len=SRV_TCP_PREFIX_LEN + name->len;
1555
+					break;
1556
+				case PROTO_TLS:
1557
+					memcpy(tmp_srv, SRV_TLS_PREFIX, SRV_TLS_PREFIX_LEN);
1558
+					memcpy(tmp_srv+SRV_TLS_PREFIX_LEN, name->s, name->len);
1559
+					tmp_srv[SRV_TLS_PREFIX_LEN + name->len] = '\0';
1560
+					len=SRV_TLS_PREFIX_LEN + name->len;
1561
+					break;
1562
+				case PROTO_SCTP:
1563
+					memcpy(tmp_srv, SRV_SCTP_PREFIX, SRV_SCTP_PREFIX_LEN);
1564
+					memcpy(tmp_srv+SRV_SCTP_PREFIX_LEN, name->s, name->len);
1565
+					tmp_srv[SRV_SCTP_PREFIX_LEN + name->len] = '\0';
1566
+					len=SRV_SCTP_PREFIX_LEN + name->len;
1567
+					break;
1568
+				default:
1569
+					LOG(L_CRIT, "BUG: sip_resolvehost: unknown proto %d\n",
1570
+							(int)srv_proto_list[i].proto);
1571
+					return 0;
1572
+			}
1573
+			/* set default port */
1574
+			if ((port)&&(*port==0)){
1575
+				*port=(srv_proto_list[i].proto==PROTO_TLS)?SIPS_PORT:SIP_PORT; /* just in case we don't find another */
1576
+			}
1577
+			srv_name.s=tmp_srv;
1578
+			srv_name.len=len;
1579
+			if ((he=dns_srv_get_he(&srv_name, port, dns_flags))!=0) {
1580
+				return he;
1581
+			}
1582
+		}
1583
+	}
1584
+	return 0;
1452 1585
 
1586
+} 
1453 1587
 
1454 1588
 /* internal sip naptr resolver function: resolves a host name trying:
1455 1589
  * - NAPTR lookup if the address is not an ip and *proto==0 and *port==0.
... ...
@@ -1515,8 +1649,8 @@ struct hostent* naptr_sip_resolvehost(str* name,  unsigned short* port,
1515 1649
 				" trying SRV lookup...\n", name->len, name->s);
1516 1650
 #endif
1517 1651
 	}
1518
-	/* fallback to normal srv lookup */
1519
-	he=srv_sip_resolvehost(name, 0, port, proto, 0, 0);
1652
+	/* fallback to srv lookup */
1653
+	no_naptr_srv_sip_resolvehost(name,port,proto);
1520 1654
 end:
1521 1655
 	if (naptr_head)
1522 1656
 		free_rdata_list(naptr_head);