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 4360
 				/* let the rr point to the new structure */
4359 4361
 				rr = (struct dns_rr*)translate_pointer((char*)new, (char*)old,
4360 4362
 														(char*)rr);
4363
+				new_rr = rr;
4361 4364
 
4362 4365
 				if (type == T_SRV) {
4363 4366
 					/* fix the priority, weight, and port */
... ...
@@ -4392,6 +4395,7 @@ int dns_cache_add_record(unsigned short type,
4392 4395
 							"DNS cache entry\n");
4393 4396
 					goto error;
4394 4397
 				}
4398
+				new_rr = rr;
4395 4399
 
4396 4400
 				switch(type) {
4397 4401
 				case T_A:
... ...
@@ -4409,6 +4413,46 @@ int dns_cache_add_record(unsigned short type,
4409 4413
 				/* maximum expire value has been already fixed by 
4410 4414
 				 * dns_cache_clone_entry() */
4411 4415
 			}
4416
+
4417
+			if (type == T_SRV) {
4418
+				/* SRV records must be ordered by their priority and weight.
4419
+				 * With modifying an exising rr, or adding new rr to the DNS entry,
4420
+				 * the ordered list might got broken which needs to be fixed.
4421
+				 */
4422
+				rr_p = NULL;
4423
+				for (	rr_iter = &new->rr_lst;
4424
+					*rr_iter;
4425
+					rr_iter = &((*rr_iter)->next)
4426
+				) {
4427
+					if (*rr_iter == new_rr) {
4428
+						rr_p = rr_iter;
4429
+						continue;
4430
+					}
4431
+					srv_rd = (struct srv_rdata*)(*rr_iter)->rdata;
4432
+					if ((priority < srv_rd->priority) ||
4433
+						((priority == srv_rd->priority)	&& (weight > srv_rd->weight))
4434
+					)
4435
+						break; /* insert here */
4436
+				}
4437
+
4438
+				if (!rr_p)
4439
+					for (	rr_p = rr_iter;
4440
+						*rr_p && (*rr_p != new_rr);
4441
+						rr_p = &((*rr_p)->next)
4442
+					);
4443
+				if (!rr_p) {
4444
+					LOG(L_ERR, "ERROR: Failed to correct the orderd list of SRV resource records\n");
4445
+					goto error;
4446
+				}
4447
+
4448
+				if (*rr_iter != new_rr->next) {
4449
+					/* unlink rr from the list */
4450
+					*rr_p = (*rr_p)->next;
4451
+					/* link it before *rr_iter */
4452
+					new_rr->next = *rr_iter;
4453
+					*rr_iter = new_rr;
4454
+				}
4455
+			}
4412 4456
 		}
4413 4457
 	}
4414 4458