This is Webservice SDK for mbed. LPCXpresso1769/LPC1768/FRDM-K64F/LPC4088

Dependents:   MbedFileServer_1768MiniDK2 RedWireBridge IssueDebug_gcc MiMicRemoteMCU-for-Mbed ... more

Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers NyLPC_cMDnsServer.c Source File

NyLPC_cMDnsServer.c

00001 /*********************************************************************************
00002  * PROJECT: MiMic
00003  * --------------------------------------------------------------------------------
00004  *
00005  * This file is part of MiMic
00006  * Copyright (C)2011 Ryo Iizuka
00007  *
00008  * MiMic is free software: you can redistribute it and/or modify
00009  * it under the terms of the GNU Lesser General Public License as published
00010  * by the Free Software Foundation, either version 3 of the License, or
00011  * (at your option) any later version.
00012  *
00013  * This program is distributed in the hope that it will be useful,
00014  * but WITHOUT ANY WARRANTY; without even the implied warranty of
00015  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00016  * GNU General Public License for more details.
00017  *
00018  * You should have received a copy of the GNU Lesser General Public License
00019  * along with this program.  If not, see <http://www.gnu.org/licenses/>.
00020  *
00021  * For further information please contact.
00022  *  http://nyatla.jp/
00023  *  <airmail(at)ebony.plala.or.jp> or <nyatla(at)nyatla.jp>
00024  *
00025  *********************************************************************************/
00026 #include "NyLPC_cMDnsServer.h"
00027 #include "NyLPC_netif.h"
00028 #include "NyLPC_http.h"
00029 #include "NyLPC_utils.h"
00030 #include <stdio.h>
00031 #include <string.h>
00032 
00033 
00034 /**
00035  * mDNSのポート番号
00036  */
00037 #define MDNS_MCAST_PORT         5353
00038 static const struct NyLPC_TIPv4Addr MDNS_MCAST_IPADDR = NyLPC_TIPv4Addr_pack(224, 0, 0, 251);
00039 #define TIMEOUT_IN_MS       1000
00040 #define NyLPC_TcMDns_RES_TTL (120)    //120
00041 #define NyLPC_TcMDns_STD_TTL (30*60)  //(30min
00042 
00043 
00044 struct NyLPC_TDnsHeader
00045 {
00046     NyLPC_TUInt16 id;
00047     NyLPC_TUInt16 flag;
00048     NyLPC_TUInt16 qd;
00049     NyLPC_TUInt16 an;
00050     NyLPC_TUInt16 ns;
00051     NyLPC_TUInt16 ar;
00052 }PACK_STRUCT_END;
00053 
00054 #define NyLPC_TDnsHeader_FLAG_MASK_QR     0x8000
00055 #define NyLPC_TDnsHeader_FLAG_MASK_OPCODE 0x7800
00056 #define NyLPC_TDnsHeader_FLAG_MASK_AA     0x0400
00057 #define NyLPC_TDnsHeader_FLAG_MASK_TC     0x0200
00058 #define NyLPC_TDnsHeader_FLAG_MASK_RD     0x0100
00059 #define NyLPC_TDnsHeader_FLAG_MASK_RA     0x0080
00060 #define NyLPC_TDnsHeader_FLAG_MASK_Z      0x0070
00061 #define NyLPC_TDnsHeader_FLAG_MASK_RECODE 0x000F
00062 
00063 struct NyLPC_TDnsQuestion
00064 {
00065     const char* buf;        //Questionパケットの先頭
00066     NyLPC_TUInt16 buf_len;  //パケット長さ
00067     NyLPC_TUInt16 qtype;
00068     NyLPC_TUInt16 qclass;
00069     NyLPC_TInt16 qname_pos;//Qnameの開始位置
00070 };
00071 
00072 #define NyLPC_TDnsQuestion_QTYPR_A      1
00073 #define NyLPC_TDnsQuestion_QTYPR_NS     2
00074 #define NyLPC_TDnsQuestion_QTYPR_CNAME  5
00075 #define NyLPC_TDnsQuestion_QTYPR_SOA    6
00076 #define NyLPC_TDnsQuestion_QTYPR_PTR    12
00077 #define NyLPC_TDnsQuestion_QTYPR_MX     15
00078 #define NyLPC_TDnsQuestion_QTYPR_TXT    16
00079 #define NyLPC_TDnsQuestion_QTYPR_ANY    255
00080 #define NyLPC_TDnsQuestion_QTYPR_AAAA   28
00081 #define NyLPC_TDnsQuestion_QTYPR_NSEC   47
00082 #define NyLPC_TDnsQuestion_QCLASS_IN    1
00083 #define NyLPC_TDnsQuestion_QCLASS_CH    3
00084 #define NyLPC_TDnsQuestion_QCLASS_HS    4
00085 #define NyLPC_TDnsQuestion_QTYPR_SRV    33
00086 #define NyLPC_TDnsQuestion_QCLASS_CACHE_FLUSH  0x8000
00087 
00088 
00089 /**************************************************
00090 * TLabelCache
00091 **************************************************/
00092 /**
00093  * nameフィールドの文字列圧縮を解除して圧縮後のテキストポインタを返します。
00094  */
00095 static const char* getExtractNamePos(const char* i_packet_buf, const char* i_spos)
00096 {
00097     NyLPC_TUInt8 limit = 0;
00098     const char* s = i_spos;// question->buf + pos;//クエリの解析位置
00099     for (;;){
00100         switch (*(const NyLPC_TUInt8*)s){
00101         case 0x00:
00102             //queryが先に終了に到達するのはおかしい。
00103             return NULL;
00104         case 0xc0:
00105             s = i_packet_buf + *((const NyLPC_TUInt8*)s + 1);//参照先にジャンプ
00106             if (i_spos <= s){
00107                 //後方参照ならエラー
00108                 return NULL;
00109             }
00110             limit++;
00111             if (limit > 32){
00112                 return NULL;
00113             }
00114             continue;
00115         default:
00116             break;
00117         }
00118         break;
00119     }
00120     return s;
00121 }
00122 
00123 /**
00124  * 展開しない圧縮文字列の長さを返す
00125  */
00126 static NyLPC_TInt16 sizeofCompressName(const char* i_str)
00127 {
00128     NyLPC_TInt16 l = 0;
00129     NyLPC_TUInt8 c;
00130     for (;;){
00131         c = (NyLPC_TUInt8)*(i_str + l);
00132         switch (c){
00133         case 0xc0:
00134             return l + 2;
00135         case 0x00:
00136             return l + 1;
00137         }
00138         l += c + 1;
00139     }
00140 }
00141 /**
00142  * @return
00143  * 圧縮するとtrue i_nameは2文字に圧縮される。
00144  */
00145 static NyLPC_TBool compressNameB(char* i_packet, NyLPC_TUInt16 i_spos, NyLPC_TUInt16 i_name_pos)
00146 {
00147     NyLPC_TUInt16 ret;
00148     const char* p;  //プロトコル文字列の解析開始位置
00149     const char* s = i_packet + i_spos;  //クエリの解析位置
00150     const char* s2;
00151 
00152     //Protocol
00153     for (;;){
00154         //0xc0参照の解決
00155         s = getExtractNamePos(i_packet, s);
00156         if (s == NULL){
00157             //一致しない
00158             return 0;
00159         }
00160         for (;;){
00161             //検索位置のドメインを遡る
00162             if (*s == *(i_packet + i_name_pos)){
00163                 //先頭一致
00164                 p = i_packet + i_name_pos;
00165                 s2 = getExtractNamePos(i_packet, s);
00166                 ret = (NyLPC_TUInt16)(s2 - i_packet);
00167                 for (;;){
00168                     //一致判定
00169                     if (s2 == NULL){
00170                         break;
00171                     }
00172 
00173                     if (memcmp(p, s2, (*(NyLPC_TUInt8*)s2 + 1)) != 0){
00174                         //不一致
00175                         break;
00176                     }
00177                     //検出位置の移動
00178                     p += (*(NyLPC_TUInt8*)s2) + 1;
00179                     s2 += (*(NyLPC_TUInt8*)s2) + 1;
00180                     if (*p == 0 && *s2 == 0){
00181                         //charで扱ってるクライアントのコケ防止
00182                         if (ret>0xff){
00183                             return 0;
00184                         }
00185                         *(i_packet + i_name_pos + 0) = 0xc0;
00186                         *(i_packet + i_name_pos + 1) = (NyLPC_TUInt8)ret;
00187                         return ret;
00188                     }
00189                     s2 = getExtractNamePos(i_packet, s2);
00190                 }
00191             }
00192             //一致しない->検索パターンの次のフラグメントを調べる
00193             s += (*(NyLPC_TUInt8*)s) + 1;
00194             break;
00195         }
00196     }
00197 }
00198 /**
00199  * mDNSパケットからi_nameを検索する。
00200  * i_targetはi_packetに含まれ、NULL終端されていること
00201  * @return 0 圧縮失敗/その他:圧縮後のパケットサイズ
00202  *
00203  */
00204 static NyLPC_TUInt16 compressNameA(char* i_packet, NyLPC_TUInt16 i_name_start, NyLPC_TUInt16 i_name_pos)
00205 {
00206     NyLPC_TUInt16 s = 12;
00207     for (;;){
00208         if (i_name_start <= s){
00209             //圧縮対象文字列に到達
00210             return 0;
00211         }
00212         //i_targetとAnswer文字列が等しいか確認
00213         if (compressNameB(i_packet, s, i_name_pos)){
00214             return i_name_pos + 2;
00215         }
00216         //
00217         s += sizeofCompressName(i_packet + s);
00218         s += 2 + 2 + 4 + 2;
00219         if (i_name_start <= s){
00220             //圧縮対象文字列に到達
00221             return 0;
00222         }
00223         //          //データは圧縮ポインタにしない方がいいらしい。
00224         //          if (compressNameB(i_packet, s, i_name_pos)){
00225         //              return i_name_pos + 2;
00226         //          }
00227         s += NyLPC_ntohs(*((NyLPC_TUInt16*)(i_packet + s - 2)));
00228     }
00229 }
00230 /**
00231  * @return
00232  * 新しいi_packetの長さ
00233  */
00234 static NyLPC_TUInt16 compressName(char* i_packet, NyLPC_TUInt16 i_name_pos, NyLPC_TUInt16 i_name_len)
00235 {
00236     NyLPC_TUInt16 p;
00237     NyLPC_TUInt16 s = i_name_pos;
00238     for (;;){
00239         p = compressNameA(i_packet, i_name_pos, s);
00240         //i_targetとAnswer文字列が等しいか確認
00241         if (p != 0){
00242             return p;
00243         }
00244         s += (NyLPC_TUInt16)*(i_packet + s) + 1;
00245         if (*(i_packet + s) == 0){
00246             //圧縮対象文字列に到達
00247             return (i_name_len + i_name_pos);
00248         }
00249     }
00250 }
00251 
00252 
00253 
00254 
00255 
00256 /**
00257  * 受領可能なQuestionか確認する
00258  * @return
00259  * 受領可能なQuestionの数
00260  *
00261  */
00262 static NyLPC_TUInt16 getNumberOfQuestion(const void* i_packet, NyLPC_TUInt16 i_len)
00263 {
00264     struct NyLPC_TDnsHeader* ptr = (struct NyLPC_TDnsHeader*)i_packet;
00265     NyLPC_TUInt16 t;
00266     if (i_len<sizeof(struct NyLPC_TDnsHeader)){
00267         return NyLPC_TBool_FALSE;
00268     }
00269     //questrionの確認
00270     //QR==0 && op==0 && tc=0
00271     t = NyLPC_ntohs(ptr->flag);
00272     if (((t & NyLPC_TDnsHeader_FLAG_MASK_QR) != 0) &&
00273         ((t & NyLPC_TDnsHeader_FLAG_MASK_OPCODE) != 0) &&
00274         ((t & NyLPC_TDnsHeader_FLAG_MASK_TC) != 0))
00275     {
00276         //this is response
00277         return 0;
00278     }
00279     return NyLPC_ntohs(ptr->qd);
00280 }
00281 
00282 /**
00283  * [i_name].[i_protocol].localをquestionと比較します。i_nameは省略ができます。
00284  * i_nameはincasesensitiveです。
00285  * @return 等しい場合true
00286  */
00287 static NyLPC_TBool NyLPC_TDnsQuestion_isEqualName(const struct NyLPC_TDnsQuestion* question, const char* i_name, const char* i_protocol)
00288 {
00289     NyLPC_TUInt8 tmp;
00290     const char* p;                      //プロトコル文字列の解析開始位置
00291     const char* s = question->buf + (NyLPC_TUInt8)question->qname_pos; //クエリの解析位置
00292 
00293     //Domain
00294     if (i_name != NULL){
00295         //0xc0参照の解決
00296         s = getExtractNamePos(question->buf, s);
00297         if (s == NULL){
00298             return NyLPC_TBool_FALSE;
00299         }
00300         tmp = (NyLPC_TUInt8)strlen(i_name);
00301         if (tmp != *s || NyLPC_strnicmp(s + 1, i_name, tmp) != 0){
00302             return NyLPC_TBool_FALSE;
00303         }
00304         s += (*s) + 1;
00305     }
00306     else{
00307         s = question->buf + (NyLPC_TUInt8)question->qname_pos;//クエリの解析位置
00308     }
00309     p = i_protocol;
00310     //Protocol
00311     for (;;){
00312         //0xc0参照の解決
00313         s = getExtractNamePos(question->buf, s);
00314         if (s == NULL){
00315             return NyLPC_TBool_FALSE;
00316         }
00317         //SRVの末端到達
00318         if (*p == 0){
00319             if (question->buf + question->buf_len<s + 7 + 4){
00320                 return NyLPC_TBool_FALSE;
00321             }
00322             return (memcmp("\5local\0", s, 7) == 0);
00323         }
00324         //有効サイズなら一致検出
00325         if (question->buf + question->buf_len<s + 1 + (NyLPC_TUInt8)*s + 4){
00326             return NyLPC_TBool_FALSE;
00327         }
00328         if (memcmp(p, s + 1, (NyLPC_TUInt8)*s) != 0){
00329             //不一致
00330             return NyLPC_TBool_FALSE;
00331         }
00332         //検出位置の移動
00333         p += (*s) + 1;
00334         s += (*s) + 1;
00335     }
00336 }
00337 
00338 
00339 static NyLPC_TUInt16 NyLPC_TDnsQuestion_parse(const char* i_packet, NyLPC_TUInt16 i_packet_len, NyLPC_TInt16 i_parse_start, struct NyLPC_TDnsQuestion* o_val)
00340 {
00341     NyLPC_TUInt16 i;
00342     //解析開始位置を計算
00343     NyLPC_TUInt16 qlen = 0;
00344     for (i = i_parse_start; i<i_packet_len - 4; i++){
00345         switch ((NyLPC_TUInt8)(*(i_packet + i))){
00346         case 0x00:
00347             qlen++;
00348             break;
00349         case 0xc0:
00350             qlen += 2;
00351             break;
00352         default:
00353             qlen++;
00354             continue;
00355         }
00356         o_val->buf = i_packet;
00357         o_val->buf_len = i_packet_len;
00358         o_val->qname_pos = i_parse_start;
00359         o_val->qtype = NyLPC_ntohs(*(NyLPC_TUInt16*)(i_packet + i_parse_start + qlen));
00360         o_val->qclass = NyLPC_ntohs(*(NyLPC_TUInt16*)(i_packet + i_parse_start + qlen + sizeof(NyLPC_TUInt16)));
00361         return qlen + 4;
00362     }
00363     return 0;
00364 }
00365 
00366 /**
00367  * DNSレコードのPRTフィールドとDNSラベル文字列を比較する。
00368  */
00369 static NyLPC_TInt16 NyLPC_TDnsRecord_getMatchPtrIdx(const struct NyLPC_TDnsRecord* i_struct, const struct NyLPC_TDnsQuestion* question)
00370 {
00371     NyLPC_TInt16 i;
00372     for (i = 0; i<i_struct->num_of_srv; i++){
00373         if (NyLPC_TDnsQuestion_isEqualName(question, NULL, i_struct->srv[i].protocol)){
00374             return i;
00375         }
00376     }
00377     return -1;
00378 }
00379 static NyLPC_TInt16 NyLPC_TDnsRecord_getMatchSrvIdx(const struct NyLPC_TDnsRecord* i_struct, const struct NyLPC_TDnsQuestion* question)
00380 {
00381     NyLPC_TInt16 i;
00382     for (i = 0; i<i_struct->num_of_srv; i++){
00383         if (NyLPC_TDnsQuestion_isEqualName(question, i_struct->name, i_struct->srv[i].protocol)){
00384             return i;
00385         }
00386     }
00387     return -1;
00388 }
00389 
00390 
00391 
00392 /**
00393  * '.'区切り文字列をDNS形式の[n]text[n]text\0へ変換する。
00394  * @return
00395  * 変換後のデータブロックの長さin byte
00396  * 終端の\0の長さを含みます。
00397  */
00398 static NyLPC_TInt16 str2label(NyLPC_TChar* buf, const NyLPC_TChar* name)
00399 {
00400     //proto文字列の変換
00401     NyLPC_TChar* lp;
00402     const NyLPC_TChar* n = name;
00403     NyLPC_TChar* b = buf;
00404     while (*n != '\0'){
00405         lp = b;
00406         b++;
00407         for (; strchr(".\0", *n) == NULL;){
00408             *b = *n;
00409             b++;
00410             n++;
00411         }
00412         *lp = (char)(b - lp - 1);
00413         if (*n != '\0'){
00414             n++;
00415         }
00416     }
00417     *b = '\0';
00418     b++;
00419     return (NyLPC_TInt16)((int)b - (int)buf);
00420 }
00421 /**
00422  * query文字列をパケットに追記します。
00423  * @return 出力したバイト数
00424  */
00425 static NyLPC_TInt16 query2label(char* i_packet, NyLPC_TInt16 i_spos, NyLPC_TInt16 obuflen, const struct NyLPC_TDnsQuestion* i_query)
00426 {
00427     const char* n;
00428     NyLPC_TInt16 s = i_query->qname_pos;
00429     NyLPC_TInt16 l = 0;//出力した文字数
00430     for (;;){
00431         n = getExtractNamePos(i_query->buf, i_query->buf + s);
00432         if (n == NULL){
00433             *(i_packet + i_spos + l) = 0;
00434             l++;
00435             break;
00436         }
00437         else{
00438             memcpy(i_packet + i_spos + l, n, ((NyLPC_TUInt8)*n) + 1);
00439             l += ((NyLPC_TUInt8)*n) + 1;
00440             s = (NyLPC_TInt16)((int)n - (int)i_query->buf + ((NyLPC_TUInt8)*n) + 1);
00441             if (obuflen<i_spos + l + 1){
00442                 return 0;
00443             }
00444         }
00445     }
00446     return l;
00447 }
00448 
00449 
00450 static NyLPC_TInt16 writeSrvResourceHeader(char* i_packet, NyLPC_TInt16 i_spos, NyLPC_TInt16 buflen, const struct NyLPC_TDnsRecord* i_recode, NyLPC_TInt16 i_sid, NyLPC_TUInt16 i_type, NyLPC_TUInt16 i_class,NyLPC_TUInt16 i_ttl)
00451 {
00452     NyLPC_TInt16 s;
00453     NyLPC_TInt16 l = (NyLPC_TInt16)(1 + strlen(i_recode->name) + 1 + strlen(i_recode->srv[i_sid].protocol) + 1 + 5 + 1);
00454     if (buflen<i_spos + l + 2 + 2 + 4){
00455         return 0;
00456     }
00457     s = str2label(i_packet + i_spos, i_recode->name) - 1;
00458     s += str2label(i_packet + i_spos + s, i_recode->srv[i_sid].protocol) - 1;
00459     s += str2label(i_packet + i_spos + s, "local");
00460     l = compressName(i_packet, i_spos, s);//圧縮
00461     (*(NyLPC_TUInt16*)(i_packet + l)) = NyLPC_HTONS(i_type);
00462     (*(NyLPC_TUInt16*)(i_packet + l + 2)) = NyLPC_HTONS(i_class);
00463     (*(NyLPC_TUInt32*)(i_packet + l + 4)) = NyLPC_HTONL(i_ttl);
00464     return l + 2 + 2 + 4;
00465 }
00466 
00467 /**
00468 * パケットヘッダを書き込みます。
00469 * @return パケットサイズ
00470 */
00471 static NyLPC_TUInt16 setResponseHeader(char* i_packet, const struct NyLPC_TDnsHeader* i_in_dns_header, NyLPC_TUInt16 i_an_count, NyLPC_TUInt16 i_ns_count, NyLPC_TUInt16 i_ar_count)
00472 {
00473     struct NyLPC_TDnsHeader* p = (struct NyLPC_TDnsHeader*)i_packet;
00474     if (i_in_dns_header != NULL){
00475         memcpy(p, i_in_dns_header, sizeof(struct NyLPC_TDnsHeader));
00476         p->flag = p->flag | NyLPC_HTONS(NyLPC_TDnsHeader_FLAG_MASK_QR | NyLPC_TDnsHeader_FLAG_MASK_AA);
00477         p->flag = p->flag & NyLPC_HTONS(~(NyLPC_TDnsHeader_FLAG_MASK_RECODE | NyLPC_TDnsHeader_FLAG_MASK_TC | NyLPC_TDnsHeader_FLAG_MASK_RA));
00478     }
00479     else{
00480         p->flag = 0;
00481         p->id = 0;
00482     }
00483     p->qd = 0;
00484     p->an = NyLPC_HTONS(i_an_count);
00485     p->ns = NyLPC_HTONS(i_ns_count);
00486     p->ar = NyLPC_HTONS(i_ar_count);
00487     return sizeof(struct NyLPC_TDnsHeader);
00488 }
00489 static NyLPC_TUInt16 setAnnounceHeader(char* i_packet,NyLPC_TUInt16 i_an_count, NyLPC_TUInt16 i_ns_count, NyLPC_TUInt16 i_ar_count)
00490 {
00491     struct NyLPC_TDnsHeader* p = (struct NyLPC_TDnsHeader*)i_packet;
00492     p->id = 0;
00493     p->flag = NyLPC_HTONS(NyLPC_TDnsHeader_FLAG_MASK_QR | NyLPC_TDnsHeader_FLAG_MASK_AA);
00494     p->qd = 0;
00495     p->an = NyLPC_HTONS(i_an_count);
00496     p->ns = NyLPC_HTONS(i_ns_count);
00497     p->ar = NyLPC_HTONS(i_ar_count);
00498     return sizeof(struct NyLPC_TDnsHeader);
00499 }
00500 
00501 static NyLPC_TInt16 writeARecordData(char* i_packet, NyLPC_TInt16 i_spos,NyLPC_TInt16 obuflen,const struct NyLPC_TIPv4Addr* ip)
00502 {
00503     NyLPC_TInt16 l=i_spos;
00504     (*(NyLPC_TUInt16*)(i_packet + l)) = NyLPC_HTONS(NyLPC_TDnsQuestion_QTYPR_A);
00505     (*(NyLPC_TUInt16*)(i_packet + l + 2)) = NyLPC_HTONS(NyLPC_TDnsQuestion_QCLASS_IN | NyLPC_TDnsQuestion_QCLASS_CACHE_FLUSH);
00506     (*(NyLPC_TUInt32*)(i_packet + l + 4)) = NyLPC_HTONL(NyLPC_TcMDns_RES_TTL);
00507     l += 2 + 2 + 4;
00508     //A record header
00509     if (obuflen<l + 6){
00510         return 0;
00511     }
00512     //Aレコードを書く
00513     //IPADDR
00514     (*(NyLPC_TUInt16*)(i_packet + l)) = NyLPC_HTONS(4);
00515     (*(NyLPC_TUInt32*)(i_packet + l + 2)) = ip->v;
00516     return l + 6;//NEXT_SPOS
00517 }
00518 /**
00519 * ドメイン名からAレコードレスポンスを書きだす。
00520 */
00521 static NyLPC_TInt16 writeARecord(char* i_packet, NyLPC_TInt16 i_spos, NyLPC_TInt16 obuflen, const NyLPC_TChar* i_name, const struct NyLPC_TIPv4Addr* ip)
00522 {
00523     //AnswerはAレコードのみ
00524     NyLPC_TInt16 s = 1 + (NyLPC_TInt16)strlen(i_name) + 1 + 5 + 1;
00525     if (obuflen<i_spos + s + 4 + 4){
00526         return 0;
00527     }
00528     s = str2label(i_packet + i_spos, i_name) - 1;
00529     s += str2label(i_packet + i_spos + s, "local");
00530     //レコード圧縮
00531     s = compressName(i_packet, i_spos, s);
00532     return writeARecordData(i_packet,s,obuflen,ip);
00533 }
00534 
00535 /**
00536 * AレコードクエリからAレコードレスポンスを書きだす。
00537 */
00538 static NyLPC_TInt16 writeARecordByQuery(char* i_packet, NyLPC_TInt16 i_spos, NyLPC_TInt16 obuflen, const struct NyLPC_TDnsQuestion* i_query, const struct NyLPC_TIPv4Addr* ip)
00539 {
00540     NyLPC_TInt16 s = query2label(i_packet, i_spos, obuflen, i_query);
00541     if (s == 0){
00542         return 0;
00543     }
00544     //レコード圧縮
00545     s = compressName(i_packet, i_spos, s);
00546     return writeARecordData(i_packet,s,obuflen,ip);
00547 }
00548 
00549 /*
00550 static NyLPC_TInt16 writeAAAARecordByQueryData(char* i_packet, NyLPC_TInt16 i_spos,NyLPC_TInt16 obuflen,const struct NyLPC_TIPv4Addr* ip)
00551 {
00552     NyLPC_TInt16 l=i_spos;
00553     (*(NyLPC_TUInt16*)(i_packet + l)) = NyLPC_HTONS(NyLPC_TDnsQuestion_QTYPR_AAAA);
00554     (*(NyLPC_TUInt16*)(i_packet + l + 2)) = NyLPC_HTONS(NyLPC_TDnsQuestion_QCLASS_IN | NyLPC_TDnsQuestion_QCLASS_CACHE_FLUSH);
00555     (*(NyLPC_TUInt32*)(i_packet + l + 4)) = NyLPC_HTONL(NyLPC_TcMDns_RES_TTL);
00556     l += 2 + 2 + 4;
00557     //A record header
00558     if (obuflen<l + 2 + 16){
00559         return 0;
00560     }
00561     //AAAAレコードを書く
00562     //IPADDR
00563     (*(NyLPC_TUInt16*)(i_packet + l)) = NyLPC_HTONS(16);
00564     memset(i_packet + l + 2, 0, 10);
00565     (*(NyLPC_TUInt16*)(i_packet + l + 2 + 10)) = 0xffff;
00566     (*(NyLPC_TUInt32*)(i_packet + l + 2 + 12)) = ip->v;
00567     return l + 2 + 16;
00568 }*/
00569 
00570 
00571 /**
00572 * AレコードクエリからAレコードレスポンスを書きだす。
00573 *//*
00574 static NyLPC_TInt16 writeAAAARecordByQuery(char* i_packet, NyLPC_TInt16 i_spos, NyLPC_TInt16 obuflen, const struct NyLPC_TDnsQuestion* i_query, const struct NyLPC_TIPv4Addr* ip)
00575 {
00576     NyLPC_TInt16 s = query2label(i_packet, i_spos, obuflen, i_query);
00577     if (s == 0){
00578         return 0;
00579     }
00580     //レコード圧縮
00581     s = compressName(i_packet, i_spos, s);
00582     return writeAAAARecordByQueryData(i_packet,s,obuflen,ip);
00583 }*/
00584 /**
00585 * AレコードクエリからAレコードレスポンスを書きだす。
00586 *//*
00587 static NyLPC_TInt16 writeAAAARecord(char* i_packet, NyLPC_TInt16 i_spos, NyLPC_TInt16 obuflen, const NyLPC_TChar* i_name, const struct NyLPC_TIPv4Addr* ip)
00588 {
00589     NyLPC_TInt16 s = 1 + (NyLPC_TInt16)strlen(i_name) + 1 + 5 + 1;
00590     if (obuflen<i_spos + s + 4 + 4){
00591         return 0;
00592     }
00593     s = str2label(i_packet + i_spos, i_name) - 1;
00594     s += str2label(i_packet + i_spos + s, "local");
00595     //レコード圧縮
00596     s = compressName(i_packet, i_spos, s);
00597     return writeAAAARecordByQueryData(i_packet,s,obuflen,ip);
00598 }*/
00599 
00600 static NyLPC_TInt16 writeNSECRecordData(char* i_packet, NyLPC_TInt16 i_spos, NyLPC_TInt16 obuflen,NyLPC_TInt16 i_next_domain)
00601 {
00602     NyLPC_TInt16 l=i_spos;
00603     (*(NyLPC_TUInt16*)(i_packet + l)) = NyLPC_HTONS(NyLPC_TDnsQuestion_QTYPR_NSEC);
00604     (*(NyLPC_TUInt16*)(i_packet + l + 2)) = NyLPC_HTONS(NyLPC_TDnsQuestion_QCLASS_IN | NyLPC_TDnsQuestion_QCLASS_CACHE_FLUSH);
00605     (*(NyLPC_TUInt32*)(i_packet + l + 4)) = NyLPC_HTONL(NyLPC_TcMDns_RES_TTL);
00606     l += 2 + 2 + 4;
00607     //A record header
00608     if (obuflen<l + 2 + 2 + 6){
00609         return 0;
00610     }
00611     //NSECレコードを書く
00612     *((NyLPC_TUInt16*)(i_packet + l)) = NyLPC_HTONS(2 + 6);
00613     l += 2;
00614     *(i_packet + l) = 0xc0;
00615     *(i_packet + l + 1) = (NyLPC_TUInt8)i_next_domain;
00616     l += 2;
00617     memcpy(i_packet + l, "\x00\x04\x00\x00\x00\x08", 6);
00618     return l + 6;
00619 }
00620 /**
00621 * NSECレコードレスポンスを書きだす。
00622 * IPv6わからんし。
00623 */
00624 static NyLPC_TInt16 writeNSECRecord(char* i_packet, NyLPC_TInt16 i_spos, NyLPC_TInt16 obuflen, const NyLPC_TChar* i_name)
00625 {
00626     //AnswerはAレコードのみ
00627     NyLPC_TInt16 s = 1 + (NyLPC_TInt16)strlen(i_name) + 1 + 5 + 1;
00628     if (obuflen<i_spos + s + 4 + 4){
00629         return 0;
00630     }
00631     s = str2label(i_packet + i_spos, i_name) - 1;
00632     s += str2label(i_packet + i_spos + s, "local");
00633     //レコード圧縮
00634     s = i_spos + s;//compressName(i_packet,i_spos,s);
00635     return writeNSECRecordData(i_packet,s,obuflen,i_spos);
00636 }
00637 /**
00638 * NSECレコードレスポンスを書きだす。
00639 * IPv6わからんし。
00640 */
00641 static NyLPC_TInt16 writeNSECRecordByQuery(char* i_packet, NyLPC_TInt16 i_spos, NyLPC_TInt16 obuflen, const struct NyLPC_TDnsQuestion* i_query)
00642 {
00643     NyLPC_TInt16 s;
00644     //AnswerはAレコードのみ
00645     s = query2label(i_packet, i_spos, obuflen, i_query);
00646     if (s == 0){
00647         return 0;
00648     }
00649 
00650     //レコード圧縮
00651     s = i_spos + s;
00652     //    l=compressName(i_packet,i_spos,s);
00653     return writeNSECRecordData(i_packet,s,obuflen,i_spos);
00654 }
00655 
00656 static NyLPC_TInt16 writeSdPtrRecord(const struct NyLPC_TMDnsServiceRecord* i_srvlec, char* i_packet, NyLPC_TInt16 i_spos, NyLPC_TInt16 obuflen)
00657 {
00658     NyLPC_TInt16 l, s;
00659     NyLPC_TUInt16* rlen;
00660     //Header
00661     //    s=(NyLPC_TInt16)*(i_question->buf+i_question->qname_pos);
00662     //Headerの長さチェック
00663     if (obuflen<i_spos + 30 + 2 + 2 + 4){
00664         return 0;
00665     }
00666     //Header書込み
00667     memcpy(i_packet + i_spos, "\x09_services\x07_dns-sd\x04_udp\x05local\x00", 30);
00668     s = compressName(i_packet, i_spos, 30);
00669     (*(NyLPC_TUInt16*)(i_packet + s)) = NyLPC_HTONS(NyLPC_TDnsQuestion_QTYPR_PTR);
00670     (*(NyLPC_TUInt16*)(i_packet + s + 2)) = NyLPC_HTONS(NyLPC_TDnsQuestion_QCLASS_IN);
00671     (*(NyLPC_TUInt32*)(i_packet + s + 4)) = NyLPC_HTONL(NyLPC_TcMDns_STD_TTL);
00672     l = s + 2 + 2 + 4;
00673 
00674     //Resourceの書込み
00675     s = (NyLPC_TInt16)(1 + strlen(i_srvlec->protocol) + 1 + 5 + 1);//逆引き文字列の長さ(デリミタ×3+1)
00676     if (obuflen<s + l + 2){
00677         return 0;
00678     }
00679     rlen=(NyLPC_TUInt16*)(i_packet + l);
00680     l += 2;
00681     s = str2label(i_packet + l, i_srvlec->protocol) - 1;
00682     s += str2label(i_packet + l + s, "local");
00683     s = compressName(i_packet, l, s);//圧縮
00684     *rlen = NyLPC_ntohs(s - l);
00685     return s;
00686 }
00687 
00688 static NyLPC_TInt16 writePtrRecord(const struct NyLPC_TDnsRecord* i_recode, NyLPC_TInt16 i_sid, char* i_packet, NyLPC_TInt16 i_spos, NyLPC_TInt16 obuflen)
00689 {
00690     NyLPC_TInt16 l, s;
00691     NyLPC_TUInt16* rlen;
00692     //Header:開始文字数(1)+プレフィクス(n)+終端(1)+local(5)+1
00693     s = (NyLPC_TInt16)(1 + strlen(i_recode->srv[i_sid].protocol) + 1 + 5 + 1);
00694     //Headerの長さチェック
00695     if (obuflen<i_spos + s + 2 + 2 + 4){
00696         return 0;
00697     }
00698     //Header書込み
00699     s = str2label(i_packet + i_spos, i_recode->srv[i_sid].protocol) - 1;
00700     s += str2label(i_packet + i_spos + s, "local");
00701     s = compressName(i_packet, i_spos, s);
00702     (*(NyLPC_TUInt16*)(i_packet + s)) = NyLPC_HTONS(NyLPC_TDnsQuestion_QTYPR_PTR);
00703     (*(NyLPC_TUInt16*)(i_packet + s + 2)) = NyLPC_HTONS(NyLPC_TDnsQuestion_QCLASS_IN);
00704     (*(NyLPC_TUInt32*)(i_packet + s + 4)) = NyLPC_HTONL(NyLPC_TcMDns_STD_TTL);
00705     l = s + 2 + 2 + 4;
00706 
00707     //Resourceの書込み
00708     s = (NyLPC_TInt16)(1 + strlen(i_recode->name) + 1 + strlen(i_recode->srv[i_sid].protocol) + 1 + 5 + 1);//逆引き文字列の長さ(デリミタ×3+1)
00709     if (obuflen<s + l + 2){
00710         return 0;
00711     }
00712     rlen = (NyLPC_TUInt16*)(i_packet + l);
00713     l += 2;
00714     s = str2label(i_packet + l, i_recode->name) - 1;
00715     s += str2label(i_packet + l + s, i_recode->srv[i_sid].protocol) - 1;
00716     s += str2label(i_packet + l + s, "local");
00717     s = compressName(i_packet, l, s);//圧縮
00718     (*rlen) = NyLPC_ntohs(s - l);
00719     return s;
00720 }
00721 
00722 static NyLPC_TInt16 writeSRVRecord(NyLPC_TcMDnsServer_t* i_inst, NyLPC_TInt16 i_sid, char* i_packet, NyLPC_TUInt16 i_spos, NyLPC_TInt16 obuflen)
00723 {
00724     NyLPC_TInt16 l, s;
00725     NyLPC_TUInt16* rlen;
00726 
00727     //SRV Record
00728     s = writeSrvResourceHeader(i_packet, i_spos, obuflen, i_inst->_ref_record, i_sid, NyLPC_TDnsQuestion_QTYPR_SRV, NyLPC_TDnsQuestion_QCLASS_IN | NyLPC_TDnsQuestion_QCLASS_CACHE_FLUSH,NyLPC_TcMDns_RES_TTL);
00729     if (s == 0){
00730         return 0;
00731     }
00732 
00733     l = (NyLPC_TInt16)(1 + strlen(i_inst->_ref_record->a) + 1 + 5 + 1);//逆引き文字列の長さ(デリミタ×3+1)
00734     if (obuflen<s + 8 + l){
00735         return 0;
00736     }
00737     //IPADDR
00738     rlen = (NyLPC_TUInt16*)(i_packet + s);
00739     (*(NyLPC_TUInt16*)(i_packet + s + 2)) = NyLPC_HTONS(0);//Priority
00740     (*(NyLPC_TUInt16*)(i_packet + s + 4)) = NyLPC_HTONS(0);//Weight
00741     (*(NyLPC_TUInt16*)(i_packet + s + 6)) = NyLPC_HTONS(i_inst->_ref_record->srv[i_sid].port);//PORT
00742     l = 4 * 2 + s;
00743     s = str2label(i_packet + l, i_inst->_ref_record->a) - 1;
00744     s += str2label(i_packet + l + s, "local");
00745     s = compressName(i_packet, l, s);//圧縮
00746     (*rlen) = NyLPC_HTONS(2 + 2 + 2 + (s - l));
00747     return s;
00748 }
00749 static NyLPC_TInt16 writeTXTRecord(NyLPC_TcMDnsServer_t* i_inst, NyLPC_TInt16 i_sid, char* i_packet, NyLPC_TInt16 i_spos, NyLPC_TInt16 obuflen)
00750 {
00751     NyLPC_TInt16 ret;
00752     NyLPC_TInt16 l;
00753     //Answer
00754     ret = writeSrvResourceHeader(i_packet, i_spos, obuflen, i_inst->_ref_record, i_sid, NyLPC_TDnsQuestion_QTYPR_TXT, NyLPC_TDnsQuestion_QCLASS_IN | NyLPC_TDnsQuestion_QCLASS_CACHE_FLUSH,NyLPC_TcMDns_STD_TTL);
00755     if (ret == 0){
00756         return 0;
00757     }
00758     //name.proto.localを返す。
00759     if (obuflen<ret + 2){
00760         return 0;
00761     }
00762     (*(NyLPC_TUInt16*)(i_packet + ret)) = NyLPC_ntohs(0);
00763     //proto.name.local.
00764     l = ret + 2;
00765     return l;
00766 }
00767 
00768 
00769 
00770 
00771 
00772 
00773 static void sendAnnounse(NyLPC_TcMDnsServer_t* i_inst)
00774 {
00775     char* obuf;
00776     NyLPC_TUInt16 obuflen;
00777     NyLPC_TUInt16 l;
00778     int i,i2;
00779     for(i2=0;i2<i_inst->_ref_record->num_of_srv;i2++){
00780         //Bufferの取得
00781         obuf=NyLPC_iUdpSocket_allocSendBuf(i_inst->_socket,512,&obuflen,TIMEOUT_IN_MS);
00782         if(obuf==NULL){
00783             return;
00784         }
00785         l=setAnnounceHeader(obuf,1+i_inst->_ref_record->num_of_srv+4,0,0);
00786         //<Answer />
00787         //PTR
00788         l=writePtrRecord(i_inst->_ref_record,i2,obuf,l,obuflen);
00789         //SD-PTR
00790         if(l<=0){
00791             NyLPC_OnErrorGoto(ERROR);
00792         }
00793         for (i = 0; i<i_inst->_ref_record->num_of_srv; i++){
00794             l = writeSdPtrRecord(&(i_inst->_ref_record->srv[i]), obuf, l, obuflen);
00795             if (l <= 0){
00796                 NyLPC_OnErrorGoto(ERROR);
00797             }
00798         }
00799         //<Additional/>
00800         //SRV
00801         l=writeSRVRecord(i_inst,i2,obuf,l,obuflen);
00802         if(l<=0){
00803             NyLPC_OnErrorGoto(ERROR);
00804         }
00805         //TXT
00806         l=writeTXTRecord(i_inst,i2,obuf,l,obuflen);
00807         if(l<=0){
00808             NyLPC_OnErrorGoto(ERROR);
00809         }
00810         //Aレコード
00811         l=writeARecord(obuf,l,obuflen,i_inst->_ref_record->a,NyLPC_iUdpSocket_getSockIP(i_inst->_socket));
00812         if(l<=0){
00813             NyLPC_OnErrorGoto(ERROR);
00814         }
00815 //        //AAAAレコード
00816 //        l=writeAAAARecord(obuf,l,obuflen,i_inst->_ref_record->a,&(i_inst->_super.uip_udp_conn.lipaddr));
00817 //        if(l<=0){
00818 //            NyLPC_OnErrorGoto(ERROR);
00819 //        }
00820         //NSEC
00821         l=writeNSECRecord(obuf,l,obuflen,i_inst->_ref_record->a);
00822         if(l<=0){
00823             NyLPC_OnErrorGoto(ERROR);
00824         }          
00825         if(!NyLPC_iUdpSocket_psend(i_inst->_socket,&MDNS_MCAST_IPADDR,MDNS_MCAST_PORT,obuf,l)){
00826             NyLPC_OnErrorGoto(ERROR);
00827         }
00828     }
00829     return;
00830 ERROR:
00831     NyLPC_iUdpSocket_releaseSendBuf(i_inst->_socket,obuf);
00832     return;
00833 }
00834 
00835 
00836 
00837 static void sendReply2(NyLPC_TcMDnsServer_t* i_inst, const struct NyLPC_TDnsHeader* i_dns_header, const struct NyLPC_TDnsQuestion* q)
00838 {
00839     NyLPC_TInt16 ptr_recode;
00840     NyLPC_TInt16 i2;
00841     char* obuf;
00842     NyLPC_TUInt16 obuflen;
00843     NyLPC_TUInt16 l;
00844     //パケットヘッダの生成
00845     switch (q->qtype){
00846     case NyLPC_TDnsQuestion_QTYPR_SRV:
00847         //
00848         ptr_recode = NyLPC_TDnsRecord_getMatchSrvIdx(i_inst->_ref_record, q);
00849         if (ptr_recode<0){
00850             goto DROP;
00851         }
00852         //Bufferの取得
00853         obuf = NyLPC_iUdpSocket_allocSendBuf(i_inst->_socket, 512, &obuflen, 0);
00854         if (obuf == NULL){
00855             goto DROP;
00856         }
00857         //SRV,(TXT,A,AAAA,NSEC)
00858         l = setResponseHeader(obuf, i_dns_header, 1, 0, 3);
00859         l = writeSRVRecord(i_inst, ptr_recode, obuf, l, obuflen);
00860         if (l <= 0){
00861             NyLPC_OnErrorGoto(ERROR);
00862         }
00863         l = writeTXTRecord(i_inst, ptr_recode, obuf, l, obuflen);
00864         if (l <= 0){
00865             NyLPC_OnErrorGoto(ERROR);
00866         }
00867         //Aレコード
00868         l = writeARecord(obuf, l, obuflen, i_inst->_ref_record->a, NyLPC_iUdpSocket_getSockIP(i_inst->_socket));
00869         if (l <= 0){
00870             NyLPC_OnErrorGoto(ERROR);
00871         }
00872 //        //AAAAレコード
00873 //        l = writeAAAARecord(obuf, l, obuflen, i_inst->_ref_record->a, &(i_inst->_super.uip_udp_conn.lipaddr));
00874 //        if (l <= 0){
00875 //            NyLPC_OnErrorGoto(ERROR);
00876 //        }
00877         //NSEC
00878         l = writeNSECRecord(obuf, l, obuflen, i_inst->_ref_record->a);
00879         if (l <= 0){
00880             NyLPC_OnErrorGoto(ERROR);
00881         }
00882         break;
00883 /*    case NyLPC_TDnsQuestion_QTYPR_AAAA:
00884         //自分宛?(name.local)
00885         if (!NyLPC_TDnsQuestion_isEqualName(q, i_inst->_ref_record->a, "")){
00886             goto DROP;
00887         }
00888         //Bufferの取得
00889         obuf = NyLPC_cUdpSocket_allocSendBuf(&(i_inst->_super), 512, &obuflen, 0);
00890         if (obuf == NULL){
00891             goto DROP;
00892         }
00893         //Headerのコピー
00894         //AAAA,(A,NSEC)
00895         l = setResponseHeader(obuf, i_dns_header, 1, 0, 2);
00896         //AAAAレコード
00897         l = writeAAAARecordByQuery(obuf, l, obuflen, q, &(i_inst->_super.uip_udp_conn.lipaddr));
00898         if (l <= 0){
00899             NyLPC_OnErrorGoto(ERROR);
00900         }
00901         //Aレコードのみ
00902         l = writeARecordByQuery(obuf, l, obuflen, q, &(i_inst->_super.uip_udp_conn.lipaddr));
00903         if (l <= 0){
00904             NyLPC_OnErrorGoto(ERROR);
00905         }
00906         //NSEC
00907         l = writeNSECRecordByQuery(obuf, l, obuflen, q);
00908         if (l <= 0){
00909             NyLPC_OnErrorGoto(ERROR);
00910         }
00911         break;*/
00912     case NyLPC_TDnsQuestion_QTYPR_A:
00913         //自分宛?(name.local)
00914         if (!NyLPC_TDnsQuestion_isEqualName(q, i_inst->_ref_record->a, "")){
00915             goto DROP;
00916         }
00917         //Bufferの取得
00918         obuf = NyLPC_iUdpSocket_allocSendBuf(i_inst->_socket, 512, &obuflen, 0);
00919         if (obuf == NULL){
00920             goto DROP;
00921         }
00922         //Headerのコピー
00923         l = setResponseHeader(obuf, i_dns_header, 1, 0, 1);
00924         //A、(NSEC
00925         l = writeARecordByQuery(obuf, l, obuflen, q, NyLPC_iUdpSocket_getSockIP(i_inst->_socket));
00926         if (l <= 0){
00927             NyLPC_OnErrorGoto(ERROR);
00928         }
00929         l = writeNSECRecordByQuery(obuf, l, obuflen, q);
00930         if (l <= 0){
00931             NyLPC_OnErrorGoto(ERROR);
00932         }
00933         break;
00934     case NyLPC_TDnsQuestion_QTYPR_PTR:
00935         //_service._dns-sd._udpかどうか
00936         if (NyLPC_TDnsQuestion_isEqualName(q, NULL, "_services._dns-sd._udp")){
00937             //Bufferの取得
00938             obuf = NyLPC_iUdpSocket_allocSendBuf(i_inst->_socket, 512, &obuflen, 0);
00939             if (obuf == NULL){
00940                 goto DROP;
00941             }
00942             l = setResponseHeader(obuf, i_dns_header, i_inst->_ref_record->num_of_srv, 0, 0);
00943             for (i2 = 0; i2<i_inst->_ref_record->num_of_srv; i2++){
00944                 l = writeSdPtrRecord(&(i_inst->_ref_record->srv[i2]), obuf, l, obuflen);
00945                 if (l <= 0){
00946                     NyLPC_OnErrorGoto(ERROR);
00947                 }
00948             }
00949         }
00950         else{
00951             //自分宛?(proto.local)
00952             ptr_recode = NyLPC_TDnsRecord_getMatchPtrIdx(i_inst->_ref_record, q);
00953             if (ptr_recode<0){
00954                 goto DROP;
00955             }
00956             //Bufferの取得
00957             obuf = NyLPC_iUdpSocket_allocSendBuf(i_inst->_socket, 512, &obuflen, 0);
00958             if (obuf == NULL){
00959                 goto DROP;
00960             }
00961             l = setResponseHeader(obuf, i_dns_header, 1, 0, 4);
00962             l = writePtrRecord(i_inst->_ref_record, ptr_recode, obuf, l, obuflen);
00963             if (l <= 0){
00964                 NyLPC_OnErrorGoto(ERROR);
00965             }
00966             //SRV
00967             l = writeSRVRecord(i_inst, ptr_recode, obuf, l, obuflen);
00968             if (l <= 0){
00969                 NyLPC_OnErrorGoto(ERROR);
00970             }
00971             //TXT
00972             l = writeTXTRecord(i_inst, ptr_recode, obuf, l, obuflen);
00973             if (l <= 0){
00974                 NyLPC_OnErrorGoto(ERROR);
00975             }
00976             //Aレコード
00977             l = writeARecord(obuf, l, obuflen, i_inst->_ref_record->a,NyLPC_iUdpSocket_getSockIP(i_inst->_socket));
00978             if (l <= 0){
00979                 NyLPC_OnErrorGoto(ERROR);
00980             }
00981 //            //AAAAレコード
00982 //            l = writeAAAARecord(obuf, l, obuflen, i_inst->_ref_record->a, &(i_inst->_super.uip_udp_conn.lipaddr));
00983 //            if (l <= 0){
00984 //                NyLPC_OnErrorGoto(ERROR);
00985 //            }
00986             //NSEC
00987             l = writeNSECRecord(obuf, l, obuflen, i_inst->_ref_record->a);
00988             if (l <= 0){
00989                 NyLPC_OnErrorGoto(ERROR);
00990             }
00991         }
00992         break;
00993     case NyLPC_TDnsQuestion_QTYPR_TXT:
00994         //自分宛?(proto.local)
00995         ptr_recode = NyLPC_TDnsRecord_getMatchSrvIdx(i_inst->_ref_record, q);
00996         if (ptr_recode<0){
00997             goto DROP;
00998         }
00999         //Bufferの取得
01000         obuf = NyLPC_iUdpSocket_allocSendBuf(i_inst->_socket, 512, &obuflen, 0);
01001         l = setResponseHeader(obuf, i_dns_header, 1, 0, 2);
01002         l = writeTXTRecord(i_inst, ptr_recode, obuf, l, obuflen);
01003         if (l <= 0){
01004             NyLPC_OnErrorGoto(ERROR);
01005         }
01006         //A recoad
01007         l = writeARecord(obuf, l, obuflen, i_inst->_ref_record->a,NyLPC_iUdpSocket_getSockIP(i_inst->_socket));
01008         if (l <= 0){
01009             NyLPC_OnErrorGoto(ERROR);
01010         }
01011 //        //AAAAレコード
01012 //        l = writeAAAARecord(obuf, l, obuflen, i_inst->_ref_record->a, &(i_inst->_super.uip_udp_conn.lipaddr));
01013 //        if (l <= 0){
01014 //            NyLPC_OnErrorGoto(ERROR);
01015 //        }
01016         //NSEC
01017         l = writeNSECRecord(obuf, l, obuflen, i_inst->_ref_record->a);
01018         if (l <= 0){
01019             NyLPC_OnErrorGoto(ERROR);
01020         }
01021         break;
01022     default:
01023         goto DROP;
01024     }
01025     if (!NyLPC_iUdpSocket_psend(i_inst->_socket, &MDNS_MCAST_IPADDR, MDNS_MCAST_PORT, obuf, l)){
01026         NyLPC_OnErrorGoto(ERROR);
01027     }
01028     return;
01029 ERROR:
01030     NyLPC_iUdpSocket_releaseSendBuf(i_inst->_socket, obuf);
01031 DROP:
01032     return;
01033 }
01034 #define ST_INIT 1       //初期QUERY送信(省略)
01035 #define ST_ANNOUNCE 2   //アナウンス
01036 #define ST_WAIT 3       //待機
01037 
01038 
01039 static NyLPC_TBool onPacket(NyLPC_TiUdpSocket_t* i_inst,const void* i_buf,const struct NyLPC_TIPv4RxInfo* i_info)
01040 {
01041     NyLPC_TUInt16 in_len;
01042     NyLPC_TUInt16 num_of_query;
01043     struct NyLPC_TDnsQuestion q;
01044     NyLPC_TUInt16 s;
01045     NyLPC_TInt16 i;
01046 
01047     if(i_info->peer_port!=MDNS_MCAST_PORT || !NyLPC_TIPv4Addr_isEqual(&MDNS_MCAST_IPADDR,&i_info->ip)){
01048         return NyLPC_TBool_FALSE;
01049     }
01050 
01051     num_of_query=getNumberOfQuestion(i_buf,i_info->size);
01052     if(num_of_query==0){
01053         goto DROP;
01054     }
01055     in_len=sizeof(struct NyLPC_TDnsHeader);
01056     for(i=0;i<num_of_query;i++){
01057         //Queryのパース
01058 
01059         s=NyLPC_TDnsQuestion_parse(i_buf,i_info->size,in_len,&q);
01060         if(s==0){
01061             goto DROP;
01062         }
01063         in_len+=s;
01064         sendReply2((NyLPC_TcMDnsServer_t*)i_inst->_tag,(const struct NyLPC_TDnsHeader*)i_buf,&q);
01065     }
01066     //パケット処理終了
01067     return NyLPC_TBool_FALSE;
01068 DROP:
01069     return NyLPC_TBool_FALSE;
01070 }
01071 
01072 static void onPeriodic(NyLPC_TiUdpSocket_t* i_inst)
01073 {
01074     NyLPC_TcMDnsServer_t* inst=(NyLPC_TcMDnsServer_t*)i_inst->_tag;
01075     //Announce Timeout
01076     if(NyLPC_cStopwatch_isExpired(&((NyLPC_TcMDnsServer_t*)inst)->_periodic_sw)){
01077         switch(inst->_state){
01078         case ST_WAIT:
01079             inst->_state_val=0;
01080             inst->_state=ST_ANNOUNCE;// set Announce status
01081         case ST_ANNOUNCE:
01082             //アナウンス
01083             inst->_state_val++;
01084             if(inst->_state_val<=3){
01085                 sendAnnounse(((NyLPC_TcMDnsServer_t*)inst));
01086                 NyLPC_cStopwatch_startExpire((&((NyLPC_TcMDnsServer_t*)inst)->_periodic_sw),1000);
01087             }else{
01088                 inst->_state=ST_WAIT;
01089                 //TTL(msec)*1000*80%
01090                 NyLPC_cStopwatch_startExpire((&((NyLPC_TcMDnsServer_t*)inst)->_periodic_sw),NyLPC_TcMDns_STD_TTL*1000*4/5);
01091             }
01092         }
01093     }
01094 }
01095 
01096 NyLPC_TBool NyLPC_cMDnsServer_initialize(
01097     NyLPC_TcMDnsServer_t* i_inst,const struct NyLPC_TDnsRecord* i_ref_record)
01098 {
01099     NyLPC_cStopwatch_initialize(&(i_inst->_periodic_sw));
01100     NyLPC_cStopwatch_startExpire(&(i_inst->_periodic_sw),1000);
01101     i_inst->_socket=NyLPC_cNet_createUdpSocketEx(MDNS_MCAST_PORT,NyLPC_TSocketType_UDP_NOBUF);
01102     i_inst->_socket->_tag=i_inst;
01103     NyLPC_iUdpSocket_setOnRxHandler(i_inst->_socket,onPacket);
01104     NyLPC_iUdpSocket_setOnPeriodicHandler(i_inst->_socket,onPeriodic);
01105     NyLPC_iUdpSocket_joinMulticast(i_inst->_socket,&MDNS_MCAST_IPADDR);
01106     i_inst->_state=ST_WAIT;
01107     i_inst->_state_val=0;
01108     i_inst->_ref_record=i_ref_record;
01109     return NyLPC_TBool_TRUE;
01110 }
01111 void NyLPC_cMDnsServer_finalize(
01112     NyLPC_TcMDnsServer_t* i_inst)
01113 {
01114     NyLPC_iUdpSocket_finalize(i_inst->_socket);
01115     NyLPC_cStopwatch_finalize(&(i_inst->_periodic_sw));
01116 }
01117 
01118 
01119