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