8.2.1 multiple-cnames broken

Mark_Andrews at isc.org Mark_Andrews at isc.org
Sun Jun 27 05:02:41 UTC 1999


> 
> > Version 8.2.1 seems to have broken multiple-cnames support.  I'm
> > currently running 8.1.2, and have multiple-cnames enabled.  This allows
> > me to set up a name that has several CNAMEs attached to it, each of
> > those is a round robin with a couple dozen IP addresses.  I can't put
> > them all in one record, because many resolvers can't handle more than
> > about 30 records returned.  But I want to round robin among them all (for
> > load balancing student logins to our workstations)  When I do repeated
> > lookups of these records under 8.2.1 I keep getting the same one
> > returned over and over again, so only 1/3 of my machines would get all
> > the remote user load.
> > 
> > Any chance of a patch for this without having to wait for the next
> > release?  I don't have any really compelling reason to go to 8.2.1, but
> > I like to stay current when possible.  I didn't go to 8.2 because of
> > compilation errors due to uninitialized variables that had me a bit
> > worried.  I reported that back in March and was told the fixes would be
> > in 8.2.1.  They were, but now I can't use it either :)
> > 
> > (I am mailing this to bind-bugs as well)
> > 
> > -- 
> > Douglas Siebert                Director of Computing Facilities
> > douglas-siebert at uiowa.edu      Division of Mathematical Sciences, U of Iowa
> > 
> > I plan to live forever, or die trying.
> > 
> > 
> 
	The previous patch was incomplete.

	Mark

Index: src/bin/named/ns_resp.c
===================================================================
RCS file: /proj/cvs/isc/bind/src/bin/named/ns_resp.c,v
retrieving revision 8.109
diff -c -r8.109 ns_resp.c
*** ns_resp.c	1999/06/21 02:21:25	8.109
--- ns_resp.c	1999/06/27 04:48:00
***************
*** 193,202 ****
  static enum ordering	match_order(const struct namebuf *, int, int);
  static int 		match_name(const struct namebuf *, const char *, size_t);
  
- #if !defined (OLD_ROUND_ROBIN)
- #define MAX_FOUND 100
- #endif
- 
  #define MAX_RELATED 100
  
  static int num_related = 0;
--- 193,198 ----
***************
*** 2925,2937 ****
  	char *cp;
  	int buflen, n, count = 0;
  	char *new_dnamep = NULL;
- #if !defined(NO_RRSET_ORDER)
   	int defer = 0, found_count = 0, choice, i;
!  	struct databuf *found[MAX_FOUND];
! 	struct databuf *tmpfound[MAX_FOUND];
! #endif
  
