diff options
Diffstat (limited to 'contrib/bind/named/db_update.c')
-rw-r--r-- | contrib/bind/named/db_update.c | 110 |
1 files changed, 95 insertions, 15 deletions
diff --git a/contrib/bind/named/db_update.c b/contrib/bind/named/db_update.c index c706c66..bacc7f7 100644 --- a/contrib/bind/named/db_update.c +++ b/contrib/bind/named/db_update.c @@ -1,6 +1,6 @@ #if !defined(lint) && !defined(SABER) static char sccsid[] = "@(#)db_update.c 4.28 (Berkeley) 3/21/91"; -static char rcsid[] = "$Id: db_update.c,v 8.12 1996/08/05 08:31:30 vixie Exp $"; +static char rcsid[] = "$Id: db_update.c,v 8.18 1996/10/08 04:51:03 vixie Exp $"; #endif /* not lint */ /* @@ -72,8 +72,6 @@ static char rcsid[] = "$Id: db_update.c,v 8.12 1996/08/05 08:31:30 vixie Exp $"; #include "named.h" static void fixttl __P((struct databuf *)); -static int db_cmp __P((struct databuf *, - struct databuf *)); /* int * isRefByNS(name, htp) @@ -218,6 +216,7 @@ db_update(name, odp, newdp, flags, htp) register struct databuf *dp, *pdp; register struct namebuf *np; int zn, isHintNS; + int check_ttl = 0; const char *fname; dprintf(3, (ddt, "db_update(%s, 0x%lx, 0x%lx, 0%o, 0x%lx)%s\n", @@ -226,6 +225,9 @@ db_update(name, odp, newdp, flags, htp) np = nlookup(name, &htp, &fname, newdp != NULL); if (np == NULL || fname != name) return (NONAME); + + if (newdp && zones[newdp->d_zone].z_type == Z_PRIMARY) + check_ttl = 1; /* don't let nonauthoritative updates write in authority zones */ if (newdp && ((zn = findMyZone(np, newdp->d_class)) != DB_Z_CACHE) && @@ -312,7 +314,7 @@ db_update(name, odp, newdp, flags, htp) != OK) { dprintf(3, (ddt, "db_update: hint %lx freed\n", (u_long)dp)); - (void) free((char *)dp); + db_free(dp); } } @@ -325,10 +327,18 @@ db_update(name, odp, newdp, flags, htp) /* {class,type} doesn't match. these are * the aggregation cases. */ - if ((dp->d_type == T_CNAME || - odp->d_type == T_CNAME) && + /* Check that CNAMEs are only accompanied by + * Secure DNS RR's (KEY, SIG, and NXT). + */ + if (((dp->d_type == T_CNAME && + odp->d_type != T_KEY && + odp->d_type != T_SIG && + odp->d_type != T_NXT) || + (odp->d_type == T_CNAME && + dp->d_type != T_KEY && + dp->d_type != T_SIG && + dp->d_type != T_NXT)) && odp->d_class == dp->d_class && - odp->d_mark == dp->d_mark && #ifdef NCACHE /* neither the odp nor the new dp are * negatively cached records... @@ -338,7 +348,7 @@ db_update(name, odp, newdp, flags, htp) #endif /*NCACHE*/ zones[odp->d_zone].z_type != Z_CACHE) { syslog(LOG_INFO, - "%s has CNAME and other data (illegal)\n", + "%s has CNAME and other data (invalid)\n", name); goto skip; } @@ -520,6 +530,19 @@ db_update(name, odp, newdp, flags, htp) !bcmp(dp->d_data, newdp->d_data, INT32SZ + sizeof(u_char))) goto delete; + if (check_ttl) { + if (newdp->d_ttl != dp->d_ttl) + syslog(LOG_WARNING, + "%s %s %s differing ttls: corrected", + name[0]?name:".", + p_class(dp->d_class), + p_type(dp->d_type)); + if (newdp->d_ttl > dp->d_ttl) { + newdp->d_ttl = dp->d_ttl; + } else { + dp->d_ttl = newdp->d_ttl; + } + } } if ((flags & DB_NODATA) && !db_cmp(dp, odp)) { /* refresh ttl if cache entry */ @@ -552,6 +575,10 @@ db_update(name, odp, newdp, flags, htp) if (odp->d_size > 0) if (db_cmp(dp, odp)) goto skip; + if (odp->d_clev < dp->d_clev) + goto skip; + if (odp->d_cred < dp->d_cred) + goto skip; foundRR = 1; if (flags & DB_DELETE) { delete: dp = rm_datum(dp, np, pdp); @@ -588,9 +615,10 @@ db_update(name, odp, newdp, flags, htp) /* Add to end of list, generally preserving order */ newdp->d_next = NULL; if ((dp = np->n_data) == NULL) { -#ifdef DATUMREFCNT newdp->d_rcnt = 1; -#endif + if (newdp->d_flags & DB_F_ACTIVE) + panic(-1, "db_update: DB_F_ACTIVE set"); + newdp->d_flags |= DB_F_ACTIVE; np->n_data = newdp; return (OK); } @@ -601,9 +629,10 @@ db_update(name, odp, newdp, flags, htp) } if ((flags & DB_NODATA) && !db_cmp(dp, newdp)) return (DATAEXISTS); -#ifdef DATUMREFCNT newdp->d_rcnt = 1; -#endif + if (newdp->d_flags & DB_F_ACTIVE) + panic(-1, "db_update: DB_F_ACTIVE set"); + newdp->d_flags |= DB_F_ACTIVE; dp->d_next = newdp; return (OK); } @@ -628,7 +657,7 @@ fixttl(dp) * Must be case insensitive for some domain names. * Return 0 if equivalent, nonzero otherwise. */ -static int +int db_cmp(dp1, dp2) register struct databuf *dp1, *dp2; { @@ -639,8 +668,6 @@ db_cmp(dp1, dp2) return (1); if (dp1->d_size != dp2->d_size) return (1); - if (dp1->d_mark != dp2->d_mark) - return (1); /* old and new RR's are distinct */ #ifdef NCACHE if (dp1->d_rcode && dp2->d_rcode) return ((dp1->d_rcode == dp1->d_rcode)?0:1); @@ -650,6 +677,8 @@ db_cmp(dp1, dp2) switch (dp1->d_type) { + case T_SIG: + case T_KEY: case T_A: case T_UID: case T_GID: @@ -705,13 +734,64 @@ db_cmp(dp1, dp2) cp2 += strlen((char *)cp2) + 1; return (bcmp(cp1, cp2, INT32SZ * 5)); + case T_NAPTR: { + int t1,t2; + + if (dp1->d_size != dp2->d_size) + return (1); + cp1 = dp1->d_data; + cp2 = dp2->d_data; + + /* Order */ + if (*cp1++ != *cp2++ || *cp1++ != *cp2++) + return (1); + + /* Preference */ + if (*cp1++ != *cp2++ || *cp1++ != *cp2++) + return (1); + + /* Flags */ + t1 = *cp1++; t2 = *cp2++; + if (t1 != t2 || bcmp(cp1, cp2, t1)) + return (1); + cp1 += t1; cp2 += t2; + + /* Services */ + t1 = *cp1++; t2 = *cp2++; + if (t1 != t2 || bcmp(cp1, cp2, t1)) + return (1); + cp1 += t1; cp2 += t2; + + /* Regexp */ + t1 = *cp1++; t2 = *cp2++; + if (t1 != t2 || bcmp(cp1, cp2, t1)) + return (1); + cp1 += t1; cp2 += t2; + + /* Replacement */ + t1 = strlen((char *)cp1); t2 = strlen((char *)cp2); + if (t1 != t2 || bcmp(cp1, cp2, t1)) + return (1); + cp1 += t1 + 1; cp2 += t2 + 1; + + /* they all checked out! */ + return (0); + } + case T_MX: case T_AFSDB: case T_RT: + case T_SRV: cp1 = dp1->d_data; cp2 = dp2->d_data; if (*cp1++ != *cp2++ || *cp1++ != *cp2++) /* cmp prio */ return (1); + if (dp1->d_type == T_SRV) { + if (*cp1++ != *cp2++ || *cp1++ != *cp2++) /* weight */ + return (1); + if (*cp1++ != *cp2++ || *cp1++ != *cp2++) /* port */ + return (1); + } return (strcasecmp((char *)cp1, (char *)cp2)); case T_PX: |