115 if(len < DNS_HDR_SIZE) {
119 qdcount = RD16(&data[DNS_HDR_QDCOUNT]);
120 p = data + DNS_HDR_SIZE;
123 LOG_DBG(
"DNS64 6to4: id=0x%04x, %u questions\n",
124 RD16(&data[DNS_HDR_ID]), qdcount);
127 for(uint16_t i = 0; i < qdcount; i++) {
128 const uint8_t *after_name = skip_dns_name(p, end);
129 if(after_name == NULL || after_name + DNS_QTAIL_SIZE > end) {
130 LOG_WARN(
"DNS64 6to4: malformed question section\n");
134 uint8_t *qtail = (uint8_t *)after_name;
135 if(RD16(&qtail[DNS_QTAIL_QTYPE]) == DNS_TYPE_AAAA &&
136 RD16(&qtail[DNS_QTAIL_QCLASS]) == DNS_CLASS_IN) {
137 WR16(&qtail[DNS_QTAIL_QTYPE], DNS_TYPE_A);
139 p = qtail + DNS_QTAIL_SIZE;
145 uint8_t *ipv6data, uint16_t ipv6len,
148 uint16_t qdcount, ancount;
151 const uint8_t *src_end;
152 const uint8_t *dst_end = ipv6data + ipv6bufsiz;
154 if(ipv4len < DNS_HDR_SIZE) {
158 qdcount = RD16(&ipv4data[DNS_HDR_QDCOUNT]);
159 ancount = RD16(&ipv4data[DNS_HDR_ANCOUNT]);
160 src = ipv4data + DNS_HDR_SIZE;
161 dst = ipv6data + DNS_HDR_SIZE;
162 src_end = ipv4data + ipv4len;
164 LOG_DBG(
"DNS64 4to6: id=0x%04x, %u answers\n",
165 RD16(&ipv4data[DNS_HDR_ID]), ancount);
169 for(uint16_t i = 0; i < qdcount; i++) {
170 const uint8_t *after_name = skip_dns_name(src, src_end);
171 if(after_name == NULL || after_name + DNS_QTAIL_SIZE > src_end) {
175 dst = ipv6data + (after_name - ipv4data);
176 if(RD16(&dst[DNS_QTAIL_QTYPE]) == DNS_TYPE_A &&
177 RD16(&dst[DNS_QTAIL_QCLASS]) == DNS_CLASS_IN) {
178 WR16(&dst[DNS_QTAIL_QTYPE], DNS_TYPE_AAAA);
180 src = after_name + DNS_QTAIL_SIZE;
181 dst = ipv6data + (src - ipv4data);
190 uint16_t emitted_ancount = 0;
194 uint8_t *rr_start = dst;
195 for(uint16_t i = 0; i < ancount; i++) {
199 const uint8_t *name_end = skip_dns_name(src, src_end);
200 if(name_end == NULL) {
203 size_t name_len = name_end - src;
204 if(dst + name_len > dst_end) {
205 LOG_WARN(
"DNS64 4to6: output buffer full at name copy\n");
208 memcpy(dst, src, name_len);
213 if(src + 10 > src_end) {
217 uint16_t rr_type = RD16(&src[0]);
218 uint16_t rdlength = RD16(&src[8]);
220 if(rr_type == DNS_TYPE_A && rdlength == 4 && src + 10 + 4 <= src_end) {
223 if(dst + 10 + 16 > dst_end) {
224 LOG_WARN(
"DNS64 4to6: output buffer full\n");
227 WR16(&dst[0], DNS_TYPE_AAAA);
228 memcpy(&dst[2], &src[2], 2 + 4);
236 ip64_addr_4to6(&a4, (uip_ip6addr_t *)dst);
242 size_t rr_total = 10 + rdlength;
243 if(src + rr_total > src_end) {
246 if(dst + rr_total > dst_end) {
247 LOG_WARN(
"DNS64 4to6: output buffer full\n");
250 memcpy(dst, src, rr_total);
263 WR16(&ipv6data[DNS_HDR_ANCOUNT], emitted_ancount);
266 WR16(&ipv6data[DNS_HDR_NSCOUNT], 0);
267 WR16(&ipv6data[DNS_HDR_ARCOUNT], 0);
268 return (uint16_t)(dst - ipv6data);