1
0

Revision 47, 2022-12-16 11:26:53 +0100 (Fri, 16 Dec 2022)

This commit is contained in:
Jeroen 2023-08-27 11:48:33 +02:00
commit 7df7cb0b6d
Signed by: jeroen
GPG Key ID: 7C7028F783798BAB
7 changed files with 4275 additions and 0 deletions

42
Makefile Normal file
View File

@ -0,0 +1,42 @@
LOCALBASE?= /usr/local/
PROG= filter-dkimverify
MAN= filter-dkimverify.8
BINDIR= ${LOCALBASE}/libexec/smtpd/
MANDIR= ${LOCALBASE}/man/man
SRCS+= main.c ltok.c unpack_dns.c
.ifdef HAVE_ED25519
CFLAGS+= -DHAVE_ED25519
.endif
.ifdef LIBCRYPTOPC
CRYPT_CFLAGS!= pkg-config --cflags ${LIBCRYPTOPC}
CRYPT_LDFLAGS_L!=pkg-config --libs-only-L ${LIBCRYPTOPC}
CRYPT_LDFLAGS_libdir!=pkg-config --variable libdir ${LIBCRYPTOPC}
CRYPT_LDFLAGS= ${CRYPT_LDFLAGS_L}
CRYPT_LDFLAGS+= -Wl,-rpath,${CRYPT_LDFLAGS_libdir}
CRYPT_LDADD!= pkg-config --libs-only-l ${LIBCRYPTOPC}
.else
CRYPT_CFLAGS=
CRYPT_LDFLAGS=
CRYPT_LDADD= -lcrypto
.endif
CFLAGS+= -I${LOCALBASE}/include -I${.CURDIR}/openbsd-compat
CFLAGS+= -Wall -I${.CURDIR}
CFLAGS+= -Wstrict-prototypes -Wmissing-prototypes
CFLAGS+= -Wmissing-declarations
CFLAGS+= -Wshadow -Wpointer-arith -Wcast-qual
CFLAGS+= -Wsign-compare
CFLAGS+= ${CRYPT_CFLAGS}
LDFLAGS+= -L${LOCALBASE}/lib
LDFLAGS+= ${CRYPT_LDFLAGS}
LDADD+= ${CRYPT_LDADD} -lopensmtpd -levent
DPADD= ${LIBCRYPTO}
bindir:
${INSTALL} -d ${DESTDIR}${BINDIR}
.include <bsd.prog.mk>

32
filter-dkimverify.8 Normal file
View File

@ -0,0 +1,32 @@
.\" $OpenBSD$
.\"
.\" Copyright (c) 2019 Martijn van Duren <martijn@openbsd.org>
.\"
.\" Permission to use, copy, modify, and distribute this software for any
.\" purpose with or without fee is hereby granted, provided that the above
.\" copyright notice and this permission notice appear in all copies.
.\"
.\" THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
.\" WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
.\" MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
.\" ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
.\" WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
.\" ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
.\" OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
.\"
.Dd $Mdocdate$
.Dt FILTER-DKIMVERIFY 8
.Os
.Sh NAME
.Nm filter-dkimverify
.Nd verifies dkim signature of messages
.Sh SYNOPSIS
.Nm
.Sh DESCRIPTION
.Nm
verifies the dkim signatures of messages and adds an Authentication-Results
header to the message.
.Sh SEE ALSO
.Xr filter-admdscrub 8
.Xr filter-dkimsign 8
.Xr smtpd 8

1876
ltok.c Normal file

File diff suppressed because it is too large Load Diff

175
ltok.h Normal file
View File

