etc/services - sync with NetBSD-8
[minix.git] / external / bsd / bind / dist / contrib / zkt-1.1.3 / zfparse.c
blob6ee402d4d2f2a56748d6867fbffa47141c2c269d
1 /* $NetBSD: zfparse.c,v 1.1.1.1 2015/07/08 15:37:48 christos Exp $ */
3 /*****************************************************************
4 **
5 ** @(#) zfparse.c -- A zone file parser
6 **
7 ** Copyright (c) Jan 2010 - Jan 2010, Holger Zuleger HZnet. All rights reserved.
8 **
9 ** This software is open source.
11 ** Redistribution and use in source and binary forms, with or without
12 ** modification, are permitted provided that the following conditions
13 ** are met:
15 ** Redistributions of source code must retain the above copyright notice,
16 ** this list of conditions and the following disclaimer.
18 ** Redistributions in binary form must reproduce the above copyright notice,
19 ** this list of conditions and the following disclaimer in the documentation
20 ** and/or other materials provided with the distribution.
22 ** Neither the name of Holger Zuleger HZnet nor the names of its contributors may
23 ** be used to endorse or promote products derived from this software without
24 ** specific prior written permission.
26 ** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
27 ** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
28 ** TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
29 ** PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE
30 ** LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
31 ** CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
32 ** SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
33 ** INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
34 ** CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
35 ** ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
36 ** POSSIBILITY OF SUCH DAMAGE.
38 *****************************************************************/
39 # include <stdio.h>
40 # include <string.h>
41 # include <stdlib.h>
42 # include <unistd.h> /* for link(), unlink() */
43 # include <ctype.h>
44 # include <assert.h>
45 #ifdef HAVE_CONFIG_H
46 # include <config.h>
47 #endif
48 # include "config_zkt.h"
49 # include "zconf.h"
50 # include "misc.h"
51 # include "log.h"
52 # include "debug.h"
53 #define extern
54 # include "zfparse.h"
55 #undef extern
58 extern const char *progname;
60 /*****************************************************************
61 ** is_multiline_rr (const char *s)
62 *****************************************************************/
63 static const char *is_multiline_rr (int *multi_line_rr, const char *p)
65 while ( *p && *p != ';' )
67 if ( *p == '\"' )
69 p++;
70 while ( *p && *p != '\"' );
72 if ( *p == '(' )
73 *multi_line_rr = 1;
74 if ( *p == ')' )
75 *multi_line_rr = 0;
76 p++;
78 return p;
81 /*****************************************************************
82 ** skipws (const char *s)
83 *****************************************************************/
84 static const char *skipws (const char *s)
86 while ( *s && (*s == ' ' || *s == '\t' || *s == '\n') )
87 s++;
88 return s;
91 /*****************************************************************
92 ** skiplabel (const char *s)
93 *****************************************************************/
94 static const char *skiplabel (const char *s)
96 while ( *s && *s != ';' && *s != ' ' && *s != '\t' && *s != '\n' )
97 s++;
98 return s;
101 /*****************************************************************
102 ** setminmax ()
103 *****************************************************************/
104 static void setminmax (long *pmin, long val, long *pmax)
106 if ( val < *pmin )
107 *pmin = val;
108 if ( val > *pmax )
109 *pmax = val;
112 /*****************************************************************
113 ** get_ttl ()
114 *****************************************************************/
115 static long get_ttl (const char *s)
117 char quantity;
118 long lval;
120 quantity = 'd';
121 sscanf (s, "%ld%c", &lval, &quantity);
122 quantity = tolower (quantity);
123 if ( quantity == 'm' )
124 lval *= MINSEC;
125 else if ( quantity == 'h' )
126 lval *= HOURSEC;
127 else if ( quantity == 'd' )
128 lval *= DAYSEC;
129 else if ( quantity == 'w' )
130 lval *= WEEKSEC;
131 else if ( quantity == 'y' )
132 lval *= YEARSEC;
134 return lval;
137 /*****************************************************************
138 ** addkeydb ()
139 *****************************************************************/
140 int addkeydb (const char *file, const char *keydbfile)
142 FILE *fp;
144 if ( (fp = fopen (file, "a")) == NULL )
145 return -1;
147 fprintf (fp, "\n");
148 fprintf (fp, "$INCLUDE %s\t; this is the database of public DNSKEY RR\n", keydbfile);
150 fclose (fp);
152 return 0;
155 /*****************************************************************
156 ** parsezonefile ()
157 ** parse the BIND zone file 'file' and store the minimum and
158 ** maximum ttl value in the corresponding parameter.
159 ** if keydbfile is set, check if this file is already include.
160 ** if inclfiles is not NULL store a list of included files names
161 ** in it.
162 ** return 0 if keydbfile is not included
163 ** return 1 if keydbfile is included
164 ** return -1 on error
165 *****************************************************************/
166 int parsezonefile (const char *file, long *pminttl, long *pmaxttl, const char *keydbfile, char *inclfiles, size_t *plen)
168 FILE *infp;
169 int len;
170 int lnr;
171 long ttl;
172 int multi_line_rr;
173 int keydbfilefound;
174 char buf[1024];
175 const char *p;
177 assert (file != NULL);
178 assert (pminttl != NULL);
179 assert (pmaxttl != NULL);
181 dbg_val4 ("parsezonefile (\"%s\", %ld, %ld, \"%s\")\n", file, *pminttl, *pmaxttl, keydbfile);
183 if ( (infp = fopen (file, "r")) == NULL )
185 error ("parsezonefile: couldn't open file \"%s\" for input\n", file);
186 return -1;
189 lnr = 0;
190 keydbfilefound = 0;
191 multi_line_rr = 0;
192 while ( fgets (buf, sizeof buf, infp) != NULL )
194 len = strlen (buf);
195 if ( buf[len-1] != '\n' ) /* line too long ? */
196 fprintf (stderr, "line too long\n");
197 lnr++;
199 p = buf;
200 if ( multi_line_rr ) /* skip line if it's part of a multiline rr */
202 is_multiline_rr (&multi_line_rr, p);
203 continue;
206 if ( *p == '$' ) /* special directive ? */
208 if ( strncmp (p+1, "TTL", 3) == 0 ) /* $TTL ? */
210 ttl = get_ttl (p+4);
211 dbg_val3 ("%s:%d:ttl %ld\n", file, lnr, ttl);
212 setminmax (pminttl, ttl, pmaxttl);
214 else if ( strncmp (p+1, "INCLUDE", 7) == 0 ) /* $INCLUDE ? */
216 char fname[30+1];
218 sscanf (p+9, "%30s", fname);
219 dbg_val ("$INCLUDE directive for file \"%s\" found\n", fname);
220 if ( strcmp (fname, keydbfile) == 0 )
221 keydbfilefound = 1;
222 else
224 if ( inclfiles && plen )
226 len = snprintf (inclfiles, *plen, ",%s", fname);
227 if ( *plen <= len ) /* no space left in include file string */
228 return keydbfilefound;
229 inclfiles += len;
230 *plen -= len;
232 int ret = parsezonefile (fname, pminttl, pmaxttl, keydbfile, inclfiles, plen);
233 if ( ret ) /* keydb found or read error ? */
234 keydbfilefound = ret;
238 else if ( !isspace (*p) ) /* label ? */
239 p = skiplabel (p);
241 p = skipws (p);
242 if ( *p == ';' ) /* skip line if it's a comment line */
243 continue;
245 /* skip class (hesiod is not supported now) */
246 if ( (toupper (*p) == 'I' && toupper (p[1]) == 'N') ||
247 (toupper (*p) == 'C' && toupper (p[1]) == 'H') )
248 p += 2;
249 p = skipws (p);
251 if ( isdigit (*p) ) /* ttl ? */
253 ttl = get_ttl (p);
254 dbg_val3 ("%s:%d:ttl %ld\n", file, lnr, ttl);
255 setminmax (pminttl, ttl, pmaxttl);
258 /* check the rest of the line if it's the beginning of a multi_line_rr */
259 is_multiline_rr (&multi_line_rr, p);
262 if ( file )
263 fclose (infp);
265 dbg_val5 ("parsezonefile (\"%s\", %ld, %ld, \"%s\") ==> %d\n",
266 file, *pminttl, *pmaxttl, keydbfile, keydbfilefound);
267 return keydbfilefound;
271 #ifdef TEST
272 const char *progname;
273 int main (int argc, char *argv[])
275 long minttl;
276 long maxttl;
277 int keydbfound;
278 char *dnskeydb;
280 progname = *argv;
281 dnskeydb = NULL;
282 dnskeydb = "dnskey.db";
284 minttl = 0x7FFFFFFF;
285 maxttl = 0;
286 keydbfound = parsezonefile (argv[1], &minttl, &maxttl, dnskeydb);
287 if ( keydbfound < 0 )
288 error ("can't parse zone file %s\n", argv[1]);
290 if ( dnskeydb && !keydbfound )
292 printf ("$INCLUDE %s directive added \n", dnskeydb);
293 addkeydb (argv[1], dnskeydb);
296 printf ("minttl = %ld\n", minttl);
297 printf ("maxttl = %ld\n", maxttl);
299 return 0;
301 #endif