et/icmpv6: Remove the coupling between ICMPv6 and Ethernet by moving all Ethernet stuff to neighbor_ethernet_out.c and make the mac address as first field.

This commit is contained in:
Xiang Xiao 2018-11-09 15:41:23 -06:00 committed by Gregory Nutt
parent a3cda3867b
commit 4f25b83f8f
12 changed files with 60 additions and 275 deletions

View File

@ -128,8 +128,8 @@
* layer address taking into account a header of the two-bytes.
*/
#define ICMPv6_OPT_SIZE(a) (((a) + 2 + 7) & ~7)
#define ICMPv6_OPT_OCTECTS(a) (((a) + 2 + 7) >> 3)
#define ICMPv6_OPT_SIZE(a) ((a) > 0 ? ((a) + 2 + 7) & ~7 : 0)
#define ICMPv6_OPT_OCTECTS(a) ((a) > 0 ? ((a) + 2 + 7) >> 3 : 0)
/****************************************************************************
* Public Type Definitions

View File

@ -212,8 +212,8 @@ struct netdev_maxaddr_s
struct netdev_varaddr_s
{
uint8_t nv_addrlen;
uint8_t nv_addr[RADIO_MAX_ADDRLEN];
uint8_t nv_addrlen;
};
#endif
@ -255,9 +255,6 @@ struct net_driver_s
uint16_t d_pktsize; /* Maximum packet size */
#if defined(CONFIG_NET_ETHERNET) || defined(CONFIG_NET_6LOWPAN) || \
defined(CONFIG_NET_BLUETOOTH) || defined(CONFIG_NET_IEEE802154)
/* Link layer address */
union
@ -275,7 +272,6 @@ struct net_driver_s
struct netdev_varaddr_s radio;
#endif
} d_mac;
#endif /* CONFIG_NET_ETHERNET || CONFIG_NET_6LOWPAN ... || CONFIG_NET_IEEE802154 */
/* Network identity */

View File

