1 /**************************************************************************************************
2 	$Id: soa.c,v 1.65 2005/12/18 19:16:41 bboy Exp $
3 
4 	Copyright (C) 2002-2005  Don Moore <bboy@bboy.net>
5 
6 	This program is free software; you can redistribute it and/or modify
7 	it under the terms of the GNU General Public License as published by
8 	the Free Software Foundation; either version 2 of the License, or
9 	(at Your option) any later version.
10 
11 	This program is distributed in the hope that it will be useful,
12 	but WITHOUT ANY WARRANTY; without even the implied warranty of
13 	MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14 	GNU General Public License for more details.
15 
16 	You should have received a copy of the GNU General Public License
17 	along with this program; if not, write to the Free Software
18 	Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
19 **************************************************************************************************/
20 
21 #include "mydns.h"
22 
23 char *mydns_soa_table_name = NULL;
24 char *mydns_soa_where_clause = NULL;
25 
26 char *mydns_soa_active_types[] = { (char*)"Y", (char*)"N" };
27 
28 /* Optional columns */
29 int mydns_soa_use_active = 0;
30 int mydns_soa_use_xfer = 0;
31 int mydns_soa_use_update_acl = 0;
32 int mydns_soa_use_recursive = 0;
33 
34 /* Make this nonzero to enable debugging within this source file */
35 #define	DEBUG_LIB_SOA	1
36 
37 void
mydns_soa_get_active_types(SQL * sqlConn)38 mydns_soa_get_active_types(SQL *sqlConn) {
39   SQL_RES	*res;
40   SQL_ROW	row;
41   int		querylen;
42   char 		*query;
43 
44   char		*YES = (char*)"Y";
45   char		*NO = (char*)"N";
46 
47   querylen = sql_build_query(&query, "SELECT DISTINCT(active) FROM %s LIMIT 1", mydns_soa_table_name);
48 
49   if (!(res = sql_query(sqlConn, query, querylen))) {
50     RELEASE(query);
51     return;
52   }
53 
54 #if DEBUG_ENABLED && DEBUG_LIB_SOA
55   {
56     int numresults = sql_num_rows(res);
57     DebugX("lib-soa", 1, _("SOA get active types: %d row%s: %s"), numresults, S(numresults), query);
58   }
59 #endif
60 
61   RELEASE(query);
62 
63   while ((row = sql_getrow(res, NULL))) {
64     char *VAL = row[0];
65     if (   !strcasecmp(VAL, "yes")
66 	   || !strcasecmp(VAL, "y")
67 	   || !strcasecmp(VAL, "true")
68 	   || !strcasecmp(VAL, "t")
69 	   || !strcasecmp(VAL, "active")
70 	   || !strcasecmp(VAL, "a")
71 	   || !strcasecmp(VAL, "on")
72 	   || !strcasecmp(VAL, "1") ) { YES = STRDUP(VAL); continue; }
73     if (   !strcasecmp(VAL, "no")
74 	   || !strcasecmp(VAL, "n")
75 	   || !strcasecmp(VAL, "false")
76 	   || !strcasecmp(VAL, "f")
77 	   || !strcasecmp(VAL, "inactive")
78 	   || !strcasecmp(VAL, "i")
79 	   || !strcasecmp(VAL, "off")
80 	   || !strcasecmp(VAL, "0") ) { NO = STRDUP(VAL); continue; }
81   }
82 
83   sql_free(res);
84 
85   mydns_soa_active_types[0] = YES;
86   mydns_soa_active_types[1] = NO;
87 }
88 
89 /**************************************************************************************************
90 	MYDNS_SOA_COUNT
91 	Returns the number of zones in the soa table.
92 **************************************************************************************************/
93 long
mydns_soa_count(SQL * sqlConn)94 mydns_soa_count(SQL *sqlConn) {
95   return sql_count(sqlConn, "SELECT COUNT(*) FROM %s", mydns_soa_table_name);
96 }
97 /*--- mydns_soa_count() -------------------------------------------------------------------------*/
98 
99 
100 /**************************************************************************************************
101 	MYDNS_SET_SOA_TABLE_NAME
102 **************************************************************************************************/
103 void
mydns_set_soa_table_name(const char * name)104 mydns_set_soa_table_name(const char *name) {
105   RELEASE(mydns_soa_table_name);
106   if (!name)
107     mydns_soa_table_name = STRDUP(MYDNS_SOA_TABLE);
108   else
109     mydns_soa_table_name = STRDUP(name);
110 }
111 /*--- mydns_set_soa_table_name() ----------------------------------------------------------------*/
112 
113 
114 /**************************************************************************************************
115 	MYDNS_SET_SOA_WHERE_CLAUSE
116 **************************************************************************************************/
117 void
mydns_set_soa_where_clause(const char * where)118 mydns_set_soa_where_clause(const char *where) {
119   if (where && strlen(where)) {
120     mydns_soa_where_clause = STRDUP(where);
121   }
122 }
123 /*--- mydns_set_soa_where_clause() --------------------------------------------------------------*/
124 
125 
126 /**************************************************************************************************
127 	MYDNS_SOA_PARSE
128 **************************************************************************************************/
129 static
130 #if !PROFILING
131 inline
132 #endif
133 MYDNS_SOA *
mydns_soa_parse(SQL_ROW row)134 mydns_soa_parse(SQL_ROW row) {
135   MYDNS_SOA *rv;
136   int len;
137 
138   rv = (MYDNS_SOA *)ALLOCATE(sizeof(MYDNS_SOA), MYDNS_SOA);
139 
140   rv->next = NULL;
141 
142   rv->id = atou(row[0]);
143   strncpy(rv->origin, row[1], sizeof(rv->origin)-1);
144   strncpy(rv->ns, row[2], sizeof(rv->ns)-1);
145   if (!rv->ns[0])
146     snprintf(rv->ns, sizeof(rv->ns), "ns.%s", rv->origin);
147   strncpy(rv->mbox, row[3], sizeof(rv->mbox)-1);
148   if (!rv->mbox[0])
149     snprintf(rv->mbox, sizeof(rv->mbox), "hostmaster.%s", rv->origin);
150   rv->serial = atou(row[4]);
151   rv->refresh = atou(row[5]);
152   rv->retry = atou(row[6]);
153   rv->expire = atou(row[7]);
154   rv->minimum = atou(row[8]);
155   rv->ttl = atou(row[9]);
156 
157   { int ridx = MYDNS_SOA_NUMFIELDS;
158     ridx += (mydns_soa_use_active)?1:0;
159     rv->recursive = ((mydns_soa_use_recursive)?GETBOOL(row[ridx]):0);
160   }
161 
162   /* If 'ns' or 'mbox' don't end in a dot, append the origin */
163   len = strlen(rv->ns);
164   if (rv->ns[len-1] != '.') {
165     strncat(rv->ns, ".", sizeof(rv->ns) - len - 1);
166     strncat(rv->ns, rv->origin, sizeof(rv->ns) - len - 2);
167   }
168   len = strlen(rv->mbox);
169   if (rv->mbox[len-1] != '.') {
170     strncat(rv->mbox, ".", sizeof(rv->mbox) - len - 1);
171     strncat(rv->mbox, rv->origin, sizeof(rv->mbox) - len - 2);
172   }
173 
174   /* Make sure TTL for SOA is at least the minimum */
175   if (rv->ttl < rv->minimum)
176     rv->ttl = rv->minimum;
177 
178   return (rv);
179 }
180 /*--- mydns_soa_parse() -------------------------------------------------------------------------*/
181 
182 
183 /**************************************************************************************************
184 	MYDNS_SOA_DUP
185 	Create a duplicate copy of the record.
186 	Make and return a copy of a MYDNS_SOA record.  If 'recurse' is specified, copies all records
187 	in the list.
188 **************************************************************************************************/
189 MYDNS_SOA *
mydns_soa_dup(MYDNS_SOA * start,int recurse)190 mydns_soa_dup(MYDNS_SOA *start, int recurse) {
191   register MYDNS_SOA *first = NULL, *last = NULL, *soa, *s, *tmp;
192 
193   for (s = start; s; s = tmp) {
194     tmp = s->next;
195 
196     soa = (MYDNS_SOA *)ALLOCATE(sizeof(MYDNS_SOA), MYDNS_SOA);
197 
198     soa->id = s->id;
199     strncpy(soa->origin, s->origin, sizeof(soa->origin)-1);
200     strncpy(soa->ns, s->ns, sizeof(soa->ns)-1);
201     strncpy(soa->mbox, s->mbox, sizeof(soa->mbox)-1);
202     soa->serial = s->serial;
203     soa->refresh = s->refresh;
204     soa->retry = s->retry;
205     soa->expire = s->expire;
206     soa->minimum = s->minimum;
207     soa->ttl = s->ttl;
208     soa->recursive = s->recursive;
209     soa->next = NULL;
210     if (recurse) {
211       if (!first) first = soa;
212       if (last) last->next = soa;
213       last = soa;
214     } else
215       return (soa);
216   }
217   return (first);
218 }
219 /*--- mydns_soa_dup() ---------------------------------------------------------------------------*/
220 
221 
222 /**************************************************************************************************
223 	MYDNS_SOA_SIZE
224 **************************************************************************************************/
225 #if !PROFILING
226 inline
227 #endif
228 size_t
mydns_soa_size(MYDNS_SOA * first)229 mydns_soa_size(MYDNS_SOA *first) {
230   register MYDNS_SOA *p;
231   register size_t size = 0;
232 
233   for (p = first; p; p = p->next)
234     size += sizeof(MYDNS_SOA);
235 
236   return (size);
237 }
238 /*--- mydns_soa_size() --------------------------------------------------------------------------*/
239 
240 
241 /**************************************************************************************************
242 	_MYDNS_SOA_FREE
243 	Frees the pointed-to structure.	Don't call this function directly, call the macro.
244 **************************************************************************************************/
245 #if !PROFILING
246 inline
247 #endif
248 void
_mydns_soa_free(MYDNS_SOA * first)249 _mydns_soa_free(MYDNS_SOA *first) {
250   register MYDNS_SOA *p, *tmp;
251 
252   for (p = first; p; p = tmp) {
253     tmp = p->next;
254     RELEASE(p);
255   }
256 }
257 /*--- mydns_soa_free() --------------------------------------------------------------------------*/
258 
259 
260 /**************************************************************************************************
261 	MYDNS_SOA_LOAD
262 	Returns 0 on success or nonzero if an error occurred.
263 **************************************************************************************************/
264 int
mydns_soa_load(SQL * sqlConn,MYDNS_SOA ** rptr,const char * origin)265 mydns_soa_load(SQL *sqlConn, MYDNS_SOA **rptr, const char *origin) {
266   MYDNS_SOA		*first = NULL, *last = NULL;
267   size_t		querylen;
268   char			*query;
269   SQL_RES		*res;
270   SQL_ROW		row;
271   const char		*c;
272 #ifdef DN_COLUMN_NAMES
273   int			originlen = strlen(origin);
274 #endif
275 
276 #if DEBUG_ENABLED && DEBUG_LIB_SOA
277   DebugX("lib-soa", 1, _("mydns_soa_load(%s)"), origin);
278 #endif
279 
280   if (rptr) *rptr = NULL;
281 
282   /* Verify args */
283   if (!sqlConn || !origin || !rptr) {
284     errno = EINVAL;
285     return (-1);
286   }
287 
288   /* We're not escaping 'origin', so check it for illegal type chars */
289   for (c = origin; *c; c++)
290     if (SQL_BADCHAR(*c))
291       return (0);
292 
293 #ifdef DN_COLUMN_NAMES
294   if (origin[originlen - 1] == '.')
295     origin[originlen - 1] = '\0';				/* Remove dot from origin for DN */
296   else
297     originlen = 0;
298 #endif
299 
300   /* Construct query */
301   querylen = sql_build_query(&query,
302 			     "SELECT "MYDNS_SOA_FIELDS"%s%s FROM %s WHERE origin='%s'%s%s;",
303 			     (mydns_soa_use_active ? ",active" : ""),
304 			     (mydns_soa_use_recursive ? ",recursive" : ""),
305 			     mydns_soa_table_name, origin,
306 			     (mydns_soa_where_clause)? " AND " : "",
307 			     (mydns_soa_where_clause)? mydns_soa_where_clause : "");
308 
309 #ifdef DN_COLUMN_NAMES
310   if (originlen)
311     origin[originlen - 1] = '.';				/* Re-add dot to origin for DN */
312 #endif
313 
314   /* Submit query */
315   if (!(res = sql_query(sqlConn, query, querylen)))
316     return (-1);
317 
318 #if DEBUG_ENABLED && DEBUG_LIB_SOA
319   {
320     int numresults = sql_num_rows(res);
321 
322     DebugX("lib-soa", 1, _("SOA query: %d row%s: %s"), numresults, S(numresults), query);
323   }
324 #endif
325 
326   RELEASE(query);
327 
328   /* Add results to list */
329   while ((row = sql_getrow(res, NULL))) {
330     MYDNS_SOA *new;
331 
332 #if DEBUG_ENABLED && DEBUG_LIB_SOA
333     DebugX("lib-soa", 1, _("SOA query: use_soa_active=%d soa_active=%s,%d"), mydns_soa_use_active,
334 	   (mydns_soa_use_active)?row[MYDNS_SOA_NUMFIELDS]:"<undef>",
335 	   (mydns_soa_use_active)?GETBOOL(row[MYDNS_SOA_NUMFIELDS]):-1);
336     DebugX("lib-soa", 1, _("SOA query: id=%s, origin=%s, ns=%s, mbox=%s, serial=%s, refresh=%s, "
337 			   "retry=%s, expire=%s, minimum=%s, ttl=%s"),
338 	   row[0], row[1], row[2], row[3], row[4], row[5], row[6], row[7], row[8], row[9]);
339     { int ridx = MYDNS_SOA_NUMFIELDS;
340       ridx += (mydns_soa_use_active)?1:0;
341       DebugX("lib-soa", 1, _("Soa query: recursive = %s"),
342 	     (mydns_soa_use_recursive)?row[ridx++]:_("not recursing"));
343     }
344 #endif
345 
346     if (mydns_soa_use_active && row[MYDNS_SOA_NUMFIELDS] && !GETBOOL(row[MYDNS_SOA_NUMFIELDS]))
347       continue;
348 
349     new = mydns_soa_parse(row);
350     if (!first) first = new;
351     if (last) last->next = new;
352     last = new;
353   }
354 
355   *rptr = first;
356   sql_free(res);
357   return (0);
358 }
359 /*--- mydns_soa_load() --------------------------------------------------------------------------*/
360 
361 /* vi:set ts=3: */
362