Browse code

dns cache: fix manually inserted SRV record order

The manually inserted SRV records thought the RPC interface
were not ordered by their priority and weight which resulted in
wrong SRV look-ups, i.e. not the highest priority record
was chosen first.

Miklos Tirpak authored on 18/08/2010 13:32:36
Showing 1 changed files
... ...
@@ -4221,6 +4221,8 @@ int dns_cache_add_record(unsigned short type,
4221 4221
 	ticks_t expire;
4222 4222
 	int err, h;
4223 4223
 	int size;
4224
+	struct dns_rr	*new_rr, **rr_p, **rr_iter;
4225
+	struct srv_rdata	*srv_rd;
4224 4226
 
4225 4227
 	/* eliminate gcc warnings */
4226 4228
 	ip_addr = 0;
... ...
@@ -4358,6 +4360,7 @@ int dns_cache_add_record(unsigned short type,
4358 4358
 				/* let the rr point to the new structure */
4359 4359
 				rr = (struct dns_rr*)translate_pointer((char*)new, (char*)old,
4360 4360
 														(char*)rr);
4361
+				new_rr = rr;
4361 4362
 
4362 4363
 				if (type == T_SRV) {
4363 4364
 					/* fix the priority, weight, and port */
... ...
@@ -4392,6 +4395,7 @@ int dns_cache_add_record(unsigned short type,
4392 4392
 							"DNS cache entry\n");
4393 4393
 					goto error;
4394 4394
 				}
4395
+				new_rr = rr;
4395 4396
 
4396 4397
 				switch(type) {
4397 4398
 				case T_A:
... ...
@@ -4409,6 +4413,46 @@ int dns_cache_add_record(unsigned short type,
4409 4409
 				/* maximum expire value has been already fixed by 
4410 4410
 				 * dns_cache_clone_entry() */
4411 4411
 			}
4412
+
4413
+			if (type == T_SRV) {
4414
+				/* SRV records must be ordered by their priority and weight.
4415
+				 * With modifying an exising rr, or adding new rr to the DNS entry,
4416
+				 * the ordered list might got broken which needs to be fixed.
4417
+				 */
4418
+				rr_p = NULL;
4419
+				for (	rr_iter = &new->rr_lst;
4420
+					*rr_iter;
4421
+					rr_iter = &((*rr_iter)->next)
4422
+				) {
4423
+					if (*rr_iter == new_rr) {
4424
+						rr_p = rr_iter;
4425
+						continue;
4426
+					}
4427
+					srv_rd = (struct srv_rdata*)(*rr_iter)->rdata;
4428
+					if ((priority < srv_rd->priority) ||
4429
+						((priority == srv_rd->priority)	&& (weight > srv_rd->weight))
4430
+					)
4431
+						break; /* insert here */
4432
+				}
4433
+
4434
+				if (!rr_p)
4435
+					for (	rr_p = rr_iter;
4436
+						*rr_p && (*rr_p != new_rr);
4437
+						rr_p = &((*rr_p)->next)
4438
+					);
4439
+				if (!rr_p) {
4440
+					LOG(L_ERR, "ERROR: Failed to correct the orderd list of SRV resource records\n");
4441
+					goto error;
4442
+				}
4443
+
4444
+				if (*rr_iter != new_rr->next) {
4445
+					/* unlink rr from the list */
4446
+					*rr_p = (*rr_p)->next;
4447
+					/* link it before *rr_iter */
4448
+					new_rr->next = *rr_iter;
4449
+					*rr_iter = new_rr;
4450
+				}
4451
+			}
4412 4452
 		}
4413 4453
 	}
4414 4454