source: rubycfg_asp/trunk/asp_dcre/tinet/netapp/resolver.c@ 315

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

SVNプロパティを設定

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