home *** CD-ROM | disk | FTP | other *** search
/ InfoMagic Source Code 1993 July / THE_SOURCE_CODE_CD_ROM.iso / bsd_srcs / usr.sbin / named / db_update.c < prev    next >
Encoding:
C/C++ Source or Header  |  1991-04-24  |  10.0 KB  |  404 lines

  1. /*
  2.  * Copyright (c) 1986, 1990 Regents of the University of California.
  3.  * All rights reserved.
  4.  *
  5.  * Redistribution and use in source and binary forms, with or without
  6.  * modification, are permitted provided that the following conditions
  7.  * are met:
  8.  * 1. Redistributions of source code must retain the above copyright
  9.  *    notice, this list of conditions and the following disclaimer.
  10.  * 2. Redistributions in binary form must reproduce the above copyright
  11.  *    notice, this list of conditions and the following disclaimer in the
  12.  *    documentation and/or other materials provided with the distribution.
  13.  * 3. All advertising materials mentioning features or use of this software
  14.  *    must display the following acknowledgement:
  15.  *    This product includes software developed by the University of
  16.  *    California, Berkeley and its contributors.
  17.  * 4. Neither the name of the University nor the names of its contributors
  18.  *    may be used to endorse or promote products derived from this software
  19.  *    without specific prior written permission.
  20.  *
  21.  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
  22.  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
  23.  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
  24.  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
  25.  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
  26.  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
  27.  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
  28.  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
  29.  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
  30.  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  31.  * SUCH DAMAGE.
  32.  */
  33.  
  34. #ifndef lint
  35. static char sccsid[] = "@(#)db_update.c    4.28 (Berkeley) 3/21/91";
  36. #endif /* not lint */
  37.  
  38. #include <sys/param.h>
  39. #include <sys/socket.h>
  40. #include <sys/time.h>
  41. #include <netinet/in.h>
  42. #include <arpa/nameser.h>
  43. #include <stdio.h>
  44. #include <syslog.h>
  45. #include "ns.h"
  46. #include "db.h"
  47.  
  48. extern struct timeval    tt;
  49. extern FILE *ddt;
  50. extern struct sockaddr_in from_addr;    /* Source addr of last packet */
  51. extern int needs_prime_cache;
  52.  
  53. int    max_cache_ttl = (7*24*60*60);    /* ONE_WEEK maximum ttl */
  54. int    min_cache_ttl = (5*60);        /* 5 minute minimum ttl */
  55.  
  56. /*
  57.  * Update data base. Flags control the action.
  58.  * Inverse query tables modified.
  59.  */
  60. db_update(name, odp, newdp, flags, htp)
  61.     char name[];
  62.     struct databuf *odp, *newdp;
  63.     int flags;
  64.     struct hashbuf *htp;
  65. {
  66.     register struct namebuf *np;
  67.     register struct databuf *dp, *pdp;
  68.     char *fname;
  69.         int foundRR = 0;
  70.  
  71. #ifdef DEBUG
  72.     if (debug >= 3)
  73.         fprintf(ddt,"db_update(%s, 0x%x, 0x%x, 0%o, 0x%x)%s\n",
  74.             name, odp, newdp, flags, htp,
  75.             (odp && (odp->d_flags&DB_F_HINT)) ? " hint":"" );
  76. #endif
  77.     np = nlookup(name, &htp, &fname, newdp != NULL);
  78.     if (np == NULL || fname != name)
  79.         return (NONAME);
  80.  
  81.         /* Reflect certain updates in hint cache also... */
  82.     /* Don't stick data we are authoritative for in hints. */
  83.         if (!(flags & DB_NOHINTS) && (odp != NULL) &&
  84.         (odp->d_zone <= 0) && !(odp->d_flags & DB_F_HINT) &&
  85.             ((name[0] == '\0' && odp->d_type == T_NS) ||
  86.          (odp->d_type == T_A)))
  87.         {
  88.         register struct databuf *dp;
  89. #ifdef DEBUG
  90.         if (debug >= 3)
  91.             fprintf(ddt,"db_update: hint '%s' %d\n",
  92.                 name, odp->d_ttl);
  93. #endif
  94.         dp = savedata(odp->d_class, odp->d_type, odp->d_ttl,
  95.             odp->d_data, odp->d_size);
  96.         dp->d_zone = DB_Z_CACHE;
  97.         dp->d_flags = DB_F_HINT;
  98.         if (db_update(name, dp,dp, (flags|DB_NOHINTS), fcachetab) != OK) {
  99. #ifdef DEBUG        
  100.             if (debug > 2)
  101.                 fprintf(ddt, "db_update: hint %x freed\n", dp);
  102. #endif
  103.             (void) free((char *)dp);
  104.         }
  105.         }
  106.  
  107.     if (odp != NULL) {
  108.         pdp = NULL;
  109.         for (dp = np->n_data; dp != NULL; ) {
  110.             if (!match(dp, odp->d_class, odp->d_type)) {
  111.                 if ((dp->d_type == T_CNAME ||
  112.                     odp->d_type == T_CNAME) &&
  113.                     odp->d_mark == dp->d_mark &&
  114.                     zones[odp->d_zone].z_type != Z_CACHE) {
  115.                     syslog(LOG_ERR,
  116.                 "%s has CNAME and other data (illegal)\n",
  117.                         name);
  118. #ifdef DEBUG
  119.                     if (debug)
  120.                         fprintf(ddt,
  121.                 "db_update: %s: CNAME and more (%d, %d)\n",
  122.                         name, odp->d_type, dp->d_type);
  123. #endif
  124.                 }
  125.                 goto skip;
  126.             }
  127. #ifdef DEBUG
  128.             if (debug >= 5)
  129.                 fprintf(ddt,"db_update: flags = %#x, sizes = %d, %d (%d)\n",
  130.                     flags, odp->d_size, dp->d_size,
  131.                     db_cmp(dp, odp));
  132. #endif
  133.             if (flags & DB_NOTAUTH && dp->d_zone) {
  134. #ifdef DEBUG
  135.                 if (debug)
  136.                     fprintf(ddt,
  137.                     "%s attempted update to auth zone %d '%s'\n",
  138.                     inet_ntoa(from_addr.sin_addr),
  139.                     dp->d_zone, zones[dp->d_zone].z_origin);
  140. #endif
  141.                 return (AUTH);
  142.             }
  143.             if ((flags & DB_NODATA) && !db_cmp(dp, odp)) {
  144.                 /* refresh ttl if cache entry */
  145.                 if (dp->d_zone == 0) {
  146.                     if (odp->d_zone != 0) {    /* XXX */
  147.                         /* changing cache->auth */
  148.                         dp->d_zone = odp->d_zone;
  149.                         dp->d_ttl = odp->d_ttl;
  150. #ifdef DEBUG
  151.                         if (debug > 3)
  152.                             fprintf(ddt,
  153.                 "db_update: cache entry now in auth zone\n");
  154. #endif
  155.                         return (DATAEXISTS);
  156.                     }
  157.                     fixttl(odp);
  158.                     if (odp->d_ttl > dp->d_ttl)
  159.                         dp->d_ttl = odp->d_ttl;
  160. #ifdef DEBUG
  161.                         if (debug >= 3)
  162.                         fprintf(ddt,"db_update: new ttl %d, +%d\n",
  163.                                 dp->d_ttl, dp->d_ttl - tt.tv_sec);
  164. #endif
  165.                 }
  166.                 return (DATAEXISTS);
  167.             }
  168.             /*
  169.              * If the old databuf has some data, check that the
  170.              * data matches that in the new databuf (so UPDATED
  171.              * will delete only the matching RR)
  172.              */
  173.             if (odp->d_size > 0) {
  174.                 if (db_cmp(dp, odp))
  175.                     goto skip;
  176.             }
  177.             foundRR = 1;
  178.             if (flags & DB_DELETE)
  179.                 dp = rm_datum(dp, np, pdp);
  180.             else {
  181. skip:                pdp = dp;
  182.                 dp = dp->d_next;
  183.             }
  184.         }
  185.                 if (!foundRR) {
  186.             if (flags & DB_DELETE)
  187.                 return(NODATA);
  188.             if (flags & DB_MEXIST)
  189.                 return(NODATA);
  190.         }
  191.     }
  192.     if (newdp == NULL)
  193.         return (OK);
  194.     fixttl(newdp);
  195. #ifdef DEBUG
  196.         if (debug >= 3)
  197.             fprintf(ddt,"db_update: adding%s %x\n",
  198.             (newdp->d_flags&DB_F_HINT) ? " hint":"", newdp);
  199. #endif
  200.     if (!(newdp->d_flags & DB_F_HINT))
  201.         addinv(np, newdp);    /* modify inverse query tables */
  202.  
  203.     /* Add to end of list, generally preserving order */
  204.     newdp->d_next = NULL;
  205.     if ((dp = np->n_data) == NULL)  {
  206.         np->n_data = newdp;
  207.         return (OK);
  208.     }
  209.     /* XXX: need to check for duplicate WKS records and flag error */
  210.     while (dp->d_next != NULL) {
  211.         if ((flags & DB_NODATA) && !db_cmp(dp, newdp))
  212.             return (DATAEXISTS);
  213.         dp = dp->d_next;
  214.     }
  215.     if ((flags & DB_NODATA) && !db_cmp(dp, newdp))
  216.         return (DATAEXISTS);
  217.     dp->d_next = newdp;
  218.     return (OK);
  219. }
  220.  
  221. fixttl(dp)
  222. register struct databuf *dp;
  223. {
  224.     if (dp->d_zone == 0 && !(dp->d_flags & DB_F_HINT)) {
  225.         if (dp->d_ttl <= tt.tv_sec)
  226.             return;
  227.         else if (dp->d_ttl < tt.tv_sec+min_cache_ttl)
  228.             dp->d_ttl = tt.tv_sec+min_cache_ttl;
  229.         else if (dp->d_ttl > tt.tv_sec+max_cache_ttl)
  230.             dp->d_ttl = tt.tv_sec+max_cache_ttl;
  231.     }
  232.     return;
  233. }
  234.  
  235. struct invbuf *invtab[INVHASHSZ];    /* Inverse query hash table */
  236.  
  237. /*
  238.  * Add data 'dp' to inverse query tables for name 'np'.
  239.  */
  240. addinv(np, dp)
  241.     struct namebuf *np;
  242.     struct databuf *dp;
  243. {
  244.     register struct invbuf *ip;
  245.     register int hval, i;
  246.  
  247.     switch (dp->d_type) {
  248.     case T_A:
  249.     case T_UID:
  250.     case T_GID:
  251.         break;
  252.  
  253.     default:
  254.         return;
  255.     }
  256.  
  257.     hval = dhash(dp->d_data, dp->d_size);
  258.     for (ip = invtab[hval]; ip != NULL; ip = ip->i_next)
  259.         for (i = 0; i < INVBLKSZ; i++)
  260.             if (ip->i_dname[i] == NULL) {
  261.                 ip->i_dname[i] = np;
  262.                 return;
  263.             }
  264.     ip = saveinv();
  265.     ip->i_next = invtab[hval];
  266.     invtab[hval] = ip;
  267.     ip->i_dname[0] = np;
  268. }
  269.  
  270. /*
  271.  * Remove data 'odp' from inverse query table.
  272.  */
  273. rminv(odp)
  274.     struct databuf *odp;
  275. {
  276.     register struct invbuf *ip;
  277.     register struct databuf *dp;
  278.     struct namebuf *np;
  279.     register int i;
  280.  
  281.     for (ip = invtab[dhash(odp->d_data, odp->d_size)]; ip != NULL;
  282.         ip = ip->i_next) {
  283.         for (i = 0; i < INVBLKSZ; i++) {
  284.             if ((np = ip->i_dname[i]) == NULL)
  285.                 break;
  286.             for (dp = np->n_data; dp != NULL; dp = dp->d_next) {
  287.                 if (!match(dp, odp->d_class, odp->d_type))
  288.                     continue;
  289.                 if (db_cmp(dp, odp))
  290.                     continue;
  291.                 while (i < INVBLKSZ-1) {
  292.                     ip->i_dname[i] = ip->i_dname[i+1];
  293.                     i++;
  294.                 }
  295.                 ip->i_dname[i] = NULL;
  296.                 return;
  297.             }
  298.         }
  299.     }
  300. }
  301.  
  302. /*
  303.  * Compute hash value from data.
  304.  */
  305. dhash(dp, dlen)
  306.     char *dp;
  307.     int dlen;
  308. {
  309.     register char *cp;
  310.     register unsigned hval;
  311.     register int n;
  312.  
  313.     n = dlen;
  314.     if (n > 8)
  315.         n = 8;
  316.     hval = 0;
  317.     for (cp = dp; --n >= 0; ) {
  318.         hval <<= 1;
  319.         hval += *cp++;
  320.     }
  321.     return (hval % INVHASHSZ);
  322. }
  323.  
  324. /*
  325.  * Compare type, class and data from databufs for equivalence.
  326.  * Must be case insensitive for some domain names.
  327.  * Return 0 if equivalent, nonzero otherwise.
  328.  */
  329. db_cmp(dp1, dp2)
  330.     register struct databuf *dp1, *dp2;
  331.  
  332. {
  333.     register char *cp1, *cp2;
  334.     int len;
  335.  
  336.     if (dp1->d_type != dp2->d_type || dp1->d_class != dp2->d_class)
  337.         return(1);
  338.     if (dp1->d_size != dp2->d_size)
  339.         return(1);
  340.     if (dp1->d_mark != dp2->d_mark)
  341.         return(1);        /* old and new RR's are distinct */
  342.     switch (dp1->d_type) {
  343.  
  344.     case T_A:
  345.     case T_UID:
  346.     case T_GID:
  347.     case T_WKS:
  348.     case T_NULL:
  349. #ifdef ALLOW_T_UNSPEC
  350.         case T_UNSPEC:
  351. #endif ALLOW_T_UNSPEC
  352.         return(bcmp(dp1->d_data, dp2->d_data, dp1->d_size));
  353.  
  354.     case T_NS:
  355.     case T_CNAME:
  356.     case T_PTR:
  357.     case T_MB:
  358.     case T_MG:
  359.     case T_MR:
  360.     case T_UINFO:
  361.         return(strcasecmp(dp1->d_data, dp2->d_data));
  362.  
  363.     case T_HINFO:
  364.         cp1 = dp1->d_data;
  365.         cp2 = dp2->d_data;
  366.         len = *cp1;
  367.         if (strncasecmp(++cp1, ++cp2, len))
  368.             return(1);
  369.         cp1 += len;
  370.         cp2 += len;
  371.         len = *cp1;
  372.         return(strncasecmp(++cp1, ++cp2, len));
  373.  
  374.     case T_SOA:
  375.     case T_MINFO:
  376.         if (strcasecmp(dp1->d_data, dp2->d_data))
  377.             return(1);
  378.         cp1 = dp1->d_data + strlen(dp1->d_data) + 1;
  379.         cp2 = dp2->d_data + strlen(dp2->d_data) + 1;
  380.         if (dp1->d_type != T_SOA)
  381.             return(strcasecmp(cp1, cp2));
  382.         if (strcasecmp(cp1, cp2))
  383.             return(1);
  384.         cp1 += strlen(cp1) + 1;
  385.         cp2 += strlen(cp2) + 1;
  386.         return(bcmp(cp1, cp2, sizeof(u_long) * 5));
  387.     
  388.     case T_MX:
  389.         cp1 = dp1->d_data;
  390.         cp2 = dp2->d_data;
  391.         if (*cp1++ != *cp2++ || *cp1++ != *cp2++)    /* cmp prio */
  392.             return(1);
  393.         return(strcasecmp(cp1, cp2));
  394.  
  395.     case T_TXT:
  396.         if (dp1->d_size != dp2->d_size)
  397.             return(1);
  398.         return(bcmp(dp1->d_data, dp2->d_data, dp1->d_size));
  399.  
  400.     default:
  401.         return (1);
  402.     }
  403. }
  404.