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.
Fork of mbed-os by
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 13:15:53 by
