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