Mbed library for ENC28J60 Ethernet modules. Full support for TCP/IP and UDP Server, Client and HTTP server (webserver). DHCP and DNS is included.
Dependents: mBuino_ENC28_MQTT Nucleo_Web_ENC28J60 Nucleo_Web_ENC28J60_ADC Serial_over_Ethernet ... more
uip_arp.c
00001 /** 00002 * \addtogroup uip 00003 * @{ 00004 */ 00005 /** 00006 * \defgroup uiparp UIP Address Resolution Protocol 00007 * @{ 00008 * 00009 * The Address Resolution Protocol ARP is used for mapping between IP 00010 * addresses and link level addresses such as the Ethernet MAC 00011 * addresses. ARP uses broadcast queries to ask for the link level 00012 * address of a known IP address and the host which is configured with 00013 * the IP address for which the query was meant, will respond with its 00014 * link level address. 00015 * 00016 * \note This ARP implementation only supports Ethernet. 00017 */ 00018 /** 00019 * \file 00020 * Implementation of the ARP Address Resolution Protocol. 00021 * \author Adam Dunkels <adam@dunkels.com> 00022 * 00023 */ 00024 /* 00025 * Copyright (c) 2001-2003, Adam Dunkels. 00026 * All rights reserved. 00027 * 00028 * Redistribution and use in source and binary forms, with or without 00029 * modification, are permitted provided that the following conditions 00030 * are met: 00031 * 1. Redistributions of source code must retain the above copyright 00032 * notice, this list of conditions and the following disclaimer. 00033 * 2. Redistributions in binary form must reproduce the above copyright 00034 * notice, this list of conditions and the following disclaimer in the 00035 * documentation and/or other materials provided with the distribution. 00036 * 3. The name of the author may not be used to endorse or promote 00037 * products derived from this software without specific prior 00038 * written permission. 00039 * 00040 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS 00041 * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 00042 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 00043 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY 00044 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 00045 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE 00046 * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 00047 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, 00048 * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING 00049 * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 00050 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 00051 * 00052 * This file is part of the UIP TCP/IP stack. 00053 * 00054 * $Id: uip_arp.c,v 1.8 2006/06/02 23:36:21 adam Exp $ 00055 * 00056 */ 00057 #include "uip_arp.h" 00058 00059 #include <string.h> 00060 00061 struct arp_hdr 00062 { 00063 struct uip_eth_hdr ethhdr; 00064 u16_t hwtype; 00065 u16_t protocol; 00066 u8_t hwlen; 00067 u8_t protolen; 00068 u16_t opcode; 00069 struct uip_eth_addr shwaddr; 00070 u16_t sipaddr[2]; 00071 struct uip_eth_addr dhwaddr; 00072 u16_t dipaddr[2]; 00073 }; 00074 00075 struct ethip_hdr 00076 { 00077 struct uip_eth_hdr ethhdr; 00078 00079 /* IP header. */ 00080 u8_t vhl, tos, len[2], ipid[2], ipoffset[2], ttl, proto; 00081 u16_t ipchksum; 00082 u16_t srcipaddr[2], destipaddr[2]; 00083 }; 00084 00085 #define ARP_REQUEST 1 00086 #define ARP_REPLY 2 00087 00088 #define ARP_HWTYPE_ETH 1 00089 00090 struct arp_entry 00091 { 00092 u16_t ipaddr[2]; 00093 struct uip_eth_addr ethaddr; 00094 u8_t time; 00095 }; 00096 00097 static const struct uip_eth_addr broadcast_ethaddr = { { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff } }; 00098 static const u16_t broadcast_ipaddr[2] = { 0xffff, 0xffff }; 00099 00100 static struct arp_entry arp_table[UIP_ARPTAB_SIZE]; 00101 static u16_t ipaddr[2]; 00102 static u8_t i, c; 00103 00104 static u8_t arptime; 00105 static u8_t tmpage; 00106 00107 #define BUF ((struct arp_hdr*) &uip_buf[0]) 00108 #define IPBUF ((struct ethip_hdr*) &uip_buf[0]) 00109 /*-----------------------------------------------------------------------------------*/ 00110 00111 /** 00112 * Initialize the ARP module. 00113 * 00114 */ 00115 00116 /*-----------------------------------------------------------------------------------*/ 00117 void uip_arp_init(void) { 00118 for (i = 0; i < UIP_ARPTAB_SIZE; ++i) { 00119 memset(arp_table[i].ipaddr, 0, 4); 00120 } 00121 } 00122 00123 /*-----------------------------------------------------------------------------------*/ 00124 /** 00125 * Periodic ARP processing function. 00126 * 00127 * This function performs periodic timer processing in the ARP module 00128 * and should be called at regular intervals. The recommended interval 00129 * is 10 seconds between the calls. 00130 * 00131 */ 00132 00133 /*-----------------------------------------------------------------------------------*/ 00134 void uip_arp_timer(void) { 00135 struct arp_entry* tabptr; 00136 00137 ++arptime; 00138 for (i = 0; i < UIP_ARPTAB_SIZE; ++i) { 00139 tabptr = &arp_table[i]; 00140 if ((tabptr->ipaddr[0] | tabptr->ipaddr[1]) != 0 && arptime - tabptr->time >= UIP_ARP_MAXAGE) { 00141 memset(tabptr->ipaddr, 0, 4); 00142 } 00143 } 00144 } 00145 00146 /*-----------------------------------------------------------------------------------*/ 00147 static void uip_arp_update(u16_t* ipaddr, struct uip_eth_addr* ethaddr) { 00148 register struct arp_entry* tabptr; 00149 /* Walk through the ARP mapping table and try to find an entry to 00150 update. If none is found, the IP -> MAC address mapping is 00151 inserted in the ARP table. */ 00152 00153 for (i = 0; i < UIP_ARPTAB_SIZE; ++i) { 00154 tabptr = &arp_table[i]; 00155 00156 /* Only check those entries that are actually in use. */ 00157 if (tabptr->ipaddr[0] != 0 && tabptr->ipaddr[1] != 0) { 00158 00159 /* Check if the source IP address of the incoming packet matches 00160 the IP address in this ARP table entry. */ 00161 if (ipaddr[0] == tabptr->ipaddr[0] && ipaddr[1] == tabptr->ipaddr[1]) { 00162 00163 /* An old entry found, update this and return. */ 00164 memcpy(tabptr->ethaddr.addr, ethaddr->addr, 6); 00165 tabptr->time = arptime; 00166 00167 return; 00168 } 00169 } 00170 } 00171 00172 /* If we get here, no existing ARP table entry was found, so we 00173 create one. */ 00174 /* First, we try to find an unused entry in the ARP table. */ 00175 for (i = 0; i < UIP_ARPTAB_SIZE; ++i) { 00176 tabptr = &arp_table[i]; 00177 if (tabptr->ipaddr[0] == 0 && tabptr->ipaddr[1] == 0) { 00178 break; 00179 } 00180 } 00181 00182 /* If no unused entry is found, we try to find the oldest entry and 00183 throw it away. */ 00184 if (i == UIP_ARPTAB_SIZE) { 00185 tmpage = 0; 00186 c = 0; 00187 for (i = 0; i < UIP_ARPTAB_SIZE; ++i) { 00188 tabptr = &arp_table[i]; 00189 if (arptime - tabptr->time > tmpage) { 00190 tmpage = arptime - tabptr->time; 00191 c = i; 00192 } 00193 } 00194 00195 i = c; 00196 tabptr = &arp_table[i]; 00197 } 00198 00199 /* Now, i is the ARP table entry which we will fill with the new 00200 information. */ 00201 memcpy(tabptr->ipaddr, ipaddr, 4); 00202 memcpy(tabptr->ethaddr.addr, ethaddr->addr, 6); 00203 tabptr->time = arptime; 00204 } 00205 00206 /*-----------------------------------------------------------------------------------*/ 00207 /** 00208 * ARP processing for incoming IP packets 00209 * 00210 * This function should be called by the device driver when an IP 00211 * packet has been received. The function will check if the address is 00212 * in the ARP cache, and if so the ARP cache entry will be 00213 * refreshed. If no ARP cache entry was found, a new one is created. 00214 * 00215 * This function expects an IP packet with a prepended Ethernet header 00216 * in the uip_buf[] buffer, and the length of the packet in the global 00217 * variable uip_len. 00218 */ 00219 /*-----------------------------------------------------------------------------------*/ 00220 00221 //#if 0 00222 void uip_arp_ipin(void) { 00223 uip_len -= sizeof(struct uip_eth_hdr); 00224 00225 /* Only insert/update an entry if the source IP address of the 00226 incoming IP packet comes from a host on the local network. */ 00227 if ((IPBUF->srcipaddr[0] & uip_netmask[0]) != (uip_hostaddr[0] & uip_netmask[0])) { 00228 return; 00229 } 00230 00231 if ((IPBUF->srcipaddr[1] & uip_netmask[1]) != (uip_hostaddr[1] & uip_netmask[1])) { 00232 return; 00233 } 00234 00235 uip_arp_update(IPBUF->srcipaddr, &(IPBUF->ethhdr.src)); 00236 00237 return; 00238 } 00239 00240 //#endif /* 0 */ 00241 /*-----------------------------------------------------------------------------------*/ 00242 /** 00243 * ARP processing for incoming ARP packets. 00244 * 00245 * This function should be called by the device driver when an ARP 00246 * packet has been received. The function will act differently 00247 * depending on the ARP packet type: if it is a reply for a request 00248 * that we previously sent out, the ARP cache will be filled in with 00249 * the values from the ARP reply. If the incoming ARP packet is an ARP 00250 * request for our IP address, an ARP reply packet is created and put 00251 * into the uip_buf[] buffer. 00252 * 00253 * When the function returns, the value of the global variable uip_len 00254 * indicates whether the device driver should send out a packet or 00255 * not. If uip_len is zero, no packet should be sent. If uip_len is 00256 * non-zero, it contains the length of the outbound packet that is 00257 * present in the uip_buf[] buffer. 00258 * 00259 * This function expects an ARP packet with a prepended Ethernet 00260 * header in the uip_buf[] buffer, and the length of the packet in the 00261 * global variable uip_len. 00262 */ 00263 00264 /*-----------------------------------------------------------------------------------*/ 00265 void uip_arp_arpin(void) { 00266 if (uip_len < sizeof(struct arp_hdr)) { 00267 uip_len = 0; 00268 return; 00269 } 00270 00271 uip_len = 0; 00272 00273 switch (BUF->opcode) { 00274 case HTONS(ARP_REQUEST): 00275 /* ARP request. If it asked for our address, we send out a 00276 reply. */ 00277 if (uip_ipaddr_cmp(BUF->dipaddr, uip_hostaddr)) { 00278 00279 /* First, we register the one who made the request in our ARP 00280 table, since it is likely that we will do more communication 00281 with this host in the future. */ 00282 uip_arp_update(BUF->sipaddr, &BUF->shwaddr); 00283 00284 /* The reply opcode is 2. */ 00285 BUF->opcode = HTONS(2); 00286 00287 memcpy(BUF->dhwaddr.addr, BUF->shwaddr.addr, 6); 00288 memcpy(BUF->shwaddr.addr, uip_ethaddr.addr, 6); 00289 memcpy(BUF->ethhdr.src.addr, uip_ethaddr.addr, 6); 00290 memcpy(BUF->ethhdr.dest.addr, BUF->dhwaddr.addr, 6); 00291 00292 BUF->dipaddr[0] = BUF->sipaddr[0]; 00293 BUF->dipaddr[1] = BUF->sipaddr[1]; 00294 BUF->sipaddr[0] = uip_hostaddr[0]; 00295 BUF->sipaddr[1] = uip_hostaddr[1]; 00296 00297 BUF->ethhdr.type = HTONS(UIP_ETHTYPE_ARP); 00298 uip_len = sizeof(struct arp_hdr); 00299 } 00300 break; 00301 00302 case HTONS(ARP_REPLY): 00303 /* ARP reply. We insert or update the ARP table if it was meant 00304 for us. */ 00305 if (uip_ipaddr_cmp(BUF->dipaddr, uip_hostaddr)) { 00306 uip_arp_update(BUF->sipaddr, &BUF->shwaddr); 00307 } 00308 break; 00309 } 00310 00311 return; 00312 } 00313 00314 /*-----------------------------------------------------------------------------------*/ 00315 /** 00316 * Prepend Ethernet header to an outbound IP packet and see if we need 00317 * to send out an ARP request. 00318 * 00319 * This function should be called before sending out an IP packet. The 00320 * function checks the destination IP address of the IP packet to see 00321 * what Ethernet MAC address that should be used as a destination MAC 00322 * address on the Ethernet. 00323 * 00324 * If the destination IP address is in the local network (determined 00325 * by logical ANDing of netmask and our IP address), the function 00326 * checks the ARP cache to see if an entry for the destination IP 00327 * address is found. If so, an Ethernet header is prepended and the 00328 * function returns. If no ARP cache entry is found for the 00329 * destination IP address, the packet in the uip_buf[] is replaced by 00330 * an ARP request packet for the IP address. The IP packet is dropped 00331 * and it is assumed that they higher level protocols (e.g., TCP) 00332 * eventually will retransmit the dropped packet. 00333 * 00334 * If the destination IP address is not on the local network, the IP 00335 * address of the default router is used instead. 00336 * 00337 * When the function returns, a packet is present in the uip_buf[] 00338 * buffer, and the length of the packet is in the global variable 00339 * uip_len. 00340 */ 00341 00342 /*-----------------------------------------------------------------------------------*/ 00343 void uip_arp_out(void) { 00344 struct arp_entry* tabptr; 00345 00346 /* Find the destination IP address in the ARP table and construct 00347 the Ethernet header. If the destination IP addres isn't on the 00348 local network, we use the default router's IP address instead. 00349 00350 If not ARP table entry is found, we overwrite the original IP 00351 packet with an ARP request for the IP address. */ 00352 00353 /* First check if destination is a local broadcast. */ 00354 if (uip_ipaddr_cmp(IPBUF->destipaddr, broadcast_ipaddr)) { 00355 memcpy(IPBUF->ethhdr.dest.addr, broadcast_ethaddr.addr, 6); 00356 } 00357 else { 00358 00359 /* Check if the destination address is on the local network. */ 00360 if (!uip_ipaddr_maskcmp(IPBUF->destipaddr, uip_hostaddr, uip_netmask)) { 00361 00362 /* Destination address was not on the local network, so we need to 00363 use the default router's IP address instead of the destination 00364 address when determining the MAC address. */ 00365 uip_ipaddr_copy(ipaddr, uip_draddr); 00366 } 00367 else { 00368 00369 /* Else, we use the destination IP address. */ 00370 uip_ipaddr_copy(ipaddr, IPBUF->destipaddr); 00371 } 00372 00373 for (i = 0; i < UIP_ARPTAB_SIZE; ++i) { 00374 tabptr = &arp_table[i]; 00375 if (uip_ipaddr_cmp(ipaddr, tabptr->ipaddr)) { 00376 break; 00377 } 00378 } 00379 00380 if (i == UIP_ARPTAB_SIZE) { 00381 00382 /* The destination address was not in our ARP table, so we 00383 overwrite the IP packet with an ARP request. */ 00384 memset(BUF->ethhdr.dest.addr, 0xff, 6); 00385 memset(BUF->dhwaddr.addr, 0x00, 6); 00386 memcpy(BUF->ethhdr.src.addr, uip_ethaddr.addr, 6); 00387 memcpy(BUF->shwaddr.addr, uip_ethaddr.addr, 6); 00388 00389 uip_ipaddr_copy(BUF->dipaddr, ipaddr); 00390 uip_ipaddr_copy(BUF->sipaddr, uip_hostaddr); 00391 BUF->opcode = HTONS(ARP_REQUEST); /* ARP request. */ 00392 BUF->hwtype = HTONS(ARP_HWTYPE_ETH); 00393 BUF->protocol = HTONS(UIP_ETHTYPE_IP); 00394 BUF->hwlen = 6; 00395 BUF->protolen = 4; 00396 BUF->ethhdr.type = HTONS(UIP_ETHTYPE_ARP); 00397 00398 uip_appdata = &uip_buf[UIP_TCPIP_HLEN + UIP_LLH_LEN]; 00399 00400 uip_len = sizeof(struct arp_hdr); 00401 return; 00402 } 00403 00404 /* Build an ethernet header. */ 00405 memcpy(IPBUF->ethhdr.dest.addr, tabptr->ethaddr.addr, 6); 00406 } 00407 00408 memcpy(IPBUF->ethhdr.src.addr, uip_ethaddr.addr, 6); 00409 00410 IPBUF->ethhdr.type = HTONS(UIP_ETHTYPE_IP); 00411 00412 uip_len += sizeof(struct uip_eth_hdr); 00413 } 00414 00415 /*-----------------------------------------------------------------------------------*/ 00416 /** @} */ 00417 /** @} */
Generated on Tue Jul 12 2022 18:48:00 by 1.7.2