@ -0,0 +1,175 @@
/*
* Copyright (c) 2020-2022 Martijn van Duren <martijn@openbsd.org>
*
* Permission to use, copy, modify, and distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
* copyright notice and this permission notice appear in all copies.
*
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
/* RFC 5234 - Augmented BNF for Syntax Specifications: ABNF */
const char *osmtpd_ltok_skip_alpha(const char *, int);
const char *osmtpd_ltok_skip_bit(const char *, int);
const char *osmtpd_ltok_skip_char(const char *, int);
const char *osmtpd_ltok_skip_cr(const char *, int);
const char *osmtpd_ltok_skip_crlf(const char *, int);
const char *osmtpd_ltok_skip_ctl(const char *, int);
const char *osmtpd_ltok_skip_digit(const char *, int);
const char *osmtpd_ltok_skip_dquote(const char *, int);
const char *osmtpd_ltok_skip_hexdig(const char *, int);
const char *osmtpd_ltok_skip_htab(const char *, int);
const char *osmtpd_ltok_skip_lf(const char *, int);
const char *osmtpd_ltok_skip_octet(const char *, int);
const char *osmtpd_ltok_skip_sp(const char *, int);
const char *osmtpd_ltok_skip_vchar(const char *, int);
const char *osmtpd_ltok_skip_wsp(const char *, int);
/* RFC 5321 - Simple Mail Transfer Protocol */
const char *osmtpd_ltok_skip_keyword(const char *, int);
const char *osmtpd_ltok_skip_sub_domain(const char *, int);
const char *osmtpd_ltok_skip_let_dig(const char *, int);
const char *osmtpd_ltok_skip_ldh_string(const char *, int);
/* RFC 5322 - Internet Message Format */
const char *osmtpd_ltok_skip_quoted_pair(const char *, int);
const char *osmtpd_ltok_skip_fws(const char *, int);
const char *osmtpd_ltok_skip_ctext(const char *, int);
const char *osmtpd_ltok_skip_ccontent(const char *, int);
const char *osmtpd_ltok_skip_comment(const char *, int);
const char *osmtpd_ltok_skip_cfws(const char *, int);
const char *osmtpd_ltok_skip_atext(const char *, int);
const char *osmtpd_ltok_skip_atom(const char *, int);
const char *osmtpd_ltok_skip_dot_atom_text(const char *, int);
const char *osmtpd_ltok_skip_dot_atom(const char *, int);
const char *osmtpd_ltok_skip_qtext(const char *, int);
const char *osmtpd_ltok_skip_qcontent(const char *, int);
const char *osmtpd_ltok_skip_quoted_string(const char *, int);
const char *osmtpd_ltok_skip_word(const char *, int);
const char *osmtpd_ltok_skip_phrase(const char *, int);
const char *osmtpd_ltok_skip_name_addr(const char *, int);
const char *osmtpd_ltok_skip_angle_addr(const char *, int);
const char *osmtpd_ltok_skip_display_name(const char *, int);
const char *osmtpd_ltok_skip_addr_spec(const char *, int);
const char *osmtpd_ltok_skip_local_part(const char *, int);
const char *osmtpd_ltok_skip_domain(const char *, int);
const char *osmtpd_ltok_skip_domain_literal(const char *, int);
const char *osmtpd_ltok_skip_dtext(const char *, int);
const char *osmtpd_ltok_skip_field_name(const char *, int);
const char *osmtpd_ltok_skip_ftext(const char *, int);
const char *osmtpd_ltok_skip_obs_no_ws_ctl(const char *, int);
const char *osmtpd_ltok_skip_obs_ctext(const char *, int);
const char *osmtpd_ltok_skip_obs_qtext(const char *, int);
const char *osmtpd_ltok_skip_obs_qp(const char *, int);
const char *osmtpd_ltok_skip_obs_phrase(const char *, int);
const char *osmtpd_ltok_skip_obs_fws(const char *, int);
const char *osmtpd_ltok_skip_obs_angle_addr(const char *, int);
const char *osmtpd_ltok_skip_obs_route(const char *, int);
const char *osmtpd_ltok_skip_obs_domain_list(const char *, int);
const char *osmtpd_ltok_skip_obs_local_part(const char *, int);
const char *osmtpd_ltok_skip_obs_domain(const char *, int);
const char *osmtpd_ltok_skip_obs_dtext(const char *, int);
/* RFC 2045 - Multipurpose Internet Mail Extensions */
const char *osmtpd_ltok_skip_value(const char *, int);
const char *osmtpd_ltok_skip_token(const char *, int);
const char *osmtpd_ltok_skip_tspecials(const char *, int);
const char *osmtpd_ltok_skip_qp_section(const char *, int);
const char *osmtpd_ltok_skip_ptext(const char *, int);
const char *osmtpd_ltok_skip_safe_char(const char *, int);
const char *osmtpd_ltok_skip_hex_octet(const char *, int);
/* RFC 6376 - DomainKeys Identified Mail (DKIM) Signatures */
const char *osmtpd_ltok_skip_hyphenated_word(const char *, int);
const char *osmtpd_ltok_skip_alphadigitps(const char *, int);
const char *osmtpd_ltok_skip_base64string(const char *, int);
const char *osmtpd_ltok_skip_hdr_name(const char *, int);
const char *osmtpd_ltok_skip_qp_hdr_value(const char *, int);
const char *osmtpd_ltok_skip_dkim_quoted_printable(const char *, int);
const char *osmtpd_ltok_skip_dkim_safe_char(const char *, int);
const char *osmtpd_ltok_skip_selector(const char *, int);
const char *osmtpd_ltok_skip_tag_list(const char *, int);
const char *osmtpd_ltok_skip_tag_spec(const char *, int);
const char *osmtpd_ltok_skip_tag_name(const char *, int);
const char *osmtpd_ltok_skip_tag_value(const char *, int);
const char *osmtpd_ltok_skip_tval(const char *, int);
const char *osmtpd_ltok_skip_valchar(const char *, int);
const char *osmtpd_ltok_skip_alnumpunc(const char *, int);
const char *osmtpd_ltok_skip_sig_v_tag(const char *, int);
const char *osmtpd_ltok_skip_sig_v_tag_value(const char *, int);
const char *osmtpd_ltok_skip_sig_a_tag(const char *, int);
const char *osmtpd_ltok_skip_sig_a_tag_value(const char *, int);
const char *osmtpd_ltok_skip_sig_a_tag_alg(const char *, int);
const char *osmtpd_ltok_skip_sig_a_tag_k(const char *, int);
const char *osmtpd_ltok_skip_sig_a_tag_h(const char *, int);
const char *osmtpd_ltok_skip_x_sig_a_tag_k(const char *, int);
const char *osmtpd_ltok_skip_x_sig_a_tag_h(const char *, int);
const char *osmtpd_ltok_skip_sig_b_tag(const char *, int);
const char *osmtpd_ltok_skip_sig_b_tag_value(const char *, int);
const char *osmtpd_ltok_skip_sig_b_tag_data(const char *, int);
const char *osmtpd_ltok_skip_sig_bh_tag(const char *, int);
const char *osmtpd_ltok_skip_sig_bh_tag_value(const char *, int);
const char *osmtpd_ltok_skip_sig_bh_tag_data(const char *, int);
const char *osmtpd_ltok_skip_sig_c_tag(const char *, int);
const char *osmtpd_ltok_skip_sig_c_tag_value(const char *, int);
const char *osmtpd_ltok_skip_sig_c_tag_alg(const char *, int);
const char *osmtpd_ltok_skip_x_sig_c_tag_alg(const char *, int);
const char *osmtpd_ltok_skip_sig_d_tag(const char *, int);
const char *osmtpd_ltok_skip_sig_d_tag_value(const char *, int);
const char *osmtpd_ltok_skip_domain_name(const char *, int);
const char *osmtpd_ltok_skip_sig_h_tag(const char *, int);
const char *osmtpd_ltok_skip_sig_h_tag_value(const char *, int);
const char *osmtpd_ltok_skip_sig_i_tag(const char *, int);
const char *osmtpd_ltok_skip_sig_i_tag_value(const char *, int);
const char *osmtpd_ltok_skip_sig_l_tag(const char *, int);
const char *osmtpd_ltok_skip_sig_l_tag_value(const char *, int);
const char *osmtpd_ltok_skip_sig_q_tag(const char *, int);
const char *osmtpd_ltok_skip_sig_q_tag_value(const char *, int);
const char *osmtpd_ltok_skip_sig_q_tag_method(const char *, int);
const char *osmtpd_ltok_skip_x_sig_q_tag_type(const char *, int);
const char *osmtpd_ltok_skip_x_sig_q_tag_args(const char *, int);
const char *osmtpd_ltok_skip_sig_s_tag(const char *, int);
const char *osmtpd_ltok_skip_sig_s_tag_value(const char *, int);
const char *osmtpd_ltok_skip_sig_t_tag(const char *, int);
const char *osmtpd_ltok_skip_sig_t_tag_value(const char *, int);
const char *osmtpd_ltok_skip_sig_x_tag(const char *, int);
const char *osmtpd_ltok_skip_sig_x_tag_value(const char *, int);
const char *osmtpd_ltok_skip_sig_z_tag(const char *, int);
const char *osmtpd_ltok_skip_sig_z_tag_value(const char *, int);
const char *osmtpd_ltok_skip_sig_z_tag_copy(const char *, int);
const char *osmtpd_ltok_skip_key_v_tag(const char *, int);
const char *osmtpd_ltok_skip_key_v_tag_value(const char *, int);
const char *osmtpd_ltok_skip_key_h_tag(const char *, int);
const char *osmtpd_ltok_skip_key_h_tag_value(const char *, int);
const char *osmtpd_ltok_skip_key_h_tag_alg(const char *, int);
const char *osmtpd_ltok_skip_x_key_h_tag_alg(const char *, int);
const char *osmtpd_ltok_skip_key_k_tag(const char *, int);
const char *osmtpd_ltok_skip_key_k_tag_value(const char *, int);
const char *osmtpd_ltok_skip_key_k_tag_type(const char *, int);
const char *osmtpd_ltok_skip_x_key_k_tag_type(const char *, int);
const char *osmtpd_ltok_skip_key_n_tag(const char *, int);
const char *osmtpd_ltok_skip_key_n_tag_value(const char *, int);
const char *osmtpd_ltok_skip_key_p_tag(const char *, int);
const char *osmtpd_ltok_skip_key_p_tag_value(const char *, int);
const char *osmtpd_ltok_skip_key_s_tag(const char *, int);
const char *osmtpd_ltok_skip_key_s_tag_value(const char *, int);
const char *osmtpd_ltok_skip_key_s_tag_type(const char *, int);
const char *osmtpd_ltok_skip_x_key_s_tag_type(const char *, int);
const char *osmtpd_ltok_skip_key_t_tag(const char *, int);
const char *osmtpd_ltok_skip_key_t_tag_value(const char *, int);
const char *osmtpd_ltok_skip_key_t_tag_flag(const char *, int);
const char *osmtpd_ltok_skip_x_key_t_tag_flag(const char *, int);
/* Authentication-Results */
const char *osmtpd_ltok_skip_ar_pvalue(const char *, int);
const char *osmtpd_ltok_domain_uncomment(const char *);
const char *osmtpd_ltok_from_domain(const char *);
const char *osmtpd_ltok_quoted_string_normalize(const char *);

