This is Webservice SDK for mbed. LPCXpresso1769/LPC1768/FRDM-K64F/LPC4088
Dependents: MbedFileServer_1768MiniDK2 RedWireBridge IssueDebug_gcc MiMicRemoteMCU-for-Mbed ... more
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
Generated on Tue Jul 12 2022 15:46:16 by 1.7.2