home *** CD-ROM | disk | FTP | other *** search
/ PC-Online 1996 May / PCOnline_05_1996.bin / linux / source / n / bind / bind-4.001 / bind-4~ / bind-4.9.3-BETA9 / named / db_update.c < prev    next >
C/C++ Source or Header  |  1994-07-23  |  18KB  |  639 lines

  1. #if !defined(lint) && !defined(SABER)
  2. static char sccsid[] = "@(#)db_update.c    4.28 (Berkeley) 3/21/91";
  3. static char rcsid[] = "$Id: db_update.c,v 4.9.1.19 1994/07/23 23:23:56 vixie Exp $";
  4. #endif /* not lint */
  5.  
  6. /*
  7.  * ++Copyright++ 1986, 1990
  8.  * -
  9.  * Copyright (c) 1986, 1990
  10.  *    The Regents of the University of California.  All rights reserved.
  11.  * 
  12.  * Redistribution and use in source and binary forms, with or without
  13.  * modification, are permitted provided that the following conditions
  14.  * are met:
  15.  * 1. Redistributions of source code must retain the above copyright
  16.  *    notice, this list of conditions and the following disclaimer.
  17.  * 2. Redistributions in binary form must reproduce the above copyright
  18.  *    notice, this list of conditions and the following disclaimer in the
  19.  *    documentation and/or other materials provided with the distribution.
  20.  * 3. All advertising materials mentioning features or use of this software
  21.  *    must display the following acknowledgement:
  22.  *     This product includes software developed by the University of
  23.  *     California, Berkeley and its contributors.
  24.  * 4. Neither the name of the University nor the names of its contributors
  25.  *    may be used to endorse or promote products derived from this software
  26.  *    without specific prior written permission.
  27.  * 
  28.  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
  29.  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
  30.  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
  31.  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
  32.  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
  33.  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
  34.  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
  35.  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
  36.  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
  37.  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  38.  * SUCH DAMAGE.
  39.  * -
  40.  * Portions Copyright (c) 1993 by Digital Equipment Corporation.
  41.  * 
  42.  * Permission to use, copy, modify, and distribute this software for any
  43.  * purpose with or without fee is hereby granted, provided that the above
  44.  * copyright notice and this permission notice appear in all copies, and that
  45.  * the name of Digital Equipment Corporation not be used in advertising or
  46.  * publicity pertaining to distribution of the document or software without
  47.  * specific, written prior permission.
  48.  * 
  49.  * THE SOFTWARE IS PROVIDED "AS IS" AND DIGITAL EQUIPMENT CORP. DISCLAIMS ALL
  50.  * WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES
  51.  * OF MERCHANTABILITY AND FITNESS.   IN NO EVENT SHALL DIGITAL EQUIPMENT
  52.  * CORPORATION BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
  53.  * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
  54.  * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS
  55.  * ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
  56.  * SOFTWARE.
  57.  * -
  58.  * --Copyright--
  59.  */
  60.  
  61. #include <stdio.h>
  62. #include <syslog.h>
  63.  
  64. #include <sys/param.h>
  65. #include <sys/socket.h>
  66. #include <netinet/in.h>
  67. #include <arpa/inet.h>
  68. #include <arpa/nameser.h>
  69.  
  70. #include "named.h"
  71.  
  72. static void            fixttl __P((struct databuf *));
  73. static int            db_cmp __P((struct databuf *,
  74.                         struct databuf *));
  75.  
  76. /* int
  77.  * isRefByNS(name, htp)
  78.  *    recurse through all of `htp' looking for NS RR's that refer to `name'.
  79.  * returns:
  80.  *    nonzero if at least one such NS RR exists
  81.  * cautions:
  82.  *    this is very expensive; probably you only want to use on fcachetab.
  83.  */
  84. static int
  85. isRefByNS(name, htp)
  86.     char name[];
  87.     struct hashbuf *htp;
  88. {
  89.     register struct namebuf *np;
  90.     register struct databuf *dp;
  91.  
  92.     for (np = htp->h_tab[0];  np != NULL;  np = np->n_next) {
  93.         for (dp = np->n_data;  dp != NULL;  dp = dp->d_next) {
  94.             if ((dp->d_class == C_ANY || dp->d_class == C_IN) &&
  95.                 (dp->d_type == T_NS) &&
  96. #ifdef NCACHE
  97.                 (!dp->d_rcode) &&
  98. #endif
  99.                 !strcasecmp(name, (char *)dp->d_data)) {
  100.                 return (1);
  101.             }
  102.         }
  103.         if (np->n_hash && isRefByNS(name, np->n_hash)) {
  104.             return (1);
  105.         }
  106.     }
  107.     return (0);
  108. }
  109.  
  110.  
  111. /* int
  112.  * findMyZone(struct namebuf *np)
  113.  *    surf the zone cuts and find this zone the hard way
  114.  * return value:
  115.  *    zone number or DB_Z_CACHE if it's outside a zone
  116.  * interesting cases:
  117.  *        DEC.COM SOA (primary)
  118.  *    CRL.DEC.COM NS  (in primary)
  119.  *        if you start at CRL.. here, you find the DEC.COM zone
  120.  *        if you start at NS.CRL.. here, you're in the cache
  121.  *        DEC.COM SOA (primary)
  122.  *    CRL.DEC.COM NS  (in primary)
  123.  *    CRL.DEC.COM SOA (secondary)
  124.  *    CRL.DEC.COM NS  (in secondary)
  125.  *        if you start at CRL.. here, you find the CRL.DEC.COM zone
  126.  *        if you start at NS.CRL.. here, you're in the CRL.. zone
  127.  */
  128. int
  129. findMyZone(np, class)
  130.     struct namebuf *np;
  131.     register int class;
  132. {
  133.     for (; np; np = np->n_parent) {
  134.         register struct databuf *dp;
  135.  
  136.         /* if we encounter an SOA, we're in its zone (which can be
  137.          * the cache or an authoritative zone, depending).
  138.          */
  139.         for (dp = np->n_data; dp; dp = dp->d_next)
  140.             if (match(dp, class, T_SOA))
  141.                 return (dp->d_zone);
  142.  
  143.         /* if we find an NS at some node without having seen an SOA
  144.          * (above), then we're out in the cache somewhere.
  145.          */
  146.         for (dp = np->n_data; dp; dp = dp->d_next)
  147.             if (match(dp, class, T_NS))
  148.                 return (DB_Z_CACHE);
  149.     }
  150.  
  151.     /* getting all the way to the root without finding an NS or SOA
  152.      * probably means that we are in deep dip, but we'll treat it as
  153.      * being in the cache.  (XXX?)
  154.      */
  155.     return (DB_Z_CACHE);
  156. }
  157.  
  158.  
  159. /* int
  160.  * db_update(name, odp, newdp, flags, htp)
  161.  *    update data base node at `name'.  `flags' controls the action.
  162.  * side effects:
  163.  *    inverse query tables modified, if we're using them.
  164.  * return value:
  165.  *    OK - success
  166.  *    NONAME - name doesn't exist
  167.  *    AUTH - you can't do that
  168.  *    DATAEXISTS - there's something there and DB_NODATA was specified
  169.  *    NODATA - there's no data, and (DB_DELETE or DB_MEXIST) was spec'd
  170.  *
  171.  *    Policy: How to add data if one more RR is -ve data
  172.  *
  173.  *    NEND    NOERROR_NODATA
  174.  *    NXD    NXDOMAIN
  175.  *
  176.  *                match
  177.  *                old
  178.  *            Data    NEND    NXD
  179.  *        Data    Merge    Data    Data
  180.  *    new    NEND    NEND    NEND    NEND
  181.  *        NXD    NXD    NXD    NXD
  182.  *
  183.  *                 no match
  184.  *                old
  185.  *            Data    NEND    NXD
  186.  *        Data    Merge    Merge    Data
  187.  *    new    NEND    Merge    Merge    NEND
  188.  *        NXD    NXD    NXD    NXD
  189.  *
  190.  */
  191. /* XXX:    this code calls nlookup, which can create namebuf's.  if this code
  192.  *    has to exit with a fatal error, it should scan from the new np upward
  193.  *    and for each node which has no children and no data it should remove
  194.  *    the namebuf.  design notes: (1) there's no harm in doing this even if
  195.  *    success occurred; (2) stopping on the first nonremovable np is optimal;
  196.  *    the code for removal should be taken out of remove_zone() and made
  197.  *    general enough for this use, and for remove_zone()'s continued use.
  198.  *                            vix, 21jul94
  199.  */
  200. int
  201. db_update(name, odp, newdp, flags, htp)
  202.     char name[];
  203.     struct databuf *odp, *newdp;
  204.     int flags;
  205.     struct hashbuf *htp;
  206. {
  207.     register struct databuf *dp, *pdp;
  208.     register struct namebuf *np;
  209.     int zn, isHintNS;
  210.     char *fname;
  211.  
  212.     dprintf(3, (ddt, "db_update(%s, 0x%x, 0x%x, 0%o, 0x%x)%s\n",
  213.             name, odp, newdp, flags, htp,
  214.             (odp && (odp->d_flags&DB_F_HINT)) ? " hint":"" ));
  215.     np = nlookup(name, &htp, &fname, newdp != NULL);
  216.     if (np == NULL || fname != name)
  217.         return (NONAME);
  218.  
  219.     /* don't let nonauthoritative updates write in authority zones */
  220.     if (newdp && (flags & DB_NOTAUTH) && 
  221.         (zn = findMyZone(np, newdp->d_class)) != DB_Z_CACHE) {
  222.         int foundRR = 0;
  223.  
  224.         /* don't generate the warning if we've done so recently or
  225.          * if the update would have been harmless (identical data).
  226.          */
  227.         for (dp = np->n_data; dp != NULL; dp = dp->d_next) {
  228.             if (!db_cmp(dp, newdp)) {
  229.                 foundRR++;
  230.                 break;
  231.             }
  232.         }
  233.         if (!foundRR &&
  234.             !haveComplained((char*)from_addr.sin_addr.s_addr,
  235.                     (char*)dhash((u_char*)name, strlen(name))))
  236.             syslog(LOG_NOTICE,
  237.                "[%s].%d attempted update to auth zone \"%s\" (%s)",
  238.                    inet_ntoa(from_addr.sin_addr),
  239.                    ntohs(from_addr.sin_port),
  240.                    zones[zn].z_origin,
  241.                    name);
  242.         return (AUTH);
  243.     }
  244.  
  245.     /* some special checks for root NS' A RR's */
  246.     isHintNS = isRefByNS(name, fcachetab);
  247.     if (newdp && isHintNS && newdp->d_type == T_A) {
  248.         /* obviously bogus addresses die here */
  249.         if (
  250. #ifdef NCACHE
  251.             (!newdp->d_rcode) &&
  252. #endif
  253.             (((struct in_addr *)newdp->d_data)->s_addr == INADDR_ANY))
  254.         {
  255.             syslog(LOG_INFO, "bogus (0.0.0.0) root A RR received");
  256.             return (AUTH);
  257.         }
  258.         /* upgrade credibility of additional data for rootsrv addrs */
  259.         if (newdp->d_cred == DB_C_ADDITIONAL) {
  260.             dprintf(3, (ddt,
  261.                     "upgrading credibility for A RR (%s)\n",
  262.                     name));
  263.             /* XXX:    should copy NS RR's, but we really just want
  264.              *    to prevent deprecation later so this will do.
  265.              */
  266.             newdp->d_cred = DB_C_ANSWER;
  267.             newdp->d_clev = 0;
  268.         }
  269.     }
  270.  
  271.         /* Reflect certain updates in hint cache also... */
  272.     /* Don't stick data we are authoritative for in hints. */
  273.         if (!(flags & DB_NOHINTS) &&
  274.         (odp != NULL) &&
  275.         (htp != fcachetab) &&
  276.         (odp->d_zone <= 0) &&
  277.         !(odp->d_flags & DB_F_HINT) &&
  278. #ifdef NCACHE
  279.         (!newdp || !newdp->d_rcode) &&
  280. #endif
  281.             ((name[0] == '\0' && odp->d_type == T_NS) ||
  282.          (odp->d_type == T_A && isHintNS)
  283.          )
  284.         )
  285.         {
  286.         dprintf(3, (ddt, "db_update: hint '%s' %d\n",
  287.                 name, odp->d_ttl));
  288.         dp = savedata(odp->d_class, odp->d_type, odp->d_ttl,
  289.             odp->d_data, odp->d_size);
  290.         dp->d_zone = DB_Z_CACHE;
  291.         dp->d_flags = DB_F_HINT;
  292.         dp->d_cred = DB_C_CACHE;
  293.         dp->d_clev = 0;
  294.         if (db_update(name,
  295.                   dp, dp,
  296.                   (flags|DB_NOHINTS),
  297.                   fcachetab)
  298.             != OK) {
  299.             dprintf(3, (ddt, "db_update: hint %x freed\n", dp));
  300.             (void) free((char *)dp);
  301.         }
  302.         }
  303.  
  304.     if (odp != NULL) {
  305.         int foundRR = 0;
  306.  
  307.         pdp = NULL;
  308.         for (dp = np->n_data; dp != NULL; ) {
  309.             if (!match(dp, odp->d_class, odp->d_type)) {
  310.                 /* {class,type} doesn't match.  these are
  311.                  * the aggregation cases.
  312.                  */
  313.                 if ((dp->d_type == T_CNAME ||
  314.                      odp->d_type == T_CNAME) &&
  315.                     odp->d_class == dp->d_class &&
  316.                     odp->d_mark == dp->d_mark &&
  317. #ifdef NCACHE
  318.                     /* neither the odp nor the new dp are
  319.                      * negatively cached records...
  320.                      */
  321.                     !dp->d_rcode &&
  322.                     !odp->d_rcode &&
  323. #endif /*NCACHE*/
  324.                     zones[odp->d_zone].z_type != Z_CACHE) {
  325.                     syslog(LOG_ERR,
  326.                      "%s has CNAME and other data (illegal)\n",
  327.                         name);
  328.                     dprintf(1, (ddt,
  329.                     "db_update: %s: CNAME and more (%d, %d)\n",
  330.                             name, odp->d_type,
  331.                             dp->d_type));
  332.                     goto skip;
  333.                 }
  334.                 if (!newdp || newdp->d_class != dp->d_class)
  335.                     goto skip;
  336.  
  337.                 /* XXX:
  338.                  * The next three clauses do not deal
  339.                  * correctly with glue records. mpa.
  340.                  */
  341.  
  342.                 /* if the new data is authorative 
  343.                  * remove any data for this domain with
  344.                  * the same class that isn't as credable
  345.                  */
  346.                 if (newdp->d_cred >= DB_C_AUTH && 
  347.                     newdp->d_cred > dp->d_cred)
  348.                     /* better credibility and the old datum
  349.                      * was not from a zone file.  remove
  350.                      * the old datum.
  351.                      */
  352.                     goto delete;
  353.  
  354.                 /* if we have authoritative data for a
  355.                  * node, don't add in other data.
  356.                  */
  357.                 if (dp->d_cred >= DB_C_AUTH &&
  358.                     newdp->d_cred < dp->d_cred)
  359.                     return (AUTH);
  360.  
  361.                 /* if the new data is authoritative but
  362.                  * but isn't as credible, reject it.
  363.                  */
  364.                 if (newdp->d_cred >= DB_C_AUTH && 
  365.                     newdp->d_cred == dp->d_cred &&
  366.                     newdp->d_clev < dp->d_clev)
  367.                     return (AUTH);
  368. #ifdef NCACHE
  369.                 /* process NXDOMAIN */
  370.                 /* policy */
  371.                 if (newdp->d_rcode == NXDOMAIN) {
  372.                     if (dp->d_cred < DB_C_AUTH)
  373.                         goto delete;
  374.                     else
  375.                         return (DATAEXISTS);
  376.                 }
  377.  
  378.                 if (dp->d_rcode == NXDOMAIN)
  379.                     goto delete;
  380.  
  381.                 /* process NOERROR_NODATA */
  382.                 /* NO PROCESSING REQUIRED */
  383. #endif /*NCACHE*/
  384.                 goto skip;
  385.             } /*if {class,type} did not match*/
  386.  
  387.             /* {type,class} did match.  this is the replace case.
  388.              */
  389.             dprintf(5, (ddt,
  390.                "db_update: flags = %#x, sizes = %d, %d (cmp %d)\n",
  391.                     flags, odp->d_size, dp->d_size,
  392.                     db_cmp(dp, odp)));
  393.             if (newdp) {
  394.                 dprintf(4, (ddt,
  395.          "credibility for %s is %d(%d) from [%s].%d, is %d(%d) in cache\n",
  396.                         *name? name : ".",
  397.                         newdp->d_cred,
  398.                         newdp->d_clev,
  399.                         inet_ntoa(from_addr.sin_addr),
  400.                         ntohs(from_addr.sin_port),
  401.                         dp->d_cred,
  402.                         dp->d_clev));
  403.                 if (newdp->d_cred > dp->d_cred || 
  404.                     (newdp->d_cred == DB_C_ZONE && 
  405.                      newdp->d_clev > dp->d_clev)) {
  406.                     /* better credibility and the old datum
  407.                      * was not from a zone file.  remove
  408.                      * the old datum.
  409.                      */
  410.                     goto delete;
  411.                 }
  412.                 if (newdp->d_cred < dp->d_cred) {
  413.                     /* credibility is worse.  ignore it. */
  414.                     return (AUTH);
  415.                 }
  416.                 if (newdp->d_cred == DB_C_ZONE &&
  417.                     newdp->d_cred == dp->d_cred &&
  418.                     newdp->d_clev < dp->d_clev)
  419.                     return (AUTH);
  420.  
  421.                 /* credibility is the same.
  422.                  * let it aggregate in the normal way.
  423.                  */
  424. #ifdef NCACHE
  425.                 /*
  426.                  * if the new or old RR is -ve, delete old.
  427.                  */
  428.                 if (dp->d_rcode || newdp->d_rcode) {
  429.                     /* XXX: how can a zone rr be neg? */
  430.                     if (dp->d_cred != DB_C_ZONE)
  431.                         goto delete;
  432.                     else
  433.                         return (DATAEXISTS);
  434.                 }
  435. #endif
  436.                 /*
  437.                  *  Some RR types should not be aggregated.
  438.                  */
  439.                 if (dp->d_type == T_SOA)
  440.                     goto delete;
  441.                 if (dp->d_type == T_WKS &&
  442.                     !bcmp(dp->d_data, newdp->d_data, INT16SZ))
  443.                     goto delete;
  444.             }
  445.             if ((flags & DB_NODATA) && !db_cmp(dp, odp)) {
  446.                 /* refresh ttl if cache entry */
  447.                 if (dp->d_zone == 0) {
  448.                     if (odp->d_zone != 0) {    /* XXX */
  449.                         /* changing cache->auth */
  450.                         dp->d_zone = odp->d_zone;
  451.                         dp->d_ttl = odp->d_ttl;
  452.                         dprintf(4, (ddt,
  453.                     "db_update: cache entry now in auth zone\n"
  454.                                 ));
  455.                         return (DATAEXISTS);
  456.                     }
  457.                     fixttl(odp);
  458.                     if (odp->d_ttl > dp->d_ttl)
  459.                         dp->d_ttl = odp->d_ttl;
  460.                     dprintf(3, (ddt,
  461.                         "db_update: new ttl %d, +%d\n",
  462.                             dp->d_ttl,
  463.                             dp->d_ttl - tt.tv_sec));
  464.                 }
  465.                 return (DATAEXISTS);
  466.             }
  467.             /*
  468.              * If the old databuf has some data, check that the
  469.              * data matches that in the new databuf (so UPDATED
  470.              * will delete only the matching RR)
  471.              */
  472.             if (odp->d_size > 0)
  473.                 if (db_cmp(dp, odp))
  474.                     goto skip;
  475.             foundRR = 1;
  476.             if (flags & DB_DELETE) {
  477.  delete:            dp = rm_datum(dp, np, pdp);
  478.             } else {
  479.  skip:                pdp = dp;
  480.                 dp = dp->d_next;
  481.             }
  482.         }
  483.                 if (!foundRR) {
  484.             if (flags & DB_DELETE)
  485.                 return (NODATA);
  486.             if (flags & DB_MEXIST)
  487.                 return (NODATA);
  488.         }
  489.     }
  490.     if (newdp == NULL)
  491.         return (OK);
  492.     /* XXX:    empty nodes bypass credibility checks above; should check
  493.      *    response source address here if flags&NOTAUTH.
  494.      */
  495.     fixttl(newdp);
  496.     dprintf(3, (ddt, "db_update: adding%s %x\n",
  497.             (newdp->d_flags&DB_F_HINT) ? " hint":"", newdp));
  498. #ifdef INVQ
  499.     if (!(newdp->d_flags & DB_F_HINT))
  500.         addinv(np, newdp);    /* modify inverse query tables */
  501. #endif
  502.  
  503. #ifdef STATS
  504.     if (!newdp->d_zone && !(newdp->d_flags & DB_F_HINT))
  505.         newdp->d_ns = nameserFind(from_addr.sin_addr, NS_F_INSERT);
  506. #endif
  507.  
  508.     /* Add to end of list, generally preserving order */
  509.     newdp->d_next = NULL;
  510.     if ((dp = np->n_data) == NULL)  {
  511. #ifdef DATUMREFCNT
  512.         newdp->d_rcnt = 1;
  513. #endif
  514.         np->n_data = newdp;
  515.         return (OK);
  516.     }
  517.     while (dp->d_next != NULL) {
  518.         if ((flags & DB_NODATA) && !db_cmp(dp, newdp))
  519.             return (DATAEXISTS);
  520.         dp = dp->d_next;
  521.     }
  522.     if ((flags & DB_NODATA) && !db_cmp(dp, newdp))
  523.         return (DATAEXISTS);
  524. #ifdef    DATUMREFCNT
  525.     newdp->d_rcnt = 1;
  526. #endif
  527.     dp->d_next = newdp;
  528.     return (OK);
  529. }
  530.  
  531. static void
  532. fixttl(dp)
  533.     register struct databuf *dp;
  534. {
  535.     if (dp->d_zone == 0 && !(dp->d_flags & DB_F_HINT)) {
  536.         if (dp->d_ttl <= tt.tv_sec)
  537.             return;
  538.         else if (dp->d_ttl < tt.tv_sec+min_cache_ttl)
  539.             dp->d_ttl = tt.tv_sec+min_cache_ttl;
  540.         else if (dp->d_ttl > tt.tv_sec+max_cache_ttl)
  541.             dp->d_ttl = tt.tv_sec+max_cache_ttl;
  542.     }
  543.     return;
  544. }
  545.  
  546. /*
  547.  * Compare type, class and data from databufs for equivalence.
  548.  * Must be case insensitive for some domain names.
  549.  * Return 0 if equivalent, nonzero otherwise.
  550.  */
  551. static int
  552. db_cmp(dp1, dp2)
  553.     register struct databuf *dp1, *dp2;
  554. {
  555.     register u_char *cp1, *cp2;
  556.     int len;
  557.  
  558.     if (dp1->d_type != dp2->d_type || dp1->d_class != dp2->d_class)
  559.         return (1);
  560.     if (dp1->d_size != dp2->d_size)
  561.         return (1);
  562.     if (dp1->d_mark != dp2->d_mark)
  563.         return (1);        /* old and new RR's are distinct */
  564. #ifdef NCACHE
  565.     if (dp1->d_rcode && dp2->d_rcode)
  566.         return ((dp1->d_rcode == dp1->d_rcode)?0:1);
  567.     if (dp1->d_rcode || dp2->d_rcode)
  568.         return (1);
  569. #endif
  570.  
  571.     switch (dp1->d_type) {
  572.  
  573.     case T_A:
  574.     case T_UID:
  575.     case T_GID:
  576.     case T_WKS:
  577.     case T_NULL:
  578.     case T_NSAP:
  579. #ifdef ALLOW_T_UNSPEC
  580.         case T_UNSPEC:
  581. #endif
  582.         return (bcmp(dp1->d_data, dp2->d_data, dp1->d_size));
  583.  
  584.     case T_NS:
  585.     case T_CNAME:
  586.     case T_PTR:
  587.     case T_MB:
  588.     case T_MG:
  589.     case T_MR:
  590.     case T_UINFO:
  591.         return (strcasecmp((char *)dp1->d_data, (char *)dp2->d_data));
  592.  
  593.     case T_HINFO:
  594.     case T_ISDN:
  595.         cp1 = dp1->d_data;
  596.         cp2 = dp2->d_data;
  597.         len = *cp1;
  598.         if (strncasecmp((char *)++cp1, (char *)++cp2, len))
  599.             return (1);
  600.         cp1 += len;
  601.         cp2 += len;
  602.         len = *cp1;
  603.         return (strncasecmp((char *)++cp1, (char *)++cp2, len));
  604.  
  605.     case T_SOA:
  606.     case T_MINFO:
  607.     case T_RP:
  608.         if (strcasecmp((char *)dp1->d_data, (char *)dp2->d_data))
  609.             return (1);
  610.         cp1 = dp1->d_data + strlen((char *)dp1->d_data) + 1;
  611.         cp2 = dp2->d_data + strlen((char *)dp2->d_data) + 1;
  612.         if (dp1->d_type != T_SOA)
  613.             return (strcasecmp((char *)cp1, (char *)cp2));
  614.         if (strcasecmp((char *)cp1, (char *)cp2))
  615.             return (1);
  616.         cp1 += strlen((char *)cp1) + 1;
  617.         cp2 += strlen((char *)cp2) + 1;
  618.         return (bcmp(cp1, cp2, INT32SZ * 5));
  619.     
  620.     case T_MX:
  621.     case T_AFSDB:
  622.     case T_RT:
  623.         cp1 = dp1->d_data;
  624.         cp2 = dp2->d_data;
  625.         if (*cp1++ != *cp2++ || *cp1++ != *cp2++)    /* cmp prio */
  626.             return (1);
  627.         return (strcasecmp((char *)cp1, (char *)cp2));
  628.  
  629.     case T_TXT:
  630.     case T_X25:
  631.         if (dp1->d_size != dp2->d_size)
  632.             return (1);
  633.         return (bcmp(dp1->d_data, dp2->d_data, dp1->d_size));
  634.  
  635.     default:
  636.         return (1);
  637.     }
  638. }
  639.