source: azure_iot_hub/trunk/asp3_dcre/tinet/netapp/resolver.c@ 389

Last change on this file since 389 was 389, checked in by coas-nagasima, 5 years ago

ビルドが通るよう更新

  • Property svn:eol-style set to native
  • Property svn:mime-type set to text/x-csrc;charset=UTF-8
File size: 30.3 KB
Line 
1/*
2 * TINET (TCP/IP Protocol Stack)
3 *
4 * Copyright (C) 2001-2017 by Dep. of Computer Science and Engineering
5 * Tomakomai National College of Technology, JAPAN
6 *
7 * 上記著作権者は,以下の (1)~(4) の条件か,Free Software Foundation
8 * によって公表されている GNU General Public License の Version 2 に記
9 * 述されている条件を満たす場合に限り,本ソフトウェア(本ソフトウェア
10 * を改変したものを含む.以下同じ)を使用・複製・改変・再配布(以下,
11 * 利用と呼ぶ)することを無償で許諾する.
12 * (1) 本ソフトウェアをソースコードの形で利用する場合には,上記の著作
13 * 権表示,この利用条件および下記の無保証規定が,そのままの形でソー
14 * スコード中に含まれていること.
15 * (2) 本ソフトウェアを,ライブラリ形式など,他のソフトウェア開発に使
16 * 用できる形で再配布する場合には,再配布に伴うドキュメント(利用
17 * 者マニュアルなど)に,上記の著作権表示,この利用条件および下記
18 * の無保証規定を掲載すること.
19 * (3) 本ソフトウェアを,機器に組み込むなど,他のソフトウェア開発に使
20 * 用できない形で再配布する場合には,次のいずれかの条件を満たすこ
21 * と.
22 * (a) 再配布に伴うドキュメント(利用者マニュアルなど)に,上記の著
23 * 作権表示,この利用条件および下記の無保証規定を掲載すること.
24 * (b) 再配布の形態を,別に定める方法によって,TOPPERSプロジェクトに
25 * 報告すること.
26 * (4) 本ソフトウェアの利用により直接的または間接的に生じるいかなる損
27 * 害からも,上記著作権者およびTOPPERSプロジェクトを免責すること.
28 *
29 * 本ソフトウェアは,無保証で提供されているものである.上記著作権者お
30 * よびTOPPERSプロジェクトは,本ソフトウェアに関して,その適用可能性も
31 * 含めて,いかなる保証も行わない.また,本ソフトウェアの利用により直
32 * 接的または間接的に生じたいかなる損害に関しても,その責任を負わない.
33 *
34 * @(#) $Id$
35 */
36
37/*
38 * ホスト名←→IP アドレス変換
39 */
40
41#include <string.h>
42
43#ifdef TARGET_KERNEL_ASP
44
45#include <kernel.h>
46#include <t_syslog.h>
47#include <target_syssvc.h>
48#define LOGTASK_PORTID SIO_PORTID
49#include "kernel_cfg.h"
50#include "tinet_cfg.h"
51
52#endif /* of #ifdef TARGET_KERNEL_ASP */
53
54#ifdef TARGET_KERNEL_JSP
55
56#include <s_services.h>
57#include <t_services.h>
58#include "kernel_id.h"
59#include "tinet_id.h"
60
61#endif /* of #ifdef TARGET_KERNEL_JSP */
62
63#include <tinet_config.h>
64
65#include <netinet/in.h>
66#include <netinet/in_itron.h>
67
68#include <netapp/netapp.h>
69#include <netapp/netapp_var.h>
70#include <netapp/resolver.h>
71
72#if defined(USE_RESOLVER)
73
74/*
75 * 局所変数
76 */
77
78static uint8_t dns_domain_name[DNS_NAME_LENGTH + 1] = RSLV_CFG_DNS_DOMAIN_NAME_STR;
79
80#if defined(SUPPORT_INET6)
81static T_IN6_ADDR in6_addr_dns = IPV6_ADDR_DNS_INIT;
82static T_IN6_ADDR in6_addr_dns_init = IPV6_ADDR_DNS_INIT;
83#endif
84
85#if defined(SUPPORT_INET4)
86static T_IN4_ADDR in4_addr_dns = IPV4_ADDR_DNS;
87#endif
88
89static uint16_t dns_msg_id = 0;
90
91/*
92 * get_dns_header -- DNS メッセージから DNS ヘッダを取り出す。
93 */
94
95static ER_UINT
96get_dns_header (uint8_t *msg, uint_t length, T_RSLV_DNS_MSG *rslv)
97{
98 T_DNS_HDR *dns_hdr;
99
100 /* DNS ヘッダを取り出す。*/
101 if (length < sizeof(rslv->dns_hdr))
102 return EV_RSLV_ESIZE;
103 dns_hdr = (T_DNS_HDR*)msg;
104 rslv->dns_hdr.id = MSG2HOST16(dns_hdr->id);
105 rslv->dns_hdr.code = MSG2HOST16(dns_hdr->code);
106 rslv->dns_hdr.qdcount = MSG2HOST16(dns_hdr->qdcount);
107 rslv->dns_hdr.ancount = MSG2HOST16(dns_hdr->ancount);
108 rslv->dns_hdr.nscount = MSG2HOST16(dns_hdr->nscount);
109 rslv->dns_hdr.arcount = MSG2HOST16(dns_hdr->arcount);
110 return sizeof(rslv->dns_hdr);
111 }
112
113/*
114 * dns_strtype -- DNS の type の文字列を返す。
115 */
116
117static const char *
118dns_flag_qtype (uint16_t flags)
119{
120 if (flags & DNS_LUP_FLAGS_QTYPE_AAAA)
121 return "AAAA";
122 else if (flags & DNS_LUP_FLAGS_QTYPE_A)
123 return " A";
124 else if (flags & DNS_LUP_FLAGS_QTYPE_PTR)
125 return " PTR";
126 else
127 return "unknown type";
128 }
129
130#if defined(SUPPORT_INET6)
131
132/*
133 * udp6_dns -- UDP/IPv6 により DNS サーバからメッセージを受信する。
134 */
135
136static ER
137udp6_dns (uint16_t flags, T_IN6_ADDR *addr, uint8_t *msg, uint_t msg_size, uint_t length)
138{
139 T_IPV6EP ep_dns;
140 ER_UINT len = E_OK;
141 int retry;
142
143 /* DNS サーバの IPv6 アドレスが未定義の時はパラメータエラー */
144 if (IN6_IS_ADDR_UNSPECIFIED(addr) || (in6_is_addr_ipv4mapped(addr) && addr->s6_addr32[3] == IPV4_ADDRANY)) {
145 syslog(LOG_NOTICE, "[RSLV] undefined IPv6 DNS server address.");
146 return E_PAR;
147 }
148
149 memcpy(&ep_dns.ipaddr, addr, sizeof(*addr));
150 ep_dns.portno = RSLV_CFG_DNS_PORTNO;
151 for (retry = NUM_DNS_UDP_RETRY + 1; retry -- > 0; ) {
152 if ((len = udp6_snd_dat(UDP6_RESOLVER_CEPID, &ep_dns, msg, length, TMO_DNS_UDP_SND)) >= 0) {
153 if ((len = udp6_rcv_dat(UDP6_RESOLVER_CEPID, &ep_dns, msg, msg_size, TMO_DNS_UDP_RCV)) >= 0)
154 return len;
155 }
156 if (flags & DNS_LUP_FLAGS_MSG) {
157 if (len == E_TMOUT)
158 syslog(LOG_NOTICE, "[RSLV] TMOUT: %d, type: %s, server: %s.%d.",
159 NUM_DNS_UDP_RETRY + 1 - retry,
160 dns_flag_qtype(flags),
161 ipv62str(NULL, &ep_dns.ipaddr), ep_dns.portno);
162 else {
163 syslog(LOG_NOTICE, "[RSLV] error: %s, type: %s,\n server: %s.%d.",
164 itron_strerror(len),
165 dns_flag_qtype(flags),
166 ipv62str(NULL, &ep_dns.ipaddr), ep_dns.portno);
167 return len;
168 }
169 }
170 }
171 return E_TMOUT;
172 }
173
174#endif /* of #if defined(SUPPORT_INET6) */
175
176#if defined(SUPPORT_INET4)
177
178/*
179 * udp4_dns -- UDP/IPv4 により DNS サーバからメッセージを受信する。
180 */
181
182static ER
183udp4_dns (uint16_t flags, T_IN4_ADDR *addr, uint8_t *msg, uint_t msg_size, uint_t length)
184{
185 T_IPV4EP ep_dns;
186 ER_UINT len = E_OK;
187 int retry;
188
189 /* DNS サーバの IPv4 アドレスが未定義の時はパラメータエラー */
190 if (*addr == IPV4_ADDRANY) {
191 syslog(LOG_NOTICE, "[RSLV] undefined IPv4 DNS server address.");
192 return E_PAR;
193 }
194
195 memcpy(&ep_dns.ipaddr, addr, sizeof(*addr));
196 ep_dns.portno = RSLV_CFG_DNS_PORTNO;
197 for (retry = NUM_DNS_UDP_RETRY + 1; retry -- > 0; ) {
198 if ((len = udp_snd_dat(UDP4_RESOLVER_CEPID, &ep_dns, msg, length, TMO_DNS_UDP_SND)) >= 0) {
199 if ((len = udp_rcv_dat(UDP4_RESOLVER_CEPID, &ep_dns, msg, msg_size, TMO_DNS_UDP_RCV)) >= 0)
200 return len;
201 }
202 if (flags & DNS_LUP_FLAGS_MSG) {
203 if (len == E_TMOUT)
204 syslog(LOG_NOTICE, "[RSLV] TMOUT: %d, type: %s, server: %s.%d.",
205 NUM_DNS_UDP_RETRY + 1 - retry,
206 dns_flag_qtype(flags),
207 ip2str(NULL, &ep_dns.ipaddr), ep_dns.portno);
208 else {
209 syslog(LOG_NOTICE, "[RSLV] error: %s, type: %s, server: %s.%d.",
210 itron_strerror(len),
211 dns_flag_qtype(flags),
212 ip2str(NULL, &ep_dns.ipaddr), ep_dns.portno);
213 return len;
214 }
215 }
216 }
217 return E_TMOUT;
218 }
219
220#endif /* of #if defined(SUPPORT_INET4) */
221
222/*
223 * skip_label -- ラベルを読み飛ばす。
224 */
225
226static char *
227skip_label (char *name)
228{
229 while (!(*name == '\0' || *name == '.'))
230 name ++;
231 return name;
232 }
233
234/*
235 * add_name -- メッセージに名前を追加する。
236 */
237
238static ER_UINT
239add_name (uint8_t *msg, uint_t size, uint_t offset, char *name)
240{
241 uint_t label_len;
242 uint8_t *tail;
243
244 while (*name != '\0') {
245
246 /* メッセージサイズに達していたらエラー */
247 if (offset + 1 > size)
248 return E_BOVR;
249
250 /* ラベルの終わりを見つける。*/
251 tail = skip_label(name);
252
253 /* ラベル長を設定する。*/
254 label_len = tail - (uint8_t*)name;
255 if (label_len > DNS_LABEL_LENGTH) { /* 63 オクテットを超えるとエラー */
256 syslog(LOG_NOTICE, "[RSLV] label length(%d) too long > %d.",
257 label_len, DNS_LABEL_LENGTH);
258 return E_PAR;
259 }
260
261 *(msg + offset) = (uint8_t)label_len;
262 offset ++;
263
264 /* ラベル名を設定する。*/
265 if (offset + label_len > size) { /* メッセージサイズを超えるとエラー */
266 syslog(LOG_NOTICE, "[RSLV] message length(%d) too long > %d.",
267 offset + label_len, size);
268 return E_BOVR;
269 }
270
271 memcpy((void*)(msg + offset), (void*)name, label_len);
272 offset += label_len;
273
274 /* 次のラベルに移動する。*/
275 if (*tail == '\0')
276 name = tail;
277 else
278 name = tail + 1; /* '.' をスキップする。*/
279 }
280
281 return offset;
282 }
283
284/*
285 * add_ipv6addr -- メッセージに IPv6 アドレスを追加する。
286 */
287
288static ER_UINT
289add_ipv6addr (uint8_t *msg, uint_t size, uint_t offset, char *name)
290{
291 T_IN6_ADDR addr;
292 ER_UINT error;
293 uint_t len;
294 int col;
295 char digit[2];
296
297 len = strlen(name);
298 if (len == 0)
299 return E_PAR;
300
301 digit[1] = '\0';
302 get_ipv6addr(&addr, name);
303 for (col = sizeof(T_IN6_ADDR) * 2; -- col >= 0; ) {
304
305 /* 16進数 1桁の値を、名前として追加する。*/
306 digit[0] = (addr.s6_addr8[col / 2] >> ((1 - (col % 2)) << 2)) & 0x0f;
307 if (digit[0] >= 10)
308 digit[0] += 'a' - 10;
309 else
310 digit[0] += '0';
311 if ((error = add_name(msg, size, offset, digit)) < 0)
312 return error;
313 offset = error;
314 }
315
316 /* "ip6" を追加する。*/
317 if ((error = add_name(msg, size, offset, "ip6")) < 0)
318 return error;
319
320 /* "arpa" を追加する。*/
321 return add_name(msg, size, error, "arpa");
322 }
323
324/*
325 * add_ipv4addr -- メッセージに IPv4 アドレスを追加する。
326 */
327
328static ER_UINT
329add_ipv4addr (uint8_t *msg, uint_t size, uint_t offset, char *name)
330{
331 T_IN4_ADDR addr;
332 ER_UINT error;
333 uint_t len, octet;
334 int col;
335 char *op, ostr[4];
336
337 len = strlen(name);
338 if (len == 0)
339 return E_PAR;
340
341 ostr[3] = '\0';
342 get_ipv4addr(&addr, name);
343 for (col = 0; col < sizeof(T_IN4_ADDR); col ++) {
344
345 /* 1オクテットの値を、整数値からリテラルに変換する。*/
346 octet = (addr >> (col << 3)) & 0xff;
347 op = &ostr[3];
348 while (octet > 0) {
349 *(-- op) = octet % 10 + '0';
350 octet /= 10;
351 }
352
353 /* 1オクテットの値を、名前として追加する。*/
354 if ((error = add_name(msg, size, offset, op)) < 0)
355 return error;
356 offset = error;
357 }
358
359 /* "in-addr" を追加する。*/
360 if ((error = add_name(msg, size, offset, "in-addr")) < 0)
361 return error;
362
363 /* "arpa" を追加する。*/
364 return add_name(msg, size, error, "arpa");
365 }
366
367/*
368 * setup_dns_msg -- DNS メッセージを作成する。
369 */
370
371static ER
372setup_dns_msg (uint16_t flags, char *name, uint8_t *msg, uint_t msg_size)
373{
374 T_DNS_HDR dns_hdr;
375 ER_UINT offset;
376
377 memset((void*)&dns_hdr, 0, sizeof(dns_hdr));
378
379 dns_msg_id++;
380 HOST2MSG16(dns_hdr.id, dns_msg_id);
381 HOST2MSG16(dns_hdr.code, (flags & DNS_OPCODE_MASK) | DNS_RECURSION_DESIRED);
382 HOST2MSG16(dns_hdr.qdcount, 1);
383
384 memcpy((void*)msg, (void*)&dns_hdr, sizeof(dns_hdr));
385 offset = sizeof(dns_hdr);
386
387 switch (flags & DNS_LUP_FLAGS_NAME_MASK) {
388
389 case DNS_LUP_FLAGS_NAME_HOST:
390 case DNS_LUP_FLAGS_NAME_FQDN:
391
392 /* ホスト名、または FQDN の時の処理。*/
393 /* ホスト名を追加する。*/
394 if ((offset = add_name(msg, msg_size, offset, name)) < 0)
395 return offset;
396
397 if (offset - sizeof(dns_hdr) > DNS_NAME_LENGTH) { /* 名前が 255 オクテットを超えるとエラー */
398 syslog(LOG_NOTICE, "[RSLV] name length(%d) too long > %d.",
399 offset - sizeof(dns_hdr), DNS_NAME_LENGTH);
400 return E_PAR;
401 }
402
403 /* ホスト名だけの時は、ドメイン名を追加する。*/
404 if ((flags & DNS_LUP_FLAGS_NAME_MASK) == DNS_LUP_FLAGS_NAME_HOST) {
405
406 /* ドメイン名を追加する。*/
407 if ((offset = add_name(msg, msg_size, offset, dns_domain_name)) < 0)
408 return offset;
409
410 if (offset - sizeof(dns_hdr) > DNS_NAME_LENGTH) { /* 名前が 255 オクテットを超えるとエラー */
411 syslog(LOG_NOTICE, "[RSLV] name length(%d) too long > %d.",
412 offset - sizeof(dns_hdr), DNS_NAME_LENGTH);
413 return E_PAR;
414 }
415 }
416 break;
417
418 case DNS_LUP_FLAGS_NAME_IPV4:
419 if ((offset = add_ipv4addr(msg, msg_size, offset, name)) < 0)
420 return offset;
421 break;
422
423 case DNS_LUP_FLAGS_NAME_IPV6:
424 if ((offset = add_ipv6addr(msg, msg_size, offset, name)) < 0)
425 return offset;
426 break;
427
428 default:
429 syslog(LOG_NOTICE, "[RSLV] unknown name type: %04x.", flags & DNS_LUP_FLAGS_NAME_MASK);
430 return E_PAR;
431 break;
432
433 }
434
435 /* 名前の終了コード、TYPE、CLASS を追加してもメッセージ長を超えないことを確認する。*/
436 if (offset + sizeof(uint16_t) * 2 + 1 > msg_size) {
437 syslog(LOG_NOTICE, "[RSLV] message length(%d) too long > %d.",
438 offset + sizeof(uint16_t) * 2 + 1, msg_size);
439 return E_BOVR;
440 }
441
442 /* 名前の終了コードを設定する。*/
443 *(msg + offset) = '\0';
444 offset ++;
445
446 /* DNS の TYPE を設定する。*/
447 if (flags & DNS_LUP_FLAGS_QTYPE_PTR)
448 host2msg16(msg + offset, DNS_TYPE_PTR);
449 else if (flags & DNS_LUP_FLAGS_QTYPE_AAAA)
450 host2msg16(msg + offset, DNS_TYPE_AAAA);
451 else if (flags & DNS_LUP_FLAGS_QTYPE_A)
452 host2msg16(msg + offset, DNS_TYPE_A);
453 else {
454 syslog(LOG_NOTICE, "[RSLV] unknown query type: %04x.", flags & DNS_LUP_FLAGS_QTYPE_MASK);
455 return E_PAR;
456 }
457 offset += sizeof(uint16_t);
458
459 /* DNS の CLASS を設定する。*/
460 host2msg16(msg + offset, DNS_CLASS_IN);
461
462 return offset + sizeof(uint16_t);
463 }
464
465/*
466 * skip_dns_name -- DNS メッセージの名前を読み飛ばす。
467 *
468 * 注意: 圧縮形式を考慮する。上位 2ビットが 11なら圧縮形式。
469 */
470
471static ER_UINT
472skip_dns_name (uint8_t *name, uint_t offset, uint_t length)
473{
474 while (*(name + offset)) {
475 if ((*(name + offset) & 0xc0) == 0xc0) {
476 if (offset + 2 > length)
477 return EV_RSLV_ESIZE;
478 else
479 return offset + 2;
480 }
481 else if (offset + *name + 1 > length)
482 return EV_RSLV_ESIZE;
483 else
484 offset += *name + 1;
485 }
486 return offset + 1;
487 }
488
489/*
490 * skip_dns_qd -- DNS Question section を読み飛ばす。
491 */
492
493static ER_UINT
494skip_dns_qd (uint8_t *msg, uint_t offset, uint_t length, uint_t count)
495{
496 ER_UINT next;
497
498 while (count != 0) {
499 /* name を読み飛ばす。*/
500 if ((next = skip_dns_name(msg, offset, length)) < 0)
501 return next;
502 offset = next;
503
504 /* type、class を読み飛ばす。*/
505 if ((offset + sizeof(uint16_t) + sizeof(uint16_t)) > length)
506 return EV_RSLV_ESIZE;
507 offset += sizeof(uint16_t) + sizeof(uint16_t);
508
509 count --;
510 }
511
512 return offset;
513 }
514
515/*
516 * skip_dns_rr -- DNS RR を読み飛ばす。
517 */
518
519static ER_UINT
520skip_dns_rr (uint8_t *msg, uint_t offset, uint_t length, uint_t count)
521{
522 ER_UINT next;
523 uint16_t len = 0;
524
525 while (count != 0) {
526 /* name を読み飛ばす。*/
527 if ((next = skip_dns_name(msg, offset, length)) < 0)
528 return next;
529 offset = next;
530
531 /* type、class、TTL を読み飛ばす。*/
532 if (offset + sizeof(uint16_t) + sizeof(uint16_t) + sizeof(uint32_t) > length)
533 return EV_RSLV_ESIZE;
534 offset += sizeof(uint16_t) + sizeof(uint16_t) + sizeof(uint32_t);
535
536 /* RD length と RDATA を読み飛ばす。*/
537 if (offset + sizeof(uint16_t) > length)
538 return EV_RSLV_ESIZE;
539 len = msg2host16(msg + offset);
540
541 if (offset + sizeof(uint16_t) + len > length)
542 return EV_RSLV_ESIZE;
543 offset += sizeof(uint16_t) + len;
544
545 count --;
546 }
547
548 return offset;
549 }
550
551/*
552 * dns_analyze_qd -- DNS メッセージの question section を解析する。
553 */
554
555ER_UINT
556dns_analyze_qd (T_RSLV_QD *qd, uint_t offset, uint8_t *msg, uint_t length)
557{
558 ER_UINT error;
559 T_DNS_QD *dns_qd;
560
561 if ((error = skip_dns_name(msg, offset, length)) < 0)
562 return error;
563 offset = error;
564
565 /* DNS メッセージ内の形式のサイズでチェックする。*/
566 if (offset + T_DNS_QD_SIZE > length)
567 return EV_RSLV_ESIZE;
568
569 /*
570 * DNS メッセージ内の SOA RDATA をバイトオーダーを調整して
571 * 内部構造体にコピーする。
572 */
573 dns_qd = (T_DNS_QD*)(msg + offset);
574 qd->type = MSG2HOST16(dns_qd->type);
575 qd->class = MSG2HOST16(dns_qd->class);
576
577 return offset + T_DNS_QD_SIZE;
578 }
579
580/*
581 * dns_analyze_soa -- DNS メッセージの SOA RDATA を解析する。
582 */
583
584ER_UINT
585dns_analyze_soa (T_RSLV_SOA *soa, uint_t offset, uint8_t *msg, uint_t length)
586{
587 ER_UINT error;
588 T_DNS_SOA *dns_soa;
589
590 /* MNAME をスキップする。*/
591 if ((error = skip_dns_name(msg, offset, length)) < 0)
592 return error;
593 offset = error;
594
595 /* RNAME をスキップする。*/
596 if ((error = skip_dns_name(msg, offset, length)) < 0)
597 return error;
598 offset = error;
599
600 /* DNS メッセージ内の形式のサイズでチェックする。*/
601 if (offset + T_DNS_SOA_SIZE > length)
602 return EV_RSLV_ESIZE;
603
604 /*
605 * DNS メッセージ内の SOA RDATA をバイトオーダーを調整して
606 * 内部構造体にコピーする。
607 */
608 dns_soa = (T_DNS_SOA*)(msg + offset);
609 soa->serial = MSG2HOST32(dns_soa->serial);
610 soa->refresh = MSG2HOST32(dns_soa->refresh);
611 soa->retry = MSG2HOST32(dns_soa->retry);
612 soa->expire = MSG2HOST32(dns_soa->expire);
613 soa->minimum = MSG2HOST32(dns_soa->minimum);
614
615 return offset + T_DNS_SOA_SIZE;
616 }
617
618/*
619 * dns_analyze_rr -- DNS メッセージの AN/NS/AR section を解析する。
620 */
621
622ER_UINT
623dns_analyze_rr (T_RSLV_RR *rr, uint_t offset, uint8_t *msg, uint_t length)
624{
625 ER_UINT error;
626 T_DNS_RR *dns_rr;
627
628 if ((error = skip_dns_name(msg, offset, length)) < 0)
629 return error;
630 offset = error;
631
632 /* DNS メッセージ内の形式のサイズでチェックする。*/
633 if (offset + T_DNS_RR_SIZE > length)
634 return EV_RSLV_ESIZE;
635
636 /*
637 * DNS メッセージ内の SOA RDATA をバイトオーダーを調整して
638 * 内部構造体にコピーする。
639 */
640 dns_rr = (T_DNS_RR*)(msg + offset);
641 rr->type = MSG2HOST16(dns_rr->type);
642 rr->class = MSG2HOST16(dns_rr->class);
643 rr->ttl = MSG2HOST32(dns_rr->ttl);
644 rr->rdlength = MSG2HOST16(dns_rr->rdlength);
645 rr->rdata_offset= offset + sizeof(rr->type) + sizeof(rr->class)
646 + sizeof(rr->ttl) + sizeof(rr->rdlength);
647
648 return offset + T_DNS_RR_SIZE + rr->rdlength;
649 }
650
651/*
652 * analyze_dns_msg -- DNS メッセージを解析する。
653 */
654
655static ER_UINT
656analyze_dns_msg (uint8_t *msg, uint_t length, T_RSLV_DNS_MSG *rslv)
657{
658 ER_UINT offset;
659
660 /* DNS ヘッダを取り出す。*/
661 if ((offset = get_dns_header(msg, length, rslv)) < 0)
662 return offset;
663
664 /* question section を読み飛ばす。*/
665 rslv->qd_offset = offset;
666 if ((offset = skip_dns_qd(msg, offset, length, rslv->dns_hdr.qdcount)) < 0)
667 return offset;
668
669 /* answer section を読み飛ばす。*/
670 rslv->an_offset = offset;
671 if ((offset = skip_dns_rr(msg, offset, length, rslv->dns_hdr.ancount)) < 0)
672 return offset;
673
674 /* authority records section を読み飛ばす。*/
675 rslv->ns_offset = offset;
676 if ((offset = skip_dns_rr(msg, offset, length, rslv->dns_hdr.nscount)) < 0)
677 return offset;
678
679 /* additional records section を読み飛ばす。*/
680 rslv->ar_offset = offset;
681 if ((offset = skip_dns_rr(msg, offset, length, rslv->dns_hdr.arcount)) < 0)
682 return offset;
683
684 return E_OK;
685 }
686
687/*
688 * dns_lookup_host_sub -- DNS によりホストの情報を取得する(補助関数)。
689 */
690
691static ER_UINT
692dns_lookup_host_sub (uint16_t flags, char *hostname, uint8_t *msg,
693 uint_t msg_size, T_RSLV_DNS_MSG *rslv)
694{
695#if defined(SUPPORT_INET6) && defined(SUPPORT_INET4)
696 uint16_t proto;
697#endif
698 ER_UINT length;
699 ER error;
700
701 if ((length = setup_dns_msg(flags, hostname, msg, msg_size)) < 0)
702 return length;
703
704#if defined(SUPPORT_INET6)
705
706#if defined(SUPPORT_INET4)
707
708 if (flags & DNS_LUP_FLAGS_PROTO_IPV6) {
709 proto = DNS_LUP_FLAGS_PROTO_IPV6;
710 if ((length = udp6_dns(flags, &in6_addr_dns, msg, msg_size, length)) < 0)
711 return length;
712 }
713 else if (flags & DNS_LUP_FLAGS_PROTO_IPV4) {
714 proto = DNS_LUP_FLAGS_PROTO_IPV4;
715 if ((length = udp4_dns(flags, &in4_addr_dns, msg, msg_size, length)) < 0)
716 return length;
717 }
718 else {
719 syslog(LOG_NOTICE, "[RSLV] unknown lookup protocol: %04x.", flags & DNS_LUP_FLAGS_PROTO_MASK);
720 return E_PAR;
721 }
722
723#else /* of #if defined(SUPPORT_INET4) */
724
725 if (flags & DNS_LUP_FLAGS_PROTO_IPV6) {
726 if ((length = udp6_dns(flags, &in6_addr_dns, msg, msg_size, length)) < 0)
727 return length;
728 }
729 else {
730 syslog(LOG_NOTICE, "[RSLV] unknown lookup protocol: %04x.", flags & DNS_LUP_FLAGS_PROTO_MASK);
731 return E_PAR;
732 }
733
734#endif /* of #if defined(SUPPORT_INET4) */
735
736#else /* of #if defined(SUPPORT_INET6) */
737
738#if defined(SUPPORT_INET4)
739
740 if (flags & DNS_LUP_FLAGS_PROTO_IPV4) {
741 if ((length = udp4_dns(flags, &in4_addr_dns, msg, msg_size, length)) < 0)
742 return length;
743 }
744 else {
745 syslog(LOG_NOTICE, "[RSLV] unknown lookup protocol: %04x.", flags & DNS_LUP_FLAGS_PROTO_MASK);
746 return E_PAR;
747 }
748
749#endif /* of #if defined(SUPPORT_INET4) */
750
751#endif /* of #if defined(SUPPORT_INET6) */
752
753 if ((error = analyze_dns_msg(msg, length, rslv)) != E_OK)
754 return error;
755 else {
756 if ((rslv->dns_hdr.ancount > 0) && (flags & DNS_LUP_FLAGS_MSG)) {
757
758#if defined(SUPPORT_INET6)
759
760#if defined(SUPPORT_INET4)
761
762 if (proto & DNS_LUP_FLAGS_PROTO_IPV6) {
763 syslog(LOG_NOTICE, "[RSLV] reslv: type: %s, server: %s.%d.",
764 dns_flag_qtype(flags),
765 ipv62str(NULL, &in6_addr_dns),
766 RSLV_CFG_DNS_PORTNO);
767 }
768 else {
769 syslog(LOG_NOTICE, "[RSLV] reslv: type: %s, server: %s.%d.",
770 dns_flag_qtype(flags),
771 ip2str(NULL, &in4_addr_dns),
772 RSLV_CFG_DNS_PORTNO);
773 }
774
775#else /* of #if defined(SUPPORT_INET4) */
776
777 syslog(LOG_NOTICE, "[RSLV] reslv: type: %s, server: %s.%d.",
778 dns_flag_qtype(flags),
779 ipv62str(NULL, &in6_addr_dns),
780 RSLV_CFG_DNS_PORTNO);
781
782#endif /* of #if defined(SUPPORT_INET4) */
783
784#else /* of #if defined(SUPPORT_INET6) */
785
786#if defined(SUPPORT_INET4)
787
788 syslog(LOG_NOTICE, "[RSLV] reslv: type: %s, server: %s.%d.",
789 dns_flag_qtype(flags),
790 ip2str(NULL, &in4_addr_dns),
791 RSLV_CFG_DNS_PORTNO);
792
793#endif /* of #if defined(SUPPORT_INET4) */
794
795#endif /* of #if defined(SUPPORT_INET6) */
796
797 }
798 return length;
799 }
800 }
801
802#if defined(SUPPORT_INET6) && defined(SUPPORT_INET4)
803
804/*
805 * udp64_dns -- DNS/IPv6、DNS/IPv4 により DNS サーバからメッセージを受信する。
806 */
807
808static ER_UINT
809udp64_dns (uint16_t flags, char *hostname, uint8_t *msg,
810 uint_t msg_size, T_RSLV_DNS_MSG *rslv)
811{
812 ER_UINT length;
813 ER error;
814 uint16_t proto;
815
816 /* DNS メッセージを作成する。*/
817 if ((length = setup_dns_msg(flags, hostname, msg, msg_size)) < 0)
818 return length;
819
820 /* UDP/IPv6 の DNS サーバに照会する。*/
821 proto = DNS_LUP_FLAGS_PROTO_IPV6;
822 if ((length = udp6_dns(flags, &in6_addr_dns, msg, msg_size, length)) < 0) {
823 /* UDP/IPv6 の DNS サーバへの照会がエラーになった時は、UDP/IPv4 の DNS サーバに照会する。*/
824 if ((length = setup_dns_msg(flags, hostname, msg, msg_size)) < 0)
825 return length;
826
827 /* UDP/IPv4 の DNS サーバに照会する。*/
828 proto = DNS_LUP_FLAGS_PROTO_IPV4;
829 if ((length = udp4_dns(flags, &in4_addr_dns, msg, msg_size, length)) < 0)
830 return length;
831 }
832
833 /* DNS メッセージを解析する。*/
834 if ((error = analyze_dns_msg(msg, length, rslv)) != E_OK)
835 return error;
836 else {
837 if ((rslv->dns_hdr.ancount > 0) && (flags & DNS_LUP_FLAGS_MSG)) {
838 if (proto & DNS_LUP_FLAGS_PROTO_IPV6) {
839 syslog(LOG_NOTICE, "[RSLV] reslv: type: %s, server: %s.%d.",
840 dns_flag_qtype(flags),
841 ipv62str(NULL, &in6_addr_dns),
842 RSLV_CFG_DNS_PORTNO);
843 }
844 else {
845 syslog(LOG_NOTICE, "[RSLV] reslv: type: %s, server: %s.%d.",
846 dns_flag_qtype(flags),
847 ip2str(NULL, &in4_addr_dns),
848 RSLV_CFG_DNS_PORTNO);
849 }
850 }
851 return length;
852 }
853 }
854
855#endif /* of #if defined(SUPPORT_INET6) && defined(SUPPORT_INET4) */
856
857/*
858 * dns_lookup_host -- DNS によりホストの情報を取得する。
859 */
860
861ER_UINT
862dns_lookup_host (uint16_t flags, char *hostname, uint8_t *msg,
863 uint_t msg_size, T_RSLV_DNS_MSG *rslv)
864{
865 ER error;
866
867#if defined(SUPPORT_INET6) && defined(SUPPORT_INET4)
868
869 if ((flags & DNS_LUP_FLAGS_PROTO_MASK) == (DNS_LUP_FLAGS_PROTO_IPV6 | DNS_LUP_FLAGS_PROTO_IPV4)) {
870
871 /*
872 * IPv6/IPv4 の両方が指定された時の処理
873 * まず type == AAAA で DNS サーバに照会する。
874 */
875 if (flags & DNS_LUP_FLAGS_QTYPE_PTR) {
876 if ((error = udp64_dns(flags, hostname, msg, msg_size, rslv)) < 0)
877 return error;
878 }
879 else if (flags & DNS_LUP_FLAGS_QTYPE_AAAA) {
880 if ((error = udp64_dns(flags & ~DNS_LUP_FLAGS_QTYPE_A, hostname, msg, msg_size, rslv)) < 0)
881 return error;
882 }
883 else {
884 HOST2MSG16(rslv->dns_hdr.ancount, 0);
885 error = E_OK;
886 }
887
888 if (rslv->dns_hdr.ancount == 0) {
889
890 /*
891 * type == AAAA でアドレス解決ができなかった時の処理
892 * type == A で DNS サーバに照会する。
893 */
894 if (flags & DNS_LUP_FLAGS_QTYPE_A)
895 return udp64_dns(flags & ~DNS_LUP_FLAGS_QTYPE_AAAA, hostname, msg, msg_size, rslv);
896 else {
897 syslog(LOG_NOTICE, "[RSLV] unknown query type: %04x.", flags & DNS_LUP_FLAGS_QTYPE_MASK);
898 return E_PAR;
899 }
900 }
901 else
902 return error;
903 }
904
905 if ((flags & DNS_LUP_FLAGS_QTYPE_MASK) == (DNS_LUP_FLAGS_QTYPE_AAAA | DNS_LUP_FLAGS_QTYPE_A)) {
906
907 /*
908 * type == AAAA と A の両方が指定された時の処理
909 * まず type == AAAA で DNS サーバに照会する。
910 */
911 if ((error = dns_lookup_host_sub(flags & ~DNS_LUP_FLAGS_QTYPE_A, hostname, msg, msg_size, rslv)) < 0)
912 return error;
913
914 if (rslv->dns_hdr.ancount == 0) {
915
916 /*
917 * type == AAAA でアドレス解決ができなかった時の処理
918 * type == A で DNS サーバに照会する。
919 */
920 return dns_lookup_host_sub(flags & ~DNS_LUP_FLAGS_QTYPE_AAAA, hostname, msg, msg_size, rslv);
921 }
922#if 0
923 else {
924 syslog(LOG_NOTICE, "[RSLV] unknown query type: %04x.", flags & DNS_LUP_FLAGS_QTYPE_MASK);
925 return E_PAR;
926 }
927#endif
928 }
929
930 else {
931 /* IPv6/IPv4 のどちらか一方が指定された時の処理 */
932 error = dns_lookup_host_sub(flags, hostname, msg, msg_size, rslv);
933 }
934
935#else /* of #if defined(SUPPORT_INET6) && defined(SUPPORT_INET4) */
936
937 error = dns_lookup_host_sub(flags, hostname, msg, msg_size, rslv);
938
939#endif /* of #if defined(SUPPORT_INET6) && defined(SUPPORT_INET4) */
940
941 return error;
942 }
943
944#if defined(SUPPORT_INET6)
945
946/*
947 * dns_in6_set_dname -- DNS の ドメイン名を設定する(DHCPv6用)。
948 *
949 * 注意: new に NULL を指定すると、初期値に戻す。
950 */
951
952const uint8_t *
953dns_in6_set_dname (const uint8_t *new, uint_t len)
954{
955 uint8_t *dst;
956 int label_len, name_len = DNS_NAME_LENGTH;
957
958 if (new == NULL)
959 strcpy(dns_domain_name, RSLV_CFG_DNS_DOMAIN_NAME_STR);
960 else {
961 dst = dns_domain_name;
962 while ((*new != 0) && (name_len > 0) && (len > 0)) {
963 label_len = *new ++;
964 len --;
965 while ((name_len > 0) && (len > 0) && (label_len > 0)) {
966 *dst ++ = *new ++;
967 name_len --;
968 len --;
969 label_len --;
970 }
971 if ((*new != 0) && (name_len > 0)) {
972 *dst ++ = '.';
973 name_len --;
974 }
975 }
976 *dst = '\0';
977 }
978 return dns_domain_name;
979 }
980
981/*
982 * dns_in6_get_dname -- DNS の ドメイン名を得る。
983 */
984
985const uint8_t *
986dns_in6_get_dname (void)
987{
988 return dns_domain_name;
989 }
990
991/*
992 * dns_in6_set_addr -- DNS サーバの IPv6 アドレスを設定する(DHCPv6用)。
993 *
994 * 注意: new に NULL を指定すると、初期値に戻す。
995 */
996
997T_IN6_ADDR *
998dns_in6_set_addr (T_IN6_ADDR *new)
999{
1000 if (new == NULL)
1001 in6_addr_dns = in6_addr_dns_init;
1002 else
1003 in6_addr_dns = *new;
1004 return &in6_addr_dns;
1005 }
1006
1007/*
1008 * dns_in6_get_addr -- DNS サーバの IPv6 アドレスを得る。
1009 */
1010
1011T_IN6_ADDR *
1012dns_in6_get_addr (T_IN6_ADDR *dst)
1013{
1014 if (dst == NULL)
1015 return NULL;
1016 else {
1017 *dst = in6_addr_dns;
1018 return dst;
1019 }
1020 }
1021
1022#endif /* of #if defined(SUPPORT_INET6) */
1023
1024#if defined(SUPPORT_INET4)
1025
1026/*
1027 * dns_in4_set_dname -- DNS の ドメイン名を設定する(DHCPv4用)。
1028 *
1029 * 注意: new に NULL を指定すると、初期値に戻す。
1030 */
1031
1032const uint8_t *
1033dns_in4_set_dname (const uint8_t *new, uint_t len)
1034{
1035 uint8_t *dst;
1036 int name_len = DNS_NAME_LENGTH;
1037
1038 if (new == NULL)
1039 strcpy(dns_domain_name, RSLV_CFG_DNS_DOMAIN_NAME_STR);
1040 else {
1041 dst = dns_domain_name;
1042 while ((name_len -- > 0) && (len -- > 0) && *new)
1043 *dst ++ = *new ++;
1044 *dst = '\0';
1045 }
1046 return dns_domain_name;
1047 }
1048
1049/*
1050 * dns_in4_get_dname -- DNS の ドメイン名を得る。
1051 */
1052
1053const uint8_t *
1054dns_in4_get_dname (void)
1055{
1056 return dns_domain_name;
1057 }
1058
1059/*
1060 * dns_in4_set_addr -- DNS サーバの IPv4 アドレスを設定する(DHCPv4用)。
1061 *
1062 * 注意: new に NULL を指定すると、初期値に戻す。
1063 */
1064
1065T_IN4_ADDR *
1066dns_in4_set_addr (T_IN4_ADDR *new)
1067{
1068 if (new == NULL)
1069 in4_addr_dns = IPV4_ADDR_DNS;
1070 else
1071 in4_addr_dns = *new;
1072 return &in4_addr_dns;
1073 }
1074
1075/*
1076 * dns_in4_get_addr -- DNS サーバの IPv4 アドレスを得る。
1077 */
1078
1079T_IN4_ADDR *
1080dns_in4_get_addr (T_IN4_ADDR *dst)
1081{
1082 if (dst == NULL)
1083 return NULL;
1084 else {
1085 *dst = in4_addr_dns;
1086 return dst;
1087 }
1088 }
1089
1090#endif /* of #if defined(SUPPORT_INET4) */
1091
1092/*
1093 * dns_host_addr -- ホスト名を IP アドレスに変換する。
1094 */
1095
1096ER
1097dns_host_addr (uint16_t flags, char *hostname, T_IN_ADDR *addr)
1098{
1099 T_RSLV_DNS_MSG rslv;
1100 T_RSLV_RR rr;
1101 ER_UINT length, offset;
1102 ER error = E_OK;
1103 int scount;
1104 uint8_t *msg;
1105
1106#if defined(SUPPORT_INET6) && defined(SUPPORT_INET4)
1107
1108 T_IN4_ADDR addr4;
1109
1110#endif /* of #if defined(SUPPORT_INET6) && defined(SUPPORT_INET4) */
1111
1112 if ((error = tget_mpf(MPF_RSLV_SRBUF, (void*)&msg, TMO_FEVR)) != E_OK)
1113 return error;
1114
1115 if ((length = dns_lookup_host(flags, hostname, msg, DNS_UDP_MSG_LENGTH, &rslv)) < 0) {
1116 error = length;
1117 goto err_ret;
1118 }
1119
1120 offset = rslv.an_offset;
1121 for (scount = 1; scount <= rslv.dns_hdr.ancount; scount ++) {
1122 if ((offset = dns_analyze_rr(&rr, offset, msg, length)) < 0) {
1123 error = offset;
1124 goto err_ret;
1125 }
1126
1127#if defined(SUPPORT_INET6)
1128
1129 if (rr.type == DNS_TYPE_AAAA && rr.class == DNS_CLASS_IN && rr.rdlength == sizeof(*addr)) {
1130 memcpy((void*)addr, (void*)(msg + rr.rdata_offset), sizeof(*addr));
1131 break;
1132 }
1133
1134#if defined(SUPPORT_INET4)
1135
1136 if (rr.type == DNS_TYPE_A && rr.class == DNS_CLASS_IN && rr.rdlength == sizeof(addr4)) {
1137 addr4 = msg2host32(msg + rr.rdata_offset);
1138 in6_make_ipv4mapped(addr, addr4);
1139 break;
1140 }
1141
1142#endif /* of #if defined(SUPPORT_INET4) */
1143
1144#else /* of #if defined(SUPPORT_INET6) */
1145
1146#if defined(SUPPORT_INET4)
1147
1148 if (rr.type == DNS_TYPE_A && rr.class == DNS_CLASS_IN && rr.rdlength == sizeof(*addr)) {
1149 *addr = msg2host32((msg + rr.rdata_offset));
1150 break;
1151 }
1152
1153#endif /* of #if defined(SUPPORT_INET4) */
1154
1155#endif /* of #if defined(SUPPORT_INET6) */
1156
1157 }
1158 if (scount > rslv.dns_hdr.ancount)
1159 error = EV_RSLV_UNEXPCT;
1160
1161err_ret:
1162 rel_mpf(MPF_RSLV_SRBUF, (void*)msg);
1163 return error;
1164 }
1165
1166#endif /* of #if defined(USE_RESOLVER) */
Note: See TracBrowser for help on using the repository browser.