edns.c
Go to the documentation of this file.
/*
* Copyright (c) 2011 NLNet Labs. All rights reserved.
*
* Taken from NSD3 and adjusted for OpenDNSSEC, NLnet Labs.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
* GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
* IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
* OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
* IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
*/
#include "config.h"
#include "compat.h"
#include "wire/buffer.h"
#include "wire/edns.h"
#include <ldns/ldns.h>
static const char* edns_str = "edns";
edns_rr_type*
edns_rr_create()
{
edns_rr_type* err = NULL;
CHECKALLOC(err = (edns_rr_type*) malloc(sizeof(edns_rr_type))) ;
edns_rr_reset(err);
return err;
}
void
edns_init(edns_data_type* data, uint16_t max_length)
{
if (!data) {
return;
}
memset(data, 0, sizeof(edns_data_type));
/* record type: OPT */
data->ok[1] = (LDNS_RR_TYPE_OPT & 0xff00) >> 8; /* type_hi */
data->ok[2] = LDNS_RR_TYPE_OPT & 0x00ff; /* type_lo */
/* udp payload size */
data->ok[3] = (max_length & 0xff00) >> 8; /* size_hi */
data->ok[4] = max_length & 0x00ff; /* size_lo */
data->error[1] = (LDNS_RR_TYPE_OPT & 0xff00) >> 8; /* type_hi */
data->error[2] = LDNS_RR_TYPE_OPT & 0x00ff; /* type_lo */
data->error[3] = (max_length & 0xff00) >> 8; /* size_hi */
data->error[4] = max_length & 0x00ff; /* size_lo */
data->error[5] = 1; /* Extended RCODE=BAD VERS */
}
void
edns_rr_reset(edns_rr_type* err)
{
if (!err) {
return;
}
err->status = EDNS_NOT_PRESENT;
err->position = 0;
err->maxlen = 0;
err->dnssec_ok = 0;
}
int
edns_rr_parse(edns_rr_type* err, buffer_type* buffer)
{
/* OPT record type... */
uint8_t opt_owner;
uint16_t opt_type;
uint16_t opt_class;
uint8_t opt_version;
uint16_t opt_flags;
uint16_t opt_rdlen;
if (!err || !buffer) {
ods_log_debug("[%s] parse: no edns rr or no packet buffer available",
edns_str);
return 0;
}
err->position = buffer_position(buffer);
if (!buffer_available(buffer, (OPT_LEN + OPT_RDATA))) {
ods_log_debug("[%s] parse: edns rr too small", edns_str);
return 0;
}
opt_owner = buffer_read_u8(buffer);
opt_type = buffer_read_u16(buffer);
if (opt_owner != 0 || opt_type != LDNS_RR_TYPE_OPT) {
/* Not EDNS. */
ods_log_debug("[%s] parse: not OPT: owner=%02x, type=%02x", edns_str,
opt_owner, opt_type);
buffer_set_position(buffer, err->position);
return 0;
}
opt_class = buffer_read_u16(buffer);
(void)buffer_read_u8(buffer); /* opt_extended_rcode */
opt_version = buffer_read_u8(buffer);
opt_flags = buffer_read_u16(buffer);
opt_rdlen = buffer_read_u16(buffer);
buffer_skip(buffer, opt_rdlen);
if (opt_version != 0) {
/* The only error is VERSION not implemented */
ods_log_debug("[%s] parse: wrong edns version", edns_str);
err->status = EDNS_ERROR;
return 1;
}
err->status = EDNS_OK;
err->maxlen = opt_class;
err->dnssec_ok = opt_flags & DNSSEC_OK_MASK;
return 1;
}
size_t
edns_rr_reserved_space(edns_rr_type* err)
{
if (!err) {
return 0;
}
return err->status == EDNS_NOT_PRESENT ? 0 : (OPT_LEN + OPT_RDATA);
}
void
edns_rr_cleanup(edns_rr_type* err)
{
if (!err)
return;
free(err);
}
buffer_available
int buffer_available(buffer_type *buffer, size_t count)
Definition buffer.c:487
buffer_read_u16
uint16_t buffer_read_u16(buffer_type *buffer)
Definition buffer.c:721
buffer_set_position
void buffer_set_position(buffer_type *buffer, size_t pos)
Definition buffer.c:137
buffer_position
size_t buffer_position(buffer_type *buffer)
Definition buffer.c:125
buffer_skip
void buffer_skip(buffer_type *buffer, ssize_t count)
Definition buffer.c:150
buffer_read_u8
uint8_t buffer_read_u8(buffer_type *buffer)
Definition buffer.c:706
buffer.h
edns_rr_cleanup
void edns_rr_cleanup(edns_rr_type *err)
Definition edns.c:172
edns_init
void edns_init(edns_data_type *data, uint16_t max_length)
Definition edns.c:64
edns_rr_reserved_space
size_t edns_rr_reserved_space(edns_rr_type *err)
Definition edns.c:162
edns_rr_reset
void edns_rr_reset(edns_rr_type *err)
Definition edns.c:90
edns_rr_parse
int edns_rr_parse(edns_rr_type *err, buffer_type *buffer)
Definition edns.c:107
edns_rr_create
edns_rr_type * edns_rr_create()
Definition edns.c:50
edns.h
OPT_RDATA
#define OPT_RDATA
Definition edns.h:44
EDNS_NOT_PRESENT
@ EDNS_NOT_PRESENT
Definition edns.h:65
EDNS_ERROR
@ EDNS_ERROR
Definition edns.h:67
EDNS_OK
@ EDNS_OK
Definition edns.h:66
OPT_LEN
#define OPT_LEN
Definition edns.h:43
DNSSEC_OK_MASK
#define DNSSEC_OK_MASK
Definition edns.h:45
buffer_struct
Definition buffer.h:112
edns_data_struct
Definition edns.h:54
edns_data_struct::ok
unsigned char ok[OPT_LEN]
Definition edns.h:55
edns_data_struct::error
unsigned char error[OPT_LEN]
Definition edns.h:56
edns_rr_struct
Definition edns.h:76
edns_rr_struct::dnssec_ok
int dnssec_ok
Definition edns.h:80
edns_rr_struct::status
edns_status status
Definition edns.h:77
edns_rr_struct::position
size_t position
Definition edns.h:78
edns_rr_struct::maxlen
size_t maxlen
Definition edns.h:79