Commit Diff
Diff:
a0f09d4bd5a244990bae67904455a99c14c02210
0d20f8200a2ce766754bc6353361cd9d14d1ee44
Commit:
0d20f8200a2ce766754bc6353361cd9d14d1ee44
Tree:
dcf8c900f040f68af3b76f38f55e0e728e47bf43
Author:
pjp <pjp@delphinusdns.org>
Committer:
pjp <pjp@delphinusdns.org>
Date:
Mon Nov 11 09:15:40 2019 UTC
Message:
refactor lookup_zone, and Lookup_zone, this now makes the answers necessary to have a delegation.
blob - 797f97b0a443cda4736b84bf4bec5afbbd18dcd9
blob + 9bbe31830baf47c491d390bacfc2452fa665f1d4
--- dddctl.c
+++ dddctl.c
@@ -27,7 +27,7 @@
*/
/*
- * $Id: dddctl.c,v 1.86 2019/11/06 05:18:06 pjp Exp $
+ * $Id: dddctl.c,v 1.87 2019/11/11 09:15:40 pjp Exp $
*/
#include <sys/param.h>
@@ -313,7 +313,7 @@ extern char * convert_name(char *name, int namelen);
extern int mybase64_encode(u_char const *, size_t, char *, size_t);
extern int mybase64_decode(char const *, u_char *, size_t);
-extern struct rbtree * lookup_zone(ddDB *, struct question *, int *, int *, char *);
+extern struct rbtree * Lookup_zone(ddDB *, char *, int, int, int);
extern struct question *build_fake_question(char *, int, u_int16_t, char *, int);
extern char * dns_label(char *, int *);
extern int label_count(char *);
@@ -323,7 +323,6 @@ extern char * base32hex_encode(u_char *input, int len)
extern int init_entlist(ddDB *);
extern int check_ent(char *, int);
extern struct question *build_question(char *, int, int, char *);
-extern int free_question(struct question *);
struct rrtab *rrlookup(char *);
extern struct rbtree * create_rr(ddDB *db, char *name, int len, int type, void *rdata);
@@ -1090,13 +1089,10 @@ dump_db(ddDB *db, FILE *of, char *zonename)
ddDBT key, data;
struct node *n, *nx;
- struct question *q;
struct rbtree *rbt0, *rbt;
- char replystring[512];
char *dnsname;
int labellen;
- int lzerrno, retval;
fprintf(of, "; this file is automatically generated, do NOT edit\n");
fprintf(of, "; it was generated by dddctl.c\n");
@@ -1107,15 +1103,10 @@ dump_db(ddDB *db, FILE *of, char *zonename)
if (dnsname == NULL)
return -1;
- q = build_fake_question(dnsname, labellen, DNS_TYPE_SOA, NULL, 0);
- if (q == NULL) {
+ if ((rbt0 = Lookup_zone(db, dnsname, labellen, DNS_TYPE_SOA, 0)) == NULL) {
return -1;
}
- if ((rbt0 = lookup_zone(db, q, &retval, &lzerrno, (char *)&replystring)) == NULL) {
- return -1;
- }
-
if (print_rbt(of, rbt0) < 0) {
fprintf(stderr, "print_rbt error\n");
return -1;
@@ -4859,10 +4850,6 @@ create_ds(ddDB *db, char *zonename, struct keysentry *
int labels;
static int pass = 0;
- struct question *qp;
- int retval, lzerrno;
- char replystring[512];
-
/* silently ignore zsk's, no error here */
if (knp->type != KEYTYPE_KSK)
return 0;
@@ -4873,13 +4860,7 @@ create_ds(ddDB *db, char *zonename, struct keysentry *
return -1;
}
- qp = build_fake_question(dnsname, labellen, DNS_TYPE_SOA, NULL, 0);
- if (qp == NULL) {
- dolog(LOG_INFO, "qp == NULL\n");
- return -1;
- }
-
- if ((rbt = lookup_zone(db, qp, &retval, &lzerrno, (char *)&replystring)) == NULL) {
+ if ((rbt = Lookup_zone(db, dnsname, labellen, DNS_TYPE_SOA, 0)) == NULL) {
dolog(LOG_INFO, "rbt == NULL\n");
return -1;
}
@@ -5729,7 +5710,6 @@ construct_nsec3(ddDB *db, char *zone, int iterations,
{
struct node *n, *nx;
- struct question *q;
struct nsec3param n3p;
struct rbtree *rbt = NULL;
@@ -5737,7 +5717,6 @@ construct_nsec3(ddDB *db, char *zone, int iterations,
struct rr *rrp = NULL;
struct rr *rrp2 = NULL;
- char replystring[512];
char buf[4096];
char bitmap[4096];
char *dnsname;
@@ -5745,7 +5724,6 @@ construct_nsec3(ddDB *db, char *zone, int iterations,
char *p;
int labellen;
- int retval, lzerrno;
u_int32_t ttl = 0;
int j, rs, len, rootlen;
@@ -5772,15 +5750,10 @@ construct_nsec3(ddDB *db, char *zone, int iterations,
if (dnsname == NULL)
return -1;
- q = build_fake_question(dnsname, labellen, DNS_TYPE_NSEC3PARAM, NULL, 0);
- if (q == NULL) {
+ if ((rbt = Lookup_zone(db, dnsname, labellen, DNS_TYPE_NSEC3PARAM, 0)) == NULL) {
return -1;
}
- if ((rbt = lookup_zone(db, q, &retval, &lzerrno, (char *)&replystring)) == NULL) {
- return -1;
- }
-
/* get the rootzone's len */
rootlen = rbt->zonelen;
@@ -7252,14 +7225,11 @@ dump_db_bind(ddDB *db, FILE *of, char *zonename)
ddDBT key, data;
struct node *n, *nx;
- struct question *q;
struct rbtree *rbt = NULL, *rbt0 = NULL;
- char replystring[512];
char *dnsname;
int labellen;
- int lzerrno, retval;
fprintf(of, ";; This file was generated by dddctl.c of delphinusdnsd\n");
@@ -7267,15 +7237,10 @@ dump_db_bind(ddDB *db, FILE *of, char *zonename)
if (dnsname == NULL)
return -1;
- q = build_fake_question(dnsname, labellen, DNS_TYPE_SOA, NULL, 0);
- if (q == NULL) {
+ if ((rbt = Lookup_zone(db, dnsname, labellen, DNS_TYPE_SOA, 0)) == NULL) {
return -1;
}
- if ((rbt = lookup_zone(db, q, &retval, &lzerrno, (char *)&replystring)) == NULL) {
- return -1;
- }
-
if (print_rbt_bind(of, rbt) < 0) {
fprintf(stderr, "print_rbt_bind error\n");
return -1;
@@ -8011,10 +7976,8 @@ sign(int algorithm, char *key, int keylen, struct keys
void
update_soa_serial(ddDB *db, char *zonename, time_t serial)
{
- char replystring[512];
- struct question *q;
char *dnsname;
- int labellen, lzerrno, retval;
+ int labellen;
struct rbtree *rbt0 = NULL;
struct rrset *rrset = NULL;
@@ -8025,15 +7988,10 @@ update_soa_serial(ddDB *db, char *zonename, time_t ser
if (dnsname == NULL)
return;
- q = build_fake_question(dnsname, labellen, DNS_TYPE_SOA, NULL, 0);
- if (q == NULL) {
+ if ((rbt0 = Lookup_zone(db, dnsname, labellen, DNS_TYPE_SOA, 0)) == NULL) {
return;
}
- if ((rbt0 = lookup_zone(db, q, &retval, &lzerrno, (char *)&replystring)) == NULL) {
- return;
- }
-
if ((rrset = find_rr(rbt0, DNS_TYPE_SOA)) != NULL) {
if ((rrp = TAILQ_FIRST(&rrset->rr_head)) == NULL) {
return;
@@ -8043,7 +8001,6 @@ update_soa_serial(ddDB *db, char *zonename, time_t ser
}
free(rbt0);
- free_question(q);
}
@@ -8051,11 +8008,8 @@ int
notglue(ddDB *db, struct rbtree *rbt, char *zonename)
{
struct rbtree *rbt0;
- struct question *q;
char *zoneapex, *p;
- char replystring[512];
int apexlen, len;
- int retval, lzerrno;
zoneapex = dns_label(zonename, &apexlen);
@@ -8081,25 +8035,16 @@ notglue(ddDB *db, struct rbtree *rbt, char *zonename)
if (*p == '\0')
break;
- q = build_fake_question(p, len, DNS_TYPE_NS, NULL, 0);
- if (q == NULL) {
- free(zoneapex);
- return 1;
- }
-
- if ((rbt0 = lookup_zone(db, q, &retval, &lzerrno, (char *)&replystring)) == NULL) {
- free_question(q);
+ if ((rbt0 = Lookup_zone(db, p, len, DNS_TYPE_NS, 0)) == NULL) {
continue;
}
if (len > apexlen && find_rr(rbt0, DNS_TYPE_NS) != NULL) {
free(rbt0);
- free_question(q);
free(zoneapex);
return 0;
}
- free_question(q);
free(rbt0);
} while (*p && len > 0 && ! (len == apexlen && memcasecmp(p, zoneapex, len) == 0));
blob - e673b61594885fe4a27e6d4affe21542aa9dfa11
blob + 424067ab9de6f9981731e9738d023d9feecbc3b4
--- delphinusdnsd.c
+++ delphinusdnsd.c
@@ -27,7 +27,7 @@
*/
/*
- * $Id: delphinusdnsd.c,v 1.83 2019/11/11 05:04:21 pjp Exp $
+ * $Id: delphinusdnsd.c,v 1.84 2019/11/11 09:15:40 pjp Exp $
*/
@@ -170,6 +170,7 @@ extern struct rbtree * get_ns(ddDB *, struct rbtree *,
struct question *convert_question(struct parsequestion *);
void build_reply(struct sreply *, int, char *, int, struct question *, struct sockaddr *, socklen_t, struct rbtree *, struct rbtree *, u_int8_t, int, int, void *, char *);
int compress_label(u_char *, u_int16_t, int);
+int determine_glue(ddDB *db);
void mainloop(struct cfg *, struct imsgbuf **);
void master_reload(int);
void master_shutdown(int);
@@ -537,6 +538,12 @@ main(int argc, char *argv[], char *environ[])
exit(1);
}
+ if (determine_glue(db) < 0) {
+ dolog(LOG_INFO, "determine_glue() failed\n");
+ slave_shutdown();
+ exit(1);
+ }
+
if (init_entlist(db) < 0) {
dolog(LOG_INFO, "creating entlist failed\n");
slave_shutdown();
@@ -3570,4 +3577,165 @@ setup_unixsocket(char *socketpath, struct imsgbuf *ibu
} /* for (;;) */
/* NOTREACHED */
+}
+
+int
+determine_glue(ddDB *db)
+{
+ struct rbtree *rbt, *rbt0;
+ struct rrset *rrset;
+ ddDBT key, data;
+ int rs;
+ struct node *n, *nx;
+ int len;
+ char *p;
+
+ /* mark SOA's */
+ RB_FOREACH_SAFE(n, domaintree, &db->head, nx) {
+ rs = n->datalen;
+ if ((rbt = calloc(1, rs)) == NULL) {
+ dolog(LOG_INFO, "calloc: %s\n", strerror(errno));
+ exit(1);
+ }
+
+ memcpy((char *)rbt, (char *)n->data, n->datalen);
+
+ rrset = find_rr(rbt, DNS_TYPE_SOA);
+ if (rrset == NULL) {
+ free(rbt);
+ continue;
+ }
+
+ rbt->flags |= RBT_APEX;
+
+ memset(&key, 0, sizeof(key));
+ memset(&data, 0, sizeof(data));
+
+ key.data = (char *)rbt->zone;
+ key.size = rbt->zonelen;
+
+ data.data = (void *)rbt;
+ data.size = sizeof(struct rbtree);
+
+ if (db->put(db, &key, &data) != 0) {
+ dolog(LOG_INFO, "db->put failed\n");
+ free(rbt);
+ return -1;
+ }
+
+ free(rbt);
+ }
+
+ /* mark glue */
+ RB_FOREACH_SAFE(n, domaintree, &db->head, nx) {
+ rs = n->datalen;
+ if ((rbt = calloc(1, rs)) == NULL) {
+ dolog(LOG_INFO, "calloc: %s\n", strerror(errno));
+ exit(1);
+ }
+
+ memcpy((char *)rbt, (char *)n->data, n->datalen);
+
+ if (rbt->flags & RBT_APEX) {
+ free(rbt);
+ continue;
+ }
+
+ rrset = find_rr(rbt, DNS_TYPE_NS);
+ if (rrset == NULL) {
+ free(rbt);
+ continue;
+ }
+
+ rbt->flags |= RBT_GLUE;
+
+ memset(&key, 0, sizeof(key));
+ memset(&data, 0, sizeof(data));
+
+ key.data = (char *)rbt->zone;
+ key.size = rbt->zonelen;
+
+ data.data = (void *)rbt;
+ data.size = sizeof(struct rbtree);
+
+ if (db->put(db, &key, &data) != 0) {
+ dolog(LOG_INFO, "db->put failed\n");
+ free(rbt);
+ return -1;
+ }
+
+ free(rbt);
+ }
+ RB_FOREACH_SAFE(n, domaintree, &db->head, nx) {
+ rs = n->datalen;
+ if ((rbt = calloc(1, rs)) == NULL) {
+ dolog(LOG_INFO, "calloc: %s\n", strerror(errno));
+ exit(1);
+ }
+
+ memcpy((char *)rbt, (char *)n->data, n->datalen);
+
+
+ p = rbt->zone;
+ len = rbt->zonelen;
+
+ rbt0 = find_rrset(db, rbt->zone, rbt->zonelen);
+ while (! (rbt0->flags & RBT_APEX)) {
+ if (rbt0->flags & RBT_GLUE) {
+ /* repeat */
+ free(rbt0);
+ p = rbt->zone;
+ len = rbt->zonelen;
+ rbt0 = find_rrset(db, p, len);
+
+ while (!(rbt0->flags & RBT_GLUE)) {
+ rbt0->flags |= RBT_GLUE;
+
+ memset(&key, 0, sizeof(key));
+ memset(&data, 0, sizeof(data));
+
+ key.data = (char *)p;
+ key.size = len;
+
+ data.data = (void *)rbt0;
+ data.size = sizeof(struct rbtree);
+
+ if (db->put(db, &key, &data) != 0) {
+ dolog(LOG_INFO, "db->put failed\n");
+ free(rbt);
+ return -1;
+ }
+
+ free(rbt0);
+
+ len -= (*p + 1);
+ p += (*p + 1);
+
+ /* there could be ENT's so do loop */
+ while ((rbt0 = find_rrset(db, p, len)) == NULL) {
+ len -= (*p + 1);
+ p += (*p + 1);
+
+ }
+ }
+
+ break;
+ }
+ free(rbt0);
+
+ len -= (1 + *p);
+ p += (1 + *p);
+
+ /* there could be ENT's so do loop */
+ while ((rbt0 = find_rrset(db, p, len)) == NULL) {
+ len -= (*p + 1);
+ p += (*p + 1);
+
+ }
+ }
+
+ free(rbt);
+ }
+
+ return 0;
}
blob - 268130c0a6cc4e1ef5ae3943f4b864794f274843
blob + a199c65c167b61397b47d411489b091b0396bbcd
--- raxfr.c
+++ raxfr.c
@@ -26,7 +26,7 @@
*
*/
/*
- * $Id: raxfr.c,v 1.31 2019/11/06 08:45:57 pjp Exp $
+ * $Id: raxfr.c,v 1.32 2019/11/11 09:15:40 pjp Exp $
*/
#include <sys/types.h>
@@ -137,7 +137,6 @@ extern char *base32hex_encode(u_char *, int);
extern u_int64_t timethuman(time_t);
extern char * expand_compression(u_char *, u_char *, u_char *, u_char *, int *, int);
extern void dolog(int, char *, ...);
-extern struct rbtree * Lookup_zone(ddDB *, char *, u_int16_t, u_int16_t, int);
extern struct rbtree * find_rrset(ddDB *db, char *name, int len);
extern struct rrset * find_rr(struct rbtree *rbt, u_int16_t rrtype);
extern struct question *build_question(char *, int, int, char *);
blob - bc94d5f124a021a5093f2ef182cb12c45d1f373b
blob + c3b4f2ef02f62b46d311f979898e704a355c3fe1
--- reply.c
+++ reply.c
@@ -27,7 +27,7 @@
*/
/*
- * $Id: reply.c,v 1.88 2019/11/11 05:22:50 pjp Exp $
+ * $Id: reply.c,v 1.89 2019/11/11 09:15:40 pjp Exp $
*/
#include <sys/types.h>
@@ -85,7 +85,6 @@ extern struct question *build_fake_question(char *, i
extern int compress_label(u_char *, int, int);
extern void dolog(int, char *, ...);
extern int free_question(struct question *);
-extern struct rbtree * lookup_zone(ddDB *, struct question *, int *, int *, char *);
extern void slave_shutdown(void);
extern int get_record_size(ddDB *, char *, int);
extern char * dns_label(char *, int *);
@@ -1112,8 +1111,12 @@ reply_ds(struct sreply *sreply, ddDB *db)
outlen = tmplen;
- if (outlen > origlen)
- odh->answer = htons(a_count + 1 + 1);
+ if (outlen > origlen) {
+ //odh->answer = htons(a_count + 1 + 1);
+ NTOHS(odh->answer);
+ odh->answer += 1;
+ HTONS(odh->answer);
+ }
}
out:
@@ -2134,7 +2137,7 @@ reply_ns(struct sreply *sreply, ddDB *db)
SLIST_FOREACH(ad0, &addishead, addis_entries) {
addiscount = 0;
- rbt0 = Lookup_zone(db, ad0->name, ad0->namelen, htons(DNS_TYPE_AAAA), 0);
+ rbt0 = find_rrset(db, ad0->name, ad0->namelen);
if (rbt0 != NULL && find_rr(rbt0, DNS_TYPE_AAAA) != NULL) {
tmplen = additional_aaaa(ad0->name, ad0->namelen, rbt0, reply, replysize, outlen, &addiscount);
if (tmplen == 0) {
@@ -2183,7 +2186,7 @@ reply_ns(struct sreply *sreply, ddDB *db)
free(rbt0);
addiscount = 0;
- rbt0 = Lookup_zone(db, ad0->name, ad0->namelen, htons(DNS_TYPE_A), 0);
+ rbt0 = find_rrset(db, ad0->name, ad0->namelen);
if (rbt0 != NULL && find_rr(rbt0, DNS_TYPE_A) != NULL) {
tmplen = additional_a(ad0->name, ad0->namelen, rbt0, reply, replysize, outlen, &addiscount);
if (tmplen == 0) {
@@ -5201,9 +5204,11 @@ reply_noerror(struct sreply *sreply, ddDB *db)
origlen = outlen;
if (find_rr(rbt, DNS_TYPE_NSEC)) {
- rbt0 = Lookup_zone(db, q->hdr->name, q->hdr->namelen, htons(DNS_TYPE_NSEC), 0);
- tmplen = additional_nsec(q->hdr->name, q->hdr->namelen, DNS_TYPE_NSEC, rbt0, reply, replysize, outlen);
- free(rbt0);
+ rbt0 = Lookup_zone(db, q->hdr->name, q->hdr->namelen, DNS_TYPE_NSEC, 0);
+ if (rbt0 != NULL) {
+ tmplen = additional_nsec(q->hdr->name, q->hdr->namelen, DNS_TYPE_NSEC, rbt0, reply, replysize, outlen);
+ free(rbt0);
+ }
} else if (find_rr(rbt, DNS_TYPE_NSEC3PARAM)) {
rbt0 = find_nsec3_match_qname(q->hdr->name, q->hdr->namelen, rbt, db);
if (rbt0 == 0)
blob - 42245af7bcc5a97adfd8704b4cc4e6cd3fd80de5
blob + 4fa1d27b63e0396cf380944e170158a124ea957f
--- util.c
+++ util.c
@@ -27,7 +27,7 @@
*/
/*
- * $Id: util.c,v 1.50 2019/11/11 05:22:50 pjp Exp $
+ * $Id: util.c,v 1.51 2019/11/11 09:15:40 pjp Exp $
*/
#include <sys/types.h>
@@ -339,10 +339,11 @@ lookup_zone(ddDB *db, struct question *question, int *
{
struct rbtree *rbt = NULL;
+ struct rbtree *rbt0 = NULL;
struct rrset *rrset = NULL, *rrset2 = NULL;
- int plen, error;
+ int plen, splen, error;
- char *p;
+ char *p, *sp;
p = question->hdr->name;
plen = question->hdr->namelen;
@@ -350,19 +351,60 @@ lookup_zone(ddDB *db, struct question *question, int *
*returnval = 0;
/* if the find_rrset fails, the find_rr will not get questioned */
if ((rbt = find_rrset(db, p, plen)) == NULL ||
+ ((ntohs(question->hdr->qtype) != DNS_TYPE_DS) &&
+ (rbt->flags & RBT_GLUE)) ||
((rbt->flags & RBT_DNSSEC) && (rrset = find_rr(rbt, DNS_TYPE_NSEC3)) != NULL)) {
+ if (rbt == NULL) {
+ splen = plen;
+ sp = p;
+
+ while ((rbt0 = find_rrset(db, sp, splen)) == NULL) {
+ if (*sp == 0 && splen == 1)
+ break;
+ splen -= (*sp + 1);
+ sp += (*sp + 1);
+ }
+
+ if (rbt0 && rbt0->flags & RBT_GLUE)
+ rbt = rbt0;
+ }
+ /* check our delegations */
+ if (rbt && rbt->flags & RBT_GLUE) {
+ while (rbt && (rbt->flags & RBT_GLUE)) {
+ plen -= (*p + 1);
+ p += (*p + 1);
+
+ while ((rbt0 = find_rrset(db, p, plen)) == NULL) {
+ plen -= (*p + 1);
+ p += (*p + 1);
+ }
+
+ if (rbt0->flags & RBT_GLUE) {
+ free(rbt);
+ rbt = rbt0;
+ } else {
+ free(rbt0);
+ /* answer the delegation */
+ snprintf(replystring, DNS_MAXNAME, "%s", rbt->humanname);
+ *lzerrno = ERR_DELEGATE;
+ *returnval = -1;
+ return (rbt);
+ }
+ }
+ }
+
if (check_ent(p, plen) == 1) {
*lzerrno = ERR_NODATA;
*returnval = -1;
/* stop leakage */
- if (rrset != NULL)
+ if (rbt != NULL)
free(rbt);
return NULL;
}
- if (rrset != NULL)
+ if (rbt != NULL)
free(rbt);
/*
@@ -384,6 +426,7 @@ lookup_zone(ddDB *db, struct question *question, int *
}
if ((rrset = find_rr(rbt, DNS_TYPE_NS)) != NULL) {
+ snprintf(replystring, DNS_MAXNAME, "%s", rbt->humanname);
*lzerrno = ERR_DELEGATE;
*returnval = -1;
return (rbt);
@@ -400,6 +443,7 @@ lookup_zone(ddDB *db, struct question *question, int *
snprintf(replystring, DNS_MAXNAME, "%s", rbt->humanname);
if ((rrset = find_rr(rbt, DNS_TYPE_NS)) != NULL &&
+ ! ((rrset = find_rr(rbt, DNS_TYPE_DS)) != NULL) &&
(rrset2 = find_rr(rbt, DNS_TYPE_SOA)) == NULL) {
*returnval = -1;
*lzerrno = ERR_DELEGATE;
@@ -482,7 +526,7 @@ get_ns(ddDB *db, struct rbtree *rbt, int *delegation)
len = rbt->zonelen;
while (*p && len > 0) {
- rbt0 = Lookup_zone(db, p, len, htons(DNS_TYPE_NS), 0);
+ rbt0 = Lookup_zone(db, p, len, DNS_TYPE_NS, 0);
if (rbt0 == NULL) {
p += (*p + 1);
len -= (*p + 1);
@@ -511,27 +555,18 @@ struct rbtree *
Lookup_zone(ddDB *db, char *name, u_int16_t namelen, u_int16_t type, int wildcard)
{
struct rbtree *rbt;
- struct question *fakequestion;
- char fakereplystring[DNS_MAXNAME + 1];
- int mytype;
- int lzerrno;
+ struct rrset *rrset = NULL;
- fakequestion = build_fake_question(name, namelen, type, NULL, 0);
- if (fakequestion == 0) {
- dolog(LOG_INFO, "fakequestion(2) failed\n");
- return (NULL);
+ rbt = find_rrset(db, name, namelen);
+ if (rbt != NULL) {
+ rrset = find_rr(rbt, type);
+ if (rrset != NULL)
+ return (rbt);
+ else
+ free(rbt);
}
- rbt = lookup_zone(db, fakequestion, &mytype, &lzerrno, (char *)&fakereplystring);
-
- if (rbt == 0) {
- free_question(fakequestion);
- return (NULL);
- }
-
- free_question(fakequestion);
-
- return (rbt);
+ return NULL;
}
/*
repomaster@centroid.eu