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