1 /** 2 * @file 3 * Ethernet common functions 4 * 5 * @defgroup ethernet Ethernet 6 * @ingroup callbackstyle_api 7 */ 8 9 /* 10 * Copyright (c) 2001-2003 Swedish Institute of Computer Science. 11 * Copyright (c) 2003-2004 Leon Woestenberg <leon.woestenberg@axon.tv> 12 * Copyright (c) 2003-2004 Axon Digital Design B.V., The Netherlands. 13 * All rights reserved. 14 * 15 * Redistribution and use in source and binary forms, with or without modification, 16 * are permitted provided that the following conditions are met: 17 * 18 * 1. Redistributions of source code must retain the above copyright notice, 19 * this list of conditions and the following disclaimer. 20 * 2. Redistributions in binary form must reproduce the above copyright notice, 21 * this list of conditions and the following disclaimer in the documentation 22 * and/or other materials provided with the distribution. 23 * 3. The name of the author may not be used to endorse or promote products 24 * derived from this software without specific prior written permission. 25 * 26 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED 27 * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF 28 * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT 29 * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, 30 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT 31 * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 32 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 33 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING 34 * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY 35 * OF SUCH DAMAGE. 36 * 37 * This file is part of the lwIP TCP/IP stack. 38 * 39 */ 40 41 #include "lwip/opt.h" 42 43 #if LWIP_ARP || LWIP_ETHERNET 44 45 #include "netif/ethernet.h" 46 #include "lwip/def.h" 47 #include "lwip/stats.h" 48 #include "lwip/etharp.h" 49 #include "lwip/ip.h" 50 #include "lwip/snmp.h" 51 52 #include <string.h> 53 54 #include "netif/ppp/ppp_opts.h" 55 #if PPPOE_SUPPORT 56 #include "netif/ppp/pppoe.h" 57 #endif /* PPPOE_SUPPORT */ 58 59 #ifdef LWIP_HOOK_FILENAME 60 #include LWIP_HOOK_FILENAME 61 #endif 62 63 const struct eth_addr ethbroadcast = {{0xff, 0xff, 0xff, 0xff, 0xff, 0xff}}; 64 const struct eth_addr ethzero = {{0, 0, 0, 0, 0, 0}}; 65 66 /** 67 * @ingroup lwip_nosys 68 * Process received ethernet frames. Using this function instead of directly 69 * calling ip_input and passing ARP frames through etharp in ethernetif_input, 70 * the ARP cache is protected from concurrent access.<br> 71 * Don't call directly, pass to netif_add() and call netif->input(). 72 * 73 * @param p the received packet, p->payload pointing to the ethernet header 74 * @param netif the network interface on which the packet was received 75 * 76 * @see LWIP_HOOK_UNKNOWN_ETH_PROTOCOL 77 * @see ETHARP_SUPPORT_VLAN 78 * @see LWIP_HOOK_VLAN_CHECK 79 */ 80 err_t 81 ethernet_input(struct pbuf *p, struct netif *netif) 82 { 83 struct eth_hdr *ethhdr; 84 u16_t type; 85 #if LWIP_ARP || ETHARP_SUPPORT_VLAN || LWIP_IPV6 86 u16_t next_hdr_offset = SIZEOF_ETH_HDR; 87 #endif /* LWIP_ARP || ETHARP_SUPPORT_VLAN */ 88 89 LWIP_ASSERT_CORE_LOCKED(); 90 91 if (p->len <= SIZEOF_ETH_HDR) { 92 /* a packet with only an ethernet header (or less) is not valid for us */ 93 ETHARP_STATS_INC(etharp.proterr); 94 ETHARP_STATS_INC(etharp.drop); 95 MIB2_STATS_NETIF_INC(netif, ifinerrors); 96 goto free_and_return; 97 } 98 99 /* points to packet payload, which starts with an Ethernet header */ 100 ethhdr = (struct eth_hdr *)p->payload; 101 LWIP_DEBUGF(ETHARP_DEBUG | LWIP_DBG_TRACE, 102 ("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", 103 (unsigned char)ethhdr->dest.addr[0], (unsigned char)ethhdr->dest.addr[1], (unsigned char)ethhdr->dest.addr[2], 104 (unsigned char)ethhdr->dest.addr[3], (unsigned char)ethhdr->dest.addr[4], (unsigned char)ethhdr->dest.addr[5], 105 (unsigned char)ethhdr->src.addr[0], (unsigned char)ethhdr->src.addr[1], (unsigned char)ethhdr->src.addr[2], 106 (unsigned char)ethhdr->src.addr[3], (unsigned char)ethhdr->src.addr[4], (unsigned char)ethhdr->src.addr[5], 107 lwip_htons(ethhdr->type))); 108 109 type = ethhdr->type; 110 #if ETHARP_SUPPORT_VLAN 111 if (type == PP_HTONS(ETHTYPE_VLAN)) { 112 struct eth_vlan_hdr *vlan = (struct eth_vlan_hdr *)(((char *)ethhdr) + SIZEOF_ETH_HDR); 113 next_hdr_offset = SIZEOF_ETH_HDR + SIZEOF_VLAN_HDR; 114 if (p->len <= SIZEOF_ETH_HDR + SIZEOF_VLAN_HDR) { 115 /* a packet with only an ethernet/vlan header (or less) is not valid for us */ 116 ETHARP_STATS_INC(etharp.proterr); 117 ETHARP_STATS_INC(etharp.drop); 118 MIB2_STATS_NETIF_INC(netif, ifinerrors); 119 goto free_and_return; 120 } 121 #if defined(LWIP_HOOK_VLAN_CHECK) || defined(ETHARP_VLAN_CHECK) || defined(ETHARP_VLAN_CHECK_FN) /* if not, allow all VLANs */ 122 #ifdef LWIP_HOOK_VLAN_CHECK 123 if (!LWIP_HOOK_VLAN_CHECK(netif, ethhdr, vlan)) { 124 #elif defined(ETHARP_VLAN_CHECK_FN) 125 if (!ETHARP_VLAN_CHECK_FN(ethhdr, vlan)) { 126 #elif defined(ETHARP_VLAN_CHECK) 127 if (VLAN_ID(vlan) != ETHARP_VLAN_CHECK) { 128 #endif 129 /* silently ignore this packet: not for our VLAN */ 130 pbuf_free(p); 131 return ERR_OK; 132 } 133 #endif /* defined(LWIP_HOOK_VLAN_CHECK) || defined(ETHARP_VLAN_CHECK) || defined(ETHARP_VLAN_CHECK_FN) */ 134 type = vlan->tpid; 135 } 136 #endif /* ETHARP_SUPPORT_VLAN */ 137 138 #if LWIP_ARP_FILTER_NETIF 139 netif = LWIP_ARP_FILTER_NETIF_FN(p, netif, lwip_htons(type)); 140 #endif /* LWIP_ARP_FILTER_NETIF*/ 141 142 if (p->if_idx == NETIF_NO_INDEX) { 143 p->if_idx = netif_get_index(netif); 144 } 145 146 if (ethhdr->dest.addr[0] & 1) { 147 /* this might be a multicast or broadcast packet */ 148 if (ethhdr->dest.addr[0] == LL_IP4_MULTICAST_ADDR_0) { 149 #if LWIP_IPV4 150 if ((ethhdr->dest.addr[1] == LL_IP4_MULTICAST_ADDR_1) && 151 (ethhdr->dest.addr[2] == LL_IP4_MULTICAST_ADDR_2)) { 152 /* mark the pbuf as link-layer multicast */ 153 p->flags |= PBUF_FLAG_LLMCAST; 154 } 155 #endif /* LWIP_IPV4 */ 156 } 157 #if LWIP_IPV6 158 else if ((ethhdr->dest.addr[0] == LL_IP6_MULTICAST_ADDR_0) && 159 (ethhdr->dest.addr[1] == LL_IP6_MULTICAST_ADDR_1)) { 160 /* mark the pbuf as link-layer multicast */ 161 p->flags |= PBUF_FLAG_LLMCAST; 162 } 163 #endif /* LWIP_IPV6 */ 164 else if (eth_addr_cmp(ðhdr->dest, ðbroadcast)) { 165 /* mark the pbuf as link-layer broadcast */ 166 p->flags |= PBUF_FLAG_LLBCAST; 167 } 168 } 169 170 switch (type) { 171 #if LWIP_IPV4 && LWIP_ARP 172 /* IP packet? */ 173 case PP_HTONS(ETHTYPE_IP): 174 if (!(netif->flags & NETIF_FLAG_ETHARP)) { 175 goto free_and_return; 176 } 177 /* skip Ethernet header (min. size checked above) */ 178 if (pbuf_remove_header(p, next_hdr_offset)) { 179 LWIP_DEBUGF(ETHARP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_LEVEL_WARNING, 180 ("ethernet_input: IPv4 packet dropped, too short (%"U16_F"/%"U16_F")\n", 181 p->tot_len, next_hdr_offset)); 182 LWIP_DEBUGF(ETHARP_DEBUG | LWIP_DBG_TRACE, ("Can't move over header in packet\n")); 183 goto free_and_return; 184 } else { 185 /* pass to IP layer */ 186 ip4_input(p, netif); 187 } 188 break; 189 190 case PP_HTONS(ETHTYPE_ARP): 191 if (!(netif->flags & NETIF_FLAG_ETHARP)) { 192 goto free_and_return; 193 } 194 /* skip Ethernet header (min. size checked above) */ 195 if (pbuf_remove_header(p, next_hdr_offset)) { 196 LWIP_DEBUGF(ETHARP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_LEVEL_WARNING, 197 ("ethernet_input: ARP response packet dropped, too short (%"U16_F"/%"U16_F")\n", 198 p->tot_len, next_hdr_offset)); 199 LWIP_DEBUGF(ETHARP_DEBUG | LWIP_DBG_TRACE, ("Can't move over header in packet\n")); 200 ETHARP_STATS_INC(etharp.lenerr); 201 ETHARP_STATS_INC(etharp.drop); 202 goto free_and_return; 203 } else { 204 /* pass p to ARP module */ 205 etharp_input(p, netif); 206 } 207 break; 208 #endif /* LWIP_IPV4 && LWIP_ARP */ 209 #if PPPOE_SUPPORT 210 case PP_HTONS(ETHTYPE_PPPOEDISC): /* PPP Over Ethernet Discovery Stage */ 211 pppoe_disc_input(netif, p); 212 break; 213 214 case PP_HTONS(ETHTYPE_PPPOE): /* PPP Over Ethernet Session Stage */ 215 pppoe_data_input(netif, p); 216 break; 217 #endif /* PPPOE_SUPPORT */ 218 219 #if LWIP_IPV6 220 case PP_HTONS(ETHTYPE_IPV6): /* IPv6 */ 221 /* skip Ethernet header */ 222 if ((p->len < next_hdr_offset) || pbuf_remove_header(p, next_hdr_offset)) { 223 LWIP_DEBUGF(ETHARP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_LEVEL_WARNING, 224 ("ethernet_input: IPv6 packet dropped, too short (%"U16_F"/%"U16_F")\n", 225 p->tot_len, next_hdr_offset)); 226 goto free_and_return; 227 } else { 228 /* pass to IPv6 layer */ 229 ip6_input(p, netif); 230 } 231 break; 232 #endif /* LWIP_IPV6 */ 233 234 default: 235 #ifdef LWIP_HOOK_UNKNOWN_ETH_PROTOCOL 236 if (LWIP_HOOK_UNKNOWN_ETH_PROTOCOL(p, netif) == ERR_OK) { 237 break; 238 } 239 #endif 240 ETHARP_STATS_INC(etharp.proterr); 241 ETHARP_STATS_INC(etharp.drop); 242 MIB2_STATS_NETIF_INC(netif, ifinunknownprotos); 243 goto free_and_return; 244 } 245 246 /* This means the pbuf is freed or consumed, 247 so the caller doesn't have to free it again */ 248 return ERR_OK; 249 250 free_and_return: 251 pbuf_free(p); 252 return ERR_OK; 253 } 254 255 /** 256 * @ingroup ethernet 257 * Send an ethernet packet on the network using netif->linkoutput(). 258 * The ethernet header is filled in before sending. 259 * 260 * @see LWIP_HOOK_VLAN_SET 261 * 262 * @param netif the lwIP network interface on which to send the packet 263 * @param p the packet to send. pbuf layer must be @ref PBUF_LINK. 264 * @param src the source MAC address to be copied into the ethernet header 265 * @param dst the destination MAC address to be copied into the ethernet header 266 * @param eth_type ethernet type (@ref lwip_ieee_eth_type) 267 * @return ERR_OK if the packet was sent, any other err_t on failure 268 */ 269 err_t 270 ethernet_output(struct netif * netif, struct pbuf * p, 271 const struct eth_addr * src, const struct eth_addr * dst, 272 u16_t eth_type) { 273 struct eth_hdr *ethhdr; 274 u16_t eth_type_be = lwip_htons(eth_type); 275 276 #if ETHARP_SUPPORT_VLAN && (defined(LWIP_HOOK_VLAN_SET) || LWIP_VLAN_PCP) 277 s32_t vlan_prio_vid; 278 #ifdef LWIP_HOOK_VLAN_SET 279 vlan_prio_vid = LWIP_HOOK_VLAN_SET(netif, p, src, dst, eth_type); 280 #elif LWIP_VLAN_PCP 281 vlan_prio_vid = -1; 282 if (netif->hints && (netif->hints->tci >= 0)) { 283 vlan_prio_vid = (u16_t)netif->hints->tci; 284 } 285 #endif 286 if (vlan_prio_vid >= 0) { 287 struct eth_vlan_hdr *vlanhdr; 288 289 LWIP_ASSERT("prio_vid must be <= 0xFFFF", vlan_prio_vid <= 0xFFFF); 290 291 if (pbuf_add_header(p, SIZEOF_ETH_HDR + SIZEOF_VLAN_HDR) != 0) { 292 goto pbuf_header_failed; 293 } 294 vlanhdr = (struct eth_vlan_hdr *)(((u8_t *)p->payload) + SIZEOF_ETH_HDR); 295 vlanhdr->tpid = eth_type_be; 296 vlanhdr->prio_vid = lwip_htons((u16_t)vlan_prio_vid); 297 298 eth_type_be = PP_HTONS(ETHTYPE_VLAN); 299 } else 300 #endif /* ETHARP_SUPPORT_VLAN && (defined(LWIP_HOOK_VLAN_SET) || LWIP_VLAN_PCP) */ 301 { 302 if (pbuf_add_header(p, SIZEOF_ETH_HDR) != 0) { 303 goto pbuf_header_failed; 304 } 305 } 306 307 LWIP_ASSERT_CORE_LOCKED(); 308 309 ethhdr = (struct eth_hdr *)p->payload; 310 ethhdr->type = eth_type_be; 311 SMEMCPY(ðhdr->dest, dst, ETH_HWADDR_LEN); 312 SMEMCPY(ðhdr->src, src, ETH_HWADDR_LEN); 313 314 LWIP_ASSERT("netif->hwaddr_len must be 6 for ethernet_output!", 315 (netif->hwaddr_len == ETH_HWADDR_LEN)); 316 LWIP_DEBUGF(ETHARP_DEBUG | LWIP_DBG_TRACE, 317 ("ethernet_output: sending packet %p\n", (void *)p)); 318 319 /* send the packet */ 320 return netif->linkoutput(netif, p); 321 322 pbuf_header_failed: 323 LWIP_DEBUGF(ETHARP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_LEVEL_SERIOUS, 324 ("ethernet_output: could not allocate room for header.\n")); 325 LINK_STATS_INC(link.lenerr); 326 return ERR_BUF; 327 } 328 329 #endif /* LWIP_ARP || LWIP_ETHERNET */ 330