1 /* 2 * edns.c -- EDNS definitions (RFC 2671). 3 * 4 * Copyright (c) 2001-2006, NLnet Labs. All rights reserved. 5 * 6 * See LICENSE for the license. 7 * 8 */ 9 10 11 #include "config.h" 12 13 #include <string.h> 14 15 #include "dns.h" 16 #include "edns.h" 17 18 void 19 edns_init_data(edns_data_type *data, uint16_t max_length) 20 { 21 memset(data, 0, sizeof(edns_data_type)); 22 /* record type: OPT */ 23 data->ok[1] = (TYPE_OPT & 0xff00) >> 8; /* type_hi */ 24 data->ok[2] = TYPE_OPT & 0x00ff; /* type_lo */ 25 /* udp payload size */ 26 data->ok[3] = (max_length & 0xff00) >> 8; /* size_hi */ 27 data->ok[4] = max_length & 0x00ff; /* size_lo */ 28 29 data->error[1] = (TYPE_OPT & 0xff00) >> 8; /* type_hi */ 30 data->error[2] = TYPE_OPT & 0x00ff; /* type_lo */ 31 data->error[3] = (max_length & 0xff00) >> 8; /* size_hi */ 32 data->error[4] = max_length & 0x00ff; /* size_lo */ 33 data->error[5] = 1; /* XXX Extended RCODE=BAD VERS */ 34 } 35 36 void 37 edns_init_nsid(edns_data_type *data, uint16_t nsid_len) 38 { 39 /* add nsid length bytes */ 40 data->rdata_nsid[0] = ((OPT_HDR + nsid_len) & 0xff00) >> 8; /* length_hi */ 41 data->rdata_nsid[1] = ((OPT_HDR + nsid_len) & 0x00ff); /* length_lo */ 42 43 /* NSID OPT HDR */ 44 data->nsid[0] = (NSID_CODE & 0xff00) >> 8; 45 data->nsid[1] = (NSID_CODE & 0x00ff); 46 data->nsid[2] = (nsid_len & 0xff00) >> 8; 47 data->nsid[3] = (nsid_len & 0x00ff); 48 } 49 50 void 51 edns_init_record(edns_record_type *edns) 52 { 53 edns->status = EDNS_NOT_PRESENT; 54 edns->position = 0; 55 edns->maxlen = 0; 56 edns->dnssec_ok = 0; 57 edns->nsid = 0; 58 } 59 60 int 61 edns_parse_record(edns_record_type *edns, buffer_type *packet) 62 { 63 /* OPT record type... */ 64 uint8_t opt_owner; 65 uint16_t opt_type; 66 uint16_t opt_class; 67 uint8_t opt_version; 68 uint16_t opt_flags; 69 uint16_t opt_rdlen; 70 uint16_t opt_nsid; 71 72 edns->position = buffer_position(packet); 73 74 if (!buffer_available(packet, (OPT_LEN + OPT_RDATA))) 75 return 0; 76 77 opt_owner = buffer_read_u8(packet); 78 opt_type = buffer_read_u16(packet); 79 if (opt_owner != 0 || opt_type != TYPE_OPT) { 80 /* Not EDNS. */ 81 buffer_set_position(packet, edns->position); 82 return 0; 83 } 84 85 opt_class = buffer_read_u16(packet); 86 (void)buffer_read_u8(packet); /* opt_extended_rcode */ 87 opt_version = buffer_read_u8(packet); 88 opt_flags = buffer_read_u16(packet); 89 opt_rdlen = buffer_read_u16(packet); 90 91 if (opt_version != 0) { 92 /* The only error is VERSION not implemented */ 93 edns->status = EDNS_ERROR; 94 return 1; 95 } 96 97 if (opt_rdlen > 0) { 98 /* there is more to come, read opt code 99 * should be NSID - there are no others */ 100 opt_nsid = buffer_read_u16(packet); 101 edns->nsid = (opt_nsid == NSID_CODE); 102 /* extra check for the value */ 103 } 104 105 edns->status = EDNS_OK; 106 edns->maxlen = opt_class; 107 edns->dnssec_ok = opt_flags & DNSSEC_OK_MASK; 108 return 1; 109 } 110 111 size_t 112 edns_reserved_space(edns_record_type *edns) 113 { 114 /* MIEK; when a pkt is too large?? */ 115 return edns->status == EDNS_NOT_PRESENT ? 0 : (OPT_LEN + OPT_RDATA); 116 } 117