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.\n 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 s16_t ip_hdr_offset = SIZEOF_ETH_HDR; 87 #endif /* LWIP_ARP || ETHARP_SUPPORT_VLAN */ 88 89 if (p->len <= SIZEOF_ETH_HDR) { 90 /* a packet with only an ethernet header (or less) is not valid for us */ 91 ETHARP_STATS_INC(etharp.proterr); 92 ETHARP_STATS_INC(etharp.drop); 93 MIB2_STATS_NETIF_INC(netif, ifinerrors); 94 goto free_and_return; 95 } 96 97 if (p->if_idx == NETIF_NO_INDEX) { 98 p->if_idx = netif_get_index(netif); 99 } 100 101 /* points to packet payload, which starts with an Ethernet header */ 102 ethhdr = (struct eth_hdr *)p->payload; 103 LWIP_DEBUGF(ETHARP_DEBUG | LWIP_DBG_TRACE, 104 ("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", 105 (unsigned)ethhdr->dest.addr[0], (unsigned)ethhdr->dest.addr[1], (unsigned)ethhdr->dest.addr[2], 106 (unsigned)ethhdr->dest.addr[3], (unsigned)ethhdr->dest.addr[4], (unsigned)ethhdr->dest.addr[5], 107 (unsigned)ethhdr->src.addr[0], (unsigned)ethhdr->src.addr[1], (unsigned)ethhdr->src.addr[2], 108 (unsigned)ethhdr->src.addr[3], (unsigned)ethhdr->src.addr[4], (unsigned)ethhdr->src.addr[5], 109 lwip_htons(ethhdr->type))); 110 111 type = ethhdr->type; 112 #if ETHARP_SUPPORT_VLAN 113 if (type == PP_HTONS(ETHTYPE_VLAN)) { 114 struct eth_vlan_hdr *vlan = (struct eth_vlan_hdr*)(((char*)ethhdr) + SIZEOF_ETH_HDR); 115 if (p->len <= SIZEOF_ETH_HDR + SIZEOF_VLAN_HDR) { 116 /* a packet with only an ethernet/vlan header (or less) is not valid for us */ 117 ETHARP_STATS_INC(etharp.proterr); 118 ETHARP_STATS_INC(etharp.drop); 119 MIB2_STATS_NETIF_INC(netif, ifinerrors); 120 goto free_and_return; 121 } 122 #if defined(LWIP_HOOK_VLAN_CHECK) || defined(ETHARP_VLAN_CHECK) || defined(ETHARP_VLAN_CHECK_FN) /* if not, allow all VLANs */ 123 #ifdef LWIP_HOOK_VLAN_CHECK 124 if (!LWIP_HOOK_VLAN_CHECK(netif, ethhdr, vlan)) { 125 #elif defined(ETHARP_VLAN_CHECK_FN) 126 if (!ETHARP_VLAN_CHECK_FN(ethhdr, vlan)) { 127 #elif defined(ETHARP_VLAN_CHECK) 128 if (VLAN_ID(vlan) != ETHARP_VLAN_CHECK) { 129 #endif 130 /* silently ignore this packet: not for our VLAN */ 131 pbuf_free(p); 132 return ERR_OK; 133 } 134 #endif /* defined(LWIP_HOOK_VLAN_CHECK) || defined(ETHARP_VLAN_CHECK) || defined(ETHARP_VLAN_CHECK_FN) */ 135 type = vlan->tpid; 136 ip_hdr_offset = SIZEOF_ETH_HDR + SIZEOF_VLAN_HDR; 137 } 138 #endif /* ETHARP_SUPPORT_VLAN */ 139 140 #if LWIP_ARP_FILTER_NETIF 141 netif = LWIP_ARP_FILTER_NETIF_FN(p, netif, lwip_htons(type)); 142 #endif /* LWIP_ARP_FILTER_NETIF*/ 143 144 if (ethhdr->dest.addr[0] & 1) { 145 /* this might be a multicast or broadcast packet */ 146 if (ethhdr->dest.addr[0] == LL_IP4_MULTICAST_ADDR_0) { 147 #if LWIP_IPV4 148 if ((ethhdr->dest.addr[1] == LL_IP4_MULTICAST_ADDR_1) && 149 (ethhdr->dest.addr[2] == LL_IP4_MULTICAST_ADDR_2)) { 150 /* mark the pbuf as link-layer multicast */ 151 p->flags |= PBUF_FLAG_LLMCAST; 152 } 153 #endif /* LWIP_IPV4 */ 154 } 155 #if LWIP_IPV6 156 else if ((ethhdr->dest.addr[0] == LL_IP6_MULTICAST_ADDR_0) && 157 (ethhdr->dest.addr[1] == LL_IP6_MULTICAST_ADDR_1)) { 158 /* mark the pbuf as link-layer multicast */ 159 p->flags |= PBUF_FLAG_LLMCAST; 160 } 161 #endif /* LWIP_IPV6 */ 162 else if (eth_addr_cmp(ðhdr->dest, ðbroadcast)) { 163 /* mark the pbuf as link-layer broadcast */ 164 p->flags |= PBUF_FLAG_LLBCAST; 165 } 166 } 167 168 switch (type) { 169 #if LWIP_IPV4 && LWIP_ARP 170 /* IP packet? */ 171 case PP_HTONS(ETHTYPE_IP): 172 if (!(netif->flags & NETIF_FLAG_ETHARP)) { 173 goto free_and_return; 174 } 175 /* skip Ethernet header */ 176 if ((p->len < ip_hdr_offset) || pbuf_header(p, (s16_t)-ip_hdr_offset)) { 177 LWIP_DEBUGF(ETHARP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_LEVEL_WARNING, 178 ("ethernet_input: IPv4 packet dropped, too short (%"S16_F"/%"S16_F")\n", 179 p->tot_len, ip_hdr_offset)); 180 LWIP_DEBUGF(ETHARP_DEBUG | LWIP_DBG_TRACE, ("Can't move over header in packet")); 181 goto free_and_return; 182 } else { 183 /* pass to IP layer */ 184 ip4_input(p, netif); 185 } 186 break; 187 188 case PP_HTONS(ETHTYPE_ARP): 189 if (!(netif->flags & NETIF_FLAG_ETHARP)) { 190 goto free_and_return; 191 } 192 /* skip Ethernet header */ 193 if ((p->len < ip_hdr_offset) || pbuf_header(p, (s16_t)-ip_hdr_offset)) { 194 LWIP_DEBUGF(ETHARP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_LEVEL_WARNING, 195 ("ethernet_input: ARP response packet dropped, too short (%"S16_F"/%"S16_F")\n", 196 p->tot_len, ip_hdr_offset)); 197 LWIP_DEBUGF(ETHARP_DEBUG | LWIP_DBG_TRACE, ("Can't move over header in packet")); 198 ETHARP_STATS_INC(etharp.lenerr); 199 ETHARP_STATS_INC(etharp.drop); 200 goto free_and_return; 201 } else { 202 /* pass p to ARP module */ 203 etharp_input(p, netif); 204 } 205 break; 206 #endif /* LWIP_IPV4 && LWIP_ARP */ 207 #if PPPOE_SUPPORT 208 case PP_HTONS(ETHTYPE_PPPOEDISC): /* PPP Over Ethernet Discovery Stage */ 209 pppoe_disc_input(netif, p); 210 break; 211 212 case PP_HTONS(ETHTYPE_PPPOE): /* PPP Over Ethernet Session Stage */ 213 pppoe_data_input(netif, p); 214 break; 215 #endif /* PPPOE_SUPPORT */ 216 217 #if LWIP_IPV6 218 case PP_HTONS(ETHTYPE_IPV6): /* IPv6 */ 219 /* skip Ethernet header */ 220 if ((p->len < ip_hdr_offset) || pbuf_header(p, (s16_t)-ip_hdr_offset)) { 221 LWIP_DEBUGF(ETHARP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_LEVEL_WARNING, 222 ("ethernet_input: IPv6 packet dropped, too short (%"S16_F"/%"S16_F")\n", 223 p->tot_len, ip_hdr_offset)); 224 goto free_and_return; 225 } else { 226 /* pass to IPv6 layer */ 227 ip6_input(p, netif); 228 } 229 break; 230 #endif /* LWIP_IPV6 */ 231 232 default: 233 #ifdef LWIP_HOOK_UNKNOWN_ETH_PROTOCOL 234 if(LWIP_HOOK_UNKNOWN_ETH_PROTOCOL(p, netif) == ERR_OK) { 235 break; 236 } 237 #endif 238 ETHARP_STATS_INC(etharp.proterr); 239 ETHARP_STATS_INC(etharp.drop); 240 MIB2_STATS_NETIF_INC(netif, ifinunknownprotos); 241 goto free_and_return; 242 } 243 244 /* This means the pbuf is freed or consumed, 245 so the caller doesn't have to free it again */ 246 return ERR_OK; 247 248 free_and_return: 249 pbuf_free(p); 250 return ERR_OK; 251 } 252 253 /** 254 * @ingroup ethernet 255 * Send an ethernet packet on the network using netif->linkoutput(). 256 * The ethernet header is filled in before sending. 257 * 258 * @see LWIP_HOOK_VLAN_SET 259 * 260 * @param netif the lwIP network interface on which to send the packet 261 * @param p the packet to send. pbuf layer must be @ref PBUF_LINK. 262 * @param src the source MAC address to be copied into the ethernet header 263 * @param dst the destination MAC address to be copied into the ethernet header 264 * @param eth_type ethernet type (@ref eth_type) 265 * @return ERR_OK if the packet was sent, any other err_t on failure 266 */ 267 err_t 268 ethernet_output(struct netif* netif, struct pbuf* p, 269 const struct eth_addr* src, const struct eth_addr* dst, 270 u16_t eth_type) 271 { 272 struct eth_hdr* ethhdr; 273 u16_t eth_type_be = lwip_htons(eth_type); 274 275 #if ETHARP_SUPPORT_VLAN && defined(LWIP_HOOK_VLAN_SET) 276 s32_t vlan_prio_vid = LWIP_HOOK_VLAN_SET(netif, p, src, dst, eth_type); 277 if (vlan_prio_vid >= 0) { 278 struct eth_vlan_hdr* vlanhdr; 279 280 LWIP_ASSERT("prio_vid must be <= 0xFFFF", vlan_prio_vid <= 0xFFFF); 281 282 if (pbuf_header(p, SIZEOF_ETH_HDR + SIZEOF_VLAN_HDR) != 0) { 283 goto pbuf_header_failed; 284 } 285 vlanhdr = (struct eth_vlan_hdr*)(((u8_t*)p->payload) + SIZEOF_ETH_HDR); 286 vlanhdr->tpid = eth_type_be; 287 vlanhdr->prio_vid = lwip_htons((u16_t)vlan_prio_vid); 288 289 eth_type_be = PP_HTONS(ETHTYPE_VLAN); 290 } else 291 #endif /* ETHARP_SUPPORT_VLAN && defined(LWIP_HOOK_VLAN_SET) */ 292 { 293 if (pbuf_header(p, SIZEOF_ETH_HDR) != 0) { 294 goto pbuf_header_failed; 295 } 296 } 297 298 ethhdr = (struct eth_hdr*)p->payload; 299 ethhdr->type = eth_type_be; 300 ETHADDR16_COPY(ðhdr->dest, dst); 301 ETHADDR16_COPY(ðhdr->src, src); 302 303 LWIP_ASSERT("netif->hwaddr_len must be 6 for ethernet_output!", 304 (netif->hwaddr_len == ETH_HWADDR_LEN)); 305 LWIP_DEBUGF(ETHARP_DEBUG | LWIP_DBG_TRACE, 306 ("ethernet_output: sending packet %p\n", (void *)p)); 307 308 /* send the packet */ 309 return netif->linkoutput(netif, p); 310 311 pbuf_header_failed: 312 LWIP_DEBUGF(ETHARP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_LEVEL_SERIOUS, 313 ("ethernet_output: could not allocate room for header.\n")); 314 LINK_STATS_INC(link.lenerr); 315 return ERR_BUF; 316 } 317 318 #endif /* LWIP_ARP || LWIP_ETHERNET */ 319