Skip to content

Commit

Permalink
[BACKPORT] Ethernet : changes made to support ethernet (#27)
Browse files Browse the repository at this point in the history
 - unicast
 - broadcast
 - multicast
  • Loading branch information
garfieldG authored and dagar committed Sep 6, 2018
1 parent e3b5b66 commit 0ffe7ce
Show file tree
Hide file tree
Showing 12 changed files with 543 additions and 196 deletions.
70 changes: 40 additions & 30 deletions include/nuttx/net/ip.h
Original file line number Diff line number Diff line change
Expand Up @@ -508,6 +508,46 @@ bool net_ipv6addr_maskcmp(const net_ipv6addr_t addr1,
const net_ipv6addr_t mask);
#endif

/****************************************************************************
* Name: net_ipv4addr_broadcast
*
* Description:
* Mask out the network part of an IP address, given the address and
* the netmask.
*
* Example:
*
* in_addr_t ipaddr;
* in_addr_t netmask;
* bool isbroadcast;
*
* net_ipaddr(&netmask, 255,255,255,0);
* net_ipaddr(&ipaddr, 192,16,1,255);
* isbroadcast = net_ipv4addr_broadcast(ipaddr, netmask);
*
* Will return isboadcast == true.
*
* net_ipaddr(&ipaddr, 192,16,1,2);
* isbroadcast = net_ipv4addr_broadcast(ipaddr, netmask);
*
* Will return isboadcast == false.
*
* NOTES:
* 1. This function does not check for the broadcast address
* 255.255.255.255. That must be performed as a seperate check.
* 2. You must also separately check if the ipaddress lies on the sub-net
* using, perhaps, net_ipv4addr_maskcmp().
*
* Input Parameters:
* addr - The IPv4 address to check
* mask - The network mask
*
****************************************************************************/

#define net_ipv4addr_broadcast(addr, mask) \
(((in_addr_t)(addr) & ~(in_addr_t)(mask)) == \
((in_addr_t)(0xffffffff) & ~(in_addr_t)(mask)))

/****************************************************************************
* Name: net_ipv6addr_prefixcmp
*
Expand Down Expand Up @@ -587,36 +627,6 @@ bool net_ipv6addr_maskcmp(const net_ipv6addr_t addr1,

#define net_is_addr_linklocal(a) ((a)[0] == HTONS(0xfe80))

/****************************************************************************
* Name: net_ipaddr_mask
*
* Description:
* Mask out the network part of an IP address, given the address and
* the netmask.
*
* Example:
*
* in_addr_t ipaddr1, ipaddr2, netmask;
*
* net_ipaddr(&ipaddr1, 192,16,1,2);
* net_ipaddr(&netmask, 255,255,255,0);
* net_ipaddr_mask(&ipaddr2, &ipaddr1, &netmask);
*
* In the example above, the variable "ipaddr2" will contain the IP
* address 192.168.1.0.
*
* Input Parameters:
* dest Where the result is to be placed.
* src The IP address.
* mask The netmask.
*
****************************************************************************/

#define net_ipaddr_mask(dest, src, mask) \
do { \
(in_addr_t)(dest) = (in_addr_t)(src) & (in_addr_t)(mask); \
} while (0)

#undef EXTERN
#ifdef __cplusplus
}
Expand Down
3 changes: 2 additions & 1 deletion libc/net/Make.defs
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,8 @@
# Add the networking C files to the build

CSRCS += lib_addrconfig.c lib_etherntoa.c lib_htons.c lib_htonl.c
CSRCS += lib_inetaddr.c lib_inetntoa.c lib_inetntop.c lib_inetpton.c
CSRCS += lib_inetaddr.c lib_inetaton.c lib_inetntoa.c
CSRCS += lib_inetntop.c lib_inetpton.c

