This is Webservice SDK for mbed. LPCXpresso1769/LPC1768/FRDM-K64F/LPC4088
Fork of libMiMic by
core/net/mdns/NyLPC_cMDnsServer.c
- Committer:
- nyatla
- Date:
- 2014-10-19
- Revision:
- 97:6ca5900a2d68
- Parent:
- 96:e6a0db86988e
- Child:
- 98:6284ce9a0476
File content as of revision 97:6ca5900a2d68:
/********************************************************************************* * PROJECT: MiMic * -------------------------------------------------------------------------------- * * This file is part of MiMic * Copyright (C)2011 Ryo Iizuka * * MiMic is free software: you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published * by the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this program. If not, see <http://www.gnu.org/licenses/>. * * For further information please contact. * http://nyatla.jp/ * <airmail(at)ebony.plala.or.jp> or <nyatla(at)nyatla.jp> * *********************************************************************************/ #include "NyLPC_cMDnsServer.h" #include "NyLPC_uipService.h" #include "NyLPC_http.h" #include "NyLPC_utils.h" #include <stdio.h> #include <string.h> /** * mDNSのポート番号 */ #define MDNS_MCAST_PORT 5353 static const struct NyLPC_TIPv4Addr MDNS_MCAST_IPADDR=NyLPC_TIPv4Addr_pack(224,0,0,251); #define TIMEOUT_IN_MS 1000 #define NyLPC_TcMDns_TTL (30*60) //30min struct NyLPC_TDnsHeader { NyLPC_TUInt16 id; NyLPC_TUInt16 flag; NyLPC_TUInt16 qd; NyLPC_TUInt16 an; NyLPC_TUInt16 ns; NyLPC_TUInt16 ar; }PACK_STRUCT_END; #define NyLPC_TDnsHeader_FLAG_MASK_QR 0x8000 #define NyLPC_TDnsHeader_FLAG_MASK_OPCODE 0x7800 #define NyLPC_TDnsHeader_FLAG_MASK_AA 0x0400 #define NyLPC_TDnsHeader_FLAG_MASK_TC 0x0200 #define NyLPC_TDnsHeader_FLAG_MASK_RD 0x0100 #define NyLPC_TDnsHeader_FLAG_MASK_RA 0x0080 #define NyLPC_TDnsHeader_FLAG_MASK_Z 0x0070 #define NyLPC_TDnsHeader_FLAG_MASK_RECODE 0x000F struct NyLPC_TDnsQuestion { const char* qname; NyLPC_TUInt16 qtype; NyLPC_TUInt16 qclass; }; #define NyLPC_TDnsQuestion_QTYPR_A 1 #define NyLPC_TDnsQuestion_QTYPR_NS 2 #define NyLPC_TDnsQuestion_QTYPR_CNAME 5 #define NyLPC_TDnsQuestion_QTYPR_SOA 6 #define NyLPC_TDnsQuestion_QTYPR_PTR 12 #define NyLPC_TDnsQuestion_QTYPR_MX 15 #define NyLPC_TDnsQuestion_QTYPR_TXT 16 #define NyLPC_TDnsQuestion_QTYPR_ANY 255 #define NyLPC_TDnsQuestion_QCLASS_IN 1 #define NyLPC_TDnsQuestion_QCLASS_CH 3 #define NyLPC_TDnsQuestion_QCLASS_HS 4 #define NyLPC_TDnsQuestion_QTYPR_SRV 33 /************************************************** * TLabelCache **************************************************/ struct TLabelCache { NyLPC_TUInt16 idx; const char* str; }; static void TLabelCache_reset(struct TLabelCache* i_struct) { i_struct->idx=0; i_struct->str=NULL; } static NyLPC_TInt16 TLabelCache_compress(struct TLabelCache* i_struct,NyLPC_TChar* i_src) { NyLPC_TInt16 s; NyLPC_TInt16 k; const NyLPC_TChar* q; const NyLPC_TChar* d; //初めてのインデクスは保存 if(i_struct->idx==0){ i_struct->idx=12; i_struct->str=i_src; }else{ d=i_struct->str; do{ q=i_src; do{ if(strcmp(q,d)==0){ //一致,インデクスを計算 s=(NyLPC_TInt16)(q-i_src); k=(NyLPC_TInt16)(d-i_struct->str); //新しい長さを返す *((NyLPC_TInt16*)(i_src+s))=NyLPC_HTONS(0xC000|(i_struct->idx+k)); return s+2; } q+=*q+1; }while(*q!=0); d+=*d+1; }while(*d!=0); } return (NyLPC_TInt16)(strlen(i_src)+1); } /** * 受領可能なQuestionか確認する * @return * 受領可能なQuestionの数 * */ static NyLPC_TUInt16 getNumberOfQuestion(const void* i_packet,NyLPC_TUInt16 i_len) { struct NyLPC_TDnsHeader* ptr=(struct NyLPC_TDnsHeader*)i_packet; NyLPC_TUInt16 t; if(i_len<12){ return NyLPC_TBool_FALSE; } //questrionの確認 //QR==0 && op==0 && tc=0 t=NyLPC_ntohs(ptr->flag); if( ((t & NyLPC_TDnsHeader_FLAG_MASK_QR)!=0) && ((t & NyLPC_TDnsHeader_FLAG_MASK_OPCODE)!=0) && ((t & NyLPC_TDnsHeader_FLAG_MASK_TC)!=0)) { //this is response return 0; } return NyLPC_ntohs(ptr->qd); } static NyLPC_TInt16 NyLPC_TDnsQuestion_parse(const void* i_qpacket,NyLPC_TUInt16 i_len,struct NyLPC_TDnsQuestion* o_val) { NyLPC_TUInt16 l; NyLPC_TUInt16 i; const char* p=(const char*)i_qpacket; //QNameのパース'0終端' l=i_len-4-1;//スキャン長はパケットサイズ-5まで for(i=0;i<l;i++){ if(*(p+i)==0){ l=i+1;//NULL終端を加味した文字列長 o_val->qname=p; p+=l; o_val->qtype=NyLPC_ntohs(*(NyLPC_TUInt16*)p); o_val->qclass=NyLPC_ntohs(*(NyLPC_TUInt16*)(p+sizeof(NyLPC_TUInt16))); //OK return l+4; } } return 0; } /** * .区切りラベル文字列とDNSラベル文字列を比較する。 * @param record * .区切りのドメイン名 * @param question * QuestionName文字列 */ inline static NyLPC_TBool isEqualName(const char* record,const char* question) { char s; const char* q=question; const char* m=record; for(;;){ if(*m=='\0'){ //questionは最後のフラグメントが残るはず return memcmp(q,"\5local\0",7)==0; } s=*q; switch(*q) { case 0x00: return NyLPC_TBool_FALSE; case 0xc0: return NyLPC_TBool_FALSE;//offset default: q++; if(strncmp(m,q,s)!=0){ return NyLPC_TBool_FALSE; } m+=s; q+=s; } m++; } } /** * DNSレコードのPRTフィールドとDNSラベル文字列を比較する。 */ static NyLPC_TInt16 NyLPC_TDnsRecord_getMatchPtrIdx(const struct NyLPC_TDnsRecord* i_struct,const NyLPC_TChar* question) { NyLPC_TInt16 i; for(i=0;i<i_struct->num_of_srv;i++){ if(isEqualName(i_struct->srv[i].protocol,question)){ return i; } } return -1; } static NyLPC_TInt16 NyLPC_TDnsRecord_getMatchSrvIdx(const struct NyLPC_TDnsRecord* i_struct,const NyLPC_TChar* question) { NyLPC_TInt16 i; NyLPC_TInt16 l=(NyLPC_TInt16)strlen(i_struct->name); //Aレコードをチェック if(l!=question[0] || memcmp(question+1,i_struct->name,l)!=0){ return -1; } for(i=0;i<i_struct->num_of_srv;i++){ if(isEqualName(i_struct->srv[i].protocol,question+l+1)){ return i; } } return -1; } /** * _services._dns-sd._udp.localであるか確認する。 */ static NyLPC_TBool NyLPC_TDnsRecord_isServicesDnsSd(const NyLPC_TChar* question) { return memcmp(question,"\x09_services\x07_dns-sd\x04_udp\5local\x00",30)==0; } /** * '.'区切り文字列をDNS形式の[n]text[n]text\0へ変換する。 * @return * 変換後のデータブロックの長さin byte * 終端の\0の長さを含みます。 */ static NyLPC_TInt16 str2label(NyLPC_TChar* buf,const NyLPC_TChar* name) { //proto文字列の変換 NyLPC_TChar* lp; const NyLPC_TChar* n=name; NyLPC_TChar* b=buf; while(*n!='\0'){ lp=b; b++; for(;strchr(".\0",*n)==NULL;){ *b=*n; b++; n++; } *lp=(char)(b-lp-1); if(*n!='\0'){ n++; } } *b='\0'; b++; return b-buf; } /** * ResourceHeaderのライタ */ static NyLPC_TInt16 writeResourceHeader(char* buf,NyLPC_TInt16 len,const char* i_name,NyLPC_TUInt16 i_type,NyLPC_TUInt16 i_class) { NyLPC_TInt16 s; NyLPC_TInt16 l=1+(NyLPC_TInt16)strlen(i_name)+1+5+1; if(len<l+4+4){ return 0; } s=str2label(buf,i_name); str2label(buf+s-1,"local"); (*(NyLPC_TUInt16*)(buf+l))=NyLPC_HTONS(i_type); (*(NyLPC_TUInt16*)(buf+l+2))=NyLPC_HTONS(i_class); (*(NyLPC_TUInt32*)(buf+l+4))=NyLPC_HTONL(NyLPC_TcMDns_TTL); return l+2+2+4; } inline static NyLPC_TInt16 writeSrvResourceHeader(char* buf,NyLPC_TInt16 len,const struct NyLPC_TDnsRecord* i_recode,int i_sid,NyLPC_TUInt16 i_type,NyLPC_TUInt16 i_class,struct TLabelCache* i_ca) { NyLPC_TInt16 l=(NyLPC_TInt16)(1+strlen(i_recode->name)+1+strlen(i_recode->srv[i_sid].protocol)+1+5+1); if(len<l+2+2+4){ return 0; } l=str2label(buf,i_recode->name)-1; l+=str2label(buf+l,i_recode->srv[i_sid].protocol)-1; l+=str2label(buf+l,"local"); l=TLabelCache_compress(i_ca,buf);//圧縮 (*(NyLPC_TUInt16*)(buf+l))=NyLPC_HTONS(i_type); (*(NyLPC_TUInt16*)(buf+l+2))=NyLPC_HTONS(i_class); (*(NyLPC_TUInt32*)(buf+l+4))=NyLPC_HTONL(NyLPC_TcMDns_TTL); return l+2+2+4; } inline static NyLPC_TUInt16 setResponseHeader(char* obuf,const struct NyLPC_TDnsHeader* i_in_dns_header,NyLPC_TUInt16 i_an_count,NyLPC_TUInt16 i_ns_count,NyLPC_TUInt16 i_ar_count) { struct NyLPC_TDnsHeader* p=(struct NyLPC_TDnsHeader*)obuf; if(i_in_dns_header!=NULL){ memcpy(p,i_in_dns_header,sizeof(struct NyLPC_TDnsHeader)); p->flag=p->flag | NyLPC_HTONS(NyLPC_TDnsHeader_FLAG_MASK_QR|NyLPC_TDnsHeader_FLAG_MASK_AA); p->flag=p->flag & NyLPC_HTONS(~(NyLPC_TDnsHeader_FLAG_MASK_RECODE|NyLPC_TDnsHeader_FLAG_MASK_TC|NyLPC_TDnsHeader_FLAG_MASK_RA)); }else{ p->flag=0; p->id=0; } p->qd=0; p->an=NyLPC_HTONS(i_an_count); p->ns=NyLPC_HTONS(i_ns_count); p->ar=NyLPC_HTONS(i_ar_count); return sizeof(struct NyLPC_TDnsHeader); } inline static NyLPC_TInt16 writeARecord(char* obuf,NyLPC_TInt16 obuflen,const NyLPC_TChar* a_rec,const struct NyLPC_TIPv4Addr* ip) { NyLPC_TInt16 ret; //AnswerはAレコードのみ //A record header ret=writeResourceHeader(obuf,obuflen,a_rec,NyLPC_TDnsQuestion_QTYPR_A,NyLPC_TDnsQuestion_QCLASS_IN); if(ret==0 || obuflen-ret<8){ return 0; } //Aレコードを書く //IPADDR (*(NyLPC_TUInt16*)(obuf+ret))=NyLPC_HTONS(4); (*(NyLPC_TUInt32*)(obuf+ret+2))=ip->v; return ret+8; } static NyLPC_TInt16 writeSdPtrRecord(const char* i_qname,const struct NyLPC_TMDnsServiceRecord* i_srvlec,char* obuf,NyLPC_TInt16 obuflen) { NyLPC_TInt16 l,s; //Header s=(NyLPC_TInt16)strlen(i_qname)+1; //Headerの長さチェック if(obuflen<s+2+2+4){ return 0; } //Header書込み memcpy(obuf,i_qname,s); (*(NyLPC_TUInt16*)(obuf+s))=NyLPC_HTONS(NyLPC_TDnsQuestion_QTYPR_PTR); (*(NyLPC_TUInt16*)(obuf+s+2))=NyLPC_HTONS(NyLPC_TDnsQuestion_QCLASS_IN); (*(NyLPC_TUInt32*)(obuf+s+4))=NyLPC_HTONL(NyLPC_TcMDns_TTL); l=s+2+2+4; //Resourceの書込み s=(NyLPC_TInt16)(1+strlen(i_srvlec->protocol)+1+5+1);//逆引き文字列の長さ(デリミタ×3+1) if(obuflen<s+l+2){ return 0; } (*(NyLPC_TUInt16*)(obuf+l))=NyLPC_ntohs(s); l+=2; l+=str2label(obuf+l,i_srvlec->protocol)-1; l+=str2label(obuf+l,"local"); return l; } static NyLPC_TInt16 writePtrRecord(const struct NyLPC_TDnsRecord* i_recode,NyLPC_TInt16 i_sid,char* obuf,NyLPC_TInt16 obuflen,struct TLabelCache* i_ca) { NyLPC_TInt16 l,s; NyLPC_TUInt16* rlen; //Header:開始文字数(1)+プレフィクス(n)+終端(1)+local(5)+1 s=(NyLPC_TInt16)(1+strlen(i_recode->srv[i_sid].protocol)+1+5+1); //Headerの長さチェック if(obuflen<s+2+2+4){ return 0; } //Header書込み s=str2label(obuf,i_recode->srv[i_sid].protocol)-1; s+=str2label(obuf+s,"local"); s=TLabelCache_compress(i_ca,obuf); (*(NyLPC_TUInt16*)(obuf+s))=NyLPC_HTONS(NyLPC_TDnsQuestion_QTYPR_PTR); (*(NyLPC_TUInt16*)(obuf+s+2))=NyLPC_HTONS(NyLPC_TDnsQuestion_QCLASS_IN); (*(NyLPC_TUInt32*)(obuf+s+4))=NyLPC_HTONL(NyLPC_TcMDns_TTL); l=s+2+2+4; //Resourceの書込み s=1+strlen(i_recode->name)+1+strlen(i_recode->srv[i_sid].protocol)+1+5+1;//逆引き文字列の長さ(デリミタ×3+1) if(obuflen<s+l+2){ return 0; } rlen=(NyLPC_TUInt16*)(obuf+l); l+=2; s=str2label(obuf+l,i_recode->name)-1; s+=str2label(obuf+l+s,i_recode->srv[i_sid].protocol)-1; s+=str2label(obuf+l+s,"local"); s=TLabelCache_compress(i_ca,obuf+l);//圧縮 (*rlen)=NyLPC_ntohs(s); return l+s; } static NyLPC_TInt16 writeSRVRecord(NyLPC_TcMDnsServer_t* i_inst,NyLPC_TInt16 i_sid,char* obuf,NyLPC_TInt16 obuflen,struct TLabelCache* i_ca) { NyLPC_TInt16 l,s; NyLPC_TUInt16* rlen; //SRV Record s=writeSrvResourceHeader(obuf,obuflen,i_inst->_ref_record,i_sid,NyLPC_TDnsQuestion_QTYPR_SRV,NyLPC_TDnsQuestion_QCLASS_IN,i_ca); if(s==0){ return 0; } l=1+strlen(i_inst->_ref_record->a)+1+5+1;//逆引き文字列の長さ(デリミタ×3+1) if(obuflen-s-l<8){ return 0; } //IPADDR rlen=(NyLPC_TUInt16*)(obuf+s); (*(NyLPC_TUInt16*)(obuf+s+2))=NyLPC_HTONS(0);//Priority (*(NyLPC_TUInt16*)(obuf+s+4))=NyLPC_HTONS(0);//Weight (*(NyLPC_TUInt16*)(obuf+s+6))=NyLPC_HTONS(i_inst->_ref_record->srv[i_sid].port);//PORT l=4*2+s; s=str2label(obuf+l,i_inst->_ref_record->a)-1; s+=str2label(obuf+l+s,"local"); s=TLabelCache_compress(i_ca,obuf+l);//圧縮 (*rlen)=NyLPC_HTONS(2+2+2+s); return l+s; } static NyLPC_TInt16 writeTXTRecord(NyLPC_TcMDnsServer_t* i_inst,NyLPC_TInt16 i_sid,char* obuf,NyLPC_TInt16 obuflen,struct TLabelCache* i_ca) { NyLPC_TInt16 ret; NyLPC_TInt16 l; //Answer ret=writeSrvResourceHeader(obuf,obuflen,i_inst->_ref_record,i_sid,NyLPC_TDnsQuestion_QTYPR_TXT,NyLPC_TDnsQuestion_QCLASS_IN,i_ca); if(ret==0){ return 0; } //name.proto.localを返す。 if(obuflen-ret<2){ return 0; } (*(NyLPC_TUInt16*)(obuf+ret))=NyLPC_ntohs(0); //proto.name.local. l=ret+2; return l; } static void sendAnnounse(NyLPC_TcMDnsServer_t* i_inst) { char* obuf; NyLPC_TUInt16 obuflen; NyLPC_TUInt16 l,s; int i2; struct TLabelCache cache; for(i2=0;i2<i_inst->_ref_record->num_of_srv;i2++){ TLabelCache_reset(&cache); //Bufferの取得 obuf=NyLPC_cUdpSocket_allocSendBuf(&(i_inst->_super),512,&obuflen,TIMEOUT_IN_MS); if(obuf==NULL){ return; } l=setResponseHeader(obuf,NULL,1,0,3); s=writePtrRecord(i_inst->_ref_record,i2,obuf+l,obuflen-l,&cache); if(s<=0){ NyLPC_OnErrorGoto(ERROR); } l+=s; s=writeSRVRecord(i_inst,i2,obuf+l,obuflen-l,&cache); if(s<=0){ NyLPC_OnErrorGoto(ERROR); } l+=s; s=writeTXTRecord(i_inst,i2,obuf+l,obuflen-l,&cache); if(s<=0){ NyLPC_OnErrorGoto(ERROR); } l+=s; //Aレコード s=writeARecord(obuf+l,obuflen-l,i_inst->_ref_record->a,&(i_inst->_super.uip_udp_conn.lipaddr)); if(s<=0){ NyLPC_OnErrorGoto(ERROR); } l+=s; if(!NyLPC_cUdpSocket_psend(&(i_inst->_super),&MDNS_MCAST_IPADDR,MDNS_MCAST_PORT,obuf,l)){ NyLPC_OnErrorGoto(ERROR); } } return; ERROR: NyLPC_cUdpSocket_releaseSendBuf(&(i_inst->_super),obuf); return; } static void sendReply2(NyLPC_TcMDnsServer_t* i_inst,const struct NyLPC_TDnsHeader* i_dns_header,const struct NyLPC_TDnsQuestion* q) { NyLPC_TInt16 ptr_recode; NyLPC_TInt16 i2; char* obuf; NyLPC_TUInt16 obuflen; NyLPC_TUInt16 l,s; struct TLabelCache cache; TLabelCache_reset(&cache); //パケットヘッダの生成 switch(q->qtype){ case NyLPC_TDnsQuestion_QTYPR_SRV: //SRV,A record ptr_recode=NyLPC_TDnsRecord_getMatchSrvIdx(i_inst->_ref_record,q->qname); if(ptr_recode<0){ goto DROP; } //Bufferの取得 obuf=NyLPC_cUdpSocket_allocSendBuf(&(i_inst->_super),512,&obuflen,0); if(obuf==NULL){ goto DROP; } l=setResponseHeader(obuf,i_dns_header,1,0,2); s=writeSRVRecord(i_inst,ptr_recode,obuf+l,obuflen-l,&cache); if(s<=0){ NyLPC_OnErrorGoto(ERROR); } l+=s; s=writeTXTRecord(i_inst,ptr_recode,obuf+l,obuflen-l,&cache); if(s<=0){ NyLPC_OnErrorGoto(ERROR); } l+=s; //Aレコード s=writeARecord(obuf+l,obuflen-l,i_inst->_ref_record->a,&(i_inst->_super.uip_udp_conn.lipaddr)); if(s<=0){ NyLPC_OnErrorGoto(ERROR); } l+=s; break; case NyLPC_TDnsQuestion_QTYPR_A: //自分宛?(name.local) if(!isEqualName(i_inst->_ref_record->a,q->qname)){ goto DROP; } //Bufferの取得 obuf=NyLPC_cUdpSocket_allocSendBuf(&(i_inst->_super),512,&obuflen,0); if(obuf==NULL){ goto DROP; } //Headerのコピー l=setResponseHeader(obuf,i_dns_header,1,0,0); //Aレコードのみ s=writeARecord(obuf+l,obuflen-l,i_inst->_ref_record->a,&(i_inst->_super.uip_udp_conn.lipaddr)); if(s<=0){ NyLPC_OnErrorGoto(ERROR); } l+=s; break; case NyLPC_TDnsQuestion_QTYPR_PTR: if(NyLPC_TDnsRecord_isServicesDnsSd(q->qname)){ //Bufferの取得 obuf=NyLPC_cUdpSocket_allocSendBuf(&(i_inst->_super),512,&obuflen,0); if(obuf==NULL){ goto DROP; } l=setResponseHeader(obuf,i_dns_header,i_inst->_ref_record->num_of_srv,0,0); for(i2=0;i2<i_inst->_ref_record->num_of_srv;i2++){ s=writeSdPtrRecord(q->qname,&(i_inst->_ref_record->srv[i2]),obuf+l,obuflen-l); if(s<=0){ NyLPC_OnErrorGoto(ERROR); } l+=s; } }else{ //自分宛?(proto.local) ptr_recode=NyLPC_TDnsRecord_getMatchPtrIdx(i_inst->_ref_record,q->qname); if(ptr_recode<0){ goto DROP; } //Bufferの取得 obuf=NyLPC_cUdpSocket_allocSendBuf(&(i_inst->_super),512,&obuflen,0); if(obuf==NULL){ goto DROP; } l=setResponseHeader(obuf,i_dns_header,1,0,3); s=writePtrRecord(i_inst->_ref_record,ptr_recode,obuf+l,obuflen-l,&cache); if(s<=0){ NyLPC_OnErrorGoto(ERROR); } l+=s; s=writeSRVRecord(i_inst,ptr_recode,obuf+l,obuflen-l,&cache); if(s<=0){ NyLPC_OnErrorGoto(ERROR); } l+=s; s=writeTXTRecord(i_inst,ptr_recode,obuf+l,obuflen-l,&cache); if(s<=0){ NyLPC_OnErrorGoto(ERROR); } l+=s; //Aレコード s=writeARecord(obuf+l,obuflen-l,i_inst->_ref_record->a,&(i_inst->_super.uip_udp_conn.lipaddr)); if(s<=0){ NyLPC_OnErrorGoto(ERROR); } l+=s; } break; case NyLPC_TDnsQuestion_QTYPR_TXT: //自分宛?(proto.local) ptr_recode=NyLPC_TDnsRecord_getMatchSrvIdx(i_inst->_ref_record,q->qname); if(ptr_recode<0){ goto DROP; } //Bufferの取得 obuf=NyLPC_cUdpSocket_allocSendBuf(&(i_inst->_super),512,&obuflen,0); l=setResponseHeader(obuf,i_dns_header,1,0,1); s=writeTXTRecord(i_inst,ptr_recode,obuf+l,obuflen-l,&cache); if(s<=0){ NyLPC_OnErrorGoto(ERROR); } l+=s; s=writeARecord(obuf+l,obuflen-l,i_inst->_ref_record->a,&(i_inst->_super.uip_udp_conn.lipaddr)); if(s<=0){ NyLPC_OnErrorGoto(ERROR); } l+=s; break; default: goto DROP; } if(!NyLPC_cUdpSocket_psend(&(i_inst->_super),&MDNS_MCAST_IPADDR,MDNS_MCAST_PORT,obuf,l)){ NyLPC_OnErrorGoto(ERROR); } return; ERROR: NyLPC_cUdpSocket_releaseSendBuf(&(i_inst->_super),obuf); DROP: return; } #define CTRL_FLAG_INIT 0x00 #define CTRL_FLAG_STARTED 0x80 #define CTRL_FLAG_STOP_REQUESTED 0x40 #define CTRL_FLAG_PROCESS_PACKET 0x20 //パケット処理中の間1 static NyLPC_TBool onPacket(NyLPC_TcUdpSocket_t* i_inst,const void* i_buf,const struct NyLPC_TIPv4RxInfo* i_info) { NyLPC_TUInt16 in_len=i_info->size; NyLPC_TUInt16 num_of_query; const char* qptr; struct NyLPC_TDnsQuestion q; NyLPC_TUInt16 s; NyLPC_TInt16 i; if(i_info->peer_port!=MDNS_MCAST_PORT || !NyLPC_TIPv4Addr_isEqual(&MDNS_MCAST_IPADDR,&i_info->ip)){ return NyLPC_TBool_FALSE; } num_of_query=getNumberOfQuestion(i_buf,in_len); if(num_of_query==0){ goto DROP; } qptr=(const char*)i_buf+sizeof(struct NyLPC_TDnsHeader); in_len-=sizeof(struct NyLPC_TDnsHeader); for(i=0;i<num_of_query;i++){ //Queryのパース s=NyLPC_TDnsQuestion_parse(qptr,in_len,&q); if(s==0){ goto DROP; } qptr+=s; in_len-=s; sendReply2((NyLPC_TcMDnsServer_t*)i_inst,(const struct NyLPC_TDnsHeader*)i_buf,&q); } //パケット処理終了 return NyLPC_TBool_FALSE; DROP: return NyLPC_TBool_FALSE; } static void onPeriodic(NyLPC_TcUdpSocket_t* i_inst) { if(NyLPC_cStopwatch_isExpired(&((NyLPC_TcMDnsServer_t*)i_inst)->_periodic_sw)){ //アナウンス sendAnnounse(((NyLPC_TcMDnsServer_t*)i_inst)); //TTL(msec)*1000*80% NyLPC_cStopwatch_startExpire((&((NyLPC_TcMDnsServer_t*)i_inst)->_periodic_sw),NyLPC_TcMDns_TTL*1000/2); } } NyLPC_TBool NyLPC_cMDnsServer_initialize( NyLPC_TcMDnsServer_t* i_inst,const struct NyLPC_TDnsRecord* i_ref_record) { NyLPC_cStopwatch_initialize(&(i_inst->_periodic_sw)); NyLPC_cStopwatch_startExpire(&(i_inst->_periodic_sw),1000); NyLPC_cUdpSocket_initialize(&(i_inst->_super),MDNS_MCAST_PORT,NULL,0); NyLPC_cUdpSocket_setOnRxHandler(&(i_inst->_super),onPacket); NyLPC_cUdpSocket_setOnPeriodicHandler(&(i_inst->_super),onPeriodic); NyLPC_cUdpSocket_joinMulticast(&(i_inst->_super),&MDNS_MCAST_IPADDR); i_inst->_ref_record=i_ref_record; return NyLPC_TBool_TRUE; } void NyLPC_cMDnsServer_finalize( NyLPC_TcMDnsServer_t* i_inst) { NyLPC_cUdpSocket_finalize(&(i_inst->_super)); NyLPC_cStopwatch_finalize(&(i_inst->_periodic_sw)); }