! 	n = delete_stale(np);
  
  	/* We don't want to return cached SIG records when asked for SIGs,
  	 * since we may have an incomplete set.
--- 2930,2943 ----
  	char *cp;
  	int buflen, n, count = 0;
  	char *new_dnamep = NULL;
   	int defer = 0, found_count = 0, choice, i;
!  	struct databuf **found = NULL;
! 	struct databuf **tmpfound = NULL;
! 	int foundcname;
! 	int stalecount;
! 	int ret = 0;
  
! 	stalecount = delete_stale(np);
  
  	/* We don't want to return cached SIG records when asked for SIGs,
  	 * since we may have an incomplete set.
***************
*** 2939,3002 ****
  	if (type == T_SIG && findMyZone(np, class) == DB_Z_CACHE)
  		return(0);
  
! #if !defined(NO_RRSET_ORDER)
! 	if (type != T_ANY && type != T_PTR && type != T_NXT && n < MAX_FOUND)
  		defer = 1;
- #else
- 
- #ifdef ROUND_ROBIN
- #ifdef OLD_ROUND_ROBIN
- 	if (type != T_ANY && type != T_PTR) {
- 		/* cycle order of RRs, for a load balancing effect... */
- 
- 		struct databuf **dpp;
-  
- 		for (dpp = &np->n_data; (dp = *dpp) != NULL;
- 		     dpp = &dp->d_next) {
- 			if (dp->d_next && wanted(dp, class, type)) {
- 				struct databuf *lp;
- 
- 				*dpp = lp = dp->d_next;
- 				dp->d_next = NULL;
- 
- 				for (dpp = &lp->d_next;
- 				     *dpp;
- 				     dpp = &lp->d_next)
- 					lp = *dpp;
- 				*dpp = dp;
- 				break;
- 			}
- 		}
- 	}
- #else /* Security aware Round Robin code */
- 	/* cycle order of RRs, for a load balancing effect... 
- 	 * This code sorts SIG(x) records to the end of the list. 
- 	 * This guarantees that SIG records will always appear last in a RRset
- 	 * Example:  will order the records into following order, 
- 	 *   rr1a, rr2a, rr1b, sig(rr1), sig(rr2) 
- 	 * after a query for type rr1 
- 	 *   rr1b, rr1a, rr2a, sig(rr1), sig(rr2)
- 	 * after a query for type rr2
- 	 *   rr2a, rr1b, rr1a, sig(rr1), sig(rr2)
- 	 */
- 	if (type != T_ANY && type != T_PTR && type != T_SIG) {
- 		struct databuf *pdp=NULL, *pldp=NULL, *dp;
- 		for (dp = np->n_data; dp != NULL; dp = dp->d_next) {
- 			/* signatures should sort to the end */
- 			if (dp->d_type != T_SIG && wanted(dp, class, type))
- 				pldp = pdp; /* pred of this RR record */
- 			pdp = dp;
- 		}
- 		if (pldp != NULL) { /* no need to reorder if first record */
- 			dp = pldp->d_next;
- 			pldp->d_next = dp->d_next; /* remove ldp from queue */
- 			dp->d_next = np->n_data;   /* move first to second */
- 			np->n_data = dp;	   /* insert at front */
- 		}
  	}
- #endif /* Security aware Round Robin */
- #endif /*ROUND_ROBIN*/
- #endif /* NO_RRSET_ORDER */
  
  	buflen = *lenp;
  	
--- 2945,2957 ----
  	if (type == T_SIG && findMyZone(np, class) == DB_Z_CACHE)
  		return(0);
  
! 	if (type != T_ANY && type != T_PTR && type != T_NXT) {
! 		found = memget((stalecount + 1) * sizeof *found);
! 		tmpfound = memget((stalecount + 1) * sizeof *tmpfound);
! 		if (found == NULL || tmpfound == NULL)
! 			ns_panic(ns_log_default, 1, "finddata: out of memory");
  		defer = 1;
  	}
  
  	buflen = *lenp;
  	
***************
*** 3005,3010 ****
--- 2960,2966 ----
  		ns_debug(ns_log_default, 1, "finddata(): buflen=%d", buflen);
  #endif
  	cp = ((char *)hp) + *countp;
+ 	foundcname = 0;
  	for (dp = np->n_data; dp != NULL; dp = dp->d_next) {
  		if (!wanted(dp, class, type)) {
  			if (type == T_CNAME && class == dp->d_class) {
***************
*** 3012,3019 ****
  				if (dp->d_type != T_NXT &&
  				    dp->d_type != T_KEY &&
  				    dp->d_type != T_SIG) {
! 					*countp = 0;
! 					return 0;
  				}
  			}
  			continue;
--- 2968,2975 ----
  				if (dp->d_type != T_NXT &&
  				    dp->d_type != T_KEY &&
  				    dp->d_type != T_SIG) {
! 					ret = 0;
! 					goto done;
  				}
  			}
  			continue;
***************
*** 3051,3058 ****
  				continue;
  			hp->rcode = NOERROR_NODATA;
  			if (dp->d_size == 0) { /* !RETURNSOA */
! 				*countp = 0;
! 				return 1; /* XXX - we have to report success */
  			}
  		}
  		if (dp->d_rcode == NXDOMAIN) {
--- 3007,3014 ----
  				continue;
  			hp->rcode = NOERROR_NODATA;
  			if (dp->d_size == 0) { /* !RETURNSOA */
! 				ret = 1;
! 				goto done;
  			}
  		}
  		if (dp->d_rcode == NXDOMAIN) {
***************
*** 3067,3074 ****
  			}
  			hp->rcode = NXDOMAIN;
  			if (dp->d_size == 0) { /* !RETURNSOA */	
! 				*countp = 0;
! 				return 1; /* XXX - we have to report success */
  			}
  		}
  
