「オープンソースハードウェアセミナーVol1」レポート Arduino Ethernet Shieldでインターネットから名前を引こう DNSの実現 [ATmarquino Arduino]
しまった。「名前を引こう!」では逆引きみたいだな。
結構この機能欲しい人も多い筈!。
元々DNSの正引き機能は、HOS上にプロトコルスタックを載せたNavajoのUDPアプリケーションの一つとして、HOSの開発メンバーであるm-arai氏に作ってもらい、その後Project-HOSの著作物となったものです。
それをArduino用に載せ換えました。
なので、このプログラムの二次利用は自由ですが、著作権表示の削除や改竄はしないでくださいね。
今回UDPの機能を実現したのでやってみました。スケッチは下の方に掲載して置きます。
上の図はDOS窓からnslookupを行って正引きを行った結果です。
下は勿論Arduino上で実行した結果です。
ね!、引けているでしょう。
今までこのDNS正引きを使った感触ですが、結構引けます。でも完全に引ける訳ではないのも事実です。
その辺に注意して使ってね。
元々DNSの正引き機能は、HOS上にプロトコルスタックを載せたNavajoのUDPアプリケーションの一つとして、HOSの開発メンバーであるm-arai氏に作ってもらい、その後Project-HOSの著作物となったものです。
それをArduino用に載せ換えました。
なので、このプログラムの二次利用は自由ですが、著作権表示の削除や改竄はしないでくださいね。
今回UDPの機能を実現したのでやってみました。スケッチは下の方に掲載して置きます。
上の図はDOS窓からnslookupを行って正引きを行った結果です。
下は勿論Arduino上で実行した結果です。
ね!、引けているでしょう。
今までこのDNS正引きを使った感触ですが、結構引けます。でも完全に引ける訳ではないのも事実です。
その辺に注意して使ってね。
/* ------------------------------------------------------------------------ */ /* Hyper Operating System V4 */ /* test program for Navajo */ /* お題: いい加減なDNS IPアドレス正引き */ /* */ /* このプログラムは、m-arai氏の好意で、Project HOSの著作物となりました。 */ /* Copyright (C) 1998-2004 by Project HOS */ /* http://sourceforge.jp/projects/hos/ */ /* ------------------------------------------------------------------------ */ #include <Ethernet.h> #include <ctype.h> #include <string.h> #include <stdlib.h> #define DNS_PSIZE 512 #define DNS_PORT 53 #define LENGTHIPV4 4 #define E_LONG (-1) /* ドメイン名が長過ぎる */ #define E_BADID (-2) /* 回答のIDが違う */ #define E_BADHD (-3) /* 回答のヘッダ部が正常でない */ #define E_SNDFAIL (-4) /* なんか知らんがUDPsendに失敗 */ #define E_SCKFAIL (-5) /* なんか知らんがUDPsocketに失敗 */ const byte mac[] = { 0xDE, 0xAD, 0xBE, 0xEF, 0xFE, 0xED }; const byte ip[] = { 192, 168, 100, 177 }; const byte gateway[] = { 192, 168, 100, 1 }; const byte DomainNameServer[] = { 192, 168, 100, 1 }; const char query_hamayan_name[] = "hamayan.ddo.jp"; const char query_google_name[] = "google.com"; static const byte head_qa[] = { 0x01,0x00, /* 再帰照会 */ 0x00,0x01, /* 質問数 1 */ 0x00,0x00, /* 回答数 */ 0x00,0x00, /* 権威 */ 0x00,0x00 /* 追加 */ }; static const byte tail_qa[] = { 0x00, /* ドメイン名終端 */ 0x00,0x01, /* type A */ 0x00,0x01 /* class INET */ }; static const byte repl_head[] = { 0x81, 0x00, /* FLAG: 回答,再帰照会 */ 0x00, 0x01, /* Qnum: 質問数 1 */ 0x00, 0x01, /* Anum: 回答数 1 */ 0x00, 0x00, /* 権威: 0 */ 0x00, 0x00, /* 追加: 0 */ }; static int id; Udp udp = Udp(); /*UDP socketの生成*/ void setup() { byte addr[4]; Ethernet.begin( (uint8_t *)mac, (uint8_t *)ip, (uint8_t *)gateway ); Serial.begin( 38400 ); delay( 3000 ); /*シリアルモニタへの切り替え時間分、待ちを入れてある*/ getaddrbydns( query_hamayan_name, addr ); Serial.print( "ip=" ); for( int i = 0; i < sizeof(addr) / sizeof(addr[0]); i++ ) { Serial.print( addr[i], DEC ); Serial.print( "." ); } Serial.println(); delay( 100 ); getaddrbydns( query_google_name, addr ); Serial.print( "ip=" ); for( int i = 0; i < sizeof(addr) / sizeof(addr[0]); i++ ) { Serial.print( addr[i], DEC ); Serial.print( "." ); } Serial.println(); } void loop() { } /* DNS Aの問い合わせパケットを作成する 返り値はパケットサイズあるいは負のエラーコード */ int setup_query_pkt( const char *dname, byte buff[] ) { const char *p,*q; int i,len,lid; /* idをユニークに */ lid = id++; /* ID設定 */ buff[0] = (lid >> 8) & 0xff; buff[1] = lid & 0xff; /* FLAG~ドメイン名以前の設定 */ memcpy( &buff[2], head_qa, sizeof( head_qa)); for( i = 12, p = dname;*p != '\0'; i += len, p = q + 1 ) { /* 次の'.'又は文末の検索 */ for( q = p; *q != '.' && *q != '\0'; q++ ) ; /* パケット溢れチェック */ if( (len = q-p)+i > DNS_PSIZE-5) { return E_LONG; } buff[i++] = len; /* 文字列コピー */ strncpy( (char *)&buff[i], p, len); if (*q=='\0') { i += len; break; } } /* ドメイン名終端~パケット終了の設定 */ memcpy( &buff[i], tail_qa, sizeof( tail_qa) ); return i + sizeof( tail_qa ); } int getaddr_from_pkt( int qid, byte buff[], byte addr[] ) { int i; /* 回答のIDが合致しているかチェック */ if( qid != ((buff[0] << 8) + buff[1]) ) { return E_BADID; } /* ヘッダ部が正常回答がチェック 2009/6/8 修正:一つの質問に複数の回答があるケースに対応させる為*/ if( ((buff[2] & 0xfb) != 0x81) || ((buff[3] & 0x0f) != 0) || ((buff[4] << 8) + buff[5]) != 1 ) { return E_BADHD; } /* ドメインの終端を探す */ for( i = 12; buff[i] != '\0'; i++ ) ; /* もうこの後,回答のタイプは一切チェックしない */ if( ( buff[i+5] & 0xc0) == 0xc0 ) { /* ドメインは圧縮されている */ memcpy( addr, &buff[ i + 17], LENGTHIPV4 ); } else { /* 多分有り得ないが,圧縮されていない */ /* ドメイン終端を検索 */ for( i = i + 6; buff[i] != '\0'; i++ ) ; memcpy( addr, &buff[i + 11], LENGTHIPV4 ); } return 0; } int getaddrbydns( const char *dname, byte addr[] ) { int ssz,ret,qid; byte server_ip[4]; uint16 dport; byte *buff; /*UDPソケットOPEN*/ if( !udp.Open() ) return E_SCKFAIL; /* 共有メモリからDNSパケットバッファ用メモリを取得 */ buff = (byte *)malloc( DNS_PSIZE ); /* DNS A問い合わせパケット作成 */ ssz = setup_query_pkt( dname, buff); qid = ( buff[0] << 8 ) + buff[1]; /* パケット送信 */ udp.sendTo( (const uint8 *)buff, ssz, (uint8 *)DomainNameServer, DNS_PORT ); delay( 100 ); while( udp.recvFrom( (uint8 *)buff, DNS_PSIZE, (uint8 *)server_ip, &dport ) == (-1) ) delay( 10 ); /* 回答からIPアドレスを取得する */ ret = getaddr_from_pkt( qid, buff, (byte *)addr ); /* DNSパケットバッファ用メモリを解放 */ free( buff ); /*ソケットのクローズ*/ udp.Close(); return ret; } /* ------------------------------------------------------------------------ */ /* Copyright (C) 1998-2004 by Project HOS */ /* http://sourceforge.jp/projects/hos/ */ /* ------------------------------------------------------------------------ */
2009-06-06 15:11
nice!(0)
コメント(0)
トラックバック(0)
コメント 0