This is Webservice SDK for mbed. LPCXpresso1769/LPC1768/FRDM-K64F/LPC4088
Dependents: MbedFileServer_1768MiniDK2 RedWireBridge IssueDebug_gcc MiMicRemoteMCU-for-Mbed ... more
NyLPC_cDhcpClient.c
00001 /********************************************************************************* 00002 * PROJECT: MiMic 00003 * -------------------------------------------------------------------------------- 00004 * 00005 * This file is part of MiMic 00006 * Copyright (C)2011-2013 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_cDhcpClient.h" 00027 #include "../NyLPC_cNet.h" 00028 #include <stdio.h> 00029 #include <string.h> 00030 00031 struct NyLPC_TDhcpHeader 00032 { 00033 NyLPC_TUInt8 op; 00034 NyLPC_TUInt8 htype; 00035 NyLPC_TUInt8 hlen; 00036 NyLPC_TUInt8 hops; 00037 NyLPC_TUInt32 xid; 00038 NyLPC_TUInt16 secs; 00039 NyLPC_TUInt16 flags; 00040 NyLPC_TUInt32 ciaddr; 00041 NyLPC_TUInt32 yiaddr; 00042 NyLPC_TUInt32 siaddr; 00043 NyLPC_TUInt32 giaddr; 00044 struct{ 00045 struct NyLPC_TEthAddr emac; 00046 NyLPC_TChar padding[10]; 00047 }chaddr; 00048 NyLPC_TChar sname[64]; 00049 NyLPC_TChar file[128]; 00050 }PACK_STRUCT_END; 00051 00052 #define NyLPC_TDhcpHeader_BOOTREQUEST 1 00053 #define NyLPC_TDhcpHeader_BOOTREPLY 2 00054 00055 #define DHCP_OPT_ID_ROUTER 3 00056 #define DHCP_OPT_ID_SERVER_ID 54 00057 #define DHCP_OPT_ID_NETMASK 1 00058 #define DHCP_OPT_ID_MESSAGETYPE 53 00059 00060 00061 00062 /** 00063 * DHCPパケットから32bit値を読み出す。 00064 * @return 00065 * ネットワークオーダー 00066 */ 00067 static NyLPC_TBool getUInt32Option(const NyLPC_TUInt8* i_buf,NyLPC_TUInt16 len,NyLPC_TUInt8 i_id,NyLPC_TUInt32* o_v) 00068 { 00069 const NyLPC_TUInt8* p=i_buf+sizeof(struct NyLPC_TDhcpHeader)+4; 00070 while(*p!=0x00 && p<(i_buf+len-5)){ 00071 if(*p==i_id){ 00072 if(*(p+1)==4){ 00073 *o_v=*((NyLPC_TUInt32*)(p+2)); 00074 return NyLPC_TBool_TRUE; 00075 } 00076 }else{ 00077 p+=(*(p+1))+2; 00078 } 00079 } 00080 return NyLPC_TBool_FALSE; 00081 } 00082 static NyLPC_TBool getUInt8Option(const NyLPC_TUInt8* i_buf,NyLPC_TUInt16 len,NyLPC_TUInt8 i_id,NyLPC_TUInt8* o_v) 00083 { 00084 const NyLPC_TUInt8* p=i_buf+sizeof(struct NyLPC_TDhcpHeader)+4; 00085 while(*p!=0x00 && p<(i_buf+len-5)){ 00086 if(*p==i_id){ 00087 if(*(p+1)==1){ 00088 *o_v=*(p+2); 00089 return NyLPC_TBool_TRUE; 00090 } 00091 }else{ 00092 p+=(*(p+1))+2; 00093 } 00094 } 00095 return NyLPC_TBool_FALSE; 00096 } 00097 static NyLPC_TBool NyLPC_TDhcpHeader_parseDHCPOFFER(const NyLPC_TUInt8* i_buf,NyLPC_TUInt16 i_len,NyLPC_TUInt32 i_xid,NyLPC_TcDhcpClient_t* i_inst) 00098 { 00099 struct NyLPC_TDhcpHeader* p=(struct NyLPC_TDhcpHeader*)i_buf; 00100 //XIDのチェック 00101 if(p->xid!=NyLPC_HTONL(i_xid)){ 00102 return NyLPC_TBool_FALSE; 00103 } 00104 //OFFERのclient IPアドレスをresultへ保存情報の保存 00105 i_inst->_result->ip_addr.v=p->yiaddr; 00106 //SERVER IDを保存 00107 if(!getUInt32Option(i_buf,i_len,DHCP_OPT_ID_SERVER_ID,&i_inst->_offerserver.v)){ 00108 return NyLPC_TBool_FALSE; 00109 } 00110 return NyLPC_TBool_TRUE; 00111 } 00112 00113 static NyLPC_TBool NyLPC_TDhcpHeader_parseDHCPACK(const NyLPC_TUInt8* i_buf,NyLPC_TUInt16 i_len,NyLPC_TUInt32 i_xid,NyLPC_TcIPv4Config_t* result) 00114 { 00115 struct NyLPC_TDhcpHeader* p=(struct NyLPC_TDhcpHeader*)i_buf; 00116 //XIDのチェック 00117 if(p->xid!=NyLPC_HTONL(i_xid)){ 00118 return NyLPC_TBool_FALSE; 00119 } 00120 if(!getUInt32Option(i_buf,i_len,DHCP_OPT_ID_ROUTER,&result->dr_addr.v)){ 00121 result->dr_addr=NyLPC_TIPv4Addr_ZERO; 00122 } 00123 if(!getUInt32Option(i_buf,i_len,DHCP_OPT_ID_NETMASK,&result->netmask.v)){ 00124 result->netmask=NyLPC_TIPv4Addr_ZERO; 00125 } 00126 result->ip_addr.v=p->yiaddr; 00127 return NyLPC_TBool_TRUE; 00128 } 00129 00130 static void NyLPC_TDhcpHeader_setDHCPDISCOVER(char* i_buf,NyLPC_TUInt32 i_xid,const struct NyLPC_TEthAddr* emac,NyLPC_TUInt16* o_len) 00131 { 00132 struct NyLPC_TDhcpHeader* p=(struct NyLPC_TDhcpHeader*)i_buf; 00133 memset(i_buf,0,sizeof(struct NyLPC_TDhcpHeader)); 00134 p->op=NyLPC_TDhcpHeader_BOOTREQUEST; 00135 p->htype=1; 00136 p->hlen=6; 00137 p->xid=NyLPC_HTONL(i_xid); 00138 p->chaddr.emac=*emac; 00139 p->flags=NyLPC_HTONS(0x8000); 00140 memcpy(i_buf+sizeof(struct NyLPC_TDhcpHeader), 00141 "\x63\x82\x53\x63" //4 00142 "\x35\x01\x01" //3 MESSAGE TYPE 00143 "\x37\x03\x01\x03\x06" //5 REQUEST LIST(1,3,6) 00144 "\x3d\x07\x01\x00\x00\x00\x00\x00\x00" //9 CLIENT INDIFIRE 00145 "\xff",4+3+5+9+1); 00146 //emacの上書き 00147 memcpy((i_buf+sizeof(struct NyLPC_TDhcpHeader)+4+3+5+3),emac->addr,6); 00148 //送信するパケットの長さ 00149 *o_len=sizeof(struct NyLPC_TDhcpHeader)+4+3+5+9+1; 00150 return; 00151 } 00152 static void NyLPC_TDhcpHeader_setDHCPREQUEST(char* i_buf,NyLPC_TUInt32 i_xid,const struct NyLPC_TIPv4Addr* i_sid,const struct NyLPC_TIPv4Addr* i_reqid,const struct NyLPC_TEthAddr* emac,NyLPC_TUInt16* o_len) 00153 { 00154 struct NyLPC_TDhcpHeader* p=(struct NyLPC_TDhcpHeader*)i_buf; 00155 memset(i_buf,0,sizeof(struct NyLPC_TDhcpHeader)); 00156 p->op=NyLPC_TDhcpHeader_BOOTREQUEST; 00157 p->htype=1; 00158 p->hlen=6; 00159 p->xid=NyLPC_HTONL(i_xid); 00160 p->chaddr.emac=*emac; 00161 p->flags=NyLPC_HTONS(0x8000); 00162 memcpy(i_buf+sizeof(struct NyLPC_TDhcpHeader), 00163 "\x63\x82\x53\x63" //4 00164 "\x35\x01\x03" //3 MESSAGE TYPE 00165 "\x37\x03\x01\x03\x06" //5 REQUEST LIST(1,3,6) 00166 "\x3d\x07\x01\x00\x00\x00\x00\x00\x00" //9 CLIENT INDIFIRE 00167 "\x36\x04\x00\x00\x00\x00" // 6 SERVER ID 00168 "\x32\x04\x00\x00\x00\x00" // 6 Reqested IP 00169 "\xff",4+3+5+9+6+6+1); 00170 //emacの上書き 00171 memcpy((i_buf+sizeof(struct NyLPC_TDhcpHeader)+4+3+5+3),emac->addr,6); 00172 //sidの上書き 00173 memcpy((i_buf+sizeof(struct NyLPC_TDhcpHeader)+4+3+5+9+2),i_sid,4); 00174 //reqidの上書き 00175 memcpy((i_buf+sizeof(struct NyLPC_TDhcpHeader)+4+3+5+9+6+2),i_reqid,4); 00176 //送信するパケットの長さ 00177 *o_len=sizeof(struct NyLPC_TDhcpHeader)+4+3+5+9+6+6+1; 00178 return; 00179 } 00180 00181 00182 00183 #define TcDhcpSock_ST_WAIT_OFFER 1 00184 #define TcDhcpSock_ST_WAIT_OFFER_OK 2 00185 #define TcDhcpSock_ST_WAIT_ACK 3 00186 #define TcDhcpSock_ST_WAIT_ACK_OK 4 00187 #define TcDhcpSock_ST_DONE_NG 3 00188 #define TcDhcpSock_ST_DONE_OK 4 00189 00190 00191 00192 00193 #define DHCP_OPT_ID_MESSAGETYPE_ACK 5 00194 #define DHCP_OPT_ID_MESSAGETYPE_OFFER 2 00195 00196 static NyLPC_TBool onPacket(NyLPC_TiUdpSocket_t* i_inst,const void* i_buf,const struct NyLPC_TIPv4RxInfo* i_info); 00197 00198 /** 00199 * DHCPソケットを作成します。 00200 */ 00201 NyLPC_TBool NyLPC_cDhcpClient_initialize(NyLPC_TcDhcpClient_t* i_inst) 00202 { 00203 i_inst->_socket=NyLPC_cNet_createUdpSocketEx(68,NyLPC_TSocketType_UDP_NOBUF); 00204 if(i_inst->_socket==NULL){ 00205 return NyLPC_TBool_FALSE; 00206 } 00207 i_inst->_socket->_tag=i_inst; 00208 NyLPC_iUdpSocket_setBroadcast(i_inst->_socket); 00209 NyLPC_iUdpSocket_setOnRxHandler(i_inst->_socket,onPacket); 00210 return NyLPC_TBool_TRUE; 00211 } 00212 void NyLPC_cDhcpClient_finalize(NyLPC_TcDhcpClient_t* i_inst) 00213 { 00214 NyLPC_iUdpSocket_finalize(i_inst->_socket); 00215 } 00216 #define TIMEOUT_SOCKAPI_MS 1000 00217 #define TIMEOUT_RECVMSG_MS 3000 00218 00219 /** 00220 * ネットワークを更新します。 00221 * emac/default_mssを設定したネットワークが必要です。 00222 */ 00223 static NyLPC_TBool NyLPC_cDhcpClient_dhcpRequest(NyLPC_TcDhcpClient_t* i_inst,NyLPC_TcIPv4Config_t* i_result) 00224 { 00225 char* buf; 00226 NyLPC_TcStopwatch_t sw; 00227 NyLPC_TUInt16 s; 00228 NyLPC_TInt16 hint=sizeof(struct NyLPC_TDhcpHeader)+128; 00229 i_inst->txid+=(*(NyLPC_TUInt16*)(&(i_result->eth_mac.addr[2])))+(*(NyLPC_TUInt16*)(&(i_result->eth_mac.addr[4]))); 00230 i_inst->_result=i_result; 00231 buf=NyLPC_iUdpSocket_allocSendBuf(i_inst->_socket,hint,&s,TIMEOUT_SOCKAPI_MS); 00232 if(buf==NULL || s<hint){ 00233 return NyLPC_TBool_FALSE; 00234 } 00235 NyLPC_TDhcpHeader_setDHCPDISCOVER(buf,i_inst->txid,&i_inst->_result->eth_mac,&s); 00236 i_inst->_status=TcDhcpSock_ST_WAIT_OFFER; 00237 if(!NyLPC_iUdpSocket_psend(i_inst->_socket,&NyLPC_TIPv4Addr_BROADCAST,67,buf,s)){ 00238 NyLPC_iUdpSocket_releaseSendBuf(i_inst->_socket,buf); 00239 return NyLPC_TBool_FALSE; 00240 } 00241 NyLPC_cStopwatch_initialize(&sw); 00242 NyLPC_cStopwatch_startExpire(&sw,TIMEOUT_RECVMSG_MS); 00243 while(i_inst->_status==TcDhcpSock_ST_WAIT_OFFER){ 00244 if(NyLPC_cStopwatch_isExpired(&sw)){ 00245 return NyLPC_TBool_FALSE; 00246 } 00247 } 00248 //レスポンスのチェック 00249 if(i_inst->_status!=TcDhcpSock_ST_WAIT_OFFER_OK) 00250 { 00251 return NyLPC_TBool_FALSE; 00252 } 00253 buf=NyLPC_iUdpSocket_allocSendBuf(i_inst->_socket,hint,&s,TIMEOUT_SOCKAPI_MS); 00254 if(buf==NULL || s<hint){ 00255 return NyLPC_TBool_FALSE; 00256 } 00257 NyLPC_TDhcpHeader_setDHCPREQUEST(buf,i_inst->txid,&(i_inst->_offerserver),&(i_inst->_result->ip_addr),&i_inst->_result->eth_mac,&s); 00258 i_inst->_status=TcDhcpSock_ST_WAIT_ACK; 00259 if(!NyLPC_iUdpSocket_psend(i_inst->_socket,&NyLPC_TIPv4Addr_BROADCAST,67,buf,s)){ 00260 NyLPC_iUdpSocket_releaseSendBuf(i_inst->_socket,buf); 00261 return NyLPC_TBool_FALSE; 00262 } 00263 NyLPC_cStopwatch_startExpire(&sw,TIMEOUT_RECVMSG_MS); 00264 while(i_inst->_status==TcDhcpSock_ST_WAIT_ACK){ 00265 if(NyLPC_cStopwatch_isExpired(&sw)){ 00266 return NyLPC_TBool_FALSE; 00267 } 00268 } 00269 //レスポンスのチェック 00270 if(i_inst->_status!=TcDhcpSock_ST_WAIT_ACK_OK) 00271 { 00272 return NyLPC_TBool_FALSE; 00273 } 00274 return NyLPC_TBool_TRUE; 00275 } 00276 00277 /** 00278 * NyLPC_TcIPv4Config_tをDHCPで更新します。 00279 * この関数をコールする時は、サービスは停止中でなければなりません。 00280 * @param i_cfg 00281 * 更新するi_cfg構造体。 00282 * emac,default_mssは設定済である必要があります。他のフィールド値は不定で構いません。 00283 * 更新されるフィールドは、ip,netmast,default_rootの3つです。 00284 * @return 00285 * 更新に成功した場合TRUE 00286 */ 00287 NyLPC_TBool NyLPC_cDhcpClient_requestAddr(NyLPC_TcDhcpClient_t* i_inst,NyLPC_TcIPv4Config_t* i_cfg,NyLPC_TInt16 i_repeat) 00288 { 00289 NyLPC_TInt16 i; 00290 NyLPC_TBool ret=NyLPC_TBool_FALSE; 00291 NyLPC_TcIPv4Config_t c2; 00292 //工場出荷時設定でリセットしてIPを0に 00293 NyLPC_cIPv4Config_initialzeCopy(&c2,i_cfg); 00294 NyLPC_cIPv4Config_setIp(&c2,&NyLPC_TIPv4Addr_ZERO,&NyLPC_TIPv4Addr_ZERO); 00295 NyLPC_cIPv4Config_setDefaultRoute(&c2,&NyLPC_TIPv4Addr_ZERO); 00296 //netを開始 00297 NyLPC_cNet_start(&c2); 00298 for(i=i_repeat-1;i>=0;i--){ 00299 ret=NyLPC_cDhcpClient_dhcpRequest(i_inst,i_cfg); 00300 if(ret){ 00301 break; 00302 } 00303 } 00304 NyLPC_cNet_stop(); 00305 NyLPC_cIPv4Config_finalize(&c2); 00306 return ret; 00307 } 00308 00309 00310 00311 static NyLPC_TBool onPacket(NyLPC_TiUdpSocket_t* i_inst,const void* i_buf,const struct NyLPC_TIPv4RxInfo* i_info) 00312 { 00313 NyLPC_TUInt8 mt;//message type 00314 NyLPC_TcDhcpClient_t* inst=(NyLPC_TcDhcpClient_t*)i_inst->_tag; 00315 struct NyLPC_TDhcpHeader* dnsh=(struct NyLPC_TDhcpHeader*)i_buf; 00316 if(i_info->size<sizeof(struct NyLPC_TDhcpHeader)+1){ 00317 return NyLPC_TBool_FALSE;//DROP 00318 } 00319 switch(inst->_status) 00320 { 00321 case TcDhcpSock_ST_WAIT_ACK: 00322 if(dnsh->op!=NyLPC_TDhcpHeader_BOOTREPLY){ 00323 return NyLPC_TBool_FALSE; 00324 } 00325 if(!getUInt8Option(i_buf,i_info->size,DHCP_OPT_ID_MESSAGETYPE,&mt)){ 00326 return NyLPC_TBool_FALSE; 00327 } 00328 if(mt!=DHCP_OPT_ID_MESSAGETYPE_ACK){ 00329 return NyLPC_TBool_FALSE; 00330 } 00331 if(!NyLPC_TDhcpHeader_parseDHCPACK(i_buf,i_info->size,inst->txid,inst->_result)){ 00332 return NyLPC_TBool_FALSE; 00333 } 00334 inst->_status=TcDhcpSock_ST_WAIT_ACK_OK; 00335 break; 00336 case TcDhcpSock_ST_WAIT_OFFER: 00337 if(dnsh->op!=NyLPC_TDhcpHeader_BOOTREPLY){ 00338 return NyLPC_TBool_FALSE; 00339 } 00340 if(!getUInt8Option(i_buf,i_info->size,DHCP_OPT_ID_MESSAGETYPE,&mt)){ 00341 return NyLPC_TBool_FALSE; 00342 } 00343 if(mt!=DHCP_OPT_ID_MESSAGETYPE_OFFER){ 00344 return NyLPC_TBool_FALSE; 00345 } 00346 if(!NyLPC_TDhcpHeader_parseDHCPOFFER(i_buf,i_info->size,inst->txid,inst)){ 00347 return NyLPC_TBool_FALSE; 00348 } 00349 inst->_status=TcDhcpSock_ST_WAIT_OFFER_OK; 00350 break; 00351 } 00352 return NyLPC_TBool_FALSE; 00353 00354 }
Generated on Tue Jul 12 2022 15:46:15 by 1.7.2