1 /**************************************************************************************************
2 $Id: rr.c,v 1.65 2005/04/29 16:10:27 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 #define __MYDNS_RR_NAME(__rrp) ((__rrp)->_name)
24 #define __MYDNS_RR_DATA(__rrp) ((__rrp)->_data)
25 #define __MYDNS_RR_DATA_LENGTH(__rrp) ((__rrp)->_data.len)
26 #define __MYDNS_RR_DATA_VALUE(__rrp) ((__rrp)->_data.value)
27 #define __MYDNS_RR_SRV_WEIGHT(__rrp) ((__rrp)->recData.srv.weight)
28 #define __MYDNS_RR_SRV_PORT(__rrp) ((__rrp)->recData.srv.port)
29 #define __MYDNS_RR_RP_TXT(__rrp) ((__rrp)->recData._rp_txt)
30 #define __MYDNS_RR_NAPTR_ORDER(__rrp) ((__rrp)->recData.naptr.order)
31 #define __MYDNS_RR_NAPTR_PREF(__rrp) ((__rrp)->recData.naptr.pref)
32 #define __MYDNS_RR_NAPTR_FLAGS(__rrp) ((__rrp)->recData.naptr.flags)
33 #define __MYDNS_RR_NAPTR_SERVICE(__rrp) ((__rrp)->recData.naptr._service)
34 #define __MYDNS_RR_NAPTR_REGEX(__rrp) ((__rrp)->recData.naptr._regex)
35 #define __MYDNS_RR_NAPTR_REPLACEMENT(__rrp) ((__rrp)->recData.naptr._replacement)
36
37 char *mydns_rr_table_name = NULL;
38 char *mydns_rr_where_clause = NULL;
39
40 size_t mydns_rr_data_length = DNS_DATALEN;
41
42 /* Optional columns */
43 int mydns_rr_extended_data = 0;
44 int mydns_rr_use_active = 0;
45 int mydns_rr_use_stamp = 0;
46 int mydns_rr_use_serial = 0;
47
48 char *mydns_rr_active_types[] = { (char*)"Y", (char*)"N", (char*)"D" };
49
50 /* Make this nonzero to enable debugging within this source file */
51 #define DEBUG_LIB_RR 1
52
53 #if DEBUG_ENABLED
54 void *
__mydns_rr_assert_pointer(void * ptr,const char * fieldname,const char * filename,int linenumber)55 __mydns_rr_assert_pointer(void *ptr, const char *fieldname, const char *filename, int linenumber) {
56 #if DEBUG_ENABLED && DEBUG_LIB_RR
57 DebugX("lib-rr", 1, _("mydns_rr_assert_pointer() called for field=%s from %s:%d"),
58 fieldname, filename, linenumber);
59 #endif
60 if (ptr != NULL) return ptr;
61 DebugX("lib-rr", 1, _("%s Pointer is NULL at %s:%d"),
62 fieldname, filename, linenumber);
63 abort();
64 return ptr;
65 }
66 #endif
67
68 void
mydns_rr_get_active_types(SQL * sqlConn)69 mydns_rr_get_active_types(SQL *sqlConn) {
70 SQL_RES *res;
71 SQL_ROW row;
72 int querylen;
73 char *query;
74
75 char *YES = (char*)"Y";
76 char *NO = (char*)"N";
77 char *DELETED = (char*)"D";
78
79 querylen = sql_build_query(&query, "SELECT DISTINCT(active) FROM %s", mydns_rr_table_name);
80
81 if (!(res = sql_query(sqlConn, query, querylen))) return;
82
83 RELEASE(query);
84
85 while ((row = sql_getrow(res, NULL))) {
86 char *VAL = row[0];
87 if ( !strcasecmp(VAL, "yes")
88 || !strcasecmp(VAL, "y")
89 || !strcasecmp(VAL, "true")
90 || !strcasecmp(VAL, "t")
91 || !strcasecmp(VAL, "active")
92 || !strcasecmp(VAL, "a")
93 || !strcasecmp(VAL, "on")
94 || !strcmp(VAL, "1") ) { YES = STRDUP(VAL); continue; }
95 if ( !strcasecmp(VAL, "no")
96 || !strcasecmp(VAL, "n")
97 || !strcasecmp(VAL, "false")
98 || !strcasecmp(VAL, "f")
99 || !strcasecmp(VAL, "inactive")
100 || !strcasecmp(VAL, "i")
101 || !strcasecmp(VAL, "off")
102 || !strcmp(VAL, "0") ) { NO = STRDUP(VAL); continue; }
103 if ( !strcasecmp(VAL, "d")
104 || !strcasecmp(VAL, "deleted")
105 || !strcmp(VAL, "2") ) { DELETED = STRDUP(VAL); continue; }
106 }
107
108 sql_free(res);
109
110 mydns_rr_active_types[0] = YES;
111 mydns_rr_active_types[1] = NO;
112 mydns_rr_active_types[2] = DELETED;
113 }
114
115 /**************************************************************************************************
116 MYDNS_RR_COUNT
117 Returns the number of records in the rr table.
118 **************************************************************************************************/
119 long
mydns_rr_count(SQL * sqlConn)120 mydns_rr_count(SQL *sqlConn) {
121 return sql_count(sqlConn, "SELECT COUNT(*) FROM %s", mydns_rr_table_name);
122 }
123 /*--- mydns_rr_count() --------------------------------------------------------------------------*/
124
125
126 /**************************************************************************************************
127 MYDNS_SET_RR_TABLE_NAME
128 **************************************************************************************************/
129 void
mydns_set_rr_table_name(const char * name)130 mydns_set_rr_table_name(const char *name) {
131 RELEASE(mydns_rr_table_name);
132 if (!name)
133 mydns_rr_table_name = STRDUP(MYDNS_RR_TABLE);
134 else
135 mydns_rr_table_name = STRDUP(name);
136 }
137 /*--- mydns_set_rr_table_name() -----------------------------------------------------------------*/
138
139
140 /**************************************************************************************************
141 MYDNS_SET_RR_WHERE_CLAUSE
142 **************************************************************************************************/
143 void
mydns_set_rr_where_clause(const char * where)144 mydns_set_rr_where_clause(const char *where) {
145 if (where && strlen(where)) {
146 mydns_rr_where_clause = STRDUP(where);
147 }
148 }
149 /*--- mydns_set_rr_where_clause() ---------------------------------------------------------------*/
150
151
152 /**************************************************************************************************
153 MYDNS_RR_GET_TYPE
154 **************************************************************************************************/
155 inline dns_qtype_t
mydns_rr_get_type(char * type)156 mydns_rr_get_type(char *type) {
157 register char *c;
158
159 for (c = type; *c; c++)
160 *c = toupper(*c);
161
162 switch (type[0]) {
163 case 'A':
164 if (!type[1])
165 return DNS_QTYPE_A;
166
167 if (type[1] == 'A' && type[2] == 'A' && type[3] == 'A' && !type[4])
168 return DNS_QTYPE_AAAA;
169
170 #if ALIAS_ENABLED
171 if (type[1] == 'L' && type[2] == 'I' && type[3] == 'A' && type[4] == 'S' && !type[5])
172 return DNS_QTYPE_ALIAS;
173 #endif
174 break;
175
176 case 'C':
177 if (type[1] == 'N' && type[2] == 'A' && type[3] == 'M' && type[4] == 'E' && !type[5])
178 return DNS_QTYPE_CNAME;
179 break;
180
181 case 'H':
182 if (type[1] == 'I' && type[2] == 'N' && type[3] == 'F' && type[4] == 'O' && !type[5])
183 return DNS_QTYPE_HINFO;
184 break;
185
186 case 'M':
187 if (type[1] == 'X' && !type[2])
188 return DNS_QTYPE_MX;
189 break;
190
191 case 'N':
192 if (type[1] == 'S' && !type[2])
193 return DNS_QTYPE_NS;
194 if (type[1] == 'A' && type[2] == 'P' && type[3] == 'T' && type[4] == 'R' && !type[5])
195 return DNS_QTYPE_NAPTR;
196 break;
197
198 case 'T':
199 if (type[1] == 'X' && type[2] == 'T' && !type[3])
200 return DNS_QTYPE_TXT;
201 break;
202
203 case 'P':
204 if (type[1] == 'T' && type[2] == 'R' && !type[3])
205 return DNS_QTYPE_PTR;
206 break;
207
208 case 'R':
209 if (type[1] == 'P' && !type[2])
210 return DNS_QTYPE_RP;
211 break;
212
213 case 'S':
214 if (type[1] == 'R' && type[2] == 'V' && !type[3])
215 return DNS_QTYPE_SRV;
216 break;
217 }
218 return 0;
219 }
220 /*--- mydns_rr_get_type() -----------------------------------------------------------------------*/
221
222
223 /**************************************************************************************************
224 MYDNS_RR_PARSE_RP
225 RP contains two names in 'data' -- the mbox and the txt.
226 NUL-terminate mbox and fill 'rp_txt' with the txt part of the record.
227 **************************************************************************************************/
228 static inline void
mydns_rr_parse_rp(const char * origin,MYDNS_RR * rr)229 mydns_rr_parse_rp(const char *origin, MYDNS_RR *rr) {
230 char *c;
231
232 /* If no space, set txt to '.' */
233 if (!(c = strchr(__MYDNS_RR_DATA_VALUE(rr), ' '))) {
234 __MYDNS_RR_RP_TXT(rr) = STRDUP(".");
235 } else {
236 int namelen = strlen(&c[1]);
237 if (LASTCHAR(&c[1]) != '.') {
238 namelen += strlen(origin) + 1;
239 }
240 __MYDNS_RR_RP_TXT(rr) = ALLOCATE_N(namelen + 1, sizeof(char), char[]);
241 strncpy(__MYDNS_RR_RP_TXT(rr), &c[1], namelen);
242 if (LASTCHAR(__MYDNS_RR_RP_TXT(rr)) != '.') {
243 strncat(__MYDNS_RR_RP_TXT(rr), ".", namelen);
244 strncat(__MYDNS_RR_RP_TXT(rr), origin, namelen);
245 }
246 *c = '\0';
247 __MYDNS_RR_DATA_VALUE(rr) = REALLOCATE(__MYDNS_RR_DATA_VALUE(rr),
248 strlen(__MYDNS_RR_DATA_VALUE(rr))+1,
249 char[]);
250 __MYDNS_RR_DATA_LENGTH(rr) = strlen(__MYDNS_RR_DATA_VALUE(rr));
251 }
252 }
253 /*--- mydns_rr_parse_rp() -----------------------------------------------------------------------*/
254
255
256 /**************************************************************************************************
257 MYDNS_RR_PARSE_SRV
258 SRV records contain two unsigned 16-bit integers in the "data" field before the target,
259 'srv_weight' and 'srv_port' - parse them and make "data" contain only the target. Also, make
260 sure 'aux' fits into 16 bits, clamping values above 65535.
261 **************************************************************************************************/
262 static inline void
mydns_rr_parse_srv(const char * origin,MYDNS_RR * rr)263 mydns_rr_parse_srv(const char *origin, MYDNS_RR *rr) {
264 char *weight, *port, *target;
265
266 /* Clamp 'aux' if necessary */
267 if (rr->aux > 65535)
268 rr->aux = 65535;
269
270 /* Parse weight (into srv_weight), port (into srv_port), and target */
271 target = __MYDNS_RR_DATA_VALUE(rr);
272 if ((weight = strsep(&target, " \t"))) {
273 __MYDNS_RR_SRV_WEIGHT(rr) = atoi(weight);
274 if ((port = strsep(&target, " \t")))
275 __MYDNS_RR_SRV_PORT(rr) = atoi(port);
276
277 /* Strip the leading data off and just hold target */
278 memmove(__MYDNS_RR_DATA_VALUE(rr), target, strlen(target)+1);
279 __MYDNS_RR_DATA_LENGTH(rr) = strlen(__MYDNS_RR_DATA_VALUE(rr));
280 __MYDNS_RR_DATA_VALUE(rr) = REALLOCATE(__MYDNS_RR_DATA_VALUE(rr),
281 __MYDNS_RR_DATA_LENGTH(rr) + 1,
282 char[]);
283 }
284 }
285 /*--- mydns_rr_parse_srv() ----------------------------------------------------------------------*/
286
287
288 /**************************************************************************************************
289 MYDNS_RR_PARSE_NAPTR
290 Returns 0 on success, -1 on error.
291 **************************************************************************************************/
292 static inline int
mydns_rr_parse_naptr(const char * origin,MYDNS_RR * rr)293 mydns_rr_parse_naptr(const char *origin, MYDNS_RR *rr) {
294 char *int_tmp, *p, *data_copy;
295
296 data_copy = STRNDUP(__MYDNS_RR_DATA_VALUE(rr), __MYDNS_RR_DATA_LENGTH(rr));
297 p = data_copy;
298
299 if (!strsep_quotes2(&p, &int_tmp))
300 return (-1);
301 __MYDNS_RR_NAPTR_ORDER(rr) = atoi(int_tmp);
302 RELEASE(int_tmp);
303
304 if (!strsep_quotes2(&p, &int_tmp))
305 return (-1);
306 __MYDNS_RR_NAPTR_PREF(rr) = atoi(int_tmp);
307 RELEASE(int_tmp);
308
309 if (!strsep_quotes(&p, __MYDNS_RR_NAPTR_FLAGS(rr), sizeof(__MYDNS_RR_NAPTR_FLAGS(rr))))
310 return (-1);
311
312 if (!strsep_quotes2(&p, &__MYDNS_RR_NAPTR_SERVICE(rr)))
313 return (-1);
314
315 if (!strsep_quotes2(&p, &__MYDNS_RR_NAPTR_REGEX(rr)))
316 return (-1);
317
318 if (!strsep_quotes2(&p, &__MYDNS_RR_NAPTR_REPLACEMENT(rr)))
319 return (-1);
320
321 //__MYDNS_RR_DATA_LENGTH(rr) = 0;
322 // RELEASE(__MYDNS_RR_DATA_VALUE(rr));
323
324 RELEASE(data_copy);
325 return 0;
326 }
327 /*--- mydns_rr_parse_naptr() --------------------------------------------------------------------*/
328
329 static inline int
mydns_rr_parse_txt(const char * origin,MYDNS_RR * rr)330 mydns_rr_parse_txt(const char *origin, MYDNS_RR *rr) {
331 int datalen = __MYDNS_RR_DATA_LENGTH(rr);
332 char *data = __MYDNS_RR_DATA_VALUE(rr);
333
334 if (datalen > DNS_MAXTXTLEN) return (-1);
335
336 while (datalen > 0) {
337 size_t elemlen = strlen(data);
338 if (elemlen > DNS_MAXTXTELEMLEN) return (-1);
339 data = &data[elemlen+1];
340 datalen -= elemlen + 1;
341 }
342
343 return 0;
344 }
345
346 static char *
__mydns_rr_append(char * s1,char * s2)347 __mydns_rr_append(char *s1, char *s2) {
348 int s1len = strlen(s1);
349 int s2len = strlen(s2);
350 int newlen = s1len;
351 char *name;
352 if (s1len) newlen += 1;
353 newlen += s2len;
354
355 name = ALLOCATE(newlen+1, char[]);
356 if (s1len) { strncpy(name, s1, s1len); name[s1len] = '.'; s1len += 1; }
357 strncpy(&name[s1len], s2, s2len);
358 name[newlen] = '\0';
359 return name;
360 }
361
362 char *
mydns_rr_append_origin(char * str,char * origin)363 mydns_rr_append_origin(char *str, char *origin) {
364 char *res = ((!*str || LASTCHAR(str) != '.')
365 ?__mydns_rr_append(str, origin)
366 :str);
367 return res;
368 }
369
370 void
mydns_rr_name_append_origin(MYDNS_RR * rr,char * origin)371 mydns_rr_name_append_origin(MYDNS_RR *rr, char *origin) {
372 char *res = mydns_rr_append_origin(__MYDNS_RR_NAME(rr), origin);
373 if (__MYDNS_RR_NAME(rr) != res) RELEASE(__MYDNS_RR_NAME(rr));
374 __MYDNS_RR_NAME(rr) = res;
375 }
376
377 void
mydns_rr_data_append_origin(MYDNS_RR * rr,char * origin)378 mydns_rr_data_append_origin(MYDNS_RR *rr, char *origin) {
379 char *res = mydns_rr_append_origin(__MYDNS_RR_DATA_VALUE(rr), origin);
380 if (__MYDNS_RR_DATA_VALUE(rr) != res) RELEASE(__MYDNS_RR_DATA_VALUE(rr));
381 __MYDNS_RR_DATA_VALUE(rr) = res;
382 __MYDNS_RR_DATA_LENGTH(rr) = strlen(__MYDNS_RR_DATA_VALUE(rr));
383 }
384
385 /**************************************************************************************************
386 _MYDNS_RR_FREE
387 Frees the pointed-to structure. Don't call this function directly, call the macro.
388 **************************************************************************************************/
389 void
_mydns_rr_free(MYDNS_RR * first)390 _mydns_rr_free(MYDNS_RR *first) {
391 register MYDNS_RR *p, *tmp;
392
393 for (p = first; p; p = tmp) {
394 tmp = p->next;
395 RELEASE(p->stamp);
396 RELEASE(__MYDNS_RR_NAME(p));
397 RELEASE(__MYDNS_RR_DATA_VALUE(p));
398 switch (p->type) {
399 case DNS_QTYPE_NAPTR:
400 RELEASE(__MYDNS_RR_NAPTR_SERVICE(p));
401 RELEASE(__MYDNS_RR_NAPTR_REGEX(p));
402 RELEASE(__MYDNS_RR_NAPTR_REPLACEMENT(p));
403 break;
404 case DNS_QTYPE_RP:
405 RELEASE(__MYDNS_RR_RP_TXT(p));
406 break;
407 default:
408 break;
409 }
410 RELEASE(p);
411 }
412 }
413 /*--- _mydns_rr_free() --------------------------------------------------------------------------*/
414
415 MYDNS_RR *
mydns_rr_build(uint32_t id,uint32_t zone,dns_qtype_t type,dns_class_t class,uint32_t aux,uint32_t ttl,char * active,timestamp * stamp,uint32_t serial,char * name,char * data,uint16_t datalen,const char * origin)416 mydns_rr_build(uint32_t id,
417 uint32_t zone,
418 dns_qtype_t type,
419 dns_class_t class,
420 uint32_t aux,
421 uint32_t ttl,
422 char *active,
423 #if USE_PGSQL
424 timestamp *stamp,
425 #else
426 MYSQL_TIME *stamp,
427 #endif
428 uint32_t serial,
429 char *name,
430 char *data,
431 uint16_t datalen,
432 const char *origin) {
433 MYDNS_RR *rr = NULL;
434 uint32_t namelen;
435
436 #if DEBUG_ENABLED && DEBUG_LIB_RR
437 DebugX("lib-rr", 1, _("mydns_rr_build(): called for id=%d, zone=%d, type=%d, class=%d, aux=%d, "
438 "ttl=%d, active='%s', stamp=%p, serial=%d, name='%s', data=%p, datalen=%d, origin='%s'"),
439 id, zone, type, class, aux, ttl, active, stamp, serial,
440 (name)?name:_("<NULL>"), data, datalen, origin);
441 #endif
442
443 if ((namelen = (name)?strlen(name):0) > DNS_MAXNAMELEN) {
444 /* Name exceeds permissable length - should report error */
445 goto PARSEFAILED;
446 }
447
448 rr = (MYDNS_RR *)ALLOCATE(sizeof(MYDNS_RR), MYDNS_RR);
449 memset(rr, '\0', sizeof(MYDNS_RR));
450 rr->next = NULL;
451
452 rr->id = id;
453 rr->zone = zone;
454
455 __MYDNS_RR_NAME(rr) = ALLOCATE(namelen+1, char[]);
456 memset(__MYDNS_RR_NAME(rr), 0, namelen+1);
457 if (name) strncpy(__MYDNS_RR_NAME(rr), name, namelen);
458
459 /* Should store length and buffer rather than handle as a string */
460 __MYDNS_RR_DATA_LENGTH(rr) = datalen;
461 __MYDNS_RR_DATA_VALUE(rr) = ALLOCATE(datalen+1, char[]);
462 memcpy(__MYDNS_RR_DATA_VALUE(rr), data, datalen);
463
464 rr->class = class;
465 rr->aux = aux;
466 rr->ttl = ttl;
467 rr->type = type;
468 #if ALIAS_ENABLED
469 if (rr->type == DNS_QTYPE_ALIAS) {
470 rr->type = DNS_QTYPE_A;
471 rr->alias = 1;
472 } else
473 rr->alias = 0;
474 #endif
475
476 /* Find a constant value so we do not have to allocate or free this one */
477 if (active) {
478 int i;
479 for (i = 0; i < 3; i++) {
480 if (!strcasecmp(mydns_rr_active_types[i], active)) { active = mydns_rr_active_types[i]; break; }
481 }
482 }
483 rr->active = active;
484 rr->stamp = stamp;
485 rr->serial = serial;
486
487 switch (rr->type) {
488
489 case DNS_QTYPE_TXT:
490 if (mydns_rr_parse_txt(origin, rr) < 0) {
491 goto PARSEFAILED;
492 }
493 break;
494
495 case DNS_QTYPE_NAPTR:
496 /* Populate special fields for NAPTR records */
497 if (mydns_rr_parse_naptr(origin, rr) < 0) {
498 goto PARSEFAILED;
499 }
500 break;
501
502 case DNS_QTYPE_RP:
503 /* Populate special fields for RP records */
504 mydns_rr_parse_rp(origin, rr);
505 goto DOORIGIN;
506
507 case DNS_QTYPE_SRV:
508 mydns_rr_parse_srv(origin, rr);
509 goto DOORIGIN;
510
511 DOORIGIN:
512
513 case DNS_QTYPE_CNAME:
514 case DNS_QTYPE_MX:
515 case DNS_QTYPE_NS:
516
517 /* Append origin to data if it's not there for these types: */
518 if (origin) {
519 datalen = __MYDNS_RR_DATA_LENGTH(rr);
520 #ifdef DN_COLUMN_NAMES
521 datalen += 1;
522 __MYDNS_RR_DATA_LENGTH(rr) = datalen;
523 __MYDNS_RR_DATA_VALUE(rr) = REALLOCATE(__MYDNS_RR_DATA_VALUE(rr), datalen+1, char[]);
524 /* Just append dot for DN */
525 ((char*)__MYDNS_RR_DATA_VALUE(rr))[datalen-1] = '.';
526 #else
527 if (datalen && ((char*)__MYDNS_RR_DATA_VALUE(rr))[datalen-1] != '.') {
528 datalen = datalen + 1 + strlen(origin);
529 __MYDNS_RR_DATA_VALUE(rr) = REALLOCATE(__MYDNS_RR_DATA_VALUE(rr), datalen+1, char[]);
530 ((char*)__MYDNS_RR_DATA_VALUE(rr))[__MYDNS_RR_DATA_LENGTH(rr)] = '.';
531 memcpy(&((char*)__MYDNS_RR_DATA_VALUE(rr))[__MYDNS_RR_DATA_LENGTH(rr)+1], origin, strlen(origin));
532 __MYDNS_RR_DATA_LENGTH(rr) = datalen;
533 }
534 #endif
535 ((char*)__MYDNS_RR_DATA_VALUE(rr))[__MYDNS_RR_DATA_LENGTH(rr)] = '\0';
536 }
537 break;
538 default:
539 break;
540 }
541
542 #if DEBUG_ENABLED && DEBUG_LIB_RR
543 DebugX("lib-rr", 1, _("mydns_rr_build(): returning result=%p"), rr);
544 #endif
545 return (rr);
546
547 PARSEFAILED:
548 mydns_rr_free(rr);
549 return (NULL);
550 }
551
552 /**************************************************************************************************
553 MYDNS_RR_PARSE
554 Given the SQL results with RR data, populates and returns a matching MYDNS_RR structure.
555 Returns NULL on error.
556 **************************************************************************************************/
557 inline MYDNS_RR *
mydns_rr_parse(SQL_ROW row,unsigned long * lengths,const char * origin)558 mydns_rr_parse(SQL_ROW row, unsigned long *lengths, const char *origin) {
559 dns_qtype_t type;
560 char *active = NULL;
561 #if USE_PGSQL
562 timestamp *stamp = NULL;
563 #else
564 MYSQL_TIME *stamp = NULL;
565 #endif
566 uint32_t serial = 0;
567 int ridx = MYDNS_RR_NUMFIELDS;
568 char *data;
569 uint16_t datalen;
570 MYDNS_RR *rr;
571
572 #if DEBUG_ENABLED && DEBUG_LIB_RR
573 DebugX("lib-rr", 1, _("mydns_rr_parse(): called for origin %s"), origin);
574 #endif
575
576 /* #60 */
577 //if (!(type = mydns_rr_get_type(row[6]))) {
578 if (!row[6] || !(type = mydns_rr_get_type(row[6]))) {
579 /* Ignore unknown RR type(s) */
580 return (NULL);
581 }
582
583 data = row[3];
584 datalen = lengths[3];
585 if (mydns_rr_extended_data) {
586 if (lengths[ridx]) {
587 char *newdata = ALLOCATE(datalen + lengths[ridx], char[]);
588 memcpy(newdata, data, datalen);
589 memcpy(&newdata[datalen], row[ridx], lengths[ridx]);
590 datalen += lengths[ridx];
591 data = newdata;
592 }
593 ridx++;
594 }
595
596 /* Copy storage? */
597 if (mydns_rr_use_active) active = row[ridx++];
598 if (mydns_rr_use_stamp) {
599 #if USE_PGSQL
600 /* Copy storage? */
601 stamp = row[ridx++];
602 #else
603 stamp = (MYSQL_TIME*)ALLOCATE(sizeof(MYSQL_TIME), MYSQL_TIME);
604 memcpy(stamp, row[ridx++], sizeof(MYSQL_TIME));
605 #endif
606 }
607 if (mydns_rr_use_serial && row[ridx]) {
608 serial = atou(row[ridx++]);
609 }
610
611 rr = mydns_rr_build(atou(row[0]),
612 atou(row[1]),
613 type,
614 DNS_CLASS_IN,
615 atou(row[4]),
616 atou(row[5]),
617 active,
618 stamp,
619 serial,
620 row[2],
621 data,
622 datalen,
623 origin);
624
625 if (mydns_rr_extended_data && lengths[MYDNS_RR_NUMFIELDS]) RELEASE(data);
626
627 return (rr);
628 }
629 /*--- mydns_rr_parse() --------------------------------------------------------------------------*/
630
631
632 /**************************************************************************************************
633 MYDNS_RR_DUP
634 Make and return a copy of a MYDNS_RR record. If 'recurse' is specified, copies all records
635 in the RRset.
636 **************************************************************************************************/
637 MYDNS_RR *
mydns_rr_dup(MYDNS_RR * start,int recurse)638 mydns_rr_dup(MYDNS_RR *start, int recurse) {
639 register MYDNS_RR *first = NULL, *last = NULL, *rr, *s, *tmp;
640
641 for (s = start; s; s = tmp) {
642 tmp = s->next;
643
644 rr = (MYDNS_RR *)ALLOCATE(sizeof(MYDNS_RR), MYDNS_RR);
645
646 memset(rr, '\0', sizeof(MYDNS_RR));
647 rr->id = s->id;
648 rr->zone = s->zone;
649 __MYDNS_RR_NAME(rr) = STRDUP(__MYDNS_RR_NAME(s));
650 rr->type = s->type;
651 rr->class = s->class;
652 __MYDNS_RR_DATA_LENGTH(rr) = __MYDNS_RR_DATA_LENGTH(s);
653 __MYDNS_RR_DATA_VALUE(rr) = ALLOCATE(__MYDNS_RR_DATA_LENGTH(s)+1, char[]);
654 memcpy(__MYDNS_RR_DATA_VALUE(rr), __MYDNS_RR_DATA_VALUE(s), __MYDNS_RR_DATA_LENGTH(s));
655 ((char*)__MYDNS_RR_DATA_VALUE(rr))[__MYDNS_RR_DATA_LENGTH(rr)] = '\0';
656 rr->aux = s->aux;
657 rr->ttl = s->ttl;
658 #if ALIAS_ENABLED
659 rr->alias = s->alias;
660 #endif
661
662 rr->active = s->active;
663 if (s->stamp) {
664 #if USE_PGSQL
665 rr->stamp = s->stamp;
666 #else
667 rr->stamp = (MYSQL_TIME*)ALLOCATE(sizeof(MYSQL_TIME), MYSQL_TIME);
668 memcpy(rr->stamp, s->stamp, sizeof(MYSQL_TIME));
669 #endif
670 } else
671 rr->stamp = NULL;
672 rr->serial = s->serial;
673
674 switch (rr->type) {
675 case DNS_QTYPE_SRV:
676 __MYDNS_RR_SRV_WEIGHT(rr) = __MYDNS_RR_SRV_WEIGHT(s);
677 __MYDNS_RR_SRV_PORT(rr) = __MYDNS_RR_SRV_PORT(s);
678 break;
679
680 case DNS_QTYPE_RP:
681 /* Copy rp_txt only for RP records */
682 __MYDNS_RR_RP_TXT(rr) = STRDUP(__MYDNS_RR_RP_TXT(s));
683 break;
684
685 case DNS_QTYPE_NAPTR:
686 /* Copy naptr fields only for NAPTR records */
687 __MYDNS_RR_NAPTR_ORDER(rr) = __MYDNS_RR_NAPTR_ORDER(s);
688 __MYDNS_RR_NAPTR_PREF(rr) = __MYDNS_RR_NAPTR_PREF(s);
689 memcpy(__MYDNS_RR_NAPTR_FLAGS(rr), __MYDNS_RR_NAPTR_FLAGS(s), sizeof(__MYDNS_RR_NAPTR_FLAGS(rr)));
690 __MYDNS_RR_NAPTR_SERVICE(rr) = STRDUP(__MYDNS_RR_NAPTR_SERVICE(s));
691 __MYDNS_RR_NAPTR_REGEX(rr) = STRDUP(__MYDNS_RR_NAPTR_REGEX(s));
692 __MYDNS_RR_NAPTR_REPLACEMENT(rr) = STRDUP(__MYDNS_RR_NAPTR_REPLACEMENT(s));
693 break;
694
695 default:
696 break;
697 }
698
699 rr->next = NULL;
700 if (recurse) {
701 if (!first) first = rr;
702 if (last) last->next = rr;
703 last = rr;
704 } else
705 return (rr);
706 }
707 return (first);
708 }
709 /*--- mydns_rr_dup() ----------------------------------------------------------------------------*/
710
711
712 /**************************************************************************************************
713 MYDNS_RR_SIZE
714 **************************************************************************************************/
715 inline size_t
mydns_rr_size(MYDNS_RR * first)716 mydns_rr_size(MYDNS_RR *first) {
717 register MYDNS_RR *p;
718 register size_t size = 0;
719
720 for (p = first; p; p = p->next) {
721 size += sizeof(MYDNS_RR)
722 + (strlen(__MYDNS_RR_NAME(p)) + 1)
723 + (__MYDNS_RR_DATA_LENGTH(p) + 1);
724 #if USE_PGSQL
725 #else
726 size += sizeof(MYSQL_TIME);
727 #endif
728 switch (p->type) {
729 case DNS_QTYPE_NAPTR:
730 size += strlen(__MYDNS_RR_NAPTR_SERVICE(p)) + 1;
731 size += strlen(__MYDNS_RR_NAPTR_REGEX(p)) + 1;
732 size += strlen(__MYDNS_RR_NAPTR_REPLACEMENT(p)) + 1;
733 break;
734
735 case DNS_QTYPE_RP:
736 size += strlen(__MYDNS_RR_RP_TXT(p)) + 1;
737 break;
738
739 default:
740 break;
741 }
742 }
743
744 return (size);
745 }
746 /*--- mydns_rr_size() ---------------------------------------------------------------------------*/
747
748
749 /**************************************************************************************************
750 MYDNS_RR_LOAD
751 Returns 0 on success or nonzero if an error occurred.
752 If "name" is NULL, all resource records for the zone will be loaded.
753 **************************************************************************************************/
754 char *
mydns_rr_columns()755 mydns_rr_columns() {
756 char *columns = NULL;
757 size_t columnslen = 0;
758
759 columnslen = sql_build_query(&columns, MYDNS_RR_FIELDS"%s%s%s%s",
760 /* Optional columns */
761 (mydns_rr_extended_data ? ",edata" : ""),
762 (mydns_rr_use_active ? ",active" : ""),
763 (mydns_rr_use_stamp ? ",stamp" : ""),
764 (mydns_rr_use_serial ? ",serial" : ""));
765 return columns;
766 }
767
768 char *
mydns_rr_prepare_query(uint32_t zone,dns_qtype_t type,const char * name,const char * origin,const char * active,const char * columns,const char * filter)769 mydns_rr_prepare_query(uint32_t zone, dns_qtype_t type, const char *name, const char *origin,
770 const char *active, const char *columns, const char *filter) {
771 size_t querylen;
772 char *query = NULL;
773 char *namequery = NULL;
774 const char *wheretype;
775 const char *cp;
776 #ifdef DN_COLUMN_NAMES
777 int originlen = origin ? strlen(origin) : 0;
778 int namelen = name ? strlen(name) : 0;
779 #endif
780
781 #if DEBUG_ENABLED && DEBUG_LIB_RR
782 DebugX("lib-rr", 1, _("mydns_rr_prepare_query(zone=%u, type='%s', name='%s', origin='%s')"),
783 zone, mydns_qtype_str(type), name ?: _("NULL"), origin ?: _("NULL"));
784 #endif
785
786 /* Get the type='XX' part of the WHERE clause */
787 switch (type) {
788 #if ALIAS_ENABLED
789 case DNS_QTYPE_A: wheretype = " AND (type='A' OR type='ALIAS')"; break;
790 #else
791 case DNS_QTYPE_A: wheretype = " AND type='A'"; break;
792 #endif
793 case DNS_QTYPE_AAAA: wheretype = " AND type='AAAA'"; break;
794 case DNS_QTYPE_CNAME: wheretype = " AND type='CNAME'"; break;
795 case DNS_QTYPE_HINFO: wheretype = " AND type='HINFO'"; break;
796 case DNS_QTYPE_MX: wheretype = " AND type='MX'"; break;
797 case DNS_QTYPE_NAPTR: wheretype = " AND type='NAPTR'"; break;
798 case DNS_QTYPE_NS: wheretype = " AND type='NS'"; break;
799 case DNS_QTYPE_PTR: wheretype = " AND type='PTR'"; break;
800 case DNS_QTYPE_SOA: wheretype = " AND type='SOA'"; break;
801 case DNS_QTYPE_SRV: wheretype = " AND type='SRV'"; break;
802 case DNS_QTYPE_TXT: wheretype = " AND type='TXT'"; break;
803 case DNS_QTYPE_ANY: wheretype = ""; break;
804 default:
805 errno = EINVAL;
806 return (NULL);
807 }
808
809 /* Make sure 'name' and 'origin' (if present) are valid */
810 if (name) {
811 for (cp = name; *cp; cp++)
812 if (SQL_BADCHAR(*cp))
813 return (NULL);
814 }
815 if (origin) {
816 for (cp = origin; *cp; cp++)
817 if (SQL_BADCHAR(*cp))
818 return (NULL);
819 }
820
821 #ifdef DN_COLUMN_NAMES
822 /* Remove dot from origin and name for DN */
823 if (originlen && origin[originlen - 1] == '.')
824 origin[originlen-1] = '\0';
825 else
826 originlen = 0;
827
828 if (name) {
829 if (namelen && name[namelen - 1] == '.')
830 name[namelen-1] = '\0';
831 else
832 namelen = 0;
833 }
834 #endif
835
836 /* Construct query */
837 if (name) {
838 if (origin) {
839 if (!name[0])
840 sql_build_query(&namequery, "(name='' OR name='%s')", origin);
841 else {
842 #ifdef DN_COLUMN_NAMES
843 sql_build_query(&namequery, "name='%s'", name);
844 #else
845 sql_build_query(&namequery, "(name='%s' OR name='%s.%s')", name, name, origin);
846 #endif
847 }
848 }
849 else
850 sql_build_query(&namequery, "name='%s'", name);
851 }
852
853 #ifdef DN_COLUMN_NAMES
854 if (originlen)
855 origin[originlen - 1] = '.'; /* Re-add dot to origin for DN */
856
857 if (name) {
858 if (namelen)
859 name[namelen - 1] = '.';
860 }
861 #endif
862
863 querylen = sql_build_query(&query, "SELECT %s FROM %s WHERE "
864 #ifdef DN_COLUMN_NAMES
865 "zone_id=%u%s"
866 #else
867 "zone=%u%s"
868 #endif
869 "%s%s"
870 "%s%s%s"
871 "%s%s"
872 "%s%s"
873 "%s",
874
875 columns,
876
877 /* Fixed data */
878 mydns_rr_table_name,
879 zone, wheretype,
880
881 /* Name based query */
882 (namequery)? " AND " : "",
883 (namequery)? namequery : "",
884
885 /* Optional check for active value */
886 (mydns_rr_use_active)? " AND active='" : "",
887 (mydns_rr_use_active)? active : "",
888 (mydns_rr_use_active)? "'" : "",
889
890 /* Optional where clause for rr table */
891 (mydns_rr_where_clause)? " AND " : "",
892 (mydns_rr_where_clause)? mydns_rr_where_clause : "",
893
894 /* Apply additional filter if requested */
895 (filter)? " AND " : "",
896 (filter)? filter : "",
897
898 /* Optional sorting */
899 (mydns_rr_use_stamp)? " ORDER BY stamp DESC" : "");
900
901 RELEASE(namequery);
902
903 return (query);
904 }
905
__mydns_rr_do_load(SQL * sqlConn,MYDNS_RR ** rptr,const char * query,const char * origin)906 static int __mydns_rr_do_load(SQL *sqlConn, MYDNS_RR **rptr, const char *query, const char *origin) {
907 MYDNS_RR *first = NULL, *last = NULL;
908 char *cp;
909 SQL_RES *res;
910 SQL_ROW row;
911 unsigned long *lengths;
912
913
914 #if DEBUG_ENABLED && DEBUG_LIB_RR
915 DebugX("lib-rr", 1, _("mydns_rr_do_load(query='%s', origin='%s')"), query, origin ? origin : _("NULL"));
916 #endif
917
918 if (rptr) *rptr = NULL;
919
920 /* Verify args */
921 if (!sqlConn || !rptr || !query) {
922 errno = EINVAL;
923 return (-1);
924 }
925
926 /* Submit query */
927 if (!(res = sql_query(sqlConn, query, strlen(query))))
928 return (-1);
929
930 #if DEBUG_ENABLED && DEBUG_LIB_RR
931 {
932 int numresults = sql_num_rows(res);
933
934 DebugX("lib-rr", 1, _("RR query: %d row%s: %s"), numresults, S(numresults), query);
935 }
936 #endif
937
938 RELEASE(query);
939
940 /* Add results to list */
941 while ((row = sql_getrow(res, &lengths))) {
942 MYDNS_RR *new;
943
944 if (!(new = mydns_rr_parse(row, lengths, origin)))
945 continue;
946
947 /* Always trim origin from name (XXX: Why? When did I add this?) */
948 /* Apparently removing this code breaks RRs where the name IS the origin */
949 /* But trim only where the name is exactly the origin */
950 if (origin && (cp = strstr(__MYDNS_RR_NAME(new), origin)) && !(cp - __MYDNS_RR_NAME(new)))
951 *cp = '\0';
952
953 if (!first) first = new;
954 if (last) last->next = new;
955 last = new;
956 }
957
958 *rptr = first;
959 sql_free(res);
960 return (0);
961 }
962
963 static int
__mydns_rr_count(SQL * sqlConn,uint32_t zone,dns_qtype_t type,const char * name,const char * origin,const char * active,const char * filter)964 __mydns_rr_count(SQL *sqlConn, uint32_t zone,
965 dns_qtype_t type,
966 const char *name, const char *origin, const char *active, const char *filter) {
967 char *query = NULL;
968 int result;
969
970 SQL_RES *res;
971 SQL_ROW row;
972
973 query = mydns_rr_prepare_query(zone, type, name, origin, active, (char*)"COUNT(*)", filter);
974
975 if (!query || !(res = sql_query(sqlConn, query, strlen(query)))) {
976 WarnSQL(sqlConn, _("error processing count with filter %s"), filter);
977 return (-1);
978 }
979
980 RELEASE(query);
981
982 if ((row = sql_getrow(res, NULL)))
983 result = atoi(row[0]);
984 else
985 result = 0;
986
987 sql_free(res);
988
989 return result;
990 }
991
992 static int
__mydns_rr_load(SQL * sqlConn,MYDNS_RR ** rptr,uint32_t zone,dns_qtype_t type,const char * name,const char * origin,const char * active,const char * filter)993 __mydns_rr_load(SQL *sqlConn, MYDNS_RR **rptr, uint32_t zone,
994 dns_qtype_t type,
995 const char *name, const char *origin, const char *active, const char *filter) {
996 char *query = NULL;
997 int res;
998 char *columns = NULL;
999
1000 columns = mydns_rr_columns();
1001
1002 query = mydns_rr_prepare_query(zone, type, name, origin, active, columns, filter);
1003
1004 RELEASE(columns);
1005
1006 res = __mydns_rr_do_load(sqlConn, rptr, query, origin);
1007
1008 return res;
1009 }
1010
mydns_rr_load_all(SQL * sqlConn,MYDNS_RR ** rptr,uint32_t zone,dns_qtype_t type,const char * name,const char * origin)1011 int mydns_rr_load_all(SQL *sqlConn, MYDNS_RR **rptr, uint32_t zone,
1012 dns_qtype_t type,
1013 const char *name, const char *origin) {
1014
1015 return __mydns_rr_load(sqlConn, rptr, zone, type, name, origin, NULL, NULL);
1016 }
1017
mydns_rr_load_active(SQL * sqlConn,MYDNS_RR ** rptr,uint32_t zone,dns_qtype_t type,const char * name,const char * origin)1018 int mydns_rr_load_active(SQL *sqlConn, MYDNS_RR **rptr, uint32_t zone,
1019 dns_qtype_t type,
1020 const char *name, const char *origin) {
1021
1022 return __mydns_rr_load(sqlConn, rptr, zone, type, name, origin, mydns_rr_active_types[0], NULL);
1023 }
1024
mydns_rr_load_inactive(SQL * sqlConn,MYDNS_RR ** rptr,uint32_t zone,dns_qtype_t type,const char * name,const char * origin)1025 int mydns_rr_load_inactive(SQL *sqlConn, MYDNS_RR **rptr, uint32_t zone,
1026 dns_qtype_t type,
1027 const char *name, const char *origin) {
1028
1029 return __mydns_rr_load(sqlConn, rptr, zone, type, name, origin, mydns_rr_active_types[1], NULL);
1030 }
1031
mydns_rr_load_deleted(SQL * sqlConn,MYDNS_RR ** rptr,uint32_t zone,dns_qtype_t type,const char * name,const char * origin)1032 int mydns_rr_load_deleted(SQL *sqlConn, MYDNS_RR **rptr, uint32_t zone,
1033 dns_qtype_t type,
1034 const char *name, const char *origin) {
1035
1036 return __mydns_rr_load(sqlConn, rptr, zone, type, name, origin, mydns_rr_active_types[2], NULL);
1037 }
1038
mydns_rr_count_all(SQL * sqlConn,uint32_t zone,dns_qtype_t type,const char * name,const char * origin)1039 int mydns_rr_count_all(SQL *sqlConn, uint32_t zone,
1040 dns_qtype_t type,
1041 const char *name, const char *origin) {
1042
1043 return __mydns_rr_count(sqlConn, zone, type, name, origin, mydns_rr_active_types[0], NULL);
1044 }
1045
mydns_rr_count_active(SQL * sqlConn,uint32_t zone,dns_qtype_t type,const char * name,const char * origin)1046 int mydns_rr_count_active(SQL *sqlConn, uint32_t zone,
1047 dns_qtype_t type,
1048 const char *name, const char *origin) {
1049
1050 return __mydns_rr_count(sqlConn, zone, type, name, origin, mydns_rr_active_types[0], NULL);
1051 }
1052
mydns_rr_count_inactive(SQL * sqlConn,uint32_t zone,dns_qtype_t type,const char * name,const char * origin)1053 int mydns_rr_count_inactive(SQL *sqlConn, uint32_t zone,
1054 dns_qtype_t type,
1055 const char *name, const char *origin) {
1056
1057 return __mydns_rr_count(sqlConn, zone, type, name, origin, mydns_rr_active_types[1], NULL);
1058 }
1059
mydns_rr_count_deleted(SQL * sqlConn,uint32_t zone,dns_qtype_t type,const char * name,const char * origin)1060 int mydns_rr_count_deleted(SQL *sqlConn, uint32_t zone,
1061 dns_qtype_t type,
1062 const char *name, const char *origin) {
1063
1064 return __mydns_rr_count(sqlConn, zone, type, name, origin, mydns_rr_active_types[2], NULL);
1065 }
1066
1067
mydns_rr_load_all_filtered(SQL * sqlConn,MYDNS_RR ** rptr,uint32_t zone,dns_qtype_t type,const char * name,const char * origin,const char * filter)1068 int mydns_rr_load_all_filtered(SQL *sqlConn, MYDNS_RR **rptr, uint32_t zone,
1069 dns_qtype_t type,
1070 const char *name, const char *origin, const char *filter) {
1071
1072 return __mydns_rr_load(sqlConn, rptr, zone, type, name, origin, NULL, filter);
1073 }
1074
mydns_rr_load_active_filtered(SQL * sqlConn,MYDNS_RR ** rptr,uint32_t zone,dns_qtype_t type,const char * name,const char * origin,const char * filter)1075 int mydns_rr_load_active_filtered(SQL *sqlConn, MYDNS_RR **rptr, uint32_t zone,
1076 dns_qtype_t type,
1077 const char *name, const char *origin, const char *filter) {
1078
1079 return __mydns_rr_load(sqlConn, rptr, zone, type, name, origin, mydns_rr_active_types[0], filter);
1080 }
1081
mydns_rr_load_inactive_filtered(SQL * sqlConn,MYDNS_RR ** rptr,uint32_t zone,dns_qtype_t type,const char * name,const char * origin,const char * filter)1082 int mydns_rr_load_inactive_filtered(SQL *sqlConn, MYDNS_RR **rptr, uint32_t zone,
1083 dns_qtype_t type,
1084 const char *name, const char *origin, const char *filter) {
1085
1086 return __mydns_rr_load(sqlConn, rptr, zone, type, name, origin, mydns_rr_active_types[1], filter);
1087 }
1088
mydns_rr_load_deleted_filtered(SQL * sqlConn,MYDNS_RR ** rptr,uint32_t zone,dns_qtype_t type,const char * name,const char * origin,const char * filter)1089 int mydns_rr_load_deleted_filtered(SQL *sqlConn, MYDNS_RR **rptr, uint32_t zone,
1090 dns_qtype_t type,
1091 const char *name, const char *origin, const char *filter) {
1092
1093 return __mydns_rr_load(sqlConn, rptr, zone, type, name, origin, mydns_rr_active_types[2], filter);
1094 }
1095
mydns_rr_count_all_filtered(SQL * sqlConn,uint32_t zone,dns_qtype_t type,const char * name,const char * origin,const char * filter)1096 int mydns_rr_count_all_filtered(SQL *sqlConn, uint32_t zone,
1097 dns_qtype_t type,
1098 const char *name, const char *origin, const char *filter) {
1099
1100 return __mydns_rr_count(sqlConn, zone, type, name, origin, mydns_rr_active_types[0], filter);
1101 }
1102
mydns_rr_count_active_filtered(SQL * sqlConn,uint32_t zone,dns_qtype_t type,const char * name,const char * origin,const char * filter)1103 int mydns_rr_count_active_filtered(SQL *sqlConn, uint32_t zone,
1104 dns_qtype_t type,
1105 const char *name, const char *origin, const char *filter) {
1106
1107 return __mydns_rr_count(sqlConn, zone, type, name, origin, mydns_rr_active_types[0], filter);
1108 }
1109
mydns_rr_count_inactive_filtered(SQL * sqlConn,uint32_t zone,dns_qtype_t type,const char * name,const char * origin,const char * filter)1110 int mydns_rr_count_inactive_filtered(SQL *sqlConn, uint32_t zone,
1111 dns_qtype_t type,
1112 const char *name, const char *origin, const char *filter) {
1113
1114 return __mydns_rr_count(sqlConn, zone, type, name, origin, mydns_rr_active_types[1], filter);
1115 }
1116
mydns_rr_count_deleted_filtered(SQL * sqlConn,uint32_t zone,dns_qtype_t type,const char * name,const char * origin,const char * filter)1117 int mydns_rr_count_deleted_filtered(SQL *sqlConn, uint32_t zone,
1118 dns_qtype_t type,
1119 const char *name, const char *origin, const char *filter) {
1120
1121 return __mydns_rr_count(sqlConn, zone, type, name, origin, mydns_rr_active_types[2], filter);
1122 }
1123
1124 /*--- mydns_rr_load() ---------------------------------------------------------------------------*/
1125
1126 /* vi:set ts=3: */
1127