Commit Diff
Diff:
44be7f81e1904ffa21241cd9e694e79cdff78e55
f59896890eafe25e88fbff1b14e3c1c5242f4a25
Commit:
f59896890eafe25e88fbff1b14e3c1c5242f4a25
Tree:
a2a15e3c90ce709dd89a90b01506b7c9fa35ae01
Author:
pjp <pjp@delphinusdns.org>
Committer:
pjp <pjp@delphinusdns.org>
Date:
Mon Apr 21 12:10:43 2014 UTC
Message:
* SPF (RR 99) rfc 4408 support tested on OpenBSD
blob - 57d15b7bc7850e51209d285994eb1fcb9b08735f
blob + 58dababdeb89314adb351c89a9e64403aecd032d
--- db.h
+++ db.h
@@ -87,6 +87,7 @@ struct domain {
#define DOMAIN_STATIC_ZONE 0x100
#define DOMAIN_NEGATIVE_CACHE 0x200
#define DOMAIN_HAVE_SRV 0x400
+#define DOMAIN_HAVE_SPF 0x800
struct soa soa; /* start of authority */
u_int32_t ttl; /* time to live */
time_t created; /* time created, for dynamic zones */
@@ -112,6 +113,8 @@ struct domain {
int ptrlen; /* len of PTR */
char txt[DNS_MAXNAME]; /* TXT string */
int txtlen; /* len of TXT */
+ char spf[DNS_MAXNAME]; /* SPF string */
+ int spflen; /* len of SPF */
struct srv srv[RECORD_COUNT]; /* SRV resource record */
int srv_count; /* count of SRV resource record */
} __attribute__((packed));
blob - db0492cb205573961e41c712de191eff9f6e7f4d
blob + f42af467b79f9f681a20380d074a0feefe8f3ee4
--- dns.h
+++ dns.h
@@ -137,6 +137,8 @@ struct dns_question_hdr {
#define DNS_TYPE_SRV 33 /* RFC 2782, page 8 */
+#define DNS_TYPE_SPF 99 /* RFC 4408 */
+
#define DNS_TYPE_TSIG 250 /* RFC 2845, page 3 */
#define DNS_TYPE_IXFR 251 /* RFC 1995, page 2 */
#define DNS_TYPE_AXFR 252 /* RFC 5936, page 10 */
blob - 21fb7d317d70b85859c4b92739f3521cc6a14f2a
blob + eb7aa657e2c4f7efd18a60b079a997c15c073432
--- example8.conf
+++ example8.conf
@@ -9,7 +9,7 @@ options "cool stuff" {
;bind 127.0.0.1;
;bind 192.168.34.4;
- port 10034;
+ port 53;
;fork 2;
log;
@@ -26,6 +26,8 @@ zone "centroid.eu" {
;
centroid.eu,mx,3600,10,proteus.solarscale.de.
centroid.eu,aaaa,3600,2001:a60:f074::8
+ ;
+ centroid.eu,spf,3600,"v=spf1 ip4:200.46.208.61 ~all"
;
www.centroid.eu,a,3600,62.75.160.180
www.centroid.eu,a,3600,200.46.208.61
blob - fa002e0aa4e855b0d233685f99a79b5b629d1809
blob + 0dea2f3fd90eaf3897f0083e1a701aa6669f30cf
--- main.c
+++ main.c
@@ -51,6 +51,7 @@ extern void reply_cname(struct sreply *);
extern void reply_mx(struct sreply *, DB *);
extern void reply_ns(struct sreply *, DB *);
extern void reply_txt(struct sreply *);
+extern void reply_spf(struct sreply *);
extern void reply_any(struct sreply *);
extern void reply_srv(struct sreply *, DB *);
extern u_int8_t find_region(struct sockaddr_storage *sst, int family);
@@ -102,6 +103,7 @@ struct typetable {
{ "AAAA", DNS_TYPE_AAAA},
{ "ANY", DNS_TYPE_ANY },
{ "SRV", DNS_TYPE_SRV },
+ { "SPF", DNS_TYPE_SPF },
{ NULL, 0}
};
@@ -152,7 +154,7 @@ struct tcps {
} *tn1, *tn2, *tnp;
-static const char rcsid[] = "$Id: main.c,v 1.83 2014/04/16 06:53:18 pjp Exp $";
+static const char rcsid[] = "$Id: main.c,v 1.84 2014/04/21 12:10:43 pjp Exp $";
/*
* MAIN - set up arguments, set up database, set up sockets, call mainloop
@@ -1394,6 +1396,7 @@ compress_label(u_char *buf, u_int16_t offset, int labe
p += 16; /* sizeof 4 * 32 bit */
break;
case DNS_TYPE_TXT:
+ case DNS_TYPE_SPF:
p += *p;
p++;
break;
@@ -1750,6 +1753,14 @@ lookup_zone(DB *db, struct question *question, struct
}
*lzerrno = ERR_NOERROR;
return -1;
+ case DNS_TYPE_SPF:
+ if ((sd->flags & DOMAIN_HAVE_SPF) ==
+ DOMAIN_HAVE_SPF) {
+ returnval = DNS_TYPE_SPF;
+ break;
+ }
+ *lzerrno = ERR_NOERROR;
+ return -1;
default: /* RR's that we don't support, but have a zone for */
*lzerrno = ERR_NOERROR;
return -1;
@@ -1896,6 +1907,14 @@ lookup_zone(DB *db, struct question *question, struct
}
*lzerrno = ERR_NOERROR;
return -1;
+ case DNS_TYPE_SPF:
+ if ((sd->flags & DOMAIN_HAVE_SPF) ==
+ DOMAIN_HAVE_SPF) {
+ returnval = DNS_TYPE_SPF;
+ break;
+ }
+ *lzerrno = ERR_NOERROR;
+ return -1;
default: /* RR's that we don't support, but have a zone for */
*lzerrno = ERR_NOERROR;
return -1;
@@ -2603,6 +2622,15 @@ tcpnxdomain:
}
break;
+ case DNS_TYPE_SPF:
+ if (type0 == DNS_TYPE_SPF) {
+ build_reply(&sreply, tnp->so, pbuf, len, question, from, \
+ fromlen, &sd0, NULL, tnp->region, istcp, tnp->wildcard, NULL);
+ reply_spf(&sreply);
+ }
+ break;
+
+
default:
/*
@@ -3034,6 +3062,13 @@ udpnxdomain:
build_reply(&sreply, so, buf, len, question, from, \
fromlen, &sd0, NULL, aregion, istcp, wildcard, NULL);
reply_txt(&sreply);
+ }
+ break;
+ case DNS_TYPE_SPF:
+ if (type0 == DNS_TYPE_SPF) {
+ build_reply(&sreply, so, buf, len, question, from, \
+ fromlen, &sd0, NULL, aregion, istcp, wildcard, NULL);
+ reply_spf(&sreply);
}
break;
default:
blob - 7795aa414ca235be30f80726ad1d5893f9426fb0
blob + 5848fca5cd26084d40f851a2d51a1287d9423420
--- parse.y
+++ parse.y
@@ -58,7 +58,7 @@ typedef struct {
int lineno;
} YYSTYPE;
-static const char rcsid[] = "$Id: parse.y,v 1.12 2014/04/16 07:19:04 pjp Exp $";
+static const char rcsid[] = "$Id: parse.y,v 1.13 2014/04/21 12:10:43 pjp Exp $";
static int version = 0;
static int state = 0;
static uint8_t region = 0;
@@ -113,6 +113,7 @@ int fill_balance(char *name, char *type, int myttl, ch
int fill_mx(char *name, char *type, int myttl, int priority, char *mxhost);
int fill_srv(char *, char *, int, int, int, int, char *);
int fill_txt(char *name, char *type, int myttl, char *msg);
+int fill_spf(char *name, char *type, int myttl, char *msg);
int get_record(struct domain *sdomain, char *converted_name, int converted_namelen);
void set_record(struct domain *sdomain, char *converted_name, int converted_namelen);
struct file *pushfile(const char *, int);
@@ -473,9 +474,16 @@ zonestatement:
if (debug)
printf(" %s TXT -> %s\n", $1, $7);
+ } else if (strcasecmp($3, "spf") == 0) {
+ if (fill_spf($1, $3, $5, $7) < 0) {
+ return -1;
+ }
+
+ if (debug)
+ printf(" %s SPF -> %s\n", $1, $7);
} else {
if (debug)
- printf("another txt like record I don't know?\n");
+ printf("another txt/spf like record I don't know?\n");
return (-1);
}
@@ -949,6 +957,7 @@ struct rrtab {
{ "delegate", DNS_TYPE_DELEGATE },
{ "balance", DNS_TYPE_BALANCE },
{ "srv", DNS_TYPE_SRV },
+ { "spf", DNS_TYPE_SPF },
{ NULL, 0 },
};
@@ -1498,6 +1507,59 @@ fill_ptr(char *name, char *type, int myttl, char *host
free(myname);
sdomain.flags |= DOMAIN_HAVE_PTR;
+
+ set_record(&sdomain, converted_name, converted_namelen);
+
+ if (converted_name)
+ free (converted_name);
+
+ return (0);
+
+}
+
+/* based on fill_txt */
+int
+fill_spf(char *name, char *type, int myttl, char *msg)
+{
+ struct domain sdomain;
+ int converted_namelen;
+ char *converted_name;
+ int len, i;
+
+ for (i = 0; i < strlen(name); i++) {
+ name[i] = tolower(name[i]);
+ }
+
+ if ((len = strlen(msg)) > 255) {
+ dolog(LOG_ERR, "SPF record too long line %d\n", file->lineno);
+ return (-1);
+ }
+
+ converted_name = check_rr(name, type, DNS_TYPE_SPF, &converted_namelen);
+ if (converted_name == NULL) {
+ return -1;
+ }
+
+ memset(&sdomain, 0, sizeof(sdomain));
+ if (get_record(&sdomain, converted_name, converted_namelen) < 0) {
+ return (-1);
+ }
+
+#ifdef __linux__
+ strncpy((char *)sdomain.zonename, (char *)name, DNS_MAXNAME + 1);
+ sdomain.zonename[DNS_MAXNAME] = '\0';
+#else
+ strlcpy((char *)sdomain.zonename, (char *)name, DNS_MAXNAME + 1);
+#endif
+ memcpy(sdomain.zone, converted_name, converted_namelen);
+ sdomain.zonelen = converted_namelen;
+
+ sdomain.ttl = myttl;
+
+ memcpy(&sdomain.spf, msg, len);
+ sdomain.spflen = len;
+
+ sdomain.flags |= DOMAIN_HAVE_SPF;
set_record(&sdomain, converted_name, converted_namelen);
blob - cfc57ad28445692333285f5798706f3364e76234
blob + b72a3a963a0b1abafd550f50e2506a031bf9b83f
--- reply.c
+++ reply.c
@@ -39,6 +39,7 @@ void reply_noerror(struct sreply *);
void reply_soa(struct sreply *);
void reply_ptr(struct sreply *);
void reply_txt(struct sreply *sreply);
+void reply_spf(struct sreply *sreply);
void reply_cname(struct sreply *);
void reply_any(struct sreply *);
void reply_fmterror(struct sreply *);
@@ -83,7 +84,7 @@ struct collects {
extern int debug, verbose;
-static const char rcsid[] = "$Id: reply.c,v 1.50 2014/04/13 09:05:42 pjp Exp $";
+static const char rcsid[] = "$Id: reply.c,v 1.51 2014/04/21 12:10:43 pjp Exp $";
/*
* REPLY_A() - replies a DNS question (*q) on socket (so)
@@ -1315,6 +1316,121 @@ reply_soa(struct sreply *sreply)
answer->rdlength = htons(&reply[outlen] - &answer->rdata);
+ if (sreply->sr != NULL) {
+ reply_raw2(so, reply, outlen, sreply->sr);
+ } else {
+ if (istcp) {
+ char *tmpbuf;
+ u_int16_t *plen;
+
+ tmpbuf = malloc(outlen + 2);
+ if (tmpbuf == NULL) {
+ dolog(LOG_INFO, "malloc: %s\n", strerror(errno));
+ }
+ plen = (u_int16_t *)tmpbuf;
+ *plen = htons(outlen);
+
+ memcpy(&tmpbuf[2], reply, outlen);
+
+ if (send(so, tmpbuf, outlen + 2, 0) < 0) {
+ dolog(LOG_INFO, "send: %s\n", strerror(errno));
+ }
+ free(tmpbuf);
+ } else {
+ if (sendto(so, reply, outlen, 0, sa, salen) < 0) {
+ dolog(LOG_INFO, "sendto: %s\n", strerror(errno));
+ }
+ }
+ }
+
+ return;
+}
+
+/*
+ * REPLY_SPF() - replies a DNS question (*q) on socket (so)
+ * based on reply_txt...
+ */
+
+
+void
+reply_spf(struct sreply *sreply)
+{
+ char reply[512];
+ struct dns_header *odh;
+ u_int16_t outlen;
+ char *p;
+
+ struct answer {
+ char name[2];
+ u_int16_t type;
+ u_int16_t class;
+ u_int32_t ttl;
+ u_int16_t rdlength; /* 12 */
+ char rdata;
+ } __attribute__((packed));
+
+ struct answer *answer;
+
+ int so = sreply->so;
+ char *buf = sreply->buf;
+ int len = sreply->len;
+ struct question *q = sreply->q;
+ struct sockaddr *sa = sreply->sa;
+ int salen = sreply->salen;
+ struct domain *sd = sreply->sd1;
+ int istcp = sreply->istcp;
+
+ /* st */
+
+ odh = (struct dns_header *)&reply[0];
+ outlen = sizeof(struct dns_header);
+
+ if (len > sizeof(reply)) {
+ return;
+ }
+
+ /* copy question to reply */
+ memcpy(&reply, buf, sizeof(struct dns_header) + q->hdr->namelen + 4);
+ /* blank query */
+ memset((char *)&odh->query, 0, sizeof(u_int16_t));
+
+ outlen += (q->hdr->namelen + 4);
+
+ SET_DNS_REPLY(odh);
+ if (sreply->sr == NULL)
+ SET_DNS_AUTHORITATIVE(odh);
+ else
+ SET_DNS_RECURSION_AVAIL(odh);
+
+ HTONS(odh->query);
+
+ odh->question = htons(1);
+ odh->answer = htons(1);
+ odh->nsrr = 0;
+ odh->additional = 0;
+
+ answer = (struct answer *)(&reply[0] + sizeof(struct dns_header) +
+ q->hdr->namelen + 4);
+
+ answer->name[0] = 0xc0;
+ answer->name[1] = 0x0c;
+ answer->type = q->hdr->qtype;
+ answer->class = q->hdr->qclass;
+ if (sreply->sr != NULL)
+ answer->ttl = htonl(sd->ttl - (time(NULL) - sd->created));
+ else
+ answer->ttl = htonl(sd->ttl);
+
+ outlen += 12; /* up to rdata length */
+
+ p = (char *)&answer->rdata;
+
+ *p = sd->spflen;
+ memcpy((p + 1), sd->spf, sd->spflen);
+ outlen += (sd->spflen + 1);
+
+ answer->rdlength = htons(sd->spflen + 1);
+
if (sreply->sr != NULL) {
reply_raw2(so, reply, outlen, sreply->sr);
} else {
repomaster@centroid.eu