Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Support INARP request and reply (IDFGH-13604) #14491

Open
MoegerleS opened this issue Sep 3, 2024 · 0 comments
Open

Support INARP request and reply (IDFGH-13604) #14491

MoegerleS opened this issue Sep 3, 2024 · 0 comments
Assignees
Labels
Status: Opened Issue is new Type: Feature Request Feature request for IDF

Comments

@MoegerleS
Copy link

MoegerleS commented Sep 3, 2024

Is your feature request related to a problem?

In order to resolve an IP address by a MAC address in the network, an INARP request / reply is needed. This is useful if the MAC address is know and the IP address as to find out.
With this solution the INARP request can be called by the etharp_raw funtion.

For future optimization the request should be done by a single INARP request function.

Describe the solution you'd like.

Complete the etharp_opcode struct in lwip/prot/etharp.h

enum etharp_opcode {
  ARP_REQUEST = 1,
  ARP_REPLY   = 2,
  INARP_REQUEST = 8,
  INARP_REPLY   = 9
};

Add following functions in lwip/src/include/lwip/etharp.h

    err_t etharp_request_dst(struct netif *netif, const ip4_addr_t *ipaddr, const struct eth_addr *hw_dst_addr);
    err_t etharp_raw(struct netif *netif, const struct eth_addr *ethsrc_addr,
            const struct eth_addr *ethdst_addr,
            const struct eth_addr *hwsrc_addr, const ip4_addr_t *ipsrc_addr,
            const struct eth_addr *hwdst_addr, const ip4_addr_t *ipdst_addr,
            const u16_t opcode);

