ethernet.c 11 KB

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