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