Change the function types and replace the function etharp_input in lwip/src/core/ipv4/etharp.c

    // Remove function declerations
    static err_t etharp_request_dst(struct netif *netif, const ip4_addr_t *ipaddr, const struct eth_addr *hw_dst_addr);
    static err_t etharp_raw(struct netif *netif,
                        const struct eth_addr *ethsrc_addr, const struct eth_addr *ethdst_addr,
                        const struct eth_addr *hwsrc_addr, const ip4_addr_t *ipsrc_addr,
                        const struct eth_addr *hwdst_addr, const ip4_addr_t *ipdst_addr,
                        const u16_t opcode);
    // Remove static delcaration in front of etharp_raw decleration
    err_t
    etharp_request_dst(struct netif *netif, const ip4_addr_t *ipaddr, const struct eth_addr *hw_dst_addr)
    // Remove static
        err_t ICACHE_FLASH_ATTR
        etharp_raw(struct netif *netif, const struct eth_addr *ethsrc_addr,
                   const struct eth_addr *ethdst_addr,
                   const struct eth_addr *hwsrc_addr, const ip_addr_t *ipsrc_addr,
                   const struct eth_addr *hwdst_addr, const ip_addr_t *ipdst_addr,
                   const u16_t opcode)
        {      
// Replace ehtarp_input function
void
etharp_input(struct pbuf *p, struct netif *netif)
{
  struct etharp_hdr *hdr;
  /* these are aligned properly, whereas the ARP header fields might not be */
  ip4_addr_t sipaddr, dipaddr;
  u8_t for_us;

  LWIP_ASSERT_CORE_LOCKED();

  LWIP_ERROR("netif != NULL", (netif != NULL), return;);

  hdr = (struct etharp_hdr *)p->payload;

  /* RFC 826 "Packet Reception": */
  if ((hdr->hwtype != PP_HTONS(LWIP_IANA_HWTYPE_ETHERNET)) ||
      (hdr->hwlen != ETH_HWADDR_LEN) ||
      (hdr->protolen != sizeof(ip4_addr_t)) ||
      (hdr->proto != PP_HTONS(ETHTYPE_IP)))  {
    LWIP_DEBUGF(ETHARP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_LEVEL_WARNING,
                ("etharp_input: packet dropped, wrong hw type, hwlen, proto, protolen or ethernet type (%"U16_F"/%"U16_F"/%"U16_F"/%"U16_F")\n",
                 hdr->hwtype, (u16_t)hdr->hwlen, hdr->proto, (u16_t)hdr->protolen));
    ETHARP_STATS_INC(etharp.proterr);
    ETHARP_STATS_INC(etharp.drop);
    pbuf_free(p);
    return;
  }
  ETHARP_STATS_INC(etharp.recv);

#if LWIP_AUTOIP
  /* We have to check if a host already has configured our random
   * created link local address and continuously check if there is
   * a host with this IP-address so we can detect collisions */
  autoip_arp_reply(netif, hdr);
#endif /* LWIP_AUTOIP */

  /* Copy struct ip4_addr_wordaligned to aligned ip4_addr, to support compilers without
   * structure packing (not using structure copy which breaks strict-aliasing rules). */
  IPADDR_WORDALIGNED_COPY_TO_IP4_ADDR_T(&sipaddr, &hdr->sipaddr);
  IPADDR_WORDALIGNED_COPY_TO_IP4_ADDR_T(&dipaddr, &hdr->dipaddr);

  /* this interface is not configured? */
  if ((hdr->opcode == PP_HTONS(INARP_REQUEST)) || (hdr->opcode == PP_HTONS(INARP_REPLY))){
    if ((((&hdr->dhwaddr)->addr[0]) == (netif->hwaddr[0])) && (((&hdr->dhwaddr)->addr[1]) == (netif->hwaddr[1])) && (((&hdr->dhwaddr)->addr[2]) == (netif->hwaddr[2])) && (((&hdr->dhwaddr)->addr[3]) == (netif->hwaddr[3])) && (((&hdr->dhwaddr)->addr[4]) == (netif->hwaddr[4])) && (((&hdr->dhwaddr)->addr[5]) == (netif->hwaddr[5]))){
      for_us = 1;
    } else {
      for_us = 0;
    }
  } else {
    if (ip4_addr_isany_val(*netif_ip4_addr(netif))) {
      for_us = 0;
    } else {
      /* ARP packet directed to us? */
      for_us = (u8_t)ip4_addr_cmp(&dipaddr, netif_ip4_addr(netif));
    }
  }

  /* ARP message directed to us?
      -> add IP address in ARP cache; assume requester wants to talk to us,
         can result in directly sending the queued packets for this host.
     ARP message not directed to us?
      ->  update the source IP address in the cache, if present */
  etharp_update_arp_entry(netif, &sipaddr, &(hdr->shwaddr),
                          for_us ? ETHARP_FLAG_TRY_HARD : ETHARP_FLAG_FIND_ONLY);

  /* now act on the message itself */
  switch (hdr->opcode) {
    /* ARP request? */
    case PP_HTONS(ARP_REQUEST):
      /* ARP request. If it asked for our address, we send out a
       * reply. In any case, we time-stamp any existing ARP entry,
       * and possibly send out an IP packet that was queued on it. */

      LWIP_DEBUGF (ETHARP_DEBUG | LWIP_DBG_TRACE, ("etharp_input: incoming ARP request\n"));
      /* ARP request for our address? */
      if (for_us) {
        /* send ARP response */
        etharp_raw(netif,
                   (struct eth_addr *)netif->hwaddr, &hdr->shwaddr,
                   (struct eth_addr *)netif->hwaddr, netif_ip4_addr(netif),
                   &hdr->shwaddr, &sipaddr,
                   ARP_REPLY);
        /* we are not configured? */
      } else if (ip4_addr_isany_val(*netif_ip4_addr(netif))) {
        /* { for_us == 0 and netif->ip_addr.addr == 0 } */
        LWIP_DEBUGF(ETHARP_DEBUG | LWIP_DBG_TRACE, ("etharp_input: we are unconfigured, ARP request ignored.\n"));
        /* request was not directed to us */
      } else {
        /* { for_us == 0 and netif->ip_addr.addr != 0 } */
        LWIP_DEBUGF(ETHARP_DEBUG | LWIP_DBG_TRACE, ("etharp_input: ARP request was not for us.\n"));
      }
      break;
    case PP_HTONS(ARP_REPLY):
      /* ARP reply. We already updated the ARP cache earlier. */
      LWIP_DEBUGF(ETHARP_DEBUG | LWIP_DBG_TRACE, ("etharp_input: incoming ARP reply\n"));
#if (LWIP_DHCP && DHCP_DOES_ARP_CHECK)
      /* DHCP wants to know about ARP replies from any host with an
       * IP address also offered to us by the DHCP server. We do not
       * want to take a duplicate IP address on a single network.
       * @todo How should we handle redundant (fail-over) interfaces? */
      dhcp_arp_reply(netif, &sipaddr);
#endif /* (LWIP_DHCP && DHCP_DOES_ARP_CHECK) */
      break;
       /* INARP request? */
    case PP_HTONS(INARP_REQUEST):
      /* INARP request. If it asked for our address, we send out a
       * reply. In any case, we time-stamp any existing ARP entry,
       * and possibly send out an IP packet that was queued on it. */

      LWIP_DEBUGF (ETHARP_DEBUG | LWIP_DBG_TRACE, ("etharp_input: incoming INARP request\n"));
      /* ARP request for our address? */
      if (for_us) {
        /* send INARP response */
        etharp_raw(netif,
                   (struct eth_addr *)netif->hwaddr, &hdr->shwaddr,
                   (struct eth_addr *)netif->hwaddr, netif_ip4_addr(netif),
                   &hdr->shwaddr, &sipaddr,
                   INARP_REPLY);
        /* we are not configured? */
      } else if (ip4_addr_isany_val(*netif_ip4_addr(netif))) {
        /* { for_us == 0 and netif->ip_addr.addr == 0 } */
        LWIP_DEBUGF(ETHARP_DEBUG | LWIP_DBG_TRACE, ("etharp_input: we are unconfigured, INARP request ignored.\n"));
        /* request was not directed to us */
      } else {
        /* { for_us == 0 and netif->ip_addr.addr != 0 } */
        LWIP_DEBUGF(ETHARP_DEBUG | LWIP_DBG_TRACE, ("etharp_input: INARP request was not for us.\n"));
      }
      break;
    case PP_HTONS(INARP_REPLY):
      /* INARP reply. We already updated the ARP cache earlier. */
      LWIP_DEBUGF(ETHARP_DEBUG | LWIP_DBG_TRACE, ("etharp_input: incoming INARP reply\n"));
#if (LWIP_DHCP && DHCP_DOES_ARP_CHECK)
      /* DHCP wants to know about ARP replies from any host with an
       * IP address also offered to us by the DHCP server. We do not
       * want to take a duplicate IP address on a single network.
       * @todo How should we handle redundant (fail-over) interfaces? */
      dhcp_arp_reply(netif, &sipaddr);
#endif /* (LWIP_DHCP && DHCP_DOES_ARP_CHECK) */
      break;
    default:
      LWIP_DEBUGF(ETHARP_DEBUG | LWIP_DBG_TRACE, ("etharp_input: ARP unknown opcode type %"S16_F"\n", lwip_htons(hdr->opcode)));
      ETHARP_STATS_INC(etharp.err);
      break;
  }
  /* free ARP packet */
  pbuf_free(p);
}

Describe alternatives you've considered.

No response

Additional context.

No response

@MoegerleS MoegerleS added the Type: Feature Request Feature request for IDF label Sep 3, 2024
@espressif-bot espressif-bot added the Status: Opened Issue is new label Sep 3, 2024
@github-actions github-actions bot changed the title Support INARP request and reply Support INARP request and reply (IDFGH-13604) Sep 3, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Status: Opened Issue is new Type: Feature Request Feature request for IDF
Projects
None yet
Development

No branches or pull requests

3 participants