--- 3023,3030 ----
  			}
  			hp->rcode = NXDOMAIN;
  			if (dp->d_size == 0) { /* !RETURNSOA */	
! 				ret = 1;
! 				goto done;
  			}
  		}
  
***************
*** 3078,3132 ****
  		    (!((dp->d_type == T_SIG) || (dp->d_type == T_KEY))) )
  			continue;
  
- #if !defined(NO_RRSET_ORDER)
  		if (!defer) {
! #endif
  
  			if ((n = make_rr(*dnamep, dp, (u_char *)cp, buflen, 1,
  					 dnptrs, dnptrs_end, 0)) < 0) {
  				hp->tc = 1;
! 				*countp = count;
! 				return (*lenp - buflen);
  			}
  			if (dp->d_secure != DB_S_SECURE)
  				hp->ad = 0;
  			cp += n;
  			buflen -= n;
  			count++;
- #if !defined(NO_RRSET_ORDER)
- 		}
- 		 else
- 			 found[found_count++] = dp;
- #endif
  		
! #ifdef notdef
! 		/* this isn't right for glue records, aa is set in ns_req */
! 		if (dp->d_zone != DB_Z_CACHE &&
! 		    (zones[dp->d_zone].z_flags & Z_AUTH) != 0 &&
! 		    class != C_ANY)
! 			hp->aa = 1;			/* XXX */
! #endif
! 		if (dp->d_type == T_CNAME) {
  			/* don't alias if querying for key, sig, nxt, or any */
! 			if ((type != T_KEY) && 
! 			    (type != T_SIG) &&
! 			    (type != T_NXT) &&
! 			    (type != T_ANY)) {	/* or T_NS? */
! 				new_dnamep = (char *)dp->d_data;
! 				/*
! 				 * Only return first CNAME found.
! 				 */
! 				break;
  			}
! 		}
  	}
  
! #if !defined(NO_RRSET_ORDER)
! 	if (found_count == 0 && count == 0)
! #else
! 	if (count == 0)
! #endif
! 		return (0);
  
  	/*
  	 * If the query type was SIG or ANY we will have returned the SIG
--- 3034,3072 ----
  		    (!((dp->d_type == T_SIG) || (dp->d_type == T_KEY))) )
  			continue;
  
  		if (!defer) {
! 			if (foundcname != 0 && dp->d_type == T_CNAME)
! 				continue;
  
  			if ((n = make_rr(*dnamep, dp, (u_char *)cp, buflen, 1,
  					 dnptrs, dnptrs_end, 0)) < 0) {
  				hp->tc = 1;
! 				ret = *lenp - buflen;
! 				goto done;
  			}
  			if (dp->d_secure != DB_S_SECURE)
  				hp->ad = 0;
  			cp += n;
  			buflen -= n;
  			count++;
  		
! 			if (dp->d_type == T_CNAME) {
! 				foundcname = 1;
! #define FOLLOWCNAME(type) \
! 	(type != T_KEY) && (type != T_SIG) && (type != T_NXT) && (type != T_ANY)
  			/* don't alias if querying for key, sig, nxt, or any */
! 
! 				if (FOLLOWCNAME(type))
! 					new_dnamep = (char *)dp->d_data;
  			}
! 		} else
! 			found[found_count++] = dp;
  	}
  