1759
main.c Normal file

File diff suppressed because it is too large Load Diff

295
unpack_dns.c Normal file
View File

@ -0,0 +1,295 @@
/* $OpenBSD: unpack_dns.c,v 1.1 2018/01/06 07:57:53 sunil Exp $ */
/*
* Copyright (c) 2011-2014 Eric Faurot <eric@faurot.net>
*
* Permission to use, copy, modify, and distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
* copyright notice and this permission notice appear in all copies.
*
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
#include <arpa/inet.h>
#include <string.h>
#include "unpack_dns.h"
static int unpack_data(struct unpack *, void *, size_t);
static int unpack_u16(struct unpack *, uint16_t *);
static int unpack_u32(struct unpack *, uint32_t *);
static int unpack_inaddr(struct unpack *, struct in_addr *);
static int unpack_in6addr(struct unpack *, struct in6_addr *);
static int unpack_dname(struct unpack *, char *, size_t);
void
unpack_init(struct unpack *unpack, const char *buf, size_t len)
{
unpack->buf = buf;
unpack->len = len;
unpack->offset = 0;
unpack->err = NULL;
}
int
unpack_header(struct unpack *p, struct dns_header *h)
{
if (unpack_data(p, h, HFIXEDSZ) == -1)
return (-1);
h->flags = ntohs(h->flags);
h->qdcount = ntohs(h->qdcount);
h->ancount = ntohs(h->ancount);
h->nscount = ntohs(h->nscount);
h->arcount = ntohs(h->arcount);
return (0);
}
int
unpack_query(struct unpack *p, struct dns_query *q)
{
unpack_dname(p, q->q_dname, sizeof(q->q_dname));
unpack_u16(p, &q->q_type);
unpack_u16(p, &q->q_class);
return (p->err) ? (-1) : (0);
}
int
unpack_rr(struct unpack *p, struct dns_rr *rr)
{
uint16_t rdlen;
size_t save_offset;
unpack_dname(p, rr->rr_dname, sizeof(rr->rr_dname));
unpack_u16(p, &rr->rr_type);
unpack_u16(p, &rr->rr_class);
unpack_u32(p, &rr->rr_ttl);
unpack_u16(p, &rdlen);
if (p->err)
return (-1);
if (p->len - p->offset < rdlen) {
p->err = "too short";
return (-1);
}
save_offset = p->offset;
switch (rr->rr_type) {
case T_CNAME:
unpack_dname(p, rr->rr.cname.cname, sizeof(rr->rr.cname.cname));
break;
case T_MX:
unpack_u16(p, &rr->rr.mx.preference);
unpack_dname(p, rr->rr.mx.exchange, sizeof(rr->rr.mx.exchange));
break;
case T_NS:
unpack_dname(p, rr->rr.ns.nsname, sizeof(rr->rr.ns.nsname));
break;
case T_PTR:
unpack_dname(p, rr->rr.ptr.ptrname, sizeof(rr->rr.ptr.ptrname));
break;
case T_SOA:
unpack_dname(p, rr->rr.soa.mname, sizeof(rr->rr.soa.mname));
unpack_dname(p, rr->rr.soa.rname, sizeof(rr->rr.soa.rname));
unpack_u32(p, &rr->rr.soa.serial);
unpack_u32(p, &rr->rr.soa.refresh);
unpack_u32(p, &rr->rr.soa.retry);
unpack_u32(p, &rr->rr.soa.expire);
unpack_u32(p, &rr->rr.soa.minimum);
break;
case T_A:
if (rr->rr_class != C_IN)
goto other;
unpack_inaddr(p, &rr->rr.in_a.addr);
break;
case T_AAAA:
if (rr->rr_class != C_IN)
goto other;
unpack_in6addr(p, &rr->rr.in_aaaa.addr6);
break;
default:
other:
rr->rr.other.rdata = p->buf + p->offset;
rr->rr.other.rdlen = rdlen;
p->offset += rdlen;
}
if (p->err)
return (-1);
/* make sure that the advertised rdlen is really ok */
if (p->offset - save_offset != rdlen)
p->err = "bad dlen";
return (p->err) ? (-1) : (0);
}
ssize_t
dname_expand(const unsigned char *data, size_t len, size_t offset,
size_t *newoffset, char *dst, size_t max)
{
size_t n, count, end, ptr, start;
ssize_t res;
if (offset >= len)
return (-1);
res = 0;
end = start = offset;
for (; (n = data[offset]); ) {
if ((n & 0xc0) == 0xc0) {
if (offset + 2 > len)
return (-1);
ptr = 256 * (n & ~0xc0) + data[offset + 1];
if (ptr >= start)
return (-1);
if (end < offset + 2)
end = offset + 2;
offset = start = ptr;
continue;
}
if (offset + n + 1 > len)
return (-1);
/* copy n + at offset+1 */
if (dst != NULL && max != 0) {
count = (max < n + 1) ? (max) : (n + 1);
memmove(dst, data + offset, count);
dst += count;
max -= count;
}
res += n + 1;
offset += n + 1;
if (end < offset)
end = offset;
}
if (end < offset + 1)
end = offset + 1;
if (dst != NULL && max != 0)
dst[0] = 0;
if (newoffset)
*newoffset = end;
return (res + 1);
}
char *
print_dname(const char *_dname, char *buf, size_t max)
{
const unsigned char *dname = _dname;
char *res;
size_t left, count;
if (_dname[0] == 0) {
(void)strlcpy(buf, ".", max);
return buf;
}
res = buf;
left = max - 1;
for (; dname[0] && left;) {
count = (dname[0] < (left - 1)) ? dname[0] : (left - 1);
memmove(buf, dname + 1, count);
dname += dname[0] + 1;
left -= count;
buf += count;
if (left) {
left -= 1;
*buf++ = '.';
}
}
buf[0] = 0;
return (res);
}
static int
unpack_data(struct unpack *p, void *data, size_t len)
{
if (p->err)
return (-1);
if (p->len - p->offset < len) {
p->err = "too short";
return (-1);
}
memmove(data, p->buf + p->offset, len);
p->offset += len;
return (0);
}
static int
unpack_u16(struct unpack *p, uint16_t *u16)
{
if (unpack_data(p, u16, 2) == -1)
return (-1);
*u16 = ntohs(*u16);
return (0);
}
static int
unpack_u32(struct unpack *p, uint32_t *u32)
{
if (unpack_data(p, u32, 4) == -1)
return (-1);
*u32 = ntohl(*u32);
return (0);
}
static int
unpack_inaddr(struct unpack *p, struct in_addr *a)
{
return (unpack_data(p, a, 4));
}
static int
unpack_in6addr(struct unpack *p, struct in6_addr *a6)
{
return (unpack_data(p, a6, 16));
}
static int
unpack_dname(struct unpack *p, char *dst, size_t max)
{
ssize_t e;
if (p->err)
return (-1);
e = dname_expand(p->buf, p->len, p->offset, &p->offset, dst, max);
if (e == -1) {
p->err = "bad domain name";
return (-1);
}
if (e < 0 || e > MAXDNAME) {
p->err = "domain name too long";
return (-1);
}
return (0);
}

