This is Webservice SDK for mbed. LPCXpresso1769/LPC1768/FRDM-K64F/LPC4088
Dependents: MbedFileServer_1768MiniDK2 RedWireBridge IssueDebug_gcc MiMicRemoteMCU-for-Mbed ... more
NyLPC_cIPv4Arp.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 * Parts of this file were leveraged from uIP: 00027 * 00028 * Copyright (c) 2001-2003, Adam Dunkels. 00029 * All rights reserved. 00030 * 00031 * Redistribution and use in source and binary forms, with or without 00032 * modification, are permitted provided that the following conditions 00033 * are met: 00034 * 1. Redistributions of source code must retain the above copyright 00035 * notice, this list of conditions and the following disclaimer. 00036 * 2. Redistributions in binary form must reproduce the above copyright 00037 * notice, this list of conditions and the following disclaimer in the 00038 * documentation and/or other materials provided with the distribution. 00039 * 3. The name of the author may not be used to endorse or promote 00040 * products derived from this software without specific prior 00041 * written permission. 00042 * 00043 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS 00044 * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 00045 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 00046 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY 00047 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 00048 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE 00049 * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 00050 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, 00051 * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING 00052 * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 00053 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 00054 */ 00055 #include "NyLPC_cIPv4Arp.h" 00056 #include "../NyLPC_NetIf_ip_types.h" 00057 #include "NyLPC_cMiMicIpNetIf_protected.h" 00058 #include <string.h> 00059 00060 00061 /** 00062 * The maxium age of ARP table entries measured in 10ths of seconds. 00063 * 00064 * An UIP_ARP_MAXAGE of 120 corresponds to 20 minutes (BSD 00065 * default). 00066 */ 00067 #define UIP_ARP_MAXAGE 120 00068 00069 00070 //static const struct NyLPC_TEthAddr broadcast_ethaddr = { { 0xff, 0xff, 0xff,0xff, 0xff, 0xff } }; 00071 //static const struct NyLPC_TIPv4Addr broadcast_ipaddr = { 0xfffffff }; 00072 00073 00074 00075 00076 static void uip_arp_update(NyLPC_TcIPv4Arp_t* i_inst,const struct NyLPC_TIPv4Addr* ipaddr,const struct NyLPC_TEthAddr *ethaddr); 00077 /*-----------------------------------------------------------------------------------*/ 00078 /** 00079 * Initialize the ARP module. 00080 * 00081 */ 00082 /*-----------------------------------------------------------------------------------*/ 00083 void NyLPC_cIPv4Arp_initialize(NyLPC_TcIPv4Arp_t* i_inst,const NyLPC_TcIPv4Config_t* i_ref_config) 00084 { 00085 int i; 00086 struct NyLPC_TArpTableItem* tbl=i_inst->arp_table; 00087 i_inst->_cfg = i_ref_config; 00088 i_inst->arptime = 0; 00089 i_inst->tmpage = 0; 00090 for (i = 0; i < NyLPC_TcIPv4Arp_ARPTAB_SIZE; ++i) { 00091 memset(&(tbl[i].ipaddr), 0, sizeof(struct NyLPC_TIPv4Addr)); 00092 } 00093 } 00094 /*-----------------------------------------------------------------------------------*/ 00095 /** 00096 * Periodic ARP processing function. 00097 * 00098 * This function performs periodic timer processing in the ARP module 00099 * and should be called at regular intervals. The recommended interval 00100 * is 10 seconds between the calls. 00101 * 00102 */ 00103 /*-----------------------------------------------------------------------------------*/ 00104 void NyLPC_cIPv4Arp_periodic(NyLPC_TcIPv4Arp_t* i_inst) 00105 { 00106 struct NyLPC_TArpTableItem* tbl=i_inst->arp_table; 00107 struct NyLPC_TArpTableItem* tabptr; 00108 int i; 00109 i_inst->arptime++; 00110 for (i = 0; i < NyLPC_TcIPv4Arp_ARPTAB_SIZE; ++i) { 00111 tabptr = &tbl[i]; 00112 if (tabptr->ipaddr.v != 0 && i_inst->arptime - tabptr->time >= UIP_ARP_MAXAGE) 00113 { 00114 tabptr->ipaddr.v = 0; 00115 } 00116 } 00117 00118 } 00119 /*-----------------------------------------------------------------------------------*/ 00120 /** 00121 * ARP processing for incoming IP packets 00122 * 00123 * This function should be called by the device driver when an IP 00124 * packet has been received. The function will check if the address is 00125 * in the ARP cache, and if so the ARP cache entry will be 00126 * refreshed. If no ARP cache entry was found, a new one is created. 00127 * 00128 * This function expects an IP packet with a prepended Ethernet header 00129 * in the uip_buf[] buffer, and the length of the packet in the global 00130 * variable uip_len. 00131 */ 00132 /*-----------------------------------------------------------------------------------*/ 00133 void NyLPC_cIPv4Arp_incomingIp(NyLPC_TcIPv4Arp_t* i_inst,const struct NyLPC_TEthernetIIHeader* i_eth,struct NyLPC_TIPv4Addr i_ip_src) 00134 { 00135 //EtherとIPv4の値を読みだす。 00136 /* Only insert/update an entry if the source IP address of the 00137 incoming IP packet comes from a host on the local network. */ 00138 if ((i_ip_src.v & i_inst->_cfg->netmask.v) != (i_inst->_cfg->ip_addr.v & i_inst->_cfg->netmask.v)) { 00139 return; 00140 } 00141 uip_arp_update(i_inst,&(i_ip_src), &(i_eth->src)); 00142 return; 00143 } 00144 /** 00145 * ARP processing for incoming ARP packets. 00146 * 00147 * This function should be called by the device driver when an ARP 00148 * packet has been received. The function will act differently 00149 * depending on the ARP packet type: if it is a reply for a request 00150 * that we previously sent out, the ARP cache will be filled in with 00151 * the values from the ARP reply. If the incoming ARP packet is an ARP 00152 * request for our IP address, an ARP reply packet is created and put 00153 * into the uip_buf[] buffer. 00154 * 00155 * When the function returns, the value of the global variable uip_len 00156 * indicates whether the device driver should send out a packet or 00157 * not. If uip_len is zero, no packet should be sent. If uip_len is 00158 * non-zero, it contains the length of the outbound packet that is 00159 * present in the uip_buf[] buffer. 00160 * 00161 * This function expects an ARP packet with a prepended Ethernet 00162 * header in the uip_buf[] buffer, and the length of the packet in the 00163 * global variable uip_len. 00164 */ 00165 00166 00167 /** 00168 * ARPパケットの読出し用構造体 00169 */ 00170 struct TArpPacketPtr 00171 { 00172 struct NyLPC_TEthernetIIHeader header; 00173 struct NyLPC_TArpHeader arp; 00174 }PACK_STRUCT_END; 00175 00176 /** 00177 * arpパケットを処理します。 00178 */ 00179 void* NyLPC_cIPv4Arp_rx(NyLPC_TcIPv4Arp_t* i_inst,const struct NyLPC_TArpHeader* i_arp, NyLPC_TUInt16 i_len, NyLPC_TUInt16* o_tx_len) 00180 { 00181 struct NyLPC_TArpHeader* arp_tx; 00182 if (i_len < sizeof(struct NyLPC_TArpHeader)) { 00183 return NULL; 00184 } 00185 const NyLPC_TcIPv4Config_t* cfg=i_inst->_cfg; 00186 switch (i_arp->opcode) { 00187 case NyLPC_HTONS(ARP_REQUEST): 00188 /* ARP request. If it asked for our address, we send out a reply. */ 00189 if (NyLPC_TIPv4Addr_isEqual(&(i_arp->dipaddr), &(cfg->ip_addr))) { 00190 /* First, we register the one who made the request in our ARP 00191 table, since it is likely that we will do more communication 00192 with this host in the future. */ 00193 uip_arp_update(i_inst,&(i_arp->sipaddr), &i_arp->shwaddr); 00194 //イーサネットヘッダもいじくるから 00195 arp_tx=(struct NyLPC_TArpHeader*)NyLPC_cMiMicIpNetIf_allocSysTxBuf(); 00196 00197 /* The reply opcode is 2. */ 00198 arp_tx->hwtype =i_arp->hwtype; 00199 arp_tx->protocol =i_arp->protocol; 00200 arp_tx->hwlen =i_arp->hwlen; 00201 arp_tx->protolen =i_arp->protolen; 00202 arp_tx->opcode = NyLPC_HTONS(2); 00203 memcpy(arp_tx->dhwaddr.addr, i_arp->shwaddr.addr, 6); 00204 memcpy(arp_tx->shwaddr.addr, cfg->eth_mac.addr, 6); 00205 arp_tx->dipaddr = i_arp->sipaddr; 00206 arp_tx->sipaddr = cfg->ip_addr; 00207 *o_tx_len=NyLPC_TEthernetIIHeader_setArpTx((((struct NyLPC_TEthernetIIHeader*)arp_tx)-1),&(i_inst->_cfg->eth_mac)); 00208 00209 // /* The reply opcode is 2. */ 00210 // i_arp->opcode = NyLPC_HTONS(2); 00211 // 00212 // memcpy(i_arp->dhwaddr.addr, i_arp->shwaddr.addr, 6); 00213 // memcpy(i_arp->shwaddr.addr, cfg->eth_mac.addr, 6); 00214 // 00215 // i_arp->dipaddr = i_arp->sipaddr; 00216 // i_arp->sipaddr = cfg->ip_addr; 00217 return arp_tx; 00218 } 00219 break; 00220 case NyLPC_HTONS(ARP_REPLY): 00221 // ARP reply. We insert or update the ARP table if it was meant for us. 00222 if (NyLPC_TIPv4Addr_isEqual(&(i_arp->dipaddr),&(cfg->ip_addr))) { 00223 uip_arp_update(i_inst,&(i_arp->sipaddr), &i_arp->shwaddr); 00224 } 00225 break; 00226 } 00227 return NULL; 00228 } 00229 /** 00230 * Prepend Ethernet header to an outbound IP packet and see if we need 00231 * to send out an ARP request. 00232 * 00233 * This function should be called before sending out an IP packet. The 00234 * function checks the destination IP address of the IP packet to see 00235 * what Ethernet MAC address that should be used as a destination MAC 00236 * address on the Ethernet. 00237 * 00238 * If the destination IP address is in the local network (determined 00239 * by logical ANDing of netmask and our IP address), the function 00240 * checks the ARP cache to see if an entry for the destination IP 00241 * address is found. If so, an Ethernet header is prepended and the 00242 * function returns. If no ARP cache entry is found for the 00243 * destination IP address, the packet in the uip_buf[] is replaced by 00244 * an ARP request packet for the IP address. The IP packet is dropped 00245 * and it is assumed that they higher level protocols (e.g., TCP) 00246 * eventually will retransmit the dropped packet. 00247 * 00248 * If the destination IP address is not on the local network, the IP 00249 * address of the default router is used instead. 00250 * 00251 * When the function returns, a packet is present in the uip_buf[] 00252 * buffer, and the length of the packet is in the global variable 00253 * uip_len. 00254 */ 00255 00256 /** 00257 * IPアドレス-MACアドレス交換 00258 */ 00259 const struct NyLPC_TEthAddr* NyLPC_cIPv4Arp_IPv4toEthAddr(NyLPC_TcIPv4Arp_t* i_inst,const struct NyLPC_TIPv4Addr i_ip_addr) 00260 { 00261 int i; 00262 struct NyLPC_TArpTableItem *tabptr; 00263 //ARPテーブルから検索 00264 for (i = NyLPC_TcIPv4Arp_ARPTAB_SIZE - 1; i >= 0; i--) { 00265 tabptr = &i_inst->arp_table[i]; 00266 if (NyLPC_TIPv4Addr_isEqual(&i_ip_addr,&(tabptr->ipaddr))) { 00267 return &tabptr->ethaddr; 00268 } 00269 } 00270 return NULL; 00271 } 00272 00273 00274 00275 00276 00277 00278 00279 static void uip_arp_update(NyLPC_TcIPv4Arp_t* i_inst,const struct NyLPC_TIPv4Addr* ipaddr,const struct NyLPC_TEthAddr *ethaddr) 00280 { 00281 register struct NyLPC_TArpTableItem *tabptr; 00282 int i,c; 00283 /* Walk through the ARP mapping table and try to find an entry to 00284 update. If none is found, the IP -> MAC address mapping is 00285 inserted in the ARP table. */ 00286 for (i = 0; i < NyLPC_TcIPv4Arp_ARPTAB_SIZE; ++i) { 00287 tabptr = &i_inst->arp_table[i]; 00288 /* Only check those entries that are actually in use. */ 00289 if (tabptr->ipaddr.v != 0) { 00290 /* Check if the source IP address of the incoming packet matches 00291 the IP address in this ARP table entry. */ 00292 if (ipaddr->v == tabptr->ipaddr.v) { 00293 /* An old entry found, update this and return. */ 00294 memcpy(tabptr->ethaddr.addr, ethaddr->addr, 6); 00295 tabptr->time = i_inst->arptime; 00296 00297 return; 00298 } 00299 } 00300 } 00301 00302 /* If we get here, no existing ARP table entry was found, so we 00303 create one. */ 00304 /* First, we try to find an unused entry in the ARP table. */ 00305 for (i = 0; i < NyLPC_TcIPv4Arp_ARPTAB_SIZE; ++i) { 00306 tabptr = &i_inst->arp_table[i]; 00307 if (tabptr->ipaddr.v == 0) { 00308 break; 00309 } 00310 } 00311 00312 /* If no unused entry is found, we try to find the oldest entry and 00313 throw it away. */ 00314 if (i == NyLPC_TcIPv4Arp_ARPTAB_SIZE) { 00315 i_inst->tmpage = 0; 00316 c = 0; 00317 for (i = 0; i < NyLPC_TcIPv4Arp_ARPTAB_SIZE; ++i) { 00318 tabptr = &i_inst->arp_table[i]; 00319 if (i_inst->arptime - tabptr->time > i_inst->tmpage) { 00320 i_inst->tmpage = i_inst->arptime - tabptr->time; 00321 c = i; 00322 } 00323 } 00324 i = c; 00325 tabptr = &i_inst->arp_table[i]; 00326 } 00327 00328 /* Now, i is the ARP table entry which we will fill with the new information. */ 00329 tabptr->ipaddr = *ipaddr; 00330 memcpy(tabptr->ethaddr.addr, ethaddr->addr, 6); 00331 tabptr->time = i_inst->arptime; 00332 } 00333 00334 00335
Generated on Tue Jul 12 2022 15:46:15 by 1.7.2