@ -103,8 +103,8 @@
struct pktradio_addr_s
{
uint8_t pa_addrlen; /* Length of the following address */
uint8_t pa_addr[RADIO_MAX_ADDRLEN];
uint8_t pa_addrlen; /* Length of the following address */
};
/* Different packet radios may have different properties. If there are

View File

@ -238,7 +238,7 @@ void icmpv6_poll(FAR struct net_driver_s *dev);
* Set up to send an ICMPv6 Neighbor Solicitation message
*
* Input Parameters:
* dev - Reference to an Ethernet device driver structure
* dev - Reference to a device driver structure
* ipaddr - IP address of Neighbor to be solicited
*
* Returned Value:
@ -256,7 +256,6 @@ void icmpv6_solicit(FAR struct net_driver_s *dev,
* Set up to send an ICMPv6 Router Solicitation message. This version
* is for a standalone solicitation. If formats:
*
* - The Ethernet header
* - The IPv6 header
* - The ICMPv6 Neighbor Router Message
*
@ -264,7 +263,7 @@ void icmpv6_solicit(FAR struct net_driver_s *dev,
* prior to calling this function.
*
* Input Parameters:
* dev - Reference to an Ethernet device driver structure
* dev - Reference to a device driver structure
*
* Returned Value:
* None

View File

@ -53,7 +53,6 @@
#include <nuttx/net/netdev.h>
#include <nuttx/net/net.h>
#include <nuttx/net/icmpv6.h>
#include <nuttx/net/ethernet.h>
#include "netdev/netdev.h"
#include "utils/utils.h"
@ -65,7 +64,6 @@
* Pre-processor Definitions
****************************************************************************/
#define ETHBUF ((struct eth_hdr_s *)&dev->d_buf[0])
#define IPv6BUF ((struct ipv6_hdr_s *)&dev->d_buf[NET_LL_HDRLEN(dev)])
#define ICMPv6ADVERTISE \
@ -141,9 +139,7 @@ void icmpv6_advertise(FAR struct net_driver_s *dev,
adv->opttype = ICMPv6_OPT_TGTLLADDR; /* Option type */
adv->optlen = ICMPv6_OPT_OCTECTS(lladdrsize); /* Option length in octets */
/* Copy our link layer address into the message
* REVISIT: What if the link layer is not Ethernet?
*/
/* Copy our link layer address into the message */
memcpy(adv->tgtlladdr, &dev->d_mac, lladdrsize);
@ -156,34 +152,6 @@ void icmpv6_advertise(FAR struct net_driver_s *dev,
dev->d_len = IPv6_HDRLEN + l3size;
#ifdef CONFIG_NET_ETHERNET
/* Add the size of the Ethernet header */
dev->d_len += ETH_HDRLEN;
/* Move the source and to the destination addresses in the Ethernet header
* and use our MAC as the new source address
*/
if (dev->d_lltype == NET_LL_ETHERNET)
{
FAR struct eth_hdr_s *eth = ETHBUF;
memcpy(eth->dest, eth->src, ETHER_ADDR_LEN);
memcpy(eth->src, dev->d_mac.ether.ether_addr_octet, ETHER_ADDR_LEN);
/* Set the IPv6 Ethernet type */
eth->type = HTONS(ETHTYPE_IP6);
}
#endif
/* No additional neighbor lookup is required on this packet (We are using
* a multicast address).
*/
IFF_SET_NOARP(dev->d_flags);
ninfo("Outgoing ICMPv6 Neighbor Advertise length: %d (%d)\n",
dev->d_len, (ipv6->len[0] << 8) | ipv6->len[1]);

View File

@ -1,7 +1,7 @@
/****************************************************************************
* net/icmpv6/icmpv6_autoconfig.c
*
* Copyright (C) 2015-2016 Gregory Nutt. All rights reserved.
* Copyright (C) 2015-2016, 2018 Gregory Nutt. All rights reserved.
* Author: Gregory Nutt <gnutt@nuttx.org>
*
* Redistribution and use in source and binary forms, with or without
@ -45,8 +45,6 @@
#include <errno.h>
#include <debug.h>
#include <net/ethernet.h>
#include <nuttx/semaphore.h>
#include <nuttx/net/net.h>
#include <nuttx/net/netdev.h>
@ -150,8 +148,10 @@ static uint16_t icmpv6_router_eventhandler(FAR struct net_driver_s *dev,
return flags;
}
/* It looks like we are good to send the data */
/* Copy the packet data into the device packet buffer and send it */
/* It looks like we are good to send the data.
*
* Copy the packet data into the device packet buffer and send it.
*/
if (state->snd_advertise)
{
@ -166,11 +166,7 @@ static uint16_t icmpv6_router_eventhandler(FAR struct net_driver_s *dev,
icmpv6_rsolicit(dev);
}
/* Make sure no additional Router Solicitation overwrites this one.
* This flag will be cleared in icmpv6_out().
*/
IFF_SET_NOARP(dev->d_flags);
IFF_SET_IPv6(dev->d_flags);
/* Don't allow any further call backs. */
@ -336,13 +332,6 @@ static int icmpv6_wait_radvertise(FAR struct net_driver_s *dev,
int icmpv6_autoconfig(FAR struct net_driver_s *dev)
{
#ifndef CONFIG_NET_ETHERNET
/* Only Ethernet supported for now */
nerr("ERROR: Only Ethernet is supported\n");
return -ENOSYS;
#else /* CONFIG_NET_ETHERNET */
struct icmpv6_rnotify_s notify;
net_ipv6addr_t lladdr;
int retries;
@ -353,14 +342,6 @@ int icmpv6_autoconfig(FAR struct net_driver_s *dev)
DEBUGASSERT(dev);
ninfo("Auto-configuring %s\n", dev->d_ifname);
/* Only Ethernet devices are supported for now */
if (dev->d_lltype != NET_LL_ETHERNET)
{
nerr("ERROR: Only Ethernet is supported\n");
return -ENOSYS;
}
/* The interface should be in the down state */
net_lock();
@ -534,7 +515,6 @@ int icmpv6_autoconfig(FAR struct net_driver_s *dev)
netdev_ifup(dev);
net_unlock();
return OK;
#endif /* CONFIG_NET_ETHERNET */
}
#endif /* CONFIG_NET_ICMPv6_AUTOCONF */

View File

@ -265,6 +265,13 @@ void icmpv6_input(FAR struct net_driver_s *dev, unsigned int iplen)
sol = ICMPv6SOLICIT;
if (net_ipv6addr_cmp(sol->tgtaddr, dev->d_ipv6addr))
{
if (sol->opttype == ICMPv6_OPT_SRCLLADDR)
{
/* Save the sender's address mapping in our Neighbor Table. */
neighbor_add(dev, ipicmp->srcipaddr, sol->srclladdr);
}
/* Yes.. Send a neighbor advertisement back to where the neighbor
* solicitation came from.
*/
@ -308,19 +315,19 @@ void icmpv6_input(FAR struct net_driver_s *dev, unsigned int iplen)
/* Save the sender's address mapping in our Neighbor Table. */
neighbor_add(dev, ipv6->srcipaddr, adv->tgtlladdr);
}
#ifdef CONFIG_NET_ICMPv6_NEIGHBOR
/* Then notify any logic waiting for the Neighbor Advertisement */
/* Then notify any logic waiting for the Neighbor Advertisement */
icmpv6_notify(ipv6->srcipaddr);
icmpv6_notify(ipv6->srcipaddr);
#endif
/* We consumed the packet but we don't send anything in
* response.
*/
/* We consumed the packet but we don't send anything in
* response.
*/
goto icmpv6_send_nothing;
}
goto icmpv6_send_nothing;
}
goto icmpv6_drop_packet;
@ -351,6 +358,7 @@ void icmpv6_input(FAR struct net_driver_s *dev, unsigned int iplen)
{
FAR struct icmpv6_router_advertise_s *adv;
FAR uint8_t *options;
bool prefix = false;
uint16_t pktlen;
uint16_t optlen;
int ndx;
@ -380,7 +388,7 @@ void icmpv6_input(FAR struct net_driver_s *dev, unsigned int iplen)
FAR struct icmpv6_srclladdr_s *sllopt =
(FAR struct icmpv6_srclladdr_s *)&options[ndx];
if (sllopt->opttype == 1 && sllopt->optlen == 1)
if (sllopt->opttype == ICMPv6_OPT_SRCLLADDR)
{
neighbor_add(dev, ipv6->srcipaddr, sllopt->srclladdr);
}
@ -392,14 +400,13 @@ void icmpv6_input(FAR struct net_driver_s *dev, unsigned int iplen)
* the "A" flag set?
*/
if (opt->opttype &&
opt->optlen == 4 &&
if (opt->opttype == ICMPv6_OPT_PREFIX &&
(opt->flags & ICMPv6_PRFX_FLAG_A) != 0)
{
/* Yes.. Notify any waiting threads */
icmpv6_rnotify(dev, ipv6->srcipaddr, opt->prefix, opt->preflen);
goto icmpv6_send_nothing;
prefix = true;
}
/* Skip to the next option (units of octets) */
@ -407,6 +414,11 @@ void icmpv6_input(FAR struct net_driver_s *dev, unsigned int iplen)
ndx += (opt->optlen << 3);
}
if (prefix)
{
goto icmpv6_send_nothing;
}
goto icmpv6_drop_packet;
}
break;
@ -515,7 +527,6 @@ void icmpv6_input(FAR struct net_driver_s *dev, unsigned int iplen)
}
break;
case ICMPV6_MCAST_LISTEN_REPORT_V2: /* Version 2 Multicast Listener Report, RFC 3810 */
{
FAR struct mld_mcast_listen_report_v2_s *report = MLDREPORT_V2;

View File

@ -136,16 +136,14 @@ static uint16_t icmpv6_neighbor_eventhandler(FAR struct net_driver_s *dev,
return flags;
}
/* It looks like we are good to send the data */
/* Copy the packet data into the device packet buffer and send it */
/* It looks like we are good to send the data.
*
* Copy the packet data into the device packet buffer and send it.
*/
icmpv6_solicit(dev, state->snd_ipaddr);
/* Make sure no additional Neighbor Solicitation overwrites this one.
* This flag will be cleared in icmpv6_out().
*/
IFF_SET_NOARP(dev->d_flags);
IFF_SET_IPv6(dev->d_flags);
/* Don't allow any further call backs. */
@ -232,18 +230,6 @@ int icmpv6_neighbor(const net_ipv6addr_t ipaddr)
goto errout;
}
/* Send the Neighbor Solicitation request only if this device uses the
* Ethernet link layer protocol.
*
* REVISIT: Other link layer protocols may require Neighbor Discovery
* as well.
*/
if (dev->d_lltype != NET_LL_ETHERNET)
{
return OK;
}
/* Check if the destination address is on the local network. */
if (net_ipv6addr_maskcmp(ipaddr, dev->d_ipv6addr, dev->d_ipv6netmask))

View File

@ -64,7 +64,6 @@
* Pre-processor Definitions
****************************************************************************/
#define ETHBUF ((struct eth_hdr_s *)&dev->d_buf[0])
#define IPv6BUF ((struct ipv6_hdr_s *)&dev->d_buf[NET_LL_HDRLEN(dev)])
#define ICMPv6ADVERTISE \
@ -207,7 +206,7 @@ void icmpv6_radvertise(FAR struct net_driver_s *dev)
mtu->opttype = ICMPv6_OPT_MTU;
mtu->optlen = 1;
mtu->reserved = 0;
mtu->mtu = HTONL(CONFIG_NET_ETH_PKTSIZE - ETH_HDRLEN);
mtu->mtu = HTONL(dev->d_pktsize - dev->d_llhdrlen);
/* Set up the prefix option */
@ -242,34 +241,6 @@ void icmpv6_radvertise(FAR struct net_driver_s *dev)
dev->d_len = IPv6_HDRLEN + l3size;
#ifdef CONFIG_NET_ETHERNET
/* Add the size of the Ethernet header */
dev->d_len += ETH_HDRLEN;
/* Move the source and to the destination addresses in the Ethernet header
* and use our MAC as the new source address
*/
if (dev->d_lltype == NET_LL_ETHERNET)
{
FAR struct eth_hdr_s *eth = ETHBUF;
memcpy(eth->dest, g_ipv6_ethallnodes.ether_addr_octet, ETHER_ADDR_LEN);
memcpy(eth->src, dev->d_mac.ether.ether_addr_octet, ETHER_ADDR_LEN);
/* Set the IPv6 Ethernet type */
eth->type = HTONS(ETHTYPE_IP6);
}
#endif
/* No additional neighbor lookup is required on this packet (We are using
* a multicast address).
*/
IFF_SET_NOARP(dev->d_flags);
ninfo("Outgoing ICMPv6 Router Advertise length: %d (%d)\n",
dev->d_len, (ipv6->len[0] << 8) | ipv6->len[1]);

View File

@ -58,7 +58,6 @@
* Pre-processor Definitions
****************************************************************************/
#define ETHBUF ((struct eth_hdr_s *)&dev->d_buf[0])
#define IPv6BUF ((struct ipv6_hdr_s *)&dev->d_buf[NET_LL_HDRLEN(dev)])
#define ICMPv6RSOLICIT \
((struct icmpv6_router_solicit_s *)&dev->d_buf[NET_LL_HDRLEN(dev) + IPv6_HDRLEN])
@ -74,7 +73,6 @@
* Set up to send an ICMPv6 Router Solicitation message. This version
* is for a standalone solicitation. If formats:
*
* - The Ethernet header
* - The IPv6 header
* - The ICMPv6 Router Solicitation Message
*
@ -82,7 +80,7 @@
* prior to calling this function.
*
* Input Parameters:
* dev - Reference to an Ethernet device driver structure
* dev - Reference to a device driver structure
*
* Returned Value:
* None
@ -93,7 +91,6 @@ void icmpv6_rsolicit(FAR struct net_driver_s *dev)
{
FAR struct ipv6_hdr_s *ipv6;
FAR struct icmpv6_router_solicit_s *sol;
FAR struct eth_hdr_s *eth;
uint16_t lladdrsize;
uint16_t l3size;
@ -139,9 +136,7 @@ void icmpv6_rsolicit(FAR struct net_driver_s *dev)
sol->opttype = ICMPv6_OPT_SRCLLADDR; /* Option type */
sol->optlen = ICMPv6_OPT_OCTECTS(lladdrsize); /* Option length in octets */
/* Copy our link layer address into the message
* REVISIT: What if the link layer is not Ethernet?
*/
/* Copy our link layer address into the message */
memcpy(sol->srclladdr, &dev->d_mac, lladdrsize);
@ -154,40 +149,6 @@ void icmpv6_rsolicit(FAR struct net_driver_s *dev)
dev->d_len = IPv6_HDRLEN + l3size;
#ifdef CONFIG_NET_ETHERNET
if (dev->d_lltype == NET_LL_ETHERNET)
{
/* Set the destination IPv6 all-routers multicast Ethernet
* address
*/
eth = ETHBUF;
memcpy(eth->dest, g_ipv6_ethallrouters.ether_addr_octet, ETHER_ADDR_LEN);
/* Move our source Ethernet addresses into the Ethernet header */
memcpy(eth->src, dev->d_mac.ether.ether_addr_octet, ETHER_ADDR_LEN);
/* Set the IPv6 Ethernet type */
eth->type = HTONS(ETHTYPE_IP6);
#if 0
/* No additional neighbor lookup is required on this packet.
* REVISIT: It is inappropriate to set this bit if we get here
* via neighbor_out(); It is no necessary to set this bit if we
* get here via icmpv6_input(). Is it ever necessary?
*/
IFF_SET_NOARP(dev->d_flags);
#endif
}
#endif
/* Add the size of the layer layer header to the total size of the
* outgoing packet.
*/
dev->d_len += netdev_ipv6_hdrlen(dev);
ninfo("Outgoing ICMPv6 Router Solicitation length: %d (%d)\n",
dev->d_len, (ipv6->len[0] << 8) | ipv6->len[1]);

View File

@ -46,7 +46,6 @@
#include <nuttx/net/net.h>
#include <nuttx/net/netdev.h>
#include <nuttx/net/netstats.h>
#include <nuttx/net/ethernet.h>
#include "devif/devif.h"
#include "netdev/netdev.h"
@ -59,7 +58,6 @@
* Pre-processor Definitions
****************************************************************************/
#define ETHBUF ((struct eth_hdr_s *)&dev->d_buf[0])
#define IPv6BUF ((struct ipv6_hdr_s *)&dev->d_buf[NET_LL_HDRLEN(dev)])
#define ICMPv6SOLICIT \
((struct icmpv6_neighbor_solicit_s *)&dev->d_buf[NET_LL_HDRLEN(dev) + IPv6_HDRLEN])
@ -87,12 +85,11 @@ static const uint16_t g_icmpv_mcastaddr[6] =
* Set up to send an ICMPv6 Neighbor Solicitation message. This version
* is for a standalone solicitation. If formats:
*
* - The Ethernet header
* - The IPv6 header
* - The ICMPv6 Neighbor Solicitation Message
*
* Input Parameters:
* dev - Reference to an Ethernet device driver structure
* dev - Reference to a device driver structure
* ipaddr - IP address of Neighbor to be solicited
*
* Returned Value:
@ -154,9 +151,7 @@ void icmpv6_solicit(FAR struct net_driver_s *dev,
sol->opttype = ICMPv6_OPT_SRCLLADDR; /* Option type */
sol->optlen = ICMPv6_OPT_OCTECTS(lladdrsize); /* Option length in octets */
/* Copy our link layer address into the message
* REVISIT: What if the link layer is not Ethernet?
*/
/* Copy our link layer address into the message */
memcpy(sol->srclladdr, &dev->d_mac, lladdrsize);
@ -169,56 +164,6 @@ void icmpv6_solicit(FAR struct net_driver_s *dev,
dev->d_len = IPv6_HDRLEN + l3size;
#ifdef CONFIG_NET_ETHERNET
if (dev->d_lltype == NET_LL_ETHERNET)
{
FAR struct eth_hdr_s *eth;
/* Set the destination IPv6 multicast Ethernet address:
*
* For IPv6 multicast addresses, the Ethernet MAC is derived by
* the four low-order octets OR'ed with the MAC 33:33:00:00:00:00,
* so for example the IPv6 address FF02:DEAD:BEEF::1:3 would map
* to the Ethernet MAC address 33:33:00:01:00:03.
*
* NOTES: This appears correct for the ICMPv6 Router Solicitation
* Message, but the ICMPv6 Neighbor Solicitation message seems to
* use 33:33:ff:01:00:03.
*/
eth = ETHBUF;
eth->dest[0] = 0x33;
eth->dest[1] = 0x33;
eth->dest[2] = 0xff;
eth->dest[3] = ipaddr[6] >> 8;
eth->dest[4] = ipaddr[7] & 0xff;
eth->dest[5] = ipaddr[7] >> 8;
/* Move our source Ethernet addresses into the Ethernet header */
memcpy(eth->src, dev->d_mac.ether.ether_addr_octet, ETHER_ADDR_LEN);
/* Set the IPv6 Ethernet type */
eth->type = HTONS(ETHTYPE_IP6);
#if 0
/* No additional neighbor lookup is required on this packet.
* REVISIT: It is inappropriate to set this bit if we get here
* via neighbor_out(); It is no necessary to set this bit if we
* get here via icmpv6_input(). Is it ever necessary?
*/
IFF_SET_NOARP(dev->d_flags);
#endif
}
#endif
/* Add the size of the layer layer header to the total size of the
* outgoing packet.
*/
dev->d_len += netdev_ipv6_hdrlen(dev);
ninfo("Outgoing ICMPv6 Neighbor Solicitation length: %d (%d)\n",
dev->d_len, (ipv6->len[0] << 8) | ipv6->len[1]);

View File

@ -42,7 +42,7 @@
#include <string.h>
#include <debug.h>
#include <nuttx/net/arp.h>
#include <nuttx/net/ethernet.h>
#include <nuttx/net/ip.h>
#include <nuttx/net/netdev.h>
@ -61,15 +61,6 @@
* Private Data
****************************************************************************/
/* Support for broadcast address */
static const struct ether_addr g_broadcast_ethaddr =
{
{
0xff, 0xff, 0xff, 0xff, 0xff, 0xff
}
};
/* Support for MLD multicast addresses.
*
* Well-known ethernet multicast address:
@ -83,17 +74,8 @@ static const struct ether_addr g_broadcast_ethaddr =
* 01-00-5e-xx-xx-xx 0x0800 IPv4 IGMP Multicast Address
* 33-33-00-00-00-00 0x86DD IPv6 Neighbor Discovery
* 33-33-xx-xx-xx-xx 0x86DD IPv6 Multicast Address (RFC3307)
*
* The following is the first three octects of the IGMP address:
*/
#ifdef CONFIG_NET_MLD
static const uint8_t g_multicast_ethaddr[3] =
{
0x01, 0x00, 0x5e
};
#endif
/****************************************************************************
* Private Functions
****************************************************************************/
@ -134,11 +116,9 @@ void neighbor_ethernet_out(FAR struct net_driver_s *dev)
FAR struct eth_hdr_s *eth = ETHBUF;
FAR struct ipv6_hdr_s *ip = IPv6BUF;
struct neighbor_addr_s laddr;
net_ipv6addr_t ipaddr;
/* Skip sending Neighbor Solicitations when the frame to be transmitted was
* written into a packet socket or if we are sending certain Neighbor
* messages (solicitation, advertisement, echo request).
* written into a packet socket.
*/
if (IFF_IS_NOARP(dev->d_flags))
@ -157,31 +137,12 @@ void neighbor_ethernet_out(FAR struct net_driver_s *dev)
* packet with an Neighbor Solicitation Request for the IPv6 address.
*/
/* First check if destination is a IPv6 multicast address.
*
* REVISIT: Need to revisit IPv6 broadcast support. Broadcast
* IP addresses are not used with IPv6; multicast is used instead.
* Does this mean that all multicast address should go to the
* broadcast Ethernet address?
*/
/* First check if destination isn't IPv6 multicast address. */
if (net_is_addr_mcast(ip->destipaddr))
if (!net_is_addr_mcast(ip->destipaddr))
{
memcpy(eth->dest, g_broadcast_ethaddr.ether_addr_octet,
ETHER_ADDR_LEN);
}
net_ipv6addr_t ipaddr;
#ifdef CONFIG_NET_MLD
/* Check if the destination address is a multicast address
*
* IPv6 multicast addresses are have the high-order octet of the
* addresses=0xff (ff00::/8.)
*/
#warning Missing logic
#endif
else
{
/* Check if the destination address is on the local network. */
if (!net_ipv6addr_maskcmp(ip->destipaddr, dev->d_ipv6addr,
@ -224,11 +185,18 @@ void neighbor_ethernet_out(FAR struct net_driver_s *dev)
*/
icmpv6_solicit(dev, ipaddr);
return;
}
}
/* Build an Ethernet header. */
/* Build an Ethernet header. */
if (net_is_addr_mcast(ip->destipaddr))
{
eth->dest[0] = eth->dest[1] = 0x33;
memcpy(&eth->dest[2], &ip->destipaddr[6], 4);
}
else
{
memcpy(eth->dest, laddr.u.na_ethernet.ether_addr_octet, ETHER_ADDR_LEN);
}