Important changes to repositories hosted on mbed.com
Mbed hosted mercurial repositories are deprecated and are due to be permanently deleted in July 2026.
To keep a copy of this software download the repository Zip archive or clone locally using Mercurial.
It is also possible to export all your personal repositories from the account settings page.
Dependents: mbed-TFT-example-NCS36510 mbed-Accelerometer-example-NCS36510 mbed-Accelerometer-example-NCS36510
lwip_ethernet.c
00001 /** 00002 * @file 00003 * Ethernet common functions 00004 */ 00005 00006 /* 00007 * Copyright (c) 2001-2003 Swedish Institute of Computer Science. 00008 * Copyright (c) 2003-2004 Leon Woestenberg <leon.woestenberg@axon.tv> 00009 * Copyright (c) 2003-2004 Axon Digital Design B.V., The Netherlands. 00010 * All rights reserved. 00011 * 00012 * Redistribution and use in source and binary forms, with or without modification, 00013 * are permitted provided that the following conditions are met: 00014 * 00015 * 1. Redistributions of source code must retain the above copyright notice, 00016 * this list of conditions and the following disclaimer. 00017 * 2. Redistributions in binary form must reproduce the above copyright notice, 00018 * this list of conditions and the following disclaimer in the documentation 00019 * and/or other materials provided with the distribution. 00020 * 3. The name of the author may not be used to endorse or promote products 00021 * derived from this software without specific prior written permission. 00022 * 00023 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED 00024 * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF 00025 * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT 00026 * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, 00027 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT 00028 * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 00029 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 00030 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING 00031 * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY 00032 * OF SUCH DAMAGE. 00033 * 00034 * This file is part of the lwIP TCP/IP stack. 00035 * 00036 */ 00037 00038 #include "lwip/opt.h" 00039 00040 #if LWIP_ARP || LWIP_ETHERNET 00041 00042 #include "netif/lwip_ethernet.h" 00043 #include "lwip/def.h" 00044 #include "lwip/stats.h" 00045 #include "lwip/etharp.h" 00046 #include "lwip/ip.h" 00047 #include "lwip/snmp.h" 00048 00049 #include <string.h> 00050 00051 #include "netif/ppp/ppp_opts.h" 00052 #if PPPOE_SUPPORT 00053 #include "netif/ppp/pppoe.h" 00054 #endif /* PPPOE_SUPPORT */ 00055 00056 const struct eth_addr ethbroadcast = {{0xff,0xff,0xff,0xff,0xff,0xff}}; 00057 const struct eth_addr ethzero = {{0,0,0,0,0,0}}; 00058 00059 /** 00060 * @ingroup lwip_nosys 00061 * Process received ethernet frames. Using this function instead of directly 00062 * calling ip_input and passing ARP frames through etharp in ethernetif_input, 00063 * the ARP cache is protected from concurrent access.\n 00064 * Don't call directly, pass to netif_add() and call netif->input(). 00065 * 00066 * @param p the received packet, p->payload pointing to the ethernet header 00067 * @param netif the network interface on which the packet was received 00068 */ 00069 err_t 00070 ethernet_input(struct pbuf *p, struct netif *netif) 00071 { 00072 struct eth_hdr* ethhdr; 00073 u16_t type; 00074 #if LWIP_ARP || ETHARP_SUPPORT_VLAN || LWIP_IPV6 00075 s16_t ip_hdr_offset = SIZEOF_ETH_HDR; 00076 #endif /* LWIP_ARP || ETHARP_SUPPORT_VLAN */ 00077 00078 if (p->len <= SIZEOF_ETH_HDR) { 00079 /* a packet with only an ethernet header (or less) is not valid for us */ 00080 ETHARP_STATS_INC(etharp.proterr); 00081 ETHARP_STATS_INC(etharp.drop); 00082 MIB2_STATS_NETIF_INC(netif, ifinerrors); 00083 goto free_and_return; 00084 } 00085 00086 /* points to packet payload, which starts with an Ethernet header */ 00087 ethhdr = (struct eth_hdr *)p->payload; 00088 LWIP_DEBUGF(ETHARP_DEBUG | LWIP_DBG_TRACE, 00089 ("ethernet_input: dest:%"X8_F":%"X8_F":%"X8_F":%"X8_F":%"X8_F":%"X8_F", src:%"X8_F":%"X8_F":%"X8_F":%"X8_F":%"X8_F":%"X8_F", type:%"X16_F"\n", 00090 (unsigned)ethhdr->dest.addr[0], (unsigned)ethhdr->dest.addr[1], (unsigned)ethhdr->dest.addr[2], 00091 (unsigned)ethhdr->dest.addr[3], (unsigned)ethhdr->dest.addr[4], (unsigned)ethhdr->dest.addr[5], 00092 (unsigned)ethhdr->src.addr[0], (unsigned)ethhdr->src.addr[1], (unsigned)ethhdr->src.addr[2], 00093 (unsigned)ethhdr->src.addr[3], (unsigned)ethhdr->src.addr[4], (unsigned)ethhdr->src.addr[5], 00094 htons(ethhdr->type))); 00095 00096 type = ethhdr->type; 00097 #if ETHARP_SUPPORT_VLAN 00098 if (type == PP_HTONS(ETHTYPE_VLAN)) { 00099 struct eth_vlan_hdr *vlan = (struct eth_vlan_hdr*)(((char*)ethhdr) + SIZEOF_ETH_HDR); 00100 if (p->len <= SIZEOF_ETH_HDR + SIZEOF_VLAN_HDR) { 00101 /* a packet with only an ethernet/vlan header (or less) is not valid for us */ 00102 ETHARP_STATS_INC(etharp.proterr); 00103 ETHARP_STATS_INC(etharp.drop); 00104 MIB2_STATS_NETIF_INC(netif, ifinerrors); 00105 goto free_and_return; 00106 } 00107 #if defined(LWIP_HOOK_VLAN_CHECK) || defined(ETHARP_VLAN_CHECK) || defined(ETHARP_VLAN_CHECK_FN) /* if not, allow all VLANs */ 00108 #ifdef LWIP_HOOK_VLAN_CHECK 00109 if (!LWIP_HOOK_VLAN_CHECK(netif, ethhdr, vlan)) { 00110 #elif defined(ETHARP_VLAN_CHECK_FN) 00111 if (!ETHARP_VLAN_CHECK_FN(ethhdr, vlan)) { 00112 #elif defined(ETHARP_VLAN_CHECK) 00113 if (VLAN_ID(vlan) != ETHARP_VLAN_CHECK) { 00114 #endif 00115 /* silently ignore this packet: not for our VLAN */ 00116 pbuf_free(p); 00117 return ERR_OK; 00118 } 00119 #endif /* defined(LWIP_HOOK_VLAN_CHECK) || defined(ETHARP_VLAN_CHECK) || defined(ETHARP_VLAN_CHECK_FN) */ 00120 type = vlan->tpid; 00121 ip_hdr_offset = SIZEOF_ETH_HDR + SIZEOF_VLAN_HDR; 00122 } 00123 #endif /* ETHARP_SUPPORT_VLAN */ 00124 00125 #if LWIP_ARP_FILTER_NETIF 00126 netif = LWIP_ARP_FILTER_NETIF_FN(p, netif, htons(type)); 00127 #endif /* LWIP_ARP_FILTER_NETIF*/ 00128 00129 if (ethhdr->dest.addr[0] & 1) { 00130 /* this might be a multicast or broadcast packet */ 00131 if (ethhdr->dest.addr[0] == LL_IP4_MULTICAST_ADDR_0) { 00132 #if LWIP_IPV4 00133 if ((ethhdr->dest.addr[1] == LL_IP4_MULTICAST_ADDR_1) && 00134 (ethhdr->dest.addr[2] == LL_IP4_MULTICAST_ADDR_2)) { 00135 /* mark the pbuf as link-layer multicast */ 00136 p->flags |= PBUF_FLAG_LLMCAST; 00137 } 00138 #endif /* LWIP_IPV4 */ 00139 } 00140 #if LWIP_IPV6 00141 else if ((ethhdr->dest.addr[0] == LL_IP6_MULTICAST_ADDR_0) && 00142 (ethhdr->dest.addr[1] == LL_IP6_MULTICAST_ADDR_1)) { 00143 /* mark the pbuf as link-layer multicast */ 00144 p->flags |= PBUF_FLAG_LLMCAST; 00145 } 00146 #endif /* LWIP_IPV6 */ 00147 else if (eth_addr_cmp(ðhdr->dest, ðbroadcast)) { 00148 /* mark the pbuf as link-layer broadcast */ 00149 p->flags |= PBUF_FLAG_LLBCAST; 00150 } 00151 } 00152 00153 switch (type) { 00154 #if LWIP_IPV4 && LWIP_ARP 00155 /* IP packet? */ 00156 case PP_HTONS(ETHTYPE_IP): 00157 if (!(netif->flags & NETIF_FLAG_ETHARP)) { 00158 goto free_and_return; 00159 } 00160 #if ETHARP_TRUST_IP_MAC 00161 /* update ARP table */ 00162 etharp_ip_input(netif, p); 00163 #endif /* ETHARP_TRUST_IP_MAC */ 00164 /* skip Ethernet header */ 00165 if ((p->len < ip_hdr_offset) || pbuf_header(p, (s16_t)-ip_hdr_offset)) { 00166 LWIP_DEBUGF(ETHARP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_LEVEL_WARNING, 00167 ("ethernet_input: IPv4 packet dropped, too short (%"S16_F"/%"S16_F")\n", 00168 p->tot_len, ip_hdr_offset)); 00169 LWIP_DEBUGF(ETHARP_DEBUG | LWIP_DBG_TRACE, ("Can't move over header in packet")); 00170 goto free_and_return; 00171 } else { 00172 /* pass to IP layer */ 00173 ip4_input(p, netif); 00174 } 00175 break; 00176 00177 case PP_HTONS(ETHTYPE_ARP): 00178 if (!(netif->flags & NETIF_FLAG_ETHARP)) { 00179 goto free_and_return; 00180 } 00181 /* pass p to ARP module */ 00182 etharp_arp_input(netif, (struct eth_addr*)(netif->hwaddr), p); 00183 break; 00184 #endif /* LWIP_IPV4 && LWIP_ARP */ 00185 #if PPPOE_SUPPORT 00186 case PP_HTONS(ETHTYPE_PPPOEDISC): /* PPP Over Ethernet Discovery Stage */ 00187 pppoe_disc_input(netif, p); 00188 break; 00189 00190 case PP_HTONS(ETHTYPE_PPPOE): /* PPP Over Ethernet Session Stage */ 00191 pppoe_data_input(netif, p); 00192 break; 00193 #endif /* PPPOE_SUPPORT */ 00194 00195 #if LWIP_IPV6 00196 case PP_HTONS(ETHTYPE_IPV6): /* IPv6 */ 00197 /* skip Ethernet header */ 00198 if ((p->len < ip_hdr_offset) || pbuf_header(p, (s16_t)-ip_hdr_offset)) { 00199 LWIP_DEBUGF(ETHARP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_LEVEL_WARNING, 00200 ("ethernet_input: IPv6 packet dropped, too short (%"S16_F"/%"S16_F")\n", 00201 p->tot_len, ip_hdr_offset)); 00202 goto free_and_return; 00203 } else { 00204 /* pass to IPv6 layer */ 00205 ip6_input(p, netif); 00206 } 00207 break; 00208 #endif /* LWIP_IPV6 */ 00209 00210 default: 00211 ETHARP_STATS_INC(etharp.proterr); 00212 ETHARP_STATS_INC(etharp.drop); 00213 MIB2_STATS_NETIF_INC(netif, ifinunknownprotos); 00214 goto free_and_return; 00215 } 00216 00217 /* This means the pbuf is freed or consumed, 00218 so the caller doesn't have to free it again */ 00219 return ERR_OK; 00220 00221 free_and_return: 00222 pbuf_free(p); 00223 return ERR_OK; 00224 } 00225 #endif /* LWIP_ARP || LWIP_ETHERNET */
Generated on Tue Jul 12 2022 11:02:41 by
