OpenDNSSEC-signer  2.0.2
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 
116  if (!err || !buffer) {
117  ods_log_debug("[%s] parse: no edns rr or no packet buffer available",
118  edns_str);
119  return 0;
120  }
121 
122  err->position = buffer_position(buffer);
123  if (!buffer_available(buffer, (OPT_LEN + OPT_RDATA))) {
124  ods_log_debug("[%s] parse: edns rr too small", edns_str);
125  return 0;
126  }
127  opt_owner = buffer_read_u8(buffer);
128  opt_type = buffer_read_u16(buffer);
129  if (opt_owner != 0 || opt_type != LDNS_RR_TYPE_OPT) {
130  /* Not EDNS. */
131  ods_log_debug("[%s] parse: not OPT: owner=%02x, type=%02x", edns_str,
132  opt_owner, opt_type);
133  buffer_set_position(buffer, err->position);
134  return 0;
135  }
136  opt_class = buffer_read_u16(buffer);
137  (void)buffer_read_u8(buffer); /* opt_extended_rcode */
138  opt_version = buffer_read_u8(buffer);
139  opt_flags = buffer_read_u16(buffer);
140  (void)buffer_read_u16(buffer); /* opt_rdlen */
141 
142  if (opt_version != 0) {
143  /* The only error is VERSION not implemented */
144  ods_log_debug("[%s] parse: wrong edns version", edns_str);
145  err->status = EDNS_ERROR;
146  return 1;
147  }
148  err->status = EDNS_OK;
149  err->maxlen = opt_class;
150  err->dnssec_ok = opt_flags & DNSSEC_OK_MASK;
151  return 1;
152 }
153 
154 
159 size_t
161 {
162  if (!err) {
163  return 0;
164  }
165  return err->status == EDNS_NOT_PRESENT ? 0 : (OPT_LEN + OPT_RDATA);
166 }
167 
168 
169 void
171 {
172  if (!err)
173  return;
174  free(err);
175 }
void edns_rr_cleanup(edns_rr_type *err)
Definition: edns.c:170
int edns_rr_parse(edns_rr_type *err, buffer_type *buffer)
Definition: edns.c:107
void edns_rr_reset(edns_rr_type *err)
Definition: edns.c:90
#define OPT_RDATA
Definition: edns.h:44
uint16_t buffer_read_u16(buffer_type *buffer)
Definition: buffer.c:721
uint8_t buffer_read_u8(buffer_type *buffer)
Definition: buffer.c:706
size_t position
Definition: edns.h:78
int dnssec_ok
Definition: edns.h:80
edns_rr_type * edns_rr_create()
Definition: edns.c:50
Definition: edns.h:66
#define DNSSEC_OK_MASK
Definition: edns.h:45
void buffer_set_position(buffer_type *buffer, size_t pos)
Definition: buffer.c:137
int buffer_available(buffer_type *buffer, size_t count)
Definition: buffer.c:487
size_t maxlen
Definition: edns.h:79
void edns_init(edns_data_type *data, uint16_t max_length)
Definition: edns.c:64
#define OPT_LEN
Definition: edns.h:43
size_t edns_rr_reserved_space(edns_rr_type *err)
Definition: edns.c:160
size_t buffer_position(buffer_type *buffer)
Definition: buffer.c:125
unsigned char error[OPT_LEN]
Definition: edns.h:56
unsigned char ok[OPT_LEN]
Definition: edns.h:55
edns_status status
Definition: edns.h:77