Browse code

fix dns srv failover when no UDP record is present

- refactored code for srv lookup to have less code duplication

√ėyvind Kolbu authored on 20/10/2013 20:04:16
Showing 3 changed files
... ...
@@ -2692,33 +2692,11 @@ struct hostent* dns_srv_sip_resolvehost(str* name, unsigned short* port,
2692 2692
 			}
2693 2693
 
2694 2694
 			switch(srv_proto){
2695
-				case PROTO_NONE: /* no proto specified, use udp */
2696
-					if (proto)
2697
-						*proto=PROTO_UDP;
2698
-					/* no break */
2699 2695
 				case PROTO_UDP:
2700
-					memcpy(tmp, SRV_UDP_PREFIX, SRV_UDP_PREFIX_LEN);
2701
-					memcpy(tmp+SRV_UDP_PREFIX_LEN, name->s, name->len);
2702
-					tmp[SRV_UDP_PREFIX_LEN + name->len] = '\0';
2703
-					len=SRV_UDP_PREFIX_LEN + name->len;
2704
-					break;
2705 2696
 				case PROTO_TCP:
2706
-					memcpy(tmp, SRV_TCP_PREFIX, SRV_TCP_PREFIX_LEN);
2707
-					memcpy(tmp+SRV_TCP_PREFIX_LEN, name->s, name->len);
2708
-					tmp[SRV_TCP_PREFIX_LEN + name->len] = '\0';
2709
-					len=SRV_TCP_PREFIX_LEN + name->len;
2710
-					break;
2711 2697
 				case PROTO_TLS:
2712
-					memcpy(tmp, SRV_TLS_PREFIX, SRV_TLS_PREFIX_LEN);
2713
-					memcpy(tmp+SRV_TLS_PREFIX_LEN, name->s, name->len);
2714
-					tmp[SRV_TLS_PREFIX_LEN + name->len] = '\0';
2715
-					len=SRV_TLS_PREFIX_LEN + name->len;
2716
-					break;
2717 2698
 				case PROTO_SCTP:
2718
-					memcpy(tmp, SRV_SCTP_PREFIX, SRV_SCTP_PREFIX_LEN);
2719
-					memcpy(tmp+SRV_SCTP_PREFIX_LEN, name->s, name->len);
2720
-					tmp[SRV_SCTP_PREFIX_LEN + name->len] = '\0';
2721
-					len=SRV_SCTP_PREFIX_LEN + name->len;
2699
+					create_srv_name(srv_proto, name, tmp);
2722 2700
 					break;
2723 2701
 				default:
2724 2702
 					LOG(L_CRIT, "BUG: sip_resolvehost: unknown proto %d\n",
... ...
@@ -3236,23 +3214,24 @@ error:
3236 3236
  * h must be initialized prior to  calling this function and can be used to
3237 3237
  * get the subsequent ips
3238 3238
  * returns:  <0 on error
3239
- *            0 on success and it fills *ip, *port, dns_sip_resolve_h
3240
- * WARNING: when finished, dns_sip_resolve_put(h) must be called!
3239
+ *            0 on success and it fills *ip, *port, *h
3241 3240
  */
3242 3241
 inline static int dns_srv_sip_resolve(struct dns_srv_handle* h,  str* name,
3243 3242
 						struct ip_addr* ip, unsigned short* port, char* proto,
3244 3243
 						int flags)
3245 3244
 {
3245
+	struct dns_srv_proto srv_proto_list[PROTO_LAST];
3246 3246
 	static char tmp[MAX_DNS_NAME]; /* tmp. buff. for SRV lookups */
3247
-	int len;
3248 3247
 	str srv_name;
3249 3248
 	struct ip_addr* tmp_ip;
3250 3249
 	int ret;
3251 3250
 	struct hostent* he;
3252
-	char srv_proto;
3251
+	size_t i,list_len;
3252
+	char origproto;
3253 3253
 
3254
+	origproto = *proto;
3254 3255
 	if (dns_hash==0){ /* not init => use normal, non-cached version */
3255
-		LOG(L_WARN, "WARNING: dns_sip_resolve: called before dns cache"
3256
+		LOG(L_WARN, "WARNING: dns_srv_sip_resolve: called before dns cache"
3256 3257
 					" initialization\n");
3257 3258
 		h->srv=h->a=0;
3258 3259
 		he=_sip_resolvehost(name, port, proto);
... ...
@@ -3262,25 +3241,19 @@ inline static int dns_srv_sip_resolve(struct dns_srv_handle* h,  str* name,
3262 3262
 		}
3263 3263
 		return -E_DNS_NO_SRV;
3264 3264
 	}
3265
-	len=0;
3266 3265
 	if ((h->srv==0) && (h->a==0)){ /* first call */
3267
-		if (proto){ /* makes sure we have a protocol set*/
3268
-			if (*proto==0)
3269
-				*proto=srv_proto=PROTO_UDP; /* default */
3270
-			else
3271
-				srv_proto=*proto;
3272
-		}else{
3273
-			srv_proto=PROTO_UDP;
3266
+		if (proto && *proto==0){ /* makes sure we have a protocol set*/
3267
+			*proto=PROTO_UDP; /* default */
3274 3268
 		}
3275
-		h->port=(srv_proto==PROTO_TLS)?SIPS_PORT:SIP_PORT; /* just in case we
3269
+		h->port=(*proto==PROTO_TLS)?SIPS_PORT:SIP_PORT; /* just in case we
3276 3270
 														don't find another */
3277
-		h->proto=srv_proto; /* store initial protocol */
3271
+		h->proto=*proto; /* store initial protocol */
3278 3272
 		if (port){
3279 3273
 			if (*port==0){
3280 3274
 				/* try SRV if initial call & no port specified
3281 3275
 				 * (draft-ietf-sip-srv-06) */
3282 3276
 				if ((name->len+SRV_MAX_PREFIX_LEN+1)>MAX_DNS_NAME){
3283
-					LOG(L_WARN, "WARNING: dns_sip_resolvehost: domain name too"
3277
+					LOG(L_WARN, "WARNING: dns_srv_sip_resolve: domain name too"
3284 3278
 								" long (%d), unable to perform SRV lookup\n",
3285 3279
 								name->len);
3286 3280
 				}else{
... ...
@@ -3299,51 +3272,33 @@ inline static int dns_srv_sip_resolve(struct dns_srv_handle* h,  str* name,
3299 3299
 						return 0;
3300 3300
 					}
3301 3301
 
3302
-					switch(srv_proto){
3303
-						case PROTO_NONE: /* no proto specified, use udp */
3304
-							if (proto)
3305
-								*proto=PROTO_UDP;
3306
-							/* no break */
3307
-						case PROTO_UDP:
3308
-							memcpy(tmp, SRV_UDP_PREFIX, SRV_UDP_PREFIX_LEN);
3309
-							memcpy(tmp+SRV_UDP_PREFIX_LEN, name->s, name->len);
3310
-							tmp[SRV_UDP_PREFIX_LEN + name->len] = '\0';
3311
-							len=SRV_UDP_PREFIX_LEN + name->len;
3312
-							break;
3313
-						case PROTO_TCP:
3314
-							memcpy(tmp, SRV_TCP_PREFIX, SRV_TCP_PREFIX_LEN);
3315
-							memcpy(tmp+SRV_TCP_PREFIX_LEN, name->s, name->len);
3316
-							tmp[SRV_TCP_PREFIX_LEN + name->len] = '\0';
3317
-							len=SRV_TCP_PREFIX_LEN + name->len;
3318
-							break;
3319
-						case PROTO_TLS:
3320
-							memcpy(tmp, SRV_TLS_PREFIX, SRV_TLS_PREFIX_LEN);
3321
-							memcpy(tmp+SRV_TLS_PREFIX_LEN, name->s, name->len);
3322
-							tmp[SRV_TLS_PREFIX_LEN + name->len] = '\0';
3323
-							len=SRV_TLS_PREFIX_LEN + name->len;
3324
-							break;
3325
-						case PROTO_SCTP:
3326
-							memcpy(tmp, SRV_SCTP_PREFIX, SRV_SCTP_PREFIX_LEN);
3327
-							memcpy(tmp+SRV_SCTP_PREFIX_LEN, name->s, name->len);
3328
-							tmp[SRV_SCTP_PREFIX_LEN + name->len] = '\0';
3329
-							len=SRV_SCTP_PREFIX_LEN + name->len;
3330
-							break;
3331
-						default:
3332
-							LOG(L_CRIT, "BUG: sip_resolvehost: "
3333
-									"unknown proto %d\n", (int)srv_proto);
3334
-							return -E_DNS_CRITICAL;
3335
-					}
3336
-					srv_name.s=tmp;
3337
-					srv_name.len=len;
3338
-					if ((ret=dns_srv_resolve_ip(h, &srv_name, ip,
3339
-															port, flags))>=0)
3340
-					{
3302
+					/* looping on the ordered list until we found a protocol what has srv record */
3303
+					list_len = create_srv_pref_list(&origproto, srv_proto_list);
3304
+					for (i=0; i<list_len;i++) {
3305
+						switch (srv_proto_list[i].proto) {
3306
+							case PROTO_UDP:
3307
+							case PROTO_TCP:
3308
+							case PROTO_TLS:
3309
+							case PROTO_SCTP:
3310
+								create_srv_name(srv_proto_list[i].proto, name, tmp);
3311
+								break;
3312
+							default:
3313
+								LOG(L_CRIT, "BUG: dns_srv_sip_resolve: "
3314
+										"unknown proto %d\n", (int)srv_proto_list[i].proto);
3315
+								return -E_DNS_CRITICAL;
3316
+						}
3317
+						srv_name.s=tmp;
3318
+						srv_name.len=strlen(tmp);
3319
+						if ((ret=dns_srv_resolve_ip(h, &srv_name, ip, port, flags))>=0)
3320
+						{
3321
+							*proto = srv_proto_list[i].proto;
3341 3322
 #ifdef DNS_CACHE_DEBUG
3342
-						DBG("dns_sip_resolve(%.*s, %d, %d), srv0, ret=%d\n",
3343
-							name->len, name->s, h->srv_no, h->ip_no, ret);
3323
+							DBG("dns_srv_sip_resolve(%.*s, %d, %d), srv0, ret=%d\n",
3324
+								name->len, name->s, h->srv_no, h->ip_no, ret);
3344 3325
 #endif
3345
-						/* proto already set */
3346
-						return ret;
3326
+							/* proto already set */
3327
+							return ret;
3328
+						}
3347 3329
 					}
3348 3330
 				}
3349 3331
 			}else{ /* if (*port==0) */
... ...
@@ -3358,13 +3313,12 @@ inline static int dns_srv_sip_resolve(struct dns_srv_handle* h,  str* name,
3358 3358
 			ret=dns_srv_resolve_ip(h, &srv_name, ip, port, flags);
3359 3359
 			if (proto)
3360 3360
 				*proto=h->proto;
3361
-			DBG("dns_sip_resolve(%.*s, %d, %d), srv, ret=%d\n",
3361
+			DBG("dns_srv_sip_resolve(%.*s, %d, %d), srv, ret=%d\n",
3362 3362
 					name->len, name->s, h->srv_no, h->ip_no, ret);
3363 3363
 			return ret;
3364 3364
 	}
3365
-/*skip_srv:*/
3366 3365
 	if (name->len >= MAX_DNS_NAME) {
3367
-		LOG(L_ERR, "dns_sip_resolve: domain name too long\n");
3366
+		LOG(L_ERR, "dns_srv_sip_resolve: domain name too long\n");
3368 3367
 		return -E_DNS_NAME_TOO_LONG;
3369 3368
 	}
3370 3369
 	ret=dns_ip_resolve(&h->a, &h->ip_no, name, ip, flags);
... ...
@@ -3373,7 +3327,7 @@ inline static int dns_srv_sip_resolve(struct dns_srv_handle* h,  str* name,
3373 3373
 	if (proto)
3374 3374
 		*proto=h->proto;
3375 3375
 #ifdef DNS_CACHE_DEBUG
3376
-	DBG("dns_sip_resolve(%.*s, %d, %d), ip, ret=%d\n",
3376
+	DBG("dns_srv_sip_resolve(%.*s, %d, %d), ip, ret=%d\n",
3377 3377
 			name->len, name->s, h->srv_no, h->ip_no, ret);
3378 3378
 #endif
3379 3379
 	return ret;
... ...
@@ -3403,11 +3357,12 @@ inline static int dns_naptr_sip_resolve(struct dns_srv_handle* h,  str* name,
3403 3403
 	struct ip_addr* tmp_ip;
3404 3404
 	naptr_bmp_t tried_bmp;
3405 3405
 	struct dns_hash_entry* e;
3406
-	char n_proto;
3406
+	char n_proto, origproto;
3407 3407
 	str srv_name;
3408 3408
 	int ret;
3409 3409
 
3410 3410
 	ret=-E_DNS_NO_NAPTR;
3411
+	origproto=*proto;
3411 3412
 	if (dns_hash==0){ /* not init => use normal, non-cached version */
3412 3413
 		LOG(L_WARN, "WARNING: dns_sip_resolve: called before dns cache"
3413 3414
 					" initialization\n");
... ...
@@ -3463,6 +3418,7 @@ inline static int dns_naptr_sip_resolve(struct dns_srv_handle* h,  str* name,
3463 3463
 								from previous dns_srv_sip_resolve calls */
3464 3464
 	}
3465 3465
 naptr_not_found:
3466
+	*proto=origproto;
3466 3467
 	return dns_srv_sip_resolve(h, name, ip, port, proto, flags);
3467 3468
 }
3468 3469
 #endif /* USE_NAPTR */
... ...
@@ -3480,7 +3436,6 @@ naptr_not_found:
3480 3480
  * get the subsequent ips
3481 3481
  * returns:  <0 on error
3482 3482
  *            0 on success and it fills *ip, *port, dns_sip_resolve_h
3483
- * WARNING: when finished, dns_sip_resolve_put(h) must be called!
3484 3483
  */
3485 3484
 int dns_sip_resolve(struct dns_srv_handle* h,  str* name,
3486 3485
 						struct ip_addr* ip, unsigned short* port, char* proto,
... ...
@@ -1193,7 +1193,7 @@ struct hostent* srv_sip_resolvehost(str* name, int zt, unsigned short* port,
1193 1193
 	srv_head=0;
1194 1194
 	srv_target=0;
1195 1195
 	if (name->len >= MAX_DNS_NAME) {
1196
-		LOG(L_ERR, "sip_resolvehost: domain name too long\n");
1196
+		LOG(L_ERR, "srv_sip_resolvehost: domain name too long\n");
1197 1197
 		he=0;
1198 1198
 		goto end;
1199 1199
 	}
... ...
@@ -1236,37 +1236,19 @@ struct hostent* srv_sip_resolvehost(str* name, int zt, unsigned short* port,
1236 1236
 			goto end;
1237 1237
 		}
1238 1238
 		if ((name->len+SRV_MAX_PREFIX_LEN+1)>MAX_DNS_NAME){
1239
-			LOG(L_WARN, "WARNING: sip_resolvehost: domain name too long (%d),"
1239
+			LOG(L_WARN, "WARNING: srv_sip_resolvehost: domain name too long (%d),"
1240 1240
 						" unable to perform SRV lookup\n", name->len);
1241 1241
 		}else{
1242 1242
 			
1243 1243
 			switch(srv_proto){
1244
-				case PROTO_NONE: /* no proto specified, use udp */
1245
-					if (proto)
1246
-						*proto=PROTO_UDP;
1247
-					/* no break */
1248 1244
 				case PROTO_UDP:
1249
-					memcpy(tmp, SRV_UDP_PREFIX, SRV_UDP_PREFIX_LEN);
1250
-					memcpy(tmp+SRV_UDP_PREFIX_LEN, name->s, name->len);
1251
-					tmp[SRV_UDP_PREFIX_LEN + name->len] = '\0';
1252
-					break;
1253 1245
 				case PROTO_TCP:
1254
-					memcpy(tmp, SRV_TCP_PREFIX, SRV_TCP_PREFIX_LEN);
1255
-					memcpy(tmp+SRV_TCP_PREFIX_LEN, name->s, name->len);
1256
-					tmp[SRV_TCP_PREFIX_LEN + name->len] = '\0';
1257
-					break;
1258 1246
 				case PROTO_TLS:
1259
-					memcpy(tmp, SRV_TLS_PREFIX, SRV_TLS_PREFIX_LEN);
1260
-					memcpy(tmp+SRV_TLS_PREFIX_LEN, name->s, name->len);
1261
-					tmp[SRV_TLS_PREFIX_LEN + name->len] = '\0';
1262
-					break;
1263 1247
 				case PROTO_SCTP:
1264
-					memcpy(tmp, SRV_SCTP_PREFIX, SRV_SCTP_PREFIX_LEN);
1265
-					memcpy(tmp+SRV_SCTP_PREFIX_LEN, name->s, name->len);
1266
-					tmp[SRV_SCTP_PREFIX_LEN + name->len] = '\0';
1248
+					create_srv_name(srv_proto, name, tmp);
1267 1249
 					break;
1268 1250
 				default:
1269
-					LOG(L_CRIT, "BUG: sip_resolvehost: unknown proto %d\n",
1251
+					LOG(L_CRIT, "BUG: srv_sip_resolvehost: unknown proto %d\n",
1270 1252
 							srv_proto);
1271 1253
 					he=0;
1272 1254
 					goto end;
... ...
@@ -1278,7 +1260,7 @@ do_srv:
1278 1278
 				if (l->type!=T_SRV) continue; 
1279 1279
 				srv=(struct srv_rdata*) l->rdata;
1280 1280
 				if (srv==0){
1281
-					LOG(L_CRIT, "sip_resolvehost: BUG: null rdata\n");
1281
+					LOG(L_CRIT, "srv_sip_resolvehost: BUG: null rdata\n");
1282 1282
 					/* cleanup on exit only */
1283 1283
 					break;
1284 1284
 				}
... ...
@@ -1286,7 +1268,7 @@ do_srv:
1286 1286
 				if (he!=0){
1287 1287
 					/* we found it*/
1288 1288
 #ifdef RESOLVE_DBG
1289
-					DBG("sip_resolvehost: found SRV(%s) = %s:%d in AR\n",
1289
+					DBG("srv_sip_resolvehost: found SRV(%s) = %s:%d in AR\n",
1290 1290
 							srv_target, srv->name, srv->port);
1291 1291
 #endif
1292 1292
 					*port=srv->port;
... ...
@@ -1299,7 +1281,7 @@ do_srv:
1299 1299
 				if (l->type!=T_SRV) continue; /*should never happen*/
1300 1300
 				srv=(struct srv_rdata*) l->rdata;
1301 1301
 				if (srv==0){
1302
-					LOG(L_CRIT, "sip_resolvehost: BUG: null rdata\n");
1302
+					LOG(L_CRIT, "srv_sip_resolvehost: BUG: null rdata\n");
1303 1303
 					/* cleanup on exit only */
1304 1304
 					break;
1305 1305
 				}
... ...
@@ -1307,7 +1289,7 @@ do_srv:
1307 1307
 				if (he!=0){
1308 1308
 					/* we found it*/
1309 1309
 #ifdef RESOLVE_DBG
1310
-					DBG("sip_resolvehost: SRV(%s) = %s:%d\n",
1310
+					DBG("srv_sip_resolvehost: SRV(%s) = %s:%d\n",
1311 1311
 							srv_target, srv->name, srv->port);
1312 1312
 #endif
1313 1313
 					*port=srv->port;
... ...
@@ -1323,12 +1305,11 @@ do_srv:
1323 1323
 			}
1324 1324
 			/* cleanup on exit */
1325 1325
 #ifdef RESOLVE_DBG
1326
-			DBG("sip_resolvehost: no SRV record found for %.*s," 
1326
+			DBG("srv_sip_resolvehost: no SRV record found for %.*s," 
1327 1327
 					" trying 'normal' lookup...\n", name->len, name->s);
1328 1328
 #endif
1329 1329
 		}
1330 1330
 	}
1331
-/*skip_srv:*/
1332 1331
 	if (likely(!zt)){
1333 1332
 		memcpy(tmp, name->s, name->len);
1334 1333
 		tmp[name->len] = '\0';
... ...
@@ -1429,6 +1410,89 @@ end:
1429 1429
 	return 0;
1430 1430
 }
1431 1431
 
1432
+/* Prepend srv prefix according to the proto. */
1433
+void create_srv_name(char proto, str *name, char *srv) {
1434
+	switch (proto) {
1435
+		case PROTO_UDP:
1436
+			memcpy(srv, SRV_UDP_PREFIX, SRV_UDP_PREFIX_LEN);
1437
+			memcpy(srv+SRV_UDP_PREFIX_LEN, name->s, name->len);
1438
+			srv[SRV_UDP_PREFIX_LEN + name->len] = '\0';
1439
+			break;
1440
+		case PROTO_TCP:
1441
+			memcpy(srv, SRV_TCP_PREFIX, SRV_TCP_PREFIX_LEN);
1442
+			memcpy(srv+SRV_TCP_PREFIX_LEN, name->s, name->len);
1443
+			srv[SRV_TCP_PREFIX_LEN + name->len] = '\0';
1444
+			break;
1445
+		case PROTO_TLS:
1446
+			memcpy(srv, SRV_TLS_PREFIX, SRV_TLS_PREFIX_LEN);
1447
+			memcpy(srv+SRV_TLS_PREFIX_LEN, name->s, name->len);
1448
+			srv[SRV_TLS_PREFIX_LEN + name->len] = '\0';
1449
+			break;
1450
+		case PROTO_SCTP:
1451
+			memcpy(srv, SRV_SCTP_PREFIX, SRV_SCTP_PREFIX_LEN);
1452
+			memcpy(srv+SRV_SCTP_PREFIX_LEN, name->s, name->len);
1453
+			srv[SRV_SCTP_PREFIX_LEN + name->len] = '\0';
1454
+			break;
1455
+		default:
1456
+			LOG(L_CRIT, "BUG: %s: unknown proto %d\n", __func__, proto);
1457
+	}
1458
+}
1459
+
1460
+size_t create_srv_pref_list(char *proto, struct dns_srv_proto *list) {
1461
+	struct dns_srv_proto tmp;
1462
+	size_t i,j,list_len;
1463
+	int default_order,max;
1464
+
1465
+	/* if proto available, then add only the forced protocol to the list */
1466
+	if (proto && *proto!=PROTO_NONE){
1467
+		list[0].proto=*proto;
1468
+		list_len=1;
1469
+	} else {
1470
+		list_len = 0;
1471
+		/*get protocols and preference scores, and add availble protocol(s) and score(s) to the list*/
1472
+		for (i=PROTO_UDP; i<PROTO_LAST;i++) {
1473
+			tmp.proto_pref = proto_pref_score(i);
1474
+			/* if -1 so disabled continue with next protocol*/
1475
+			if (naptr_proto_supported(i) == 0) {
1476
+				continue;
1477
+			} else {
1478
+				list[i-1].proto_pref=tmp.proto_pref;
1479
+				list[i-1].proto=i;
1480
+				list_len++;
1481
+			}
1482
+		};
1483
+
1484
+		/* if all protocol prefence scores equal, then set the perference to default values: udp,tcp,tls,sctp */
1485
+		for (i=1; i<list_len;i++) {
1486
+			if(list[0].proto_pref!=list[i].proto_pref){
1487
+				default_order=0;
1488
+			}
1489
+		}
1490
+		if (default_order){
1491
+			for (i=0; i<list_len;i++) {
1492
+				list[i].proto_pref=proto_pref_score(i);
1493
+			}
1494
+		}
1495
+
1496
+		/* sorting the list */
1497
+		for (i=0;i<list_len-1;i++) {
1498
+			max=i;
1499
+			for (j=i+1;j<list_len;j++) {
1500
+				if (list[j].proto_pref>list[max].proto_pref) { 
1501
+					max=j; 
1502
+				}
1503
+			}
1504
+			if (i!=max) {
1505
+				tmp=list[i];
1506
+				list[i]=list[max];
1507
+				list[max]=tmp;
1508
+			}
1509
+		}
1510
+
1511
+	}
1512
+	return list_len;
1513
+}
1514
+
1432 1515
 /* Resolves SRV if no naptr found. 
1433 1516
  * It reuse dns_pref values and according that resolves supported protocols. 
1434 1517
  * If dns_pref are equal then it use udp,tcp,tls,sctp order.
... ...
@@ -1438,19 +1502,14 @@ end:
1438 1438
 
1439 1439
 struct hostent* no_naptr_srv_sip_resolvehost(str* name, unsigned short* port, char* proto)
1440 1440
 {
1441
-	struct dns_srv_proto_t {
1442
-		char proto;
1443
-		int proto_pref;
1444
-	} srv_proto_list[PROTO_LAST], tmp_srv_element;
1441
+	struct dns_srv_proto srv_proto_list[PROTO_LAST];
1445 1442
 	struct hostent* he;
1446 1443
 	struct ip_addr* ip;
1447 1444
 	str srv_name;
1448 1445
 	static char tmp_srv[MAX_DNS_NAME]; /* tmp. buff. for SRV lookups */
1449
-	int len;
1450
-	unsigned char i,j,max,default_order=0,list_len=0;
1446
+	size_t i,list_len;
1451 1447
 	/* init variables */
1452 1448
 	he=0;
1453
-	len=0;
1454 1449
 
1455 1450
 	/* check if it's an ip address */
1456 1451
 	if (((ip=str2ip(name))!=0)
... ...
@@ -1471,86 +1530,18 @@ struct hostent* no_naptr_srv_sip_resolvehost(str* name, unsigned short* port, ch
1471 1471
 		LOG(L_WARN, "WARNING: no_naptr_srv_sip_resolvehost: domain name too long"
1472 1472
 						" (%d), unable to perform SRV lookup\n", name->len);
1473 1473
 	} else {
1474
-		/* if proto available, then add only the forced protocol to the list */
1475
-		if (proto && *proto!=PROTO_NONE){
1476
-			srv_proto_list[0].proto=*proto;
1477
-			list_len=1;
1478
-		} else {
1479
-	
1480
-			/*get protocols and preference scores, and add availble protocol(s) and score(s) to the list*/
1481
-			for (i=PROTO_UDP; i<PROTO_LAST;i++) {
1482
-				tmp_srv_element.proto_pref = proto_pref_score(i);
1483
-				/* if -1 so disabled continue with next protocol*/
1484
-				if (naptr_proto_supported(i) == 0 ) {
1485
-					continue;
1486
-				} else {
1487
-					srv_proto_list[i-1].proto_pref=tmp_srv_element.proto_pref;
1488
-					srv_proto_list[i-1].proto=i;
1489
-					list_len++;
1490
-				}
1491
-			};
1492
-
1493
-			/* if all protocol prefence scores equal, then set the perference to default values: udp,tcp,tls,sctp */
1494
-			for (i=1; i<list_len;i++) {
1495
-				if(srv_proto_list[0].proto_pref!=srv_proto_list[i].proto_pref){
1496
-					default_order=0;
1497
-				}
1498
-			}
1499
-			if (default_order){
1500
-				for (i=0; i<list_len;i++) {
1501
-					srv_proto_list[i].proto_pref=proto_pref_score(i);;
1502
-				}
1503
-			}
1504
-
1505
-			/* sorting the list */
1506
-			for (i=0;i<list_len-1;i++) {
1507
-				max=i;
1508
-				for (j=i+1;j<list_len;j++) {
1509
-					if (srv_proto_list[j].proto_pref>srv_proto_list[max].proto_pref) { 
1510
-						max=j; 
1511
-					}
1512
-				}
1513
-				if (i!=max) {
1514
-					tmp_srv_element=srv_proto_list[i];
1515
-					srv_proto_list[i]=srv_proto_list[max];
1516
-					srv_proto_list[max]=tmp_srv_element;
1517
-				}
1518
-			}
1519
-
1520
-		}
1521 1474
 		/* looping on the ordered list until we found a protocol what has srv record */
1475
+		list_len = create_srv_pref_list(proto, srv_proto_list);
1522 1476
 		for (i=0; i<list_len;i++) {	
1523 1477
 			switch (srv_proto_list[i].proto) {
1524
-				case PROTO_NONE: /* no proto specified, use udp */
1525
-					if (proto)
1526
-						*proto=PROTO_UDP;
1527
-					/* no break */
1528 1478
 				case PROTO_UDP:
1529
-					memcpy(tmp_srv, SRV_UDP_PREFIX, SRV_UDP_PREFIX_LEN);
1530
-					memcpy(tmp_srv+SRV_UDP_PREFIX_LEN, name->s, name->len);
1531
-					tmp_srv[SRV_UDP_PREFIX_LEN + name->len] = '\0';
1532
-					len=SRV_UDP_PREFIX_LEN + name->len;
1533
-					break;
1534 1479
 				case PROTO_TCP:
1535
-					memcpy(tmp_srv, SRV_TCP_PREFIX, SRV_TCP_PREFIX_LEN);
1536
-					memcpy(tmp_srv+SRV_TCP_PREFIX_LEN, name->s, name->len);
1537
-					tmp_srv[SRV_TCP_PREFIX_LEN + name->len] = '\0';
1538
-					len=SRV_TCP_PREFIX_LEN + name->len;
1539
-					break;
1540 1480
 				case PROTO_TLS:
1541
-					memcpy(tmp_srv, SRV_TLS_PREFIX, SRV_TLS_PREFIX_LEN);
1542
-					memcpy(tmp_srv+SRV_TLS_PREFIX_LEN, name->s, name->len);
1543
-					tmp_srv[SRV_TLS_PREFIX_LEN + name->len] = '\0';
1544
-					len=SRV_TLS_PREFIX_LEN + name->len;
1545
-					break;
1546 1481
 				case PROTO_SCTP:
1547
-					memcpy(tmp_srv, SRV_SCTP_PREFIX, SRV_SCTP_PREFIX_LEN);
1548
-					memcpy(tmp_srv+SRV_SCTP_PREFIX_LEN, name->s, name->len);
1549
-					tmp_srv[SRV_SCTP_PREFIX_LEN + name->len] = '\0';
1550
-					len=SRV_SCTP_PREFIX_LEN + name->len;
1482
+					create_srv_name(srv_proto_list[i].proto, name, tmp_srv);
1551 1483
 					break;
1552 1484
 				default:
1553
-					LOG(L_CRIT, "BUG: sip_resolvehost: unknown proto %d\n",
1485
+					LOG(L_CRIT, "BUG: no_naptr_srv_sip_resolvehost: unknown proto %d\n",
1554 1486
 							(int)srv_proto_list[i].proto);
1555 1487
 					return 0;
1556 1488
 			}
... ...
@@ -1562,13 +1553,14 @@ struct hostent* no_naptr_srv_sip_resolvehost(str* name, unsigned short* port, ch
1562 1562
 				*proto = PROTO_UDP;
1563 1563
 			}
1564 1564
 			srv_name.s=tmp_srv;
1565
-			srv_name.len=len;
1565
+			srv_name.len=strlen(tmp_srv);
1566 1566
 			#ifdef USE_DNS_CACHE
1567 1567
 			he=dns_srv_get_he(&srv_name, port, dns_flags);
1568 1568
 			#else
1569 1569
 			he=srv_sip_resolvehost(&srv_name, 0, port, proto, 1, 0);
1570 1570
 			#endif
1571 1571
 			if (he!=0) {
1572
+				*proto = srv_proto_list[i].proto;
1572 1573
 				return he;
1573 1574
 			}
1574 1575
 		}
... ...
@@ -457,6 +457,13 @@ int dns_reinit_fixup(void *handle, str *gname, str *name, void **val);
457 457
 int dns_try_ipv6_fixup(void *handle, str *gname, str *name, void **val);
458 458
 void reinit_naptr_proto_prefs(str *gname, str *name);
459 459
 
460
+struct dns_srv_proto {
461
+	char proto;
462
+	int proto_pref;
463
+};
464
+void create_srv_name(char proto, str *name, char *srv);
465
+size_t create_srv_pref_list(char *proto, struct dns_srv_proto *list);
466
+
460 467
 #ifdef DNS_WATCHDOG_SUPPORT
461 468
 /* callback function that is called by the child processes
462 469
  * when they reinitialize the resolver