96
unpack_dns.h Normal file
View File

@ -0,0 +1,96 @@
/* $OpenBSD: unpack_dns.h,v 1.1 2018/01/06 07:57:53 sunil Exp $ */
/*
* Copyright (c) 2011-2014 Eric Faurot <eric@faurot.net>
*
* Permission to use, copy, modify, and distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
* copyright notice and this permission notice appear in all copies.
*
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
#include <sys/types.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <arpa/nameser.h>
struct unpack {
const char *buf;
size_t len;
size_t offset;
const char *err;
};
struct dns_header {
uint16_t id;
uint16_t flags;
uint16_t qdcount;
uint16_t ancount;
uint16_t nscount;
uint16_t arcount;
};
struct dns_query {
char q_dname[MAXDNAME];
uint16_t q_type;
uint16_t q_class;
};
struct dns_rr {
char rr_dname[MAXDNAME];
uint16_t rr_type;
uint16_t rr_class;
uint32_t rr_ttl;
union {
struct {
char cname[MAXDNAME];
} cname;
struct {
uint16_t preference;
char exchange[MAXDNAME];
} mx;
struct {
char nsname[MAXDNAME];
} ns;
struct {
char ptrname[MAXDNAME];
} ptr;
struct {
char mname[MAXDNAME];
char rname[MAXDNAME];
uint32_t serial;
uint32_t refresh;
uint32_t retry;
uint32_t expire;
uint32_t minimum;
} soa;
struct {
struct in_addr addr;
} in_a;
struct {
struct in6_addr addr6;
} in_aaaa;
struct {
uint16_t rdlen;
const void *rdata;
} other;
} rr;
};
void unpack_init(struct unpack *, const char *, size_t);
int unpack_header(struct unpack *, struct dns_header *);
int unpack_rr(struct unpack *, struct dns_rr *);
int unpack_query(struct unpack *, struct dns_query *);
char *print_dname(const char *, char *, size_t);
ssize_t dname_expand(const unsigned char *, size_t, size_t, size_t *,
char *, size_t);