! 	if (found_count == 0 && count == 0) {
! 		ret = 0;
! 		goto done;
! 	}
  
  	/*
  	 * If the query type was SIG or ANY we will have returned the SIG
***************
*** 3151,3179 ****
  					0.95 * (int) (dp->d_ttl - tt.tv_sec);
  #endif
  			}
- #if !defined(NO_RRSET_ORDER)
  			if (!defer) {
- #endif
  				if ((n = make_rr(*dnamep, dp, (u_char *)cp,
  						 buflen, 1, dnptrs, dnptrs_end,
  						 0)) < 0) {
  					hp->tc = 1;
! 					*countp = count;
! 					return (*lenp - buflen);
  				}
  				if (dp->d_secure != DB_S_SECURE)
  					hp->ad = 0;
  				cp += n;
  				buflen -= n;
  				count++;
- #if !defined(NO_RRSET_ORDER)
  			} else
  				found[found_count++] = dp;
- #endif
  		}
  	}
  
- #if !defined(NO_RRSET_ORDER)
  	if (defer && found_count > 0) {
  		int first_sig;
  		int non_sig_count;
--- 3091,3114 ----
  					0.95 * (int) (dp->d_ttl - tt.tv_sec);
  #endif
  			}
  			if (!defer) {
  				if ((n = make_rr(*dnamep, dp, (u_char *)cp,
  						 buflen, 1, dnptrs, dnptrs_end,
  						 0)) < 0) {
  					hp->tc = 1;
! 					ret = *lenp - buflen;
! 					goto done;
  				}
  				if (dp->d_secure != DB_S_SECURE)
  					hp->ad = 0;
  				cp += n;
  				buflen -= n;
  				count++;
  			} else
  				found[found_count++] = dp;
  		}
  	}
  
  	if (defer && found_count > 0) {
  		int first_sig;
  		int non_sig_count;
***************
*** 3209,3224 ****
  			}
  		}
  
  		switch (order) {
  		case fixed_order:
  			for (i = 0; i < found_count; i++) {
  				dp = found[i];
  				if ((n = make_rr(*dnamep, dp, (u_char *)cp,
  						 buflen, 1,
  						 dnptrs, dnptrs_end, 0)) < 0) {
  					hp->tc = 1;
! 					*countp = count;
! 					return (*lenp - buflen);
  				}
  				if (dp->d_secure != DB_S_SECURE)
  					hp->ad = 0;
--- 3144,3168 ----
  			}
  		}
  
+ 		foundcname = 0;
  		switch (order) {
  		case fixed_order:
  			for (i = 0; i < found_count; i++) {
  				dp = found[i];
+ 				if (foundcname != 0 && dp->d_type == T_CNAME)
+ 					continue;
+ 				if (dp->d_type == T_CNAME) {
+ 					foundcname = 1;
+ 					if (FOLLOWCNAME(type)) {
+ 						new_dnamep = (char *)dp->d_data;
+ 					}
+ 				}
  				if ((n = make_rr(*dnamep, dp, (u_char *)cp,
  						 buflen, 1,
  						 dnptrs, dnptrs_end, 0)) < 0) {
  					hp->tc = 1;
! 					ret = *lenp - buflen;
! 					goto done;
  				}
  				if (dp->d_secure != DB_S_SECURE)
  					hp->ad = 0;
***************
*** 3236,3247 ****
  				non_sig_count--;
  				dp = found[choice];
  				found[choice] = found[non_sig_count];
  				if ((n = make_rr(*dnamep, dp, (u_char *)cp,
  						 buflen, 1,
  						 dnptrs, dnptrs_end, 0)) < 0) {
  					hp->tc = 1;
! 					*countp = count;
! 					return (*lenp - buflen);
  				}
  				if (dp->d_secure != DB_S_SECURE)
  					hp->ad = 0;
--- 3180,3199 ----
  				non_sig_count--;
  				dp = found[choice];
  				found[choice] = found[non_sig_count];
+ 				if (foundcname != 0 && dp->d_type == T_CNAME)
+ 					continue;
+ 				if (dp->d_type == T_CNAME) {
+ 					foundcname = 1;
+ 					if (FOLLOWCNAME(type)) {
+ 						new_dnamep = (char *)dp->d_data;
+ 					}
+ 				}
  				if ((n = make_rr(*dnamep, dp, (u_char *)cp,
  						 buflen, 1,
  						 dnptrs, dnptrs_end, 0)) < 0) {
  					hp->tc = 1;
! 					ret = *lenp - buflen;
! 					goto done;
  				}
  				if (dp->d_secure != DB_S_SECURE)
  					hp->ad = 0;
***************
*** 3262,3269 ****
  						 buflen, 1,
  						 dnptrs, dnptrs_end, 0)) < 0) {
  					hp->tc = 1;
! 					*countp = count;
! 					return (*lenp - buflen);
  				}
  				if (dp->d_secure != DB_S_SECURE)
  					hp->ad = 0;
--- 3214,3221 ----
  						 buflen, 1,
  						 dnptrs, dnptrs_end, 0)) < 0) {
  					hp->tc = 1;
! 					ret = *lenp - buflen;
! 					goto done;
  				}
  				if (dp->d_secure != DB_S_SECURE)
  					hp->ad = 0;
***************
*** 3276,3304 ****
  
  		case cyclic_order:
  			/* first we do the non-SIG records */
