1
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
98
99
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
125
126
127
128
129
140
141
142
143
144
145
146
169
170
171
172
173
190
191
194
195
196
197
198
199
200
201
202
203
207
208
209
210
217
218
219
220
234
244
245
246
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
286
287
288
289
290
291
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
/* ... */
/* ... */
#include "lwip/opt.h"
#if LWIP_ARP || LWIP_ETHERNET
#include "netif/ethernet.h"
#include "lwip/def.h"
#include "lwip/stats.h"
#include "lwip/etharp.h"
#include "lwip/ip.h"
#include "lwip/snmp.h"
#include <string.h>
#include "netif/ppp/ppp_opts.h"
8 includes#if PPPOE_SUPPORT
#include "netif/ppp/pppoe.h"
#endif
#ifdef LWIP_HOOK_FILENAME
#include LWIP_HOOK_FILENAME
#endif
const struct eth_addr ethbroadcast = {{0xff, 0xff, 0xff, 0xff, 0xff, 0xff}};
const struct eth_addr ethzero = {{0, 0, 0, 0, 0, 0}};
/* ... */
err_t
ethernet_input(struct pbuf *p, struct netif *netif)
{
struct eth_hdr *ethhdr;
u16_t type;
#if LWIP_ARP || ETHARP_SUPPORT_VLAN || LWIP_IPV6
u16_t next_hdr_offset = SIZEOF_ETH_HDR;
#endif
LWIP_ASSERT_CORE_LOCKED();
if (p->len <= SIZEOF_ETH_HDR) {
ETHARP_STATS_INC(etharp.proterr);
ETHARP_STATS_INC(etharp.drop);
MIB2_STATS_NETIF_INC(netif, ifinerrors);
goto free_and_return;
}if (p->len <= SIZEOF_ETH_HDR) { ... }
if (p->if_idx == NETIF_NO_INDEX) {
p->if_idx = netif_get_index(netif);
}if (p->if_idx == NETIF_NO_INDEX) { ... }
ethhdr = (struct eth_hdr *)p->payload;
LWIP_DEBUGF(ETHARP_DEBUG | LWIP_DBG_TRACE,
("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",
(unsigned char)ethhdr->dest.addr[0], (unsigned char)ethhdr->dest.addr[1], (unsigned char)ethhdr->dest.addr[2],
(unsigned char)ethhdr->dest.addr[3], (unsigned char)ethhdr->dest.addr[4], (unsigned char)ethhdr->dest.addr[5],
(unsigned char)ethhdr->src.addr[0], (unsigned char)ethhdr->src.addr[1], (unsigned char)ethhdr->src.addr[2],
(unsigned char)ethhdr->src.addr[3], (unsigned char)ethhdr->src.addr[4], (unsigned char)ethhdr->src.addr[5],
lwip_htons(ethhdr->type)));
type = ethhdr->type;
#if ETHARP_SUPPORT_VLAN
if (type == PP_HTONS(ETHTYPE_VLAN)) {
struct eth_vlan_hdr *vlan = (struct eth_vlan_hdr *)(((char *)ethhdr) + SIZEOF_ETH_HDR);
next_hdr_offset = SIZEOF_ETH_HDR + SIZEOF_VLAN_HDR;
if (p->len <= SIZEOF_ETH_HDR + SIZEOF_VLAN_HDR) {
ETHARP_STATS_INC(etharp.proterr);
ETHARP_STATS_INC(etharp.drop);
MIB2_STATS_NETIF_INC(netif, ifinerrors);
goto free_and_return;
}if (p->len <= SIZEOF_ETH_HDR + SIZEOF_VLAN_HDR) { ... }
#if defined(LWIP_HOOK_VLAN_CHECK) || defined(ETHARP_VLAN_CHECK) || defined(ETHARP_VLAN_CHECK_FN)
#ifdef LWIP_HOOK_VLAN_CHECK
if (!LWIP_HOOK_VLAN_CHECK(netif, ethhdr, vlan)) {
#elif defined(ETHARP_VLAN_CHECK_FN)
if (!ETHARP_VLAN_CHECK_FN(ethhdr, vlan)) {
#elif defined(ETHARP_VLAN_CHECK)
if (VLAN_ID(vlan) != ETHARP_VLAN_CHECK) {
#endif
pbuf_free(p);
return ERR_OK;
}if (VLAN_ID(vlan) != ETHARP_VLAN_CHECK) { ... }
#endif
type = vlan->tpid;
}if (!ETHARP_VLAN_CHECK_FN(ethhdr, vlan)) { ... }
#endif
#if LWIP_ARP_FILTER_NETIF
netif = LWIP_ARP_FILTER_NETIF_FN(p, netif, lwip_htons(type));
#endif
if (ethhdr->dest.addr[0] & 1) {
if (ethhdr->dest.addr[0] == LL_IP4_MULTICAST_ADDR_0) {
#if LWIP_IPV4
if ((ethhdr->dest.addr[1] == LL_IP4_MULTICAST_ADDR_1) &&
(ethhdr->dest.addr[2] == LL_IP4_MULTICAST_ADDR_2)) {
p->flags |= PBUF_FLAG_LLMCAST;
}if ((ethhdr->dest.addr[1] == LL_IP4_MULTICAST_ADDR_1) && (ethhdr->dest.addr[2] == LL_IP4_MULTICAST_ADDR_2)) { ... }
/* ... */#endif
}if (ethhdr->dest.addr[0] == LL_IP4_MULTICAST_ADDR_0) { ... }
#if LWIP_IPV6
else if ((ethhdr->dest.addr[0] == LL_IP6_MULTICAST_ADDR_0) &&
(ethhdr->dest.addr[1] == LL_IP6_MULTICAST_ADDR_1)) {
p->flags |= PBUF_FLAG_LLMCAST;
}else if ((ethhdr->dest.addr[0] == LL_IP6_MULTICAST_ADDR_0) && (ethhdr->dest.addr[1] == LL_IP6_MULTICAST_ADDR_1)) { ... }
/* ... */#endif
else if (eth_addr_cmp(ðhdr->dest, ðbroadcast)) {
p->flags |= PBUF_FLAG_LLBCAST;
}else if (eth_addr_cmp(ðhdr->dest, ðbroadcast)) { ... }
}if (ethhdr->dest.addr[0] & 1) { ... }
switch (type) {
#if LWIP_IPV4 && LWIP_ARP
case PP_HTONS(ETHTYPE_IP):
if (!(netif->flags & NETIF_FLAG_ETHARP)) {
goto free_and_return;
}if (!(netif->flags & NETIF_FLAG_ETHARP)) { ... }
if (pbuf_remove_header(p, next_hdr_offset)) {
LWIP_DEBUGF(ETHARP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_LEVEL_WARNING,
("ethernet_input: IPv4 packet dropped, too short (%"U16_F"/%"U16_F")\n",
p->tot_len, next_hdr_offset));
LWIP_DEBUGF(ETHARP_DEBUG | LWIP_DBG_TRACE, ("Can't move over header in packet"));
goto free_and_return;
}if (pbuf_remove_header(p, next_hdr_offset)) { ... } else {
ip4_input(p, netif);
}else { ... }
break;
case PP_HTONS(ETHTYPE_IP):
case PP_HTONS(ETHTYPE_ARP):
if (!(netif->flags & NETIF_FLAG_ETHARP)) {
goto free_and_return;
}if (!(netif->flags & NETIF_FLAG_ETHARP)) { ... }
if (pbuf_remove_header(p, next_hdr_offset)) {
LWIP_DEBUGF(ETHARP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_LEVEL_WARNING,
("ethernet_input: ARP response packet dropped, too short (%"U16_F"/%"U16_F")\n",
p->tot_len, next_hdr_offset));
LWIP_DEBUGF(ETHARP_DEBUG | LWIP_DBG_TRACE, ("Can't move over header in packet"));
ETHARP_STATS_INC(etharp.lenerr);
ETHARP_STATS_INC(etharp.drop);
goto free_and_return;
}if (pbuf_remove_header(p, next_hdr_offset)) { ... } else {
etharp_input(p, netif);
}else { ... }
break;/* ... */
#endif
#if PPPOE_SUPPORT
case PP_HTONS(ETHTYPE_PPPOEDISC):
pppoe_disc_input(netif, p);
break;
case PP_HTONS(ETHTYPE_PPPOEDISC):
case PP_HTONS(ETHTYPE_PPPOE):
pppoe_data_input(netif, p);
break;/* ... */
#endif
#if LWIP_IPV6
case PP_HTONS(ETHTYPE_IPV6):
if ((p->len < next_hdr_offset) || pbuf_remove_header(p, next_hdr_offset)) {
LWIP_DEBUGF(ETHARP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_LEVEL_WARNING,
("ethernet_input: IPv6 packet dropped, too short (%"U16_F"/%"U16_F")\n",
p->tot_len, next_hdr_offset));
goto free_and_return;
}if ((p->len < next_hdr_offset) || pbuf_remove_header(p, next_hdr_offset)) { ... } else {
ip6_input(p, netif);
}else { ... }
break;/* ... */
#endif
case PP_HTONS(ETHTYPE_IPV6):
default:
#ifdef LWIP_HOOK_UNKNOWN_ETH_PROTOCOL
if (LWIP_HOOK_UNKNOWN_ETH_PROTOCOL(p, netif) == ERR_OK) {
break;
}if (LWIP_HOOK_UNKNOWN_ETH_PROTOCOL(p, netif) == ERR_OK) { ... }
/* ... */#endif
ETHARP_STATS_INC(etharp.proterr);
ETHARP_STATS_INC(etharp.drop);
MIB2_STATS_NETIF_INC(netif, ifinunknownprotos);
goto free_and_return;default
}switch (type) { ... }
/* ... */
return ERR_OK;
free_and_return:
pbuf_free(p);
return ERR_OK;
}{ ... }
/* ... */
err_t
ethernet_output(struct netif * netif, struct pbuf * p,
const struct eth_addr * src, const struct eth_addr * dst,
u16_t eth_type) {
struct eth_hdr *ethhdr;
u16_t eth_type_be = lwip_htons(eth_type);
#if ETHARP_SUPPORT_VLAN && defined(LWIP_HOOK_VLAN_SET)
s32_t vlan_prio_vid = LWIP_HOOK_VLAN_SET(netif, p, src, dst, eth_type);
if (vlan_prio_vid >= 0) {
struct eth_vlan_hdr *vlanhdr;
LWIP_ASSERT("prio_vid must be <= 0xFFFF", vlan_prio_vid <= 0xFFFF);
if (pbuf_add_header(p, SIZEOF_ETH_HDR + SIZEOF_VLAN_HDR) != 0) {
goto pbuf_header_failed;
}if (pbuf_add_header(p, SIZEOF_ETH_HDR + SIZEOF_VLAN_HDR) != 0) { ... }
vlanhdr = (struct eth_vlan_hdr *)(((u8_t *)p->payload) + SIZEOF_ETH_HDR);
vlanhdr->tpid = eth_type_be;
vlanhdr->prio_vid = lwip_htons((u16_t)vlan_prio_vid);
eth_type_be = PP_HTONS(ETHTYPE_VLAN);
}if (vlan_prio_vid >= 0) { ... } else
#endif
{
if (pbuf_add_header(p, SIZEOF_ETH_HDR) != 0) {
goto pbuf_header_failed;
}if (pbuf_add_header(p, SIZEOF_ETH_HDR) != 0) { ... }
}else { ... }
LWIP_ASSERT_CORE_LOCKED();
ethhdr = (struct eth_hdr *)p->payload;
ethhdr->type = eth_type_be;
SMEMCPY(ðhdr->dest, dst, ETH_HWADDR_LEN);
SMEMCPY(ðhdr->src, src, ETH_HWADDR_LEN);
LWIP_ASSERT("netif->hwaddr_len must be 6 for ethernet_output!",
(netif->hwaddr_len == ETH_HWADDR_LEN));
LWIP_DEBUGF(ETHARP_DEBUG | LWIP_DBG_TRACE,
("ethernet_output: sending packet %p\n", (void *)p));
return netif->linkoutput(netif, p);
pbuf_header_failed:
LWIP_DEBUGF(ETHARP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_LEVEL_SERIOUS,
("ethernet_output: could not allocate room for header.\n"));
LINK_STATS_INC(link.lenerr);
return ERR_BUF;
}{ ... }
/* ... */#endif