missing files
[tridge/bind9.git] / contrib / zkt / zfparse.c
diff --git a/contrib/zkt/zfparse.c b/contrib/zkt/zfparse.c
new file mode 100644 (file)
index 0000000..07d966f
--- /dev/null
@@ -0,0 +1,289 @@
+/*****************************************************************
+**
+**     @(#) zfparse.c -- A zone file parser
+**
+**     Copyright (c) Jan 2010 - Jan 2010, Holger Zuleger HZnet. All rights reserved.
+**
+**     This software is open source.
+**
+**     Redistribution and use in source and binary forms, with or without
+**     modification, are permitted provided that the following conditions
+**     are met:
+**
+**     Redistributions of source code must retain the above copyright notice,
+**     this list of conditions and the following disclaimer.
+**
+**     Redistributions in binary form must reproduce the above copyright notice,
+**     this list of conditions and the following disclaimer in the documentation
+**     and/or other materials provided with the distribution.
+**
+**     Neither the name of Holger Zuleger HZnet nor the names of its contributors may
+**     be used to endorse or promote products derived from this software without
+**     specific prior written permission.
+**
+**     THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+**     "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+**     TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+**     PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE
+**     LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+**     CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+**     SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+**     INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+**     CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+**     ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+**     POSSIBILITY OF SUCH DAMAGE.
+**
+*****************************************************************/
+# include <stdio.h>
+# include <string.h>
+# include <stdlib.h>
+# include <unistd.h>   /* for link(), unlink() */
+# include <ctype.h>
+# include <assert.h>
+#if 0
+# include <sys/types.h>
+# include <sys/stat.h>
+# include <time.h>
+# include <utime.h>
+# include <errno.h>
+# include <fcntl.h>
+#endif
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+# include "config_zkt.h"
+# include "zconf.h"
+# include "log.h"
+# include "debug.h"
+#define extern
+# include "zfparse.h"
+#undef extern
+
+
+extern const   char    *progname;
+
+/*****************************************************************
+**     is_multiline_rr (const char *s)
+*****************************************************************/
+static const   char    *is_multiline_rr (int *multi_line_rr, const char *p)
+{
+       while ( *p && *p != ';' )
+       {
+               if ( *p == '\"' )
+                       do
+                               p++;
+                       while ( *p && *p != '\"' );
+
+               if ( *p == '(' )
+                       *multi_line_rr = 1;
+               if ( *p == ')' )
+                       *multi_line_rr = 0;
+               p++;
+       }
+       return p;
+}
+
+/*****************************************************************
+**     skipws (const char *s)
+*****************************************************************/
+static const   char    *skipws (const char *s)
+{
+       while ( *s && (*s == ' ' || *s == '\t' || *s == '\n') )
+               s++;
+       return s;
+}
+
+/*****************************************************************
+**     skiplabel (const char *s)
+*****************************************************************/
+static const   char    *skiplabel (const char *s)
+{
+       while ( *s && *s != ';' && *s != ' ' && *s != '\t' && *s != '\n' )
+               s++;
+       return s;
+}
+
+/*****************************************************************
+**     setminmax ()
+*****************************************************************/
+static void    setminmax (long *pmin, long val, long *pmax)
+{
+       if ( val < *pmin )
+               *pmin = val;
+       if ( val > *pmax )
+               *pmax = val;
+}
+
+/*****************************************************************
+**     get_ttl ()
+*****************************************************************/
+static long    get_ttl (const char *s)
+{
+       char    quantity;
+       long    lval;
+
+       quantity = 'd';
+       sscanf (s, "%ld%c", &lval, &quantity);
+       quantity = tolower (quantity);
+       if  ( quantity == 'm' )
+               lval *= MINSEC;
+       else if  ( quantity == 'h' )
+               lval *= HOURSEC;
+       else if  ( quantity == 'd' )
+               lval *= DAYSEC;
+       else if  ( quantity == 'w' )
+               lval *= WEEKSEC;
+       else if  ( quantity == 'y' )
+               lval *= YEARSEC;
+
+       return lval;
+}
+
+/*****************************************************************
+**     addkeydb ()
+*****************************************************************/
+int    addkeydb (const char *file, const char *keydbfile)
+{
+       FILE    *fp;
+
+       if ( (fp = fopen (file, "a")) == NULL )
+               return -1;
+
+       fprintf (fp, "\n");     
+       fprintf (fp, "$INCLUDE %s\t; this is the database of public DNSKEY RR\n", keydbfile);   
+
+       fclose (fp);
+
+       return 0;
+}
+
+/*****************************************************************
+**     parsezonefile ()
+**     parse the BIND zone file 'file' and store the minimum and
+**     maximum ttl value in the corresponding parameter.
+**     if keydbfile is set, check if this file is already include.
+**     return 0 if keydbfile is not included
+**     return 1 if keydbfile is included
+**     return -1 on error
+*****************************************************************/
+int    parsezonefile (const char *file, long *pminttl, long *pmaxttl, const char *keydbfile)
+{
+       FILE    *infp;
+       int     len;
+       int     lnr;
+       long    ttl;
+       int     multi_line_rr;
+       int     keydbfilefound;
+       char    buf[1024];
+       const   char    *p;
+
+       assert (file != NULL);
+       assert (pminttl != NULL);
+       assert (pmaxttl != NULL);
+
+       dbg_val4 ("parsezonefile (\"%s\", %ld, %ld, \"%s\")\n", file, *pminttl, *pmaxttl, keydbfile);
+
+       if ( (infp = fopen (file, "r")) == NULL )
+               return -1;
+
+       lnr = 0;
+       keydbfilefound = 0;
+       multi_line_rr = 0;
+       while ( fgets (buf, sizeof buf, infp) != NULL ) 
+       {
+               len = strlen (buf);
+               if ( buf[len-1] != '\n' )       /* line too long ? */
+                       fprintf (stderr, "line too long\n");
+               lnr++;
+
+               p = buf;
+               if ( multi_line_rr )    /* skip line if it's part of a multiline rr */
+               {
+                       is_multiline_rr (&multi_line_rr, p);
+                       continue;
+               }
+
+               if ( *p == '$' )        /* special directive ? */
+               {
+                       if ( strncmp (p+1, "TTL", 3) == 0 )     /* $TTL ? */
+                       {
+                               ttl = get_ttl (p+4);
+                               dbg_val3 ("%s:%d:ttl %ld\n", file, lnr, ttl);
+                               setminmax (pminttl, ttl, pmaxttl);
+                       }
+                       else if ( strncmp (p+1, "INCLUDE", 7) == 0 )    /* $INCLUDE ? */
+                       {
+                               char    fname[30+1];
+
+                               sscanf (p+9, "%30s", fname);
+                               dbg_val ("$INCLUDE directive for file \"%s\" found\n", fname);
+                               if ( keydbfile && strcmp (fname, keydbfile) == 0 )
+                                       keydbfilefound = 1;
+                               else
+                                       keydbfilefound = parsezonefile (fname, pminttl, pmaxttl, keydbfile);
+                       }
+               }
+               else if ( !isspace (*p) )       /* label ? */
+                       p = skiplabel (p);
+
+               p = skipws (p);
+               if ( *p == ';' )        /* skip line if it's  a comment line */
+                       continue;
+
+                       /* skip class (hesiod is not supported now) */
+               if ( (toupper (*p) == 'I' && toupper (p[1]) == 'N') ||
+                    (toupper (*p) == 'C' && toupper (p[1]) == 'H') )
+                       p += 2;
+               p = skipws (p);
+
+               if ( isdigit (*p) )     /* ttl ? */
+               {
+                       ttl = get_ttl (p);
+                       dbg_val3 ("%s:%d:ttl %ld\n", file, lnr, ttl);
+                       setminmax (pminttl, ttl, pmaxttl);
+               }
+
+               /* check the rest of the line if it's the beginning of a multi_line_rr */
+               is_multiline_rr (&multi_line_rr, p);
+       }
+
+       if ( file )
+               fclose (infp);
+
+       dbg_val5 ("parsezonefile (\"%s\", %ld, %ld, \"%s\") ==> %d\n",
+                       file, *pminttl, *pmaxttl, keydbfile, keydbfilefound);
+       return keydbfilefound;
+}
+
+
+#ifdef TEST
+const char *progname;
+int    main (int argc, char *argv[])
+{
+       long    minttl;
+       long    maxttl;
+       int     keydbfound;
+       char    *dnskeydb;
+
+       progname = *argv;
+       dnskeydb = NULL;
+       dnskeydb = "dnskey.db";
+
+       minttl = 0x7FFFFFFF;
+       maxttl = 0;
+       keydbfound = parsezonefile (argv[1], &minttl, &maxttl, dnskeydb);
+       if ( keydbfound < 0 )
+               error ("can't parse zone file %s\n", argv[1]);
+
+       if ( dnskeydb && !keydbfound )
+       {
+               printf ("$INCLUDE %s directive added \n", dnskeydb);
+               addkeydb (argv[1], dnskeydb);
+       }
+
+       printf ("minttl = %ld\n", minttl);
+       printf ("maxttl = %ld\n", maxttl);
+
+       return 0;
+}
+#endif