「オープンソースハードウェアセミナーVol1」レポート Arduino host by name ライブラリ こっそり公開 [ATmarquino Arduino]
※C++に関しては全く自信が無い。もっと上手な書き方があると思うけれど。知っていたら教えてね。
あと、PROGMEMはやっぱり面倒くさい。
勿論これを動かす為には、既に公開しているUDPライブラリも一緒に用意しておく必要があります。
※追記!以下のネットワーク設定の特殊事情に付いて。
家のネットワークは、通常のネットワークグループの下にネットワークの実験用のネットワークグループが有って、そことはルーターで区切ってあります。今回は192.168.1.0/24にArduino+Ethernet Shieldを設置しているので、このネットワークグループのデフォルトゲートウエイが192.168.1.1になっています。
また、通常ブロードバンド回線の出入り口にはブロードバンドルーターがあるかと思いますが、プライマリDNSはこのルーターとなるので、まず最初の問合せ先が192.168.100.1となっております。
const byte sip[] = { 192, 168, 1, 177 };
const byte gateway[] = { 192, 168, 1, 1 };
const byte Pri_DNS[] = { 192, 168, 100, 1 };
※ご利用は自由ですが、著作権表示の削除、改竄はできません。
Dns.cpp
Dns.h
sampleスケッチ
あと、PROGMEMはやっぱり面倒くさい。
勿論これを動かす為には、既に公開しているUDPライブラリも一緒に用意しておく必要があります。
※追記!以下のネットワーク設定の特殊事情に付いて。
家のネットワークは、通常のネットワークグループの下にネットワークの実験用のネットワークグループが有って、そことはルーターで区切ってあります。今回は192.168.1.0/24にArduino+Ethernet Shieldを設置しているので、このネットワークグループのデフォルトゲートウエイが192.168.1.1になっています。
また、通常ブロードバンド回線の出入り口にはブロードバンドルーターがあるかと思いますが、プライマリDNSはこのルーターとなるので、まず最初の問合せ先が192.168.100.1となっております。
const byte sip[] = { 192, 168, 1, 177 };
const byte gateway[] = { 192, 168, 1, 1 };
const byte Pri_DNS[] = { 192, 168, 100, 1 };
※ご利用は自由ですが、著作権表示の削除、改竄はできません。
Dns.cpp
/* ------------------------------------------------------------------------ */ /* 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 <ctype.h> #include <string.h> #include <stdlib.h> #include <wiring.h> #include <Ethernet.h> #include <Udp.h> #include <avr/pgmspace.h> #include "Dns.h" byte _dnsip[4]; Udp udp = Udp(); const unsigned char PROGMEM head_qa[] = { 0x01,0x00, /* 再帰照会 */ 0x00,0x01, /* 質問数 1 */ 0x00,0x00, /* 回答数 */ 0x00,0x00, /* 権威 */ 0x00,0x00 /* 追加 */ }; const unsigned char PROGMEM tail_qa[] = { 0x00, /* ドメイン名終端 */ 0x00,0x01, /* type A */ 0x00,0x01 /* class INET */ }; const unsigned char PROGMEM repl_head[] = { 0x81, 0x00, /* FLAG: 回答,再帰照会 */ 0x00, 0x01, /* Qnum: 質問数 1 */ 0x00, 0x01, /* Anum: 回答数 1 */ 0x00, 0x00, /* 権威: 0 */ 0x00, 0x00, /* 追加: 0 */ }; Dns::Dns( const byte addr[] ) { memcpy( _dnsip, addr, LENGTHIPV4 ); } /* DNS Aの問い合わせパケットを作成する 返り値はパケットサイズあるいは負のエラーコード */ int Dns::setup_query_pkt( const char *dname, byte buff[] ) { const char *p,*q; int i,len,lid; static int id; /* idをユニークに */ lid = id++; /* ID設定 */ buff[0] = (lid >> 8) & 0xff; buff[1] = lid & 0xff; /* FLAG~ドメイン名以前の設定 */ // memcpy( &buff[2], head_qa, sizeof( head_qa)); memcpy_P( &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) ); memcpy_P( &buff[i], tail_qa, sizeof( tail_qa) ); return i + sizeof( tail_qa ); } int Dns::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 Dns::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 *)_dnsip, 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/ */ /* ------------------------------------------------------------------------ */
Dns.h
#ifndef Dns_h #define Dns_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に失敗 */ typedef uint8_t byte; class Dns { private: byte _dnsip[]; int getaddr_from_pkt( int qid, byte buff[], byte addr[] ); int setup_query_pkt( const char *dname, byte buff[] ); public: Dns( const byte addr[] ); int getaddrbydns( const char *dname, byte addr[] ); }; #endif
sampleスケッチ
#include <Ethernet.h> #include <Dns.h> const byte mac[] = { 0xDE, 0xAD, 0xBE, 0xEF, 0xFE, 0xED }; const byte sip[] = { 192, 168, 1, 177 }; const byte gateway[] = { 192, 168, 1, 1 }; const byte Pri_DNS[] = { 192, 168, 100, 1 }; const char query_hamayan_name[] = "hamayan.ddo.jp"; const char query_google_name[] = "google.com"; Dns dns = Dns( Pri_DNS ); void setup() { int result; byte dip[4]; delay( 1000 ); Ethernet.begin( (uint8_t *)mac, (uint8_t *)sip, (uint8_t *)gateway ); Serial.begin( 38400 ); delay( 3000 ); if( (result = dns.getaddrbydns( query_hamayan_name, dip )) == 0 ) { Serial.print( "IP Adr=" ); Serial.print( dip[0], DEC ); Serial.print( '.' ); Serial.print( dip[1], DEC ); Serial.print( '.' ); Serial.print( dip[2], DEC ); Serial.print( '.' ); Serial.print( dip[3], DEC ); Serial.println(); } else { Serial.print( "NG1 type=" ); Serial.println( result, DEC ); } if( (result = dns.getaddrbydns( query_google_name, dip )) == 0 ) { Serial.print( "IP Adr=" ); Serial.print( dip[0], DEC ); Serial.print( '.' ); Serial.print( dip[1], DEC ); Serial.print( '.' ); Serial.print( dip[2], DEC ); Serial.print( '.' ); Serial.print( dip[3], DEC ); Serial.println(); } else { Serial.print( "NG2 type=" ); Serial.println( result, DEC ); } } void loop() { }
2009-06-09 01:16
nice!(0)
コメント(0)
トラックバック(0)
コメント 0