1 /* $OpenBSD: dns64_synth.c,v 1.1 2021/01/24 18:29:15 florian Exp $ */ 2 3 /* 4 * dns64/dns64.h - DNS64 module 5 * 6 * Copyright (c) 2009, Viagénie. All rights reserved. 7 * 8 * This software is open source. 9 * 10 * Redistribution and use in source and binary forms, with or without 11 * modification, are permitted provided that the following conditions 12 * are met: 13 * 14 * Redistributions of source code must retain the above copyright notice, 15 * this list of conditions and the following disclaimer. 16 * 17 * Redistributions in binary form must reproduce the above copyright notice, 18 * this list of conditions and the following disclaimer in the documentation 19 * and/or other materials provided with the distribution. 20 * 21 * Neither the name of the NLNET LABS nor the names of its contributors may 22 * be used to endorse or promote products derived from this software without 23 * specific prior written permission. 24 * 25 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 26 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED 27 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 28 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE 29 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 30 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 31 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 32 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 33 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 34 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 35 * POSSIBILITY OF SUCH DAMAGE. 36 */ 37 38 /* 39 * Copyright (c) 2021 Florian Obser <florian@openbsd.org> 40 * 41 * Permission to use, copy, modify, and distribute this software for any 42 * purpose with or without fee is hereby granted, provided that the above 43 * copyright notice and this permission notice appear in all copies. 44 * 45 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES 46 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 47 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR 48 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 49 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 50 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF 51 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 52 */ 53 54 #include <sys/types.h> 55 #include <sys/socket.h> 56 57 #include <netinet/in.h> 58 #include <net/route.h> 59 60 #include <string.h> 61 62 #include "libunbound/config.h" 63 #include "libunbound/util/regional.h" 64 #include "libunbound/util/data/msgencode.h" 65 #include "libunbound/util/data/msgparse.h" 66 #include "libunbound/util/data/msgreply.h" 67 68 #include "log.h" 69 #include "unwind.h" 70 #include "frontend.h" 71 #include "dns64_synth.h" 72 73 extern struct dns64_prefix *dns64_prefixes; 74 extern int dns64_prefix_count; 75 76 static void 77 synthesize_aaaa(const struct in6_addr *in6, int prefixlen, const uint8_t *a, 78 size_t a_len, uint8_t *aaaa, size_t aaaa_len) 79 { 80 size_t i, pos; 81 memcpy(aaaa, in6->s6_addr, sizeof(in6->s6_addr)); 82 for (i = 0, pos = prefixlen / 8; i < a_len && pos < aaaa_len; 83 i++, pos++) { 84 if (pos == 8) 85 aaaa[pos++] = 0; 86 aaaa[pos] = a[i]; 87 } 88 } 89 90 /* 91 * Copied from unbound/dns64/dns64.c and slightly extended to work with more 92 * than one IPv6 prefix. 93 */ 94 95 void 96 dns64_synth_aaaa_data(const struct ub_packed_rrset_key* fk, const struct 97 packed_rrset_data* fd, struct ub_packed_rrset_key *dk, struct 98 packed_rrset_data **dd_out, struct regional *region) 99 { 100 struct packed_rrset_data *dd; 101 size_t i, pos; 102 int j; 103 104 /* 105 * Create synthesized AAAA RR set data. We need to allocated extra 106 * memory for the RRs themselves. Each RR has a length, TTL, pointer to 107 * wireformat data, 2 bytes of data length, and 16 bytes of IPv6 108 * address. 109 */ 110 if(fd->count > RR_COUNT_MAX) { 111 *dd_out = NULL; 112 return; /* integer overflow protection in alloc */ 113 } 114 if (!(dd = *dd_out = regional_alloc(region, sizeof(struct 115 packed_rrset_data) + fd->count * dns64_prefix_count * 116 (sizeof(size_t) + sizeof(time_t) + sizeof(uint8_t*) + 2 + 16)))) { 117 log_warnx("out of memory"); 118 return; 119 } 120 121 /* Copy attributes from A RR set. */ 122 dd->ttl = fd->ttl; 123 dd->count = fd->count * dns64_prefix_count; 124 dd->rrsig_count = 0; 125 dd->trust = fd->trust; 126 dd->security = fd->security; 127 128 /* Synthesize AAAA records. Adjust pointers in structure. */ 129 dd->rr_len = (size_t*)((uint8_t*)dd + sizeof(struct packed_rrset_data)); 130 dd->rr_data = (uint8_t**)&dd->rr_len[dd->count]; 131 dd->rr_ttl = (time_t*)&dd->rr_data[dd->count]; 132 for(i = 0, pos = 0; i < fd->count; ++i) { 133 if (fd->rr_len[i] != 6 || fd->rr_data[i][0] != 0 || 134 fd->rr_data[i][1] != 4) { 135 *dd_out = NULL; 136 return; 137 } 138 for (j = 0; j < dns64_prefix_count; j++, pos++) { 139 dd->rr_len[pos] = 18; 140 dd->rr_ttl[pos] = fd->rr_ttl[i]; 141 dd->rr_data[pos] = (uint8_t*)&dd->rr_ttl[dd->count] + 142 18 * pos; 143 dd->rr_data[pos][0] = 0; 144 dd->rr_data[pos][1] = 16; 145 synthesize_aaaa(&dns64_prefixes[j].in6, 146 dns64_prefixes[j].prefixlen, &fd->rr_data[i][2], 147 fd->rr_len[i]-2, &dd->rr_data[pos][2], 148 dd->rr_len[pos]-2); 149 } 150 } 151 152 /* 153 * Create synthesized AAAA RR set key. This is mostly just bookkeeping, 154 * nothing interesting here. 155 */ 156 if(!dk) { 157 log_warnx("no key"); 158 *dd_out = NULL; 159 return; 160 } 161 162 dk->rk.dname = (uint8_t*)regional_alloc_init(region, fk->rk.dname, 163 fk->rk.dname_len); 164 165 if(!dk->rk.dname) { 166 log_warnx("out of memory"); 167 *dd_out = NULL; 168 return; 169 } 170 171 dk->rk.type = htons(LDNS_RR_TYPE_AAAA); 172 memset(&dk->entry, 0, sizeof(dk->entry)); 173 dk->entry.key = dk; 174 dk->entry.hash = rrset_key_hash(&dk->rk); 175 dk->entry.data = dd; 176 } 177