Browse code

core: dns - use all NAPTR records

- enable using of all NAPTR records instead of the first one ordered by
priority
- GH #2290

Semen Darienko authored on 03/05/2020 10:26:45 • Daniel-Constantin Mierla committed on 03/05/2020 10:26:45
Showing 3 changed files
... ...
@@ -2644,6 +2644,10 @@ struct naptr_rdata* dns_naptr_sip_iterate(struct dns_rr* naptr_head,
2644 2644
 		}
2645 2645
 		LM_DBG("found a valid sip NAPTR rr %.*s, proto %d\n",
2646 2646
 				naptr->repl_len, naptr->repl, (int)naptr_proto);
2647
+		if (naptr->skip_record) {
2648
+			i++;
2649
+			continue;
2650
+		}
2647 2651
 		if ((naptr_proto_supported(naptr_proto))){
2648 2652
 			if (naptr_choose(&naptr_saved, &saved_proto,
2649 2653
 								naptr, naptr_proto))
... ...
@@ -3203,6 +3207,63 @@ inline static int dns_srv_sip_resolve(struct dns_srv_handle* h,  str* name,
3203 3207
 
3204 3208
 
3205 3209
 #ifdef USE_NAPTR
3210
+
3211
+
3212
+static void mark_skip_current_naptr(struct dns_rr* naptr_head, struct dns_hash_entry* srv)
3213
+{
3214
+	int i;
3215
+	struct dns_rr* l;
3216
+	struct naptr_rdata* naptr;
3217
+
3218
+	if (!naptr_head || !srv) {
3219
+		return;
3220
+	}
3221
+
3222
+	for(l=naptr_head, i=0; l && (i<MAX_NAPTR_RRS); l=l->next, i++) {
3223
+		naptr = (struct naptr_rdata *) l->rdata;
3224
+		if (naptr == 0) {
3225
+			break;
3226
+		}
3227
+		if (naptr->skip_record) {
3228
+			continue;
3229
+		}
3230
+		if (srv->name_len == naptr->repl_len && !memcmp(srv->name, naptr->repl, srv->name_len)) {
3231
+			naptr->skip_record = 1;
3232
+			LM_NOTICE("Mark to skip %.*s NAPTR record due to all IPs are unreachable\n", naptr->repl_len, naptr->repl);
3233
+			break;
3234
+		}
3235
+	}
3236
+}
3237
+
3238
+
3239
+inline static int have_more_active_naptr(struct dns_rr* naptr_head)
3240
+{
3241
+	int i, res = 0;
3242
+	struct dns_rr* l;
3243
+	struct naptr_rdata* naptr;
3244
+	char naptr_proto;
3245
+
3246
+	if (!naptr_head) {
3247
+		return res;
3248
+	}
3249
+
3250
+	for(l=naptr_head, i=0; l && (i<MAX_NAPTR_RRS); l=l->next, i++) {
3251
+		naptr = (struct naptr_rdata *) l->rdata;
3252
+		if (naptr == 0) {
3253
+			break;
3254
+		}
3255
+		if (naptr->skip_record) {
3256
+			continue;
3257
+		} else if ((naptr_proto = naptr_get_sip_proto(naptr)) <= 0) {
3258
+			continue;
3259
+		} else if ((naptr_proto_supported(naptr_proto))) {
3260
+			res = 1;
3261
+			break;
3262
+		}
3263
+	}
3264
+	return res;
3265
+}
3266
+
3206 3267
 /* resolves a host name trying:
3207 3268
  * - NAPTR lookup if the address is not an ip and proto!=0, port!=0
3208 3269
  *    *port==0 and *proto=0 and if flags allow NAPTR lookups
... ...
@@ -3227,6 +3288,7 @@ inline static int dns_naptr_sip_resolve(struct dns_srv_handle* h,  str* name,
3227 3288
 	char n_proto, origproto;
3228 3289
 	str srv_name;
3229 3290
 	int ret;
3291
+	int try_lookup_naptr = 0;
3230 3292
 
3231 3293
 	ret=-E_DNS_NO_NAPTR;
3232 3294
 	if(proto) origproto=*proto;
... ...
@@ -3259,9 +3321,27 @@ inline static int dns_naptr_sip_resolve(struct dns_srv_handle* h,  str* name,
3259 3321
 			*port=h->port;
3260 3322
 			return 0;
3261 3323
 		}
3262
-		/* do naptr lookup */
3263
-		if ((e=dns_get_entry(name, T_NAPTR))==0)
3264
-			goto naptr_not_found;
3324
+		try_lookup_naptr = 1;
3325
+	}
3326
+	/* do naptr lookup */
3327
+	if ((e=dns_get_entry(name, T_NAPTR))==0)
3328
+		goto naptr_not_found;
3329
+
3330
+	if (!try_lookup_naptr) {
3331
+		if(proto) *proto=origproto;
3332
+		int res = dns_srv_sip_resolve(h, name, ip, port, proto, flags);
3333
+		if (res) {
3334
+			mark_skip_current_naptr(e->rr_lst, h->srv);
3335
+			if (have_more_active_naptr(e->rr_lst)) {
3336
+				// No more avaliable IP for current NAPTR record, let's try next one
3337
+				try_lookup_naptr = 1;
3338
+			}
3339
+		} else {
3340
+			return res;
3341
+		}
3342
+	}
3343
+
3344
+	if (try_lookup_naptr) {
3265 3345
 		naptr_iterate_init(&tried_bmp);
3266 3346
 		while(dns_naptr_sip_iterate(e->rr_lst, &tried_bmp,
3267 3347
 												&srv_name, &n_proto)){
... ...
@@ -407,6 +407,7 @@ struct naptr_rdata* dns_naptr_parser( unsigned char* msg, unsigned char* end,
407 407
 		PKG_MEM_ERROR;
408 408
 		goto error;
409 409
 	}
410
+	naptr->skip_record = 0;
410 411
 	naptr->order=ntohs(order);
411 412
 	naptr->pref=ntohs(pref);
412 413
 	
... ...
@@ -123,6 +123,7 @@ struct naptr_rdata {
123 123
 	unsigned char services_len;
124 124
 	unsigned char regexp_len;
125 125
 	unsigned char repl_len; /* not currently used */
126
+	unsigned char skip_record;
126 127
 	
127 128
 	char str_table[1]; /* contains all the strings */
128 129
 };