ifeq ($(CONFIG_NET),y)
CSRCS += lib_shutdown.c
Expand Down
125 changes: 125 additions & 0 deletions libc/net/lib_inetaton.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,125 @@
/****************************************************************************
* libc/net/lib_inetaton
*
* Copyright (C) 2018 Gregory Nutt. All rights reserved.
* Author: Juha Niskanen <juha.niskanen@haltian.com>
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in
* the documentation and/or other materials provided with the
* distribution.
* 3. Neither the name NuttX nor the names of its contributors may be
* used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
* COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
* OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
* AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
* ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*
****************************************************************************/

/****************************************************************************
* Included Files
****************************************************************************/

#include <stdint.h>
#include <arpa/inet.h>

/****************************************************************************
* Public Functions
****************************************************************************/

/****************************************************************************
* Name: inet_aton
*
* Description:
* The inet_aton() function converts the string pointed to by cp, in the
* standard IPv4 dotted decimal notation, to an integer value suitable for
* use as an Internet address.
*
* Note:
* inet_aton() returns nonzero if the address is valid, zero if not.
* Therefore macros OK and ERROR are not used here.
*
****************************************************************************/

int inet_aton(FAR const char *cp, FAR struct in_addr *inp)
{
int dots = 0;
uint32_t num = 0;
uint32_t addr = 0;
int c;

do
{
c = *cp;

switch (c)
{
case '0':
case '1':
case '2':
case '3':
case '4':
case '5':
case '6':
case '7':
case '8':
case '9':
num = 10 * num + (c - '0');
break;

case '.':
dots++;
if (dots > 3)
{
return 0;
}

/* no break */

case '\0':
if (num > 255)
{
return 0;
}

addr = addr << 8 | num;
num = 0;
break;

default:
return 0;
}
}
while (*cp++);

/* Normalize it */

if (dots < 3)
{
addr <<= 8 * (3 - dots);
}

if (inp)
{
inp->s_addr = HTONL(addr);
}

return 1;
}
107 changes: 64 additions & 43 deletions net/arp/arp_out.c
Original file line number Diff line number Diff line change
Expand Up @@ -169,6 +169,7 @@ void arp_out(FAR struct net_driver_s *dev)
if (net_ipv4addr_hdrcmp(pip->eh_destipaddr, g_broadcast_ipaddr))
{
memcpy(peth->dest, g_broadcast_ethaddr.ether_addr_octet, ETHER_ADDR_LEN);
goto finish_header;
}

#ifdef CONFIG_NET_IGMP
Expand All @@ -181,74 +182,94 @@ void arp_out(FAR struct net_driver_s *dev)
* addresses=0xff (ff00::/8.)
*/

