Browse code

dns: fix bug when using srv failover, ipv4 and ipv6

- fix crash during ipv4->ipv6 fallback when doing srv failover and when
listening on both ipv4 and ipv6 addresses (the hostname used in the
AAAA fallback lookup was null).

Reported by: Nils Ohlmeier <nils@iptel.org>.

Andrei Pelinescu-Onciul authored on 17/10/2008 19:30:07
Showing 1 changed files
... ...
@@ -42,6 +42,8 @@
42 42
  *  2008-02-04  DNS cache options are adapted for the configuration
43 43
  *		framework (Miklos)
44 44
  *  2008-02-11  dns_cache_init cfg parameter is introduced (Miklos)
45
+ *  2008-10-17  fixed srv continue with 0 hostname (when falling back to
46
+                  aaaa) (andrei)
45 47
  */
46 48
 
47 49
 #ifdef USE_DNS_CACHE
... ...
@@ -2717,6 +2719,8 @@ inline static int dns_ip_resolve(	struct dns_hash_entry** e,
2717 2717
 									int flags)
2718 2718
 {
2719 2719
 	int ret;
2720
+	str host;
2721
+	struct dns_hash_entry* orig;
2720 2722
 
2721 2723
 	ret=-E_DNS_NO_IP;
2722 2724
 	if (*e==0){ /* first call */
... ...
@@ -2738,32 +2742,49 @@ inline static int dns_ip_resolve(	struct dns_hash_entry** e,
2738 2738
 #endif /* USE_IPV6 */
2739 2739
 	}else if ((*e)->type==T_A){
2740 2740
 		/* continue A resolving */
2741
-		ret=dns_a_resolve(e, rr_no, name, ip);
2741
+		/* retrieve host name from the hash entry  (ignore name which might
2742
+		  be null when continuing a srv lookup) */
2743
+		host.s=(*e)->name;
2744
+		host.len=(*e)->name_len;
2745
+		ret=dns_a_resolve(e, rr_no, &host, ip);
2742 2746
 #ifdef USE_IPV6
2743 2747
 		if (ret>=0) return ret;
2744 2748
 		if (!(flags&(DNS_IPV6_ONLY|DNS_IPV6_FIRST|DNS_IPV4_ONLY))){
2745 2749
 			/* not found, try with AAAA */
2746
-			dns_hash_put(*e);
2750
+			orig=*e;
2747 2751
 			*e=0;
2748 2752
 			*rr_no=0;
2749
-			ret=dns_aaaa_resolve(e, rr_no, name, ip);
2753
+			ret=dns_aaaa_resolve(e, rr_no, &host, ip);
2754
+			/* delay original record release until we're finished with host*/
2755
+			dns_hash_put(orig);
2750 2756
 		}
2751 2757
 #endif /* USE_IPV6 */
2752 2758
 	}else if ((*e)->type==T_AAAA){
2759
+		/* retrieve host name from the hash entry  (ignore name which might
2760
+		  be null when continuing a srv lookup) */
2761
+		host.s=(*e)->name;
2762
+		host.len=(*e)->name_len;
2753 2763
 #ifdef USE_IPV6
2754 2764
 		/* continue AAAA resolving */
2755
-		ret=dns_aaaa_resolve(e, rr_no, name, ip);
2765
+		ret=dns_aaaa_resolve(e, rr_no, &host, ip);
2756 2766
 		if (ret>=0) return ret;
2757 2767
 		if ((flags&DNS_IPV6_FIRST) && !(flags&DNS_IPV6_ONLY)){
2758 2768
 			/* not found, try with A */
2759
-			dns_hash_put(*e);
2769
+			orig=*e;
2760 2770
 			*e=0;
2761 2771
 			*rr_no=0;
2762
-			ret=dns_a_resolve(e, rr_no, name, ip);
2772
+			ret=dns_a_resolve(e, rr_no, &host, ip);
2773
+			/* delay original record release until we're finished with host*/
2774
+			dns_hash_put(orig);
2763 2775
 		}
2764 2776
 #else /* USE_IPV6 */
2765 2777
 		/* ipv6 disabled, try with A */
2766
-		ret=dns_a_resolve(e, rr_no, name, ip);
2778
+		orig=*e;
2779
+		*e=0;
2780
+		*rr_no=0;
2781
+		ret=dns_a_resolve(e, rr_no, &host, ip);
2782
+		/* delay original record release until we're finished with host*/
2783
+		dns_hash_put(orig);
2767 2784
 #endif /* USE_IPV6 */
2768 2785
 	}else{
2769 2786
 		LOG(L_CRIT, "BUG: dns_ip_resolve: invalid record type %d\n",