Contiki-NG
Loading...
Searching...
No Matches
ip64-dns64.c
1/*
2 * Copyright (c) 2014, Thingsquare, http://www.thingsquare.com/.
3 * All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
8 * 1. Redistributions of source code must retain the above copyright
9 * notice, this list of conditions and the following disclaimer.
10 * 2. Redistributions in binary form must reproduce the above copyright
11 * notice, this list of conditions and the following disclaimer in the
12 * documentation and/or other materials provided with the distribution.
13 * 3. Neither the name of the copyright holder nor the names of its
14 * contributors may be used to endorse or promote products derived
15 * from this software without specific prior written permission.
16 *
17 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
18 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
19 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
20 * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
21 * COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
22 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
23 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
24 * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
25 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
26 * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
27 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
28 * OF THE POSSIBILITY OF SUCH DAMAGE.
29 *
30 */
31
32#include "ip64/ip64.h"
33#include "ipv6/ip64-addr.h"
34#include "ip64/ip64-dns64.h"
35
36/*---------------------------------------------------------------------------*/
37
38#include "sys/log.h"
39#define LOG_MODULE "IP64"
40#define LOG_LEVEL LOG_LEVEL_IP64
41
42/*---------------------------------------------------------------------------*/
43
44struct dns_hdr {
45 uint8_t id[2];
46 uint8_t flags1, flags2;
47#define DNS_FLAG1_RESPONSE 0x80
48#define DNS_FLAG1_OPCODE_STATUS 0x10
49#define DNS_FLAG1_OPCODE_INVERSE 0x08
50#define DNS_FLAG1_OPCODE_STANDARD 0x00
51#define DNS_FLAG1_AUTHORATIVE 0x04
52#define DNS_FLAG1_TRUNC 0x02
53#define DNS_FLAG1_RD 0x01
54#define DNS_FLAG2_RA 0x80
55#define DNS_FLAG2_ERR_MASK 0x0f
56#define DNS_FLAG2_ERR_NONE 0x00
57#define DNS_FLAG2_ERR_NAME 0x03
58 uint8_t numquestions[2];
59 uint8_t numanswers[2];
60 uint8_t numauthrr[2];
61 uint8_t numextrarr[2];
62};
63
64#define DNS_QUESTION_TYPE0 0
65#define DNS_QUESTION_TYPE1 1
66#define DNS_QUESTION_CLASS0 2
67#define DNS_QUESTION_CLASS1 3
68#define DNS_QUESTION_SIZE 4
69
70struct dns_answer {
71 /* DNS answer record starts with either a domain name or a pointer
72 * to a name already present somewhere in the packet. */
73 uint8_t type[2];
74 uint8_t class[2];
75 uint8_t ttl[4];
76 uint8_t len[2];
77 union {
78 uint8_t ip6[16];
79 uint8_t ip4[4];
80 } addr;
81};
82
83#define DNS_TYPE_A 1
84#define DNS_TYPE_AAAA 28
85
86#define DNS_CLASS_IN 1
87#define DNS_CLASS_ANY 255
88
89/*---------------------------------------------------------------------------*/
90void
91ip64_dns64_6to4(const uint8_t *ipv6data, int ipv6datalen,
92 uint8_t *ipv4data, int ipv4datalen)
93{
94 int i, j;
95 int qlen;
96 uint8_t *qdata;
97 uint8_t *q;
98 struct dns_hdr *hdr;
99
100 hdr = (struct dns_hdr *)ipv4data;
101 LOG_DBG("dns64_6to4 id: %02x%02x\n", hdr->id[0], hdr->id[1]);
102 LOG_DBG("dns64_6to4 flags1: 0x%02x\n", hdr->flags1);
103 LOG_DBG("ip64_dns64_6to4 flags2: 0x%02x\n", hdr->flags2);
104 LOG_DBG("dns64_6to4 numquestions: 0x%02x\n",
105 ((hdr->numquestions[0] << 8) + hdr->numquestions[1]));
106 LOG_DBG("dns64_6to4 numanswers: 0x%02x\n",
107 ((hdr->numanswers[0] << 8) + hdr->numanswers[1]));
108 LOG_DBG("dns64_6to4 numauthrr: 0x%02x\n",
109 ((hdr->numauthrr[0] << 8) + hdr->numauthrr[1]));
110 LOG_DBG("dns64_6to4 numextrarr: 0x%02x\n",
111 ((hdr->numextrarr[0] << 8) + hdr->numextrarr[1]));
112
113 /* Find the DNS question header by scanning through the question
114 labels. */
115 qdata = ipv4data + sizeof(struct dns_hdr);
116 for(i = 0; i < ((hdr->numquestions[0] << 8) + hdr->numquestions[1]); i++) {
117 do {
118 qlen = *qdata;
119 qdata++;
120 for(j = 0; j < qlen; j++) {
121 qdata++;
122 if(qdata > ipv4data + ipv4datalen) {
123 LOG_WARN("dns64_6to4: Packet ended while parsing\n");
124 return;
125 }
126 }
127 } while(qlen != 0);
128 q = qdata;
129 if(q[DNS_QUESTION_CLASS0] == 0 && q[DNS_QUESTION_CLASS1] == DNS_CLASS_IN &&
130 q[DNS_QUESTION_TYPE0] == 0 && q[DNS_QUESTION_TYPE1] == DNS_TYPE_AAAA) {
131 q[DNS_QUESTION_TYPE1] = DNS_TYPE_A;
132 }
133
134 qdata += DNS_QUESTION_SIZE;
135 }
136}
137/*---------------------------------------------------------------------------*/
138int
139ip64_dns64_4to6(const uint8_t *ipv4data, int ipv4datalen,
140 uint8_t *ipv6data, int ipv6datalen)
141{
142 uint8_t n;
143 int i, j;
144 int qlen, len;
145 const uint8_t *qdata, *adata;
146 uint8_t *qcopy, *acopy, *lenptr;
147 uint8_t *q;
148 struct dns_hdr *hdr;
149
150 hdr = (struct dns_hdr *)ipv4data;
151 LOG_DBG("dns64_4to6 id: %02x%02x\n", hdr->id[0], hdr->id[1]);
152 LOG_DBG("dns64_4to6 flags1: 0x%02x\n", hdr->flags1);
153 LOG_DBG("dns64_4to6 flags2: 0x%02x\n", hdr->flags2);
154 LOG_DBG("dns64_4to6 numquestions: 0x%02x\n",
155 ((hdr->numquestions[0] << 8) + hdr->numquestions[1]));
156 LOG_DBG("dns64_4to6 numanswers: 0x%02x\n",
157 ((hdr->numanswers[0] << 8) + hdr->numanswers[1]));
158 LOG_DBG("dns64_4to6 numauthrr: 0x%02x\n",
159 ((hdr->numauthrr[0] << 8) + hdr->numauthrr[1]));
160 LOG_DBG("dns64_4to6 numextrarr: 0x%02x\n",
161 ((hdr->numextrarr[0] << 8) + hdr->numextrarr[1]));
162
163 /* Find the DNS answer header by scanning through the question
164 labels. */
165 qdata = ipv4data + sizeof(struct dns_hdr);
166 qcopy = ipv6data + sizeof(struct dns_hdr);
167 for(i = 0; i < ((hdr->numquestions[0] << 8) + hdr->numquestions[1]); i++) {
168 do {
169 qlen = *qdata;
170 qdata++;
171 qcopy++;
172 for(j = 0; j < qlen; j++) {
173 qdata++;
174 qcopy++;
175 if(qdata > ipv4data + ipv4datalen) {
176 LOG_WARN("dns64_4to6: packet ended while parsing\n");
177 return ipv6datalen;
178 }
179 }
180 } while(qlen != 0);
181 q = qcopy;
182 if(q[DNS_QUESTION_CLASS0] == 0 && q[DNS_QUESTION_CLASS1] == DNS_CLASS_IN &&
183 q[DNS_QUESTION_TYPE0] == 0 && q[DNS_QUESTION_TYPE1] == DNS_TYPE_AAAA) {
184 q[DNS_QUESTION_TYPE1] = DNS_TYPE_AAAA;
185 }
186
187 qdata += DNS_QUESTION_SIZE;
188 qcopy += DNS_QUESTION_SIZE;
189 }
190
191 adata = qdata;
192 acopy = qcopy;
193
194 /* Go through the answers section and update the answers. */
195 for(i = 0; i < ((hdr->numanswers[0] << 8) + hdr->numanswers[1]); i++) {
196
197 n = *adata;
198 if(n & 0xc0) {
199 /* Short-hand name format: 2 bytes */
200 *acopy++ = *adata++;
201 *acopy++ = *adata++;
202 } else {
203 /* Name spelled out */
204 do {
205 n = *adata;
206 adata++;
207 acopy++;
208 for(j = 0; j < n; j++) {
209 *acopy++ = *adata++;
210 }
211 } while(n != 0);
212 }
213
214 if(adata[0] == 0 && adata[1] == DNS_TYPE_A) {
215 /* Update the type field from A to AAAA */
216 *acopy = *adata;
217 acopy++;
218 adata++;
219 *acopy = DNS_TYPE_AAAA;
220 acopy++;
221 adata++;
222
223 /* Get the length of the address record. Should be 4. */
224 lenptr = &acopy[6];
225 len = (adata[6] << 8) + adata[7];
226
227 /* Copy the class, the TTL, and the data length */
228 memcpy(acopy, adata, 2 + 4 + 2);
229 acopy += 8;
230 adata += 8;
231
232 if(len == 4) {
234 uip_ipaddr(&addr, adata[0], adata[1], adata[2], adata[3]);
235 ip64_addr_4to6(&addr, (uip_ip6addr_t *)acopy);
236
237 adata += len;
238 acopy += 16;
239 lenptr[0] = 0;
240 lenptr[1] = 16;
241 ipv6datalen += 12;
242
243 } else {
244 memcpy(acopy, adata, len);
245 acopy += len;
246 adata += len;
247 }
248 } else {
249 len = (adata[8] << 8) + adata[9];
250
251 /* Copy the type, class, the TTL, and the data length */
252 memcpy(acopy, adata, 2 + 2 + 4 + 2);
253 acopy += 10;
254 adata += 10;
255
256 /* Copy the data */
257 memcpy(acopy, adata, len);
258 acopy += len;
259 adata += len;
260 }
261 }
262 return ipv6datalen;
263}
264/*---------------------------------------------------------------------------*/
#define uip_ipaddr(addr, addr0, addr1, addr2, addr3)
Construct an IP address from four bytes.
Definition uip.h:898
Header file for the logging system.
static uip_ds6_addr_t * addr
Pointer to a nbr cache entry.
Definition uip-nd6.c:107
Representation of an IP address.
Definition uip.h:95