else if (NTOHS(pip->eh_destipaddr[0]) >= 0xe000 &&
NTOHS(pip->eh_destipaddr[0]) <= 0xefff)
if (NTOHS(pip->eh_destipaddr[0]) >= 0xe000 &&
NTOHS(pip->eh_destipaddr[0]) <= 0xefff)
{
/* Build the well-known IPv4 IGMP Ethernet address. The first
* three bytes are fixed; the final three variable come from the
* last three bytes of the IP address.
* last three bytes of the IPv4 address (network order).
*
* Address range : 01:00:5e:00:00:00 to 01:00:5e:7f:ff:ff
*/

FAR const uint8_t *ip = ((FAR uint8_t *)pip->eh_destipaddr) + 1;
memcpy(peth->dest, g_multicast_ethaddr, 3);
memcpy(&peth->dest[3], ip, 3);
FAR const uint8_t *ip = (FAR uint8_t *)pip->eh_destipaddr;

peth->dest[0] = g_multicast_ethaddr[0];
peth->dest[1] = g_multicast_ethaddr[1];
peth->dest[2] = g_multicast_ethaddr[2];
peth->dest[3] = ip[1] & 0x7f;
peth->dest[4] = ip[2];
peth->dest[5] = ip[3];

goto finish_header;
}
#endif
else
{
/* Check if the destination address is on the local network. */

destipaddr = net_ip4addr_conv32(pip->eh_destipaddr);
if (!net_ipv4addr_maskcmp(destipaddr, dev->d_ipaddr, dev->d_netmask))
{
/* Destination address is not on the local network */
/* Check if the destination address is on the local network. */

destipaddr = net_ip4addr_conv32(pip->eh_destipaddr);
if (!net_ipv4addr_maskcmp(destipaddr, dev->d_ipaddr, dev->d_netmask))
{
/* Destination address is not on the local network */

#ifdef CONFIG_NET_ROUTE
/* We have a routing table.. find the correct router to use in
* this case (or, as a fall-back, use the device's default router
* address). We will use the router IP address instead of the
* destination address when determining the MAC address.
*/
/* We have a routing table.. find the correct router to use in
* this case (or, as a fall-back, use the device's default router
* address). We will use the router IP address instead of the
* destination address when determining the MAC address.
*/

netdev_ipv4_router(dev, destipaddr, &ipaddr);
netdev_ipv4_router(dev, destipaddr, &ipaddr);
#else
/* Use the device's default router IP address instead of the
* destination address when determining the MAC address.
*/
/* Use the device's default router IP address instead of the
* destination address when determining the MAC address.
*/

net_ipv4addr_copy(ipaddr, dev->d_draddr);
net_ipv4addr_copy(ipaddr, dev->d_draddr);
#endif
}
else
{
/* Else, we use the destination IP address. */
}

/* The destination address is on the local network. Check if it is
* the sub-net broadcast address.
*/

net_ipv4addr_copy(ipaddr, destipaddr);
}
else if (net_ipv4addr_broadcast(destipaddr, dev->d_netmask))
{
/* Yes.. then we won't need to know the destination MAC address */

/* Check if we already have this destination address in the ARP table */
memcpy(peth->dest, g_broadcast_ethaddr.ether_addr_octet, ETHER_ADDR_LEN);
goto finish_header;
}
else
{
/* Else, we use the destination IP address. */

tabptr = arp_find(ipaddr);
if (!tabptr)
{
ninfo("ARP request for IP %08lx\n", (unsigned long)ipaddr);
net_ipv4addr_copy(ipaddr, destipaddr);
}

/* The destination address was not in our ARP table, so we
* overwrite the IP packet with an ARP request.
*/
/* Check if we already have this destination address in the ARP table */

arp_format(dev, ipaddr);
arp_dump(ARPBUF);
return;
}
tabptr = arp_find(ipaddr);
if (tabptr == NULL)
{
ninfo("ARP request for IP %08lx\n", (unsigned long)ipaddr);

/* Build an Ethernet header. */
/* The destination address was not in our ARP table, so we overwrite
* the IP packet with an ARP request.
*/

memcpy(peth->dest, tabptr->at_ethaddr.ether_addr_octet, ETHER_ADDR_LEN);
arp_format(dev, ipaddr);
arp_dump(ARPBUF);
return;
}

/* Build an Ethernet header. */

memcpy(peth->dest, tabptr->at_ethaddr.ether_addr_octet, ETHER_ADDR_LEN);

/* Finish populating the Ethernet header */

finish_header:
memcpy(peth->src, dev->d_mac.ether.ether_addr_octet, ETHER_ADDR_LEN);
peth->type = HTONS(ETHTYPE_IP);
dev->d_len += ETH_HDRLEN;
Expand Down
11 changes: 11 additions & 0 deletions net/arp/arp_send.c
Original file line number Diff line number Diff line change
Expand Up @@ -268,6 +268,17 @@ int arp_send(in_addr_t ipaddr)
ipaddr = dripaddr;
}

/* The destination address is on the local network. Check if it is
* the sub-net broadcast address.
*/

else if (net_ipv4addr_broadcast(ipaddr, dev->d_netmask))
{
/* Yes.. We don't need to send the ARP request */

return OK;
}

/* Allocate resources to receive a callback. This and the following
* initialization is performed with the network lock because we don't
* want anything to happen until we are ready.
Expand Down
Loading

0 comments on commit 0ffe7ce

Please sign in to comment.