! 			if (non_sig_count > 0) {
! 				choice = ((u_int)rand()) % non_sig_count;
! 				i = choice;
! 				do {
! 					dp = found[i];
! 					if ((n = make_rr(*dnamep, dp,
! 							 (u_char *)cp,
! 							 buflen, 1,
! 							 dnptrs,
! 							 dnptrs_end, 0)) < 0) {
! 						hp->tc = 1;
! 						*countp = count;
! 						return (*lenp - buflen);
  					}
! 					if (dp->d_secure != DB_S_SECURE)
! 						hp->ad = 0;
! 					cp += n;
! 					buflen -= n;
! 					count++;
! 					i++;
! 					if (i >= non_sig_count)
! 						i = 0;
! 				} while (i != choice);
  			}
  
  			/* now do the SIG record rotation. */
--- 3228,3256 ----
  
  		case cyclic_order:
  			/* first we do the non-SIG records */
! 			choice = ((u_int)rand()) % non_sig_count;
! 			for (i = 0; i < non_sig_count ; i++) {
! 				dp = found[(i + choice) % non_sig_count];
! 				if (foundcname != 0 && dp->d_type == T_CNAME)
! 					continue;
! 				if (dp->d_type == T_CNAME) {
! 					foundcname = 1;
! 					if (FOLLOWCNAME(type)) {
! 						new_dnamep = (char *)dp->d_data;
  					}
! 				}
! 				if ((n = make_rr(*dnamep, dp, (u_char *)cp,
! 						 buflen, 1,
! 						 dnptrs, dnptrs_end, 0)) < 0) {
! 					hp->tc = 1;
! 					ret = *lenp - buflen;
! 					goto done;
! 				}
! 				if (dp->d_secure != DB_S_SECURE)
! 					hp->ad = 0;
! 				cp += n;
! 				buflen -= n;
! 				count++;
  			}
  
  			/* now do the SIG record rotation. */
***************
*** 3314,3321 ****
  							 dnptrs,
  							 dnptrs_end, 0)) < 0) {
  						hp->tc = 1;
! 						*countp = count;
! 						return (*lenp - buflen);
  					}
  					if (dp->d_secure != DB_S_SECURE)
  						hp->ad = 0;
--- 3266,3273 ----
  							 dnptrs,
  							 dnptrs_end, 0)) < 0) {
  						hp->tc = 1;
! 						ret = *lenp - buflen;
! 						goto done;
  					}
  					if (dp->d_secure != DB_S_SECURE)
  						hp->ad = 0;
***************
*** 3327,3333 ****
  						i = first_sig;
  				} while (i != choice);
  			}
- 
  			
  			break;
  
--- 3279,3284 ----
***************
*** 3337,3351 ****
  			break;
  		}
  	}
- #endif /* !defined(OLD_ROUND_ROBIN) */
  	
  	if (new_dnamep != NULL)
  		*dnamep = new_dnamep;
  
  	ns_debug(ns_log_default, 3, "finddata: added %d class %d type %d RRs",
  		 count, class, type);
  	*countp = count;
! 	return (*lenp - buflen);
  }
  
  /*
--- 3288,3307 ----
  			break;
  		}
  	}
  	
  	if (new_dnamep != NULL)
  		*dnamep = new_dnamep;
  
  	ns_debug(ns_log_default, 3, "finddata: added %d class %d type %d RRs",
  		 count, class, type);
+ 	ret = *lenp - buflen;
+  done:
+ 	if (found != NULL)
+ 		memput(found, (stalecount + 1) * sizeof *found);
+ 	if (tmpfound != NULL)
+ 		memput(tmpfound, (stalecount + 1) * sizeof *tmpfound);
  	*countp = count;
! 	return (ret);
  }
  
  /*
--
Mark Andrews, Internet Software Consortium
1 Seymour St., Dundas Valley, NSW 2117, Australia
PHONE: +61 2 9871 4742                 INTERNET: marka at isc.org


More information about the bind-users mailing list