UbixOS V2  2.0
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 "net/opt.h"
42 
43 #if LWIP_ARP || LWIP_ETHERNET
44 
45 #include "netif/ethernet.h"
46 #include "net/def.h"
47 #include "net/stats.h"
48 #include "net/etharp.h"
49 #include "net/ip.h"
50 #include "net/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 
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  kprintf("BAD HEADER");
91  /* a packet with only an ethernet header (or less) is not valid for us */
92  ETHARP_STATS_INC(etharp.proterr);
93  ETHARP_STATS_INC(etharp.drop);
94  MIB2_STATS_NETIF_INC(netif, ifinerrors);
95  goto free_and_return;
96  }
97 
98  /* points to packet payload, which starts with an Ethernet header */
99  ethhdr = (struct eth_hdr *)p->payload;
101  ("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",
102  (unsigned)ethhdr->dest.addr[0], (unsigned)ethhdr->dest.addr[1], (unsigned)ethhdr->dest.addr[2],
103  (unsigned)ethhdr->dest.addr[3], (unsigned)ethhdr->dest.addr[4], (unsigned)ethhdr->dest.addr[5],
104  (unsigned)ethhdr->src.addr[0], (unsigned)ethhdr->src.addr[1], (unsigned)ethhdr->src.addr[2],
105  (unsigned)ethhdr->src.addr[3], (unsigned)ethhdr->src.addr[4], (unsigned)ethhdr->src.addr[5],
106  lwip_htons(ethhdr->type)));
107 
108  type = ethhdr->type;
109 #if ETHARP_SUPPORT_VLAN
110  if (type == PP_HTONS(ETHTYPE_VLAN)) {
111  struct eth_vlan_hdr *vlan = (struct eth_vlan_hdr*)(((char*)ethhdr) + SIZEOF_ETH_HDR);
112  if (p->len <= SIZEOF_ETH_HDR + SIZEOF_VLAN_HDR) {
113  /* a packet with only an ethernet/vlan header (or less) is not valid for us */
114  ETHARP_STATS_INC(etharp.proterr);
115  ETHARP_STATS_INC(etharp.drop);
116  MIB2_STATS_NETIF_INC(netif, ifinerrors);
117  goto free_and_return;
118  }
119 #if defined(LWIP_HOOK_VLAN_CHECK) || defined(ETHARP_VLAN_CHECK) || defined(ETHARP_VLAN_CHECK_FN) /* if not, allow all VLANs */
120 #ifdef LWIP_HOOK_VLAN_CHECK
121  if (!LWIP_HOOK_VLAN_CHECK(netif, ethhdr, vlan)) {
122 #elif defined(ETHARP_VLAN_CHECK_FN)
123  if (!ETHARP_VLAN_CHECK_FN(ethhdr, vlan)) {
124 #elif defined(ETHARP_VLAN_CHECK)
125  if (VLAN_ID(vlan) != ETHARP_VLAN_CHECK) {
126 #endif
127  /* silently ignore this packet: not for our VLAN */
128  pbuf_free(p);
129  return ERR_OK;
130  }
131 #endif /* defined(LWIP_HOOK_VLAN_CHECK) || defined(ETHARP_VLAN_CHECK) || defined(ETHARP_VLAN_CHECK_FN) */
132  type = vlan->tpid;
133  ip_hdr_offset = SIZEOF_ETH_HDR + SIZEOF_VLAN_HDR;
134  }
135 #endif /* ETHARP_SUPPORT_VLAN */
136 
137 #if LWIP_ARP_FILTER_NETIF
138  netif = LWIP_ARP_FILTER_NETIF_FN(p, netif, lwip_htons(type));
139 #endif /* LWIP_ARP_FILTER_NETIF*/
140 
141  if (ethhdr->dest.addr[0] & 1) {
142  /* this might be a multicast or broadcast packet */
143  if (ethhdr->dest.addr[0] == LL_IP4_MULTICAST_ADDR_0) {
144 #if LWIP_IPV4
145  if ((ethhdr->dest.addr[1] == LL_IP4_MULTICAST_ADDR_1) &&
146  (ethhdr->dest.addr[2] == LL_IP4_MULTICAST_ADDR_2)) {
147  /* mark the pbuf as link-layer multicast */
148  p->flags |= PBUF_FLAG_LLMCAST;
149  }
150 #endif /* LWIP_IPV4 */
151  }
152 #if LWIP_IPV6
153  else if ((ethhdr->dest.addr[0] == LL_IP6_MULTICAST_ADDR_0) &&
154  (ethhdr->dest.addr[1] == LL_IP6_MULTICAST_ADDR_1)) {
155  /* mark the pbuf as link-layer multicast */
156  p->flags |= PBUF_FLAG_LLMCAST;
157  }
158 #endif /* LWIP_IPV6 */
159  else if (eth_addr_cmp(&ethhdr->dest, &ethbroadcast)) {
160  /* mark the pbuf as link-layer broadcast */
161  p->flags |= PBUF_FLAG_LLBCAST;
162  }
163  }
164 
165  switch (type) {
166 #if LWIP_IPV4 && LWIP_ARP
167  /* IP packet? */
168  case PP_HTONS(ETHTYPE_IP):
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)) {
175  ("ethernet_input: IPv4 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  goto free_and_return;
179  } else {
180  /* pass to IP layer */
181  ip4_input(p, netif);
182  }
183  break;
184 
185  case PP_HTONS(ETHTYPE_ARP):
186  if (!(netif->flags & NETIF_FLAG_ETHARP)) {
187  goto free_and_return;
188  }
189  /* skip Ethernet header */
190  if ((p->len < ip_hdr_offset) || pbuf_header(p, (s16_t)-ip_hdr_offset)) {
192  ("ethernet_input: ARP response packet dropped, too short (%"S16_F"/%"S16_F")\n",
193  p->tot_len, ip_hdr_offset));
194  LWIP_DEBUGF(ETHARP_DEBUG | LWIP_DBG_TRACE, ("Can't move over header in packet"));
195  ETHARP_STATS_INC(etharp.lenerr);
196  ETHARP_STATS_INC(etharp.drop);
197  goto free_and_return;
198  } else {
199  /* pass p to ARP module */
200  etharp_input(p, netif);
201  }
202  break;
203 #endif /* LWIP_IPV4 && LWIP_ARP */
204 #if PPPOE_SUPPORT
205  case PP_HTONS(ETHTYPE_PPPOEDISC): /* PPP Over Ethernet Discovery Stage */
206  pppoe_disc_input(netif, p);
207  break;
208 
209  case PP_HTONS(ETHTYPE_PPPOE): /* PPP Over Ethernet Session Stage */
210  pppoe_data_input(netif, p);
211  break;
212 #endif /* PPPOE_SUPPORT */
213 
214 #if LWIP_IPV6
215  case PP_HTONS(ETHTYPE_IPV6): /* IPv6 */
216  /* skip Ethernet header */
217  if ((p->len < ip_hdr_offset) || pbuf_header(p, (s16_t)-ip_hdr_offset)) {
219  ("ethernet_input: IPv6 packet dropped, too short (%"S16_F"/%"S16_F")\n",
220  p->tot_len, ip_hdr_offset));
221  goto free_and_return;
222  } else {
223  /* pass to IPv6 layer */
224  ip6_input(p, netif);
225  }
226  break;
227 #endif /* LWIP_IPV6 */
228 
229  default:
230 #ifdef LWIP_HOOK_UNKNOWN_ETH_PROTOCOL
231  if(LWIP_HOOK_UNKNOWN_ETH_PROTOCOL(p, netif) == ERR_OK) {
232  break;
233  }
234 #endif
235  ETHARP_STATS_INC(etharp.proterr);
236  ETHARP_STATS_INC(etharp.drop);
237  MIB2_STATS_NETIF_INC(netif, ifinunknownprotos);
238  goto free_and_return;
239  }
240 
241  /* This means the pbuf is freed or consumed,
242  so the caller doesn't have to free it again */
243  return ERR_OK;
244 
245 free_and_return:
246  pbuf_free(p);
247  return ERR_OK;
248 }
249 
264 err_t
265 ethernet_output(struct netif* netif, struct pbuf* p,
266  const struct eth_addr* src, const struct eth_addr* dst,
267  u16_t eth_type)
268 {
269  struct eth_hdr* ethhdr;
270  u16_t eth_type_be = lwip_htons(eth_type);
271 
272 #if ETHARP_SUPPORT_VLAN && defined(LWIP_HOOK_VLAN_SET)
273  s32_t vlan_prio_vid = LWIP_HOOK_VLAN_SET(netif, p, src, dst, eth_type);
274  if (vlan_prio_vid >= 0) {
275  struct eth_vlan_hdr* vlanhdr;
276 
277  LWIP_ASSERT("prio_vid must be <= 0xFFFF", vlan_prio_vid <= 0xFFFF);
278 
279  if (pbuf_header(p, SIZEOF_ETH_HDR + SIZEOF_VLAN_HDR) != 0) {
280  goto pbuf_header_failed;
281  }
282  vlanhdr = (struct eth_vlan_hdr*)(((u8_t*)p->payload) + SIZEOF_ETH_HDR);
283  vlanhdr->tpid = eth_type_be;
284  vlanhdr->prio_vid = lwip_htons((u16_t)vlan_prio_vid);
285 
286  eth_type_be = PP_HTONS(ETHTYPE_VLAN);
287  } else
288 #endif /* ETHARP_SUPPORT_VLAN && defined(LWIP_HOOK_VLAN_SET) */
289  {
290  if (pbuf_header(p, SIZEOF_ETH_HDR) != 0) {
291  goto pbuf_header_failed;
292  }
293  }
294 
295  ethhdr = (struct eth_hdr*)p->payload;
296  ethhdr->type = eth_type_be;
297  ETHADDR32_COPY(&ethhdr->dest, dst);
298  ETHADDR16_COPY(&ethhdr->src, src);
299 
300  LWIP_ASSERT("netif->hwaddr_len must be 6 for ethernet_output!",
303  ("ethernet_output: sending packet %p\n", (void *)p));
304 
305  /* send the packet */
306  return netif->linkoutput(netif, p);
307 
308 pbuf_header_failed:
310  ("ethernet_output: could not allocate room for header.\n"));
311  LINK_STATS_INC(link.lenerr);
312  return ERR_BUF;
313 }
314 
315 #endif /* LWIP_ARP || LWIP_ETHERNET */
316 
VLAN_ID
#define VLAN_ID(vlan_hdr)
Definition: ethernet.h:103
S16_F
#define S16_F
Definition: arch.h:151
opt.h
pbuf::len
u16_t len
Definition: pbuf.h:159
s16_t
int16_t s16_t
Definition: arch.h:125
def.h
PBUF_FLAG_LLBCAST
#define PBUF_FLAG_LLBCAST
Definition: pbuf.h:135
ETHTYPE_PPPOE
Definition: ethernet.h:124
LWIP_ASSERT
#define LWIP_ASSERT(message, assertion)
Definition: debug.h:116
MIB2_STATS_NETIF_INC
#define MIB2_STATS_NETIF_INC(n, x)
Definition: snmp.h:139
ERR_BUF
Definition: err.h:67
u16_t
uint16_t u16_t
Definition: arch.h:124
string.h
pbuf::tot_len
u16_t tot_len
Definition: pbuf.h:156
NETIF_FLAG_ETHARP
#define NETIF_FLAG_ETHARP
Definition: netif.h:99
ETHARP_STATS_INC
#define ETHARP_STATS_INC(x)
Definition: stats.h:376
LINK_STATS_INC
#define LINK_STATS_INC(x)
Definition: stats.h:384
pbuf_free
u8_t pbuf_free(struct pbuf *p)
Definition: pbuf.c:715
LWIP_DBG_TRACE
#define LWIP_DBG_TRACE
Definition: debug.h:83
SIZEOF_VLAN_HDR
#define SIZEOF_VLAN_HDR
Definition: ethernet.h:102
SIZEOF_ETH_HDR
#define SIZEOF_ETH_HDR
Definition: ethernet.h:84
X16_F
#define X16_F
Definition: arch.h:154
netif::linkoutput
netif_linkoutput_fn linkoutput
Definition: netif.h:263
pbuf::flags
u8_t flags
Definition: pbuf.h:165
X8_F
#define X8_F
Definition: arch.h:145
ETHARP_DEBUG
#define ETHARP_DEBUG
Definition: lwipopts.h:431
LL_IP6_MULTICAST_ADDR_0
#define LL_IP6_MULTICAST_ADDR_0
Definition: ethernet.h:149
snmp.h
stats.h
LWIP_DBG_LEVEL_SERIOUS
#define LWIP_DBG_LEVEL_SERIOUS
Definition: debug.h:57
LL_IP4_MULTICAST_ADDR_1
#define LL_IP4_MULTICAST_ADDR_1
Definition: ethernet.h:145
PBUF_FLAG_LLMCAST
#define PBUF_FLAG_LLMCAST
Definition: pbuf.h:137
eth_type
eth_type
Definition: ethernet.h:108
s32_t
int32_t s32_t
Definition: arch.h:127
u8_t
uint8_t u8_t
Definition: arch.h:122
ETHTYPE_PPPOEDISC
Definition: ethernet.h:122
eth_hdr
Definition: ethernet.h:71
netif
Definition: netif.h:233
ETHTYPE_IPV6
Definition: ethernet.h:120
netif::hwaddr_len
u8_t hwaddr_len
Definition: netif.h:309
eth_addr_cmp
#define eth_addr_cmp(addr1, addr2)
Definition: ethernet.h:164
ethernet.h
lwip_htons
u16_t lwip_htons(u16_t n)
Definition: def.c:75
ETH_HWADDR_LEN
#define ETH_HWADDR_LEN
Definition: ethernet.h:50
ETHADDR16_COPY
#define ETHADDR16_COPY(dst, src)
Definition: ethernet.h:161
ERR_OK
Definition: err.h:63
ETHADDR32_COPY
#define ETHADDR32_COPY(dst, src)
Definition: ethernet.h:155
err_t
s8_t err_t
Definition: err.h:57
eth_addr
Definition: ethernet.h:58
ip.h
etharp.h
ppp_opts.h
LL_IP4_MULTICAST_ADDR_2
#define LL_IP4_MULTICAST_ADDR_2
Definition: ethernet.h:146
ETHTYPE_IP
Definition: ethernet.h:110
LL_IP6_MULTICAST_ADDR_1
#define LL_IP6_MULTICAST_ADDR_1
Definition: ethernet.h:150
LWIP_DBG_LEVEL_WARNING
#define LWIP_DBG_LEVEL_WARNING
Definition: debug.h:55
LL_IP4_MULTICAST_ADDR_0
#define LL_IP4_MULTICAST_ADDR_0
Definition: ethernet.h:144
ETHTYPE_VLAN
Definition: ethernet.h:118
kprintf
int kprintf(const char *,...)
Definition: kprintf.c:259
eth_vlan_hdr
Definition: ethernet.h:93
pbuf
Definition: pbuf.h:142
LWIP_DEBUGF
#define LWIP_DEBUGF(debug, message)
Definition: debug.h:164
ETHTYPE_ARP
Definition: ethernet.h:112
pbuf_header
u8_t pbuf_header(struct pbuf *p, s16_t header_size)
Definition: pbuf.c:665
pppoe.h
pbuf::payload
void * payload
Definition: pbuf.h:147
PP_HTONS
#define PP_HTONS(x)
Definition: def.h:79