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_cIPv4Arp.c Source File

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