ReactOS 0.4.16-dev-974-g5022a45
ethernet.c
Go to the documentation of this file.
1
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
63const struct eth_addr ethbroadcast = {{0xff, 0xff, 0xff, 0xff, 0xff, 0xff}};
64const struct eth_addr ethzero = {{0, 0, 0, 0, 0, 0}};
65
81ethernet_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
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;
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(&ethhdr->dest, &ethbroadcast)) {
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):
175 goto free_and_return;
176 }
177 /* skip Ethernet header (min. size checked above) */
178 if (pbuf_remove_header(p, next_hdr_offset)) {
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):
192 goto free_and_return;
193 }
194 /* skip Ethernet header (min. size checked above) */
195 if (pbuf_remove_header(p, next_hdr_offset)) {
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)) {
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
250free_and_return:
251 pbuf_free(p);
252 return ERR_OK;
253}
254
269err_t
270ethernet_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
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
308
309 ethhdr = (struct eth_hdr *)p->payload;
310 ethhdr->type = eth_type_be;
311 SMEMCPY(&ethhdr->dest, dst, ETH_HWADDR_LEN);
312 SMEMCPY(&ethhdr->src, src, ETH_HWADDR_LEN);
313
314 LWIP_ASSERT("netif->hwaddr_len must be 6 for ethernet_output!",
317 ("ethernet_output: sending packet %p\n", (void *)p));
318
319 /* send the packet */
320 return netif->linkoutput(netif, p);
321
322pbuf_header_failed:
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 */
const WCHAR * link
Definition: db.cpp:997
#define PP_HTONS(x)
Definition: def.h:90
#define lwip_htons(x)
Definition: def.h:86
#define X16_F
Definition: cc.h:21
#define U16_F
Definition: cc.h:19
#define LWIP_DEBUGF(debug, message)
Definition: debug.h:158
#define LWIP_ASSERT(message, assertion)
Definition: debug.h:116
#define MIB2_STATS_NETIF_INC(n, x)
Definition: snmp.h:139
GLuint GLuint GLsizei GLenum type
Definition: gl.h:1545
GLenum src
Definition: glext.h:6340
GLenum GLenum dst
Definition: glext.h:6340
GLbitfield flags
Definition: glext.h:7161
GLfloat GLfloat p
Definition: glext.h:8902
GLenum GLsizei len
Definition: glext.h:6722
int32_t s32_t
Definition: arch.h:130
uint8_t u8_t
Definition: arch.h:125
uint16_t u16_t
Definition: arch.h:127
#define X8_F
Definition: arch.h:150
#define LWIP_DBG_LEVEL_SERIOUS
Definition: debug.h:57
#define LWIP_DBG_LEVEL_WARNING
Definition: debug.h:55
#define LWIP_DBG_TRACE
Definition: debug.h:83
@ ETHTYPE_ARP
Definition: ieee.h:56
@ ETHTYPE_PPPOEDISC
Definition: ieee.h:66
@ ETHTYPE_PPPOE
Definition: ieee.h:68
@ ETHTYPE_IPV6
Definition: ieee.h:64
@ ETHTYPE_IP
Definition: ieee.h:54
@ ETHTYPE_VLAN
Definition: ieee.h:62
s8_t err_t
Definition: err.h:96
@ ERR_BUF
Definition: err.h:59
@ ERR_OK
Definition: err.h:55
#define ETHARP_DEBUG
Definition: opt.h:3329
#define LWIP_ASSERT_CORE_LOCKED()
Definition: opt.h:227
#define SMEMCPY(dst, src, len)
Definition: opt.h:145
#define NETIF_FLAG_ETHARP
Definition: netif.h:97
u8_t pbuf_free(struct pbuf *p)
Definition: pbuf.c:727
if(dx< 0)
Definition: linetemp.h:194
#define SIZEOF_VLAN_HDR
Definition: ethernet.h:107
#define SIZEOF_ETH_HDR
Definition: ethernet.h:89
#define LL_IP6_MULTICAST_ADDR_0
Definition: ethernet.h:116
#define LL_IP4_MULTICAST_ADDR_2
Definition: ethernet.h:113
#define eth_addr_cmp(addr1, addr2)
Definition: ethernet.h:120
#define VLAN_ID(vlan_hdr)
Definition: ethernet.h:108
#define LL_IP4_MULTICAST_ADDR_1
Definition: ethernet.h:112
#define ETH_HWADDR_LEN
Definition: ethernet.h:51
#define LL_IP6_MULTICAST_ADDR_1
Definition: ethernet.h:117
#define LL_IP4_MULTICAST_ADDR_0
Definition: ethernet.h:111
#define NETIF_NO_INDEX
Definition: netif.h:579
#define netif_get_index(netif)
Definition: netif.h:578
u8_t pbuf_add_header(struct pbuf *p, size_t header_size_increment)
Definition: pbuf.c:554
u8_t pbuf_remove_header(struct pbuf *p, size_t header_size_decrement)
Definition: pbuf.c:585
#define PBUF_FLAG_LLBCAST
Definition: pbuf.h:179
#define PBUF_FLAG_LLMCAST
Definition: pbuf.h:181
#define LINK_STATS_INC(x)
Definition: stats.h:384
#define ETHARP_STATS_INC(x)
Definition: stats.h:376
Definition: netif.h:269
netif_linkoutput_fn linkoutput
Definition: netif.h:308
u8_t hwaddr_len
Definition: netif.h:352
Definition: pbuf.h:186