OpenDNSSEC-signer  2.1.10
edns.c
Go to the documentation of this file.
1 /*
2  * Copyright (c) 2011 NLNet Labs. All rights reserved.
3  *
4  * Taken from NSD3 and adjusted for OpenDNSSEC, NLnet Labs.
5  *
6  * Redistribution and use in source and binary forms, with or without
7  * modification, are permitted provided that the following conditions
8  * are met:
9  * 1. Redistributions of source code must retain the above copyright
10  * notice, this list of conditions and the following disclaimer.
11  * 2. Redistributions in binary form must reproduce the above copyright
12  * notice, this list of conditions and the following disclaimer in the
13  * documentation and/or other materials provided with the distribution.
14  *
15  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
16  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
17  * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
18  * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
19  * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
20  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
21  * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
22  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
23  * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
24  * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
25  * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26  *
27  */
28 
34 #include "config.h"
35 #include "compat.h"
36 
37 #include "wire/buffer.h"
38 #include "wire/edns.h"
39 
40 #include <ldns/ldns.h>
41 
42 static const char* edns_str = "edns";
43 
44 
51 {
52  edns_rr_type* err = NULL;
53  CHECKALLOC(err = (edns_rr_type*) malloc(sizeof(edns_rr_type))) ;
54  edns_rr_reset(err);
55  return err;
56 }
57 
58 
63 void
64 edns_init(edns_data_type* data, uint16_t max_length)
65 {
66  if (!data) {
67  return;
68  }
69  memset(data, 0, sizeof(edns_data_type));
70  /* record type: OPT */
71  data->ok[1] = (LDNS_RR_TYPE_OPT & 0xff00) >> 8; /* type_hi */
72  data->ok[2] = LDNS_RR_TYPE_OPT & 0x00ff; /* type_lo */
73  /* udp payload size */
74  data->ok[3] = (max_length & 0xff00) >> 8; /* size_hi */
75  data->ok[4] = max_length & 0x00ff; /* size_lo */
76 
77  data->error[1] = (LDNS_RR_TYPE_OPT & 0xff00) >> 8; /* type_hi */
78  data->error[2] = LDNS_RR_TYPE_OPT & 0x00ff; /* type_lo */
79  data->error[3] = (max_length & 0xff00) >> 8; /* size_hi */
80  data->error[4] = max_length & 0x00ff; /* size_lo */
81  data->error[5] = 1; /* Extended RCODE=BAD VERS */
82 }
83 
84 
89 void
91 {
92  if (!err) {
93  return;
94  }
95  err->status = EDNS_NOT_PRESENT;
96  err->position = 0;
97  err->maxlen = 0;
98  err->dnssec_ok = 0;
99 }
100 
101 
106 int
108 {
109  /* OPT record type... */
110  uint8_t opt_owner;
111  uint16_t opt_type;
112  uint16_t opt_class;
113  uint8_t opt_version;
114  uint16_t opt_flags;
115  uint16_t opt_rdlen;
116 
117  if (!err || !buffer) {
118  ods_log_debug("[%s] parse: no edns rr or no packet buffer available",
119  edns_str);
120  return 0;
121  }
122 
123  err->position = buffer_position(buffer);
124  if (!buffer_available(buffer, (OPT_LEN + OPT_RDATA))) {
125  ods_log_debug("[%s] parse: edns rr too small", edns_str);
126  return 0;
127  }
128  opt_owner = buffer_read_u8(buffer);
129  opt_type = buffer_read_u16(buffer);
130  if (opt_owner != 0 || opt_type != LDNS_RR_TYPE_OPT) {
131  /* Not EDNS. */
132  ods_log_debug("[%s] parse: not OPT: owner=%02x, type=%02x", edns_str,
133  opt_owner, opt_type);
134  buffer_set_position(buffer, err->position);
135  return 0;
136  }
137  opt_class = buffer_read_u16(buffer);
138  (void)buffer_read_u8(buffer); /* opt_extended_rcode */
139  opt_version = buffer_read_u8(buffer);
140  opt_flags = buffer_read_u16(buffer);
141  opt_rdlen = buffer_read_u16(buffer);
142  buffer_skip(buffer, opt_rdlen);
143 
144  if (opt_version != 0) {
145  /* The only error is VERSION not implemented */
146  ods_log_debug("[%s] parse: wrong edns version", edns_str);
147  err->status = EDNS_ERROR;
148  return 1;
149  }
150  err->status = EDNS_OK;
151  err->maxlen = opt_class;
152  err->dnssec_ok = opt_flags & DNSSEC_OK_MASK;
153  return 1;
154 }
155 
156 
161 size_t
163 {
164  if (!err) {
165  return 0;
166  }
167  return err->status == EDNS_NOT_PRESENT ? 0 : (OPT_LEN + OPT_RDATA);
168 }
169 
170 
171 void
173 {
174  if (!err)
175  return;
176  free(err);
177 }
int buffer_available(buffer_type *buffer, size_t count)
Definition: buffer.c:487
uint16_t buffer_read_u16(buffer_type *buffer)
Definition: buffer.c:721
void buffer_set_position(buffer_type *buffer, size_t pos)
Definition: buffer.c:137
size_t buffer_position(buffer_type *buffer)
Definition: buffer.c:125
void buffer_skip(buffer_type *buffer, ssize_t count)
Definition: buffer.c:150
uint8_t buffer_read_u8(buffer_type *buffer)
Definition: buffer.c:706
void edns_rr_cleanup(edns_rr_type *err)
Definition: edns.c:172
void edns_init(edns_data_type *data, uint16_t max_length)
Definition: edns.c:64
size_t edns_rr_reserved_space(edns_rr_type *err)
Definition: edns.c:162
void edns_rr_reset(edns_rr_type *err)
Definition: edns.c:90
edns_rr_type * edns_rr_create()
Definition: edns.c:50
int edns_rr_parse(edns_rr_type *err, buffer_type *buffer)
Definition: edns.c:107
#define OPT_RDATA
Definition: edns.h:44
@ EDNS_NOT_PRESENT
Definition: edns.h:65
@ EDNS_ERROR
Definition: edns.h:67
@ EDNS_OK
Definition: edns.h:66
#define OPT_LEN
Definition: edns.h:43
#define DNSSEC_OK_MASK
Definition: edns.h:45
unsigned char ok[OPT_LEN]
Definition: edns.h:55
unsigned char error[OPT_LEN]
Definition: edns.h:56
int dnssec_ok
Definition: edns.h:80
edns_status status
Definition: edns.h:77
size_t position
Definition: edns.h:78
size_t maxlen
Definition: edns.h:79