/************************************************************************** * ns_ncache.c * author: anant kumar * last modification: March 17, 1993 * * implements negative caching */ #include #include #include #include #include #include #include #include #include #include #include "named.h" #ifdef NCACHE void cache_n_resp(msg, msglen) u_char *msg; int msglen; { register struct databuf *dp; HEADER *hp; u_char *cp; char dname[MAXDNAME]; int n; int type, class; #ifdef VALIDATE int Vcode; #endif int flags; nameserIncr(from_addr.sin_addr, nssRcvdNXD); hp = (HEADER *)msg; cp = msg+HFIXEDSZ; n = dn_expand(msg, msg + msglen, cp, dname, sizeof dname); if (n < 0) { dprintf(1, (ddt, "Query expand name failed:cache_n_resp\n")); hp->rcode = FORMERR; return; } cp += n; GETSHORT(type, cp); GETSHORT(class, cp); dprintf(1, (ddt, "ncache: dname %s, type %d, class %d\n", dname, type, class)); #ifdef VALIDATE Vcode = validate(dname, dname, &from_addr, type, class, NULL, 0, hp->rcode == NXDOMAIN ? NXDOMAIN : NOERROR_NODATA); if (Vcode == INVALID || Vcode == VALID_NO_CACHE) { /*Valid_no_cache should never occur but doesn't hurt to check*/ return; } #endif #ifdef RETURNSOA if (hp->nscount) { u_int32_t ttl; u_int16_t atype; u_char *tp = cp; u_char *cp1; u_char data[MAXDNAME*2 + INT32SZ*5]; size_t len = sizeof data; /* we store NXDOMAIN as T_SOA regardless of the query type */ if (hp->rcode == NXDOMAIN) type = T_SOA; /* store ther SOA record */ n = dn_skipname(tp, msg + msglen); if (n < 0) { dprintf(3, (ddt, "ncache: form error\n")); return; } tp += n; GETSHORT(atype, tp); /* type */ if (atype != T_SOA) { dprintf(3, (ddt, "ncache: type (%d) != T_SOA\n",atype)); goto no_soa; } tp += INT16SZ; /* class */ GETLONG(ttl, tp); /* ttl */ tp += INT16SZ; /* dlen */ /* origin */ n = dn_expand(msg, msg + msglen, tp, (char*)data, len); if (n < 0) { dprintf(3, (ddt, "ncache: form error 2\n")); return; } tp += n; n = strlen((char*)data) + 1; cp1 = data + n; len -= n; /* mail */ n = dn_expand(msg, msg + msglen, tp, (char*)cp1, len); if (n < 0) { dprintf(3, (ddt, "ncache: form error 2\n")); return; } tp += n; n = strlen((char*)cp1) + 1; cp1 += n; len -= n; bcopy(tp, cp1, n = 5 * INT32SZ); /* serial, refresh, retry, expire, min */ cp1 += n; len -= n; /* store the zone of the soa record */ n = dn_expand(msg, msg + msglen, cp, (char*)cp1, len); if (n < 0) { dprintf(3, (ddt, "ncache: form error 2\n")); return; } n = strlen((char*)cp1) + 1; cp1 += n; dp = savedata(class, type, MIN(ttl, NTTL) + tt.tv_sec, data, cp1 - data); } else { no_soa: #endif dp = savedata(class, type, NTTL + tt.tv_sec, NULL, 0); #ifdef RETURNSOA } #endif dp->d_zone = DB_Z_CACHE; dp->d_cred = hp->aa ? DB_C_AUTH : DB_C_ANSWER; dp->d_clev = 0; if(hp->rcode == NXDOMAIN) { dp->d_rcode = NXDOMAIN; flags = DB_NODATA|DB_NOTAUTH|DB_NOHINTS; } else { dp->d_rcode = NOERROR_NODATA; flags = DB_NOTAUTH|DB_NOHINTS; } if ((n = db_update(dname, dp, dp, flags, hashtab)) != OK) { dprintf(1, (ddt, "db_update failed return value:%d, cache_n_resp()\n", n)); db_free(dp); return; } dprintf(4, (ddt, "ncache succeeded: [%s %s %s] rcode:%d ttl:%ld\n", dname, p_type(type), p_class(class), dp->d_rcode, (long)(dp->d_ttl-tt.tv_sec))); return; } #endif /*NCACHE*/