⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 etharp.c

📁 lwip-1.4.0
💻 C
📖 第 1 页 / 共 4 页
字号:
 * @param p The ARP packet that arrived on netif. Is freed by this function. * * @return NULL * * @see pbuf_free() */static voidetharp_arp_input(struct netif *netif, struct eth_addr *ethaddr, struct pbuf *p){  struct etharp_hdr *hdr;  struct eth_hdr *ethhdr;  /* these are aligned properly, whereas the ARP header fields might not be */  ip_addr_t sipaddr, dipaddr;  u8_t for_us;#if LWIP_AUTOIP  const u8_t * ethdst_hwaddr;#endif /* LWIP_AUTOIP */  LWIP_ERROR("netif != NULL", (netif != NULL), return;);  /* drop short ARP packets: we have to check for p->len instead of p->tot_len here     since a struct etharp_hdr is pointed to p->payload, so it musn't be chained! */  if (p->len < SIZEOF_ETHARP_PACKET) {    LWIP_DEBUGF(ETHARP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_LEVEL_WARNING,      ("etharp_arp_input: packet dropped, too short (%"S16_F"/%"S16_F")\n", p->tot_len,      (s16_t)SIZEOF_ETHARP_PACKET));    ETHARP_STATS_INC(etharp.lenerr);    ETHARP_STATS_INC(etharp.drop);    pbuf_free(p);    return;  }  ethhdr = (struct eth_hdr *)p->payload;  hdr = (struct etharp_hdr *)((u8_t*)ethhdr + SIZEOF_ETH_HDR);#if ETHARP_SUPPORT_VLAN  if (ethhdr->type == PP_HTONS(ETHTYPE_VLAN)) {    hdr = (struct etharp_hdr *)(((u8_t*)ethhdr) + SIZEOF_ETH_HDR + SIZEOF_VLAN_HDR);  }#endif /* ETHARP_SUPPORT_VLAN */  /* RFC 826 "Packet Reception": */  if ((hdr->hwtype != PP_HTONS(HWTYPE_ETHERNET)) ||      (hdr->hwlen != ETHARP_HWADDR_LEN) ||      (hdr->protolen != sizeof(ip_addr_t)) ||      (hdr->proto != PP_HTONS(ETHTYPE_IP)))  {    LWIP_DEBUGF(ETHARP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_LEVEL_WARNING,      ("etharp_arp_input: packet dropped, wrong hw type, hwlen, proto, protolen or ethernet type (%"U16_F"/%"U16_F"/%"U16_F"/%"U16_F")\n",      hdr->hwtype, hdr->hwlen, hdr->proto, 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 continously 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 ip_addr2 to aligned ip_addr, to support compilers without   * structure packing (not using structure copy which breaks strict-aliasing rules). */  IPADDR2_COPY(&sipaddr, &hdr->sipaddr);  IPADDR2_COPY(&dipaddr, &hdr->dipaddr);  /* this interface is not configured? */  if (ip_addr_isany(&netif->ip_addr)) {    for_us = 0;  } else {    /* ARP packet directed to us? */    for_us = (u8_t)ip_addr_cmp(&dipaddr, &(netif->ip_addr));  }  /* 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 */  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 possiby send out an IP packet that was queued on it. */    LWIP_DEBUGF (ETHARP_DEBUG | LWIP_DBG_TRACE, ("etharp_arp_input: incoming ARP request\n"));    /* ARP request for our address? */    if (for_us) {      LWIP_DEBUGF(ETHARP_DEBUG | LWIP_DBG_TRACE, ("etharp_arp_input: replying to ARP request for our IP address\n"));      /* Re-use pbuf to send ARP reply.         Since we are re-using an existing pbuf, we can't call etharp_raw since         that would allocate a new pbuf. */      hdr->opcode = htons(ARP_REPLY);      IPADDR2_COPY(&hdr->dipaddr, &hdr->sipaddr);      IPADDR2_COPY(&hdr->sipaddr, &netif->ip_addr);      LWIP_ASSERT("netif->hwaddr_len must be the same as ETHARP_HWADDR_LEN for etharp!",                  (netif->hwaddr_len == ETHARP_HWADDR_LEN));#if LWIP_AUTOIP      /* If we are using Link-Local, all ARP packets that contain a Link-Local       * 'sender IP address' MUST be sent using link-layer broadcast instead of       * link-layer unicast. (See RFC3927 Section 2.5, last paragraph) */      ethdst_hwaddr = ip_addr_islinklocal(&netif->ip_addr) ? (u8_t*)(ethbroadcast.addr) : hdr->shwaddr.addr;#endif /* LWIP_AUTOIP */      ETHADDR16_COPY(&hdr->dhwaddr, &hdr->shwaddr);#if LWIP_AUTOIP      ETHADDR16_COPY(&ethhdr->dest, ethdst_hwaddr);#else  /* LWIP_AUTOIP */      ETHADDR16_COPY(&ethhdr->dest, &hdr->shwaddr);#endif /* LWIP_AUTOIP */      ETHADDR16_COPY(&hdr->shwaddr, ethaddr);      ETHADDR16_COPY(&ethhdr->src, ethaddr);      /* hwtype, hwaddr_len, proto, protolen and the type in the ethernet header         are already correct, we tested that before */      /* return ARP reply */      netif->linkoutput(netif, p);    /* we are not configured? */    } else if (ip_addr_isany(&netif->ip_addr)) {      /* { for_us == 0 and netif->ip_addr.addr == 0 } */      LWIP_DEBUGF(ETHARP_DEBUG | LWIP_DBG_TRACE, ("etharp_arp_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_arp_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_arp_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;  default:    LWIP_DEBUGF(ETHARP_DEBUG | LWIP_DBG_TRACE, ("etharp_arp_input: ARP unknown opcode type %"S16_F"\n", htons(hdr->opcode)));    ETHARP_STATS_INC(etharp.err);    break;  }  /* free ARP packet */  pbuf_free(p);}/** * Resolve and fill-in Ethernet address header for outgoing IP packet. * * For IP multicast and broadcast, corresponding Ethernet addresses * are selected and the packet is transmitted on the link. * * For unicast addresses, the packet is submitted to etharp_query(). In * case the IP address is outside the local network, the IP address of * the gateway is used. * * @param netif The lwIP network interface which the IP packet will be sent on. * @param q The pbuf(s) containing the IP packet to be sent. * @param ipaddr The IP address of the packet destination. * * @return * - ERR_RTE No route to destination (no gateway to external networks), * or the return type of either etharp_query() or etharp_send_ip(). */err_tetharp_output(struct netif *netif, struct pbuf *q, ip_addr_t *ipaddr){  struct eth_addr *dest, mcastaddr;  /* make room for Ethernet header - should not fail */  if (pbuf_header(q, sizeof(struct eth_hdr)) != 0) {    /* bail out */    LWIP_DEBUGF(ETHARP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_LEVEL_SERIOUS,      ("etharp_output: could not allocate room for header.\n"));    LINK_STATS_INC(link.lenerr);    return ERR_BUF;  }  /* assume unresolved Ethernet address */  dest = NULL;  /* Determine on destination hardware address. Broadcasts and multicasts   * are special, other IP addresses are looked up in the ARP table. */  /* broadcast destination IP address? */  if (ip_addr_isbroadcast(ipaddr, netif)) {    /* broadcast on Ethernet also */    dest = (struct eth_addr *)&ethbroadcast;  /* multicast destination IP address? */  } else if (ip_addr_ismulticast(ipaddr)) {    /* Hash IP multicast address to MAC address.*/    mcastaddr.addr[0] = 0x01;    mcastaddr.addr[1] = 0x00;    mcastaddr.addr[2] = 0x5e;    mcastaddr.addr[3] = ip4_addr2(ipaddr) & 0x7f;    mcastaddr.addr[4] = ip4_addr3(ipaddr);    mcastaddr.addr[5] = ip4_addr4(ipaddr);    /* destination Ethernet address is multicast */    dest = &mcastaddr;  /* unicast destination IP address? */  } else {    /* outside local network? */    if (!ip_addr_netcmp(ipaddr, &(netif->ip_addr), &(netif->netmask)) &&        !ip_addr_islinklocal(ipaddr)) {#if LWIP_AUTOIP      struct ip_hdr *iphdr = (struct ip_hdr*)((u8_t*)q->payload +        sizeof(struct eth_hdr));      /* According to RFC 3297, chapter 2.6.2 (Forwarding Rules), a packet with         a link-local source address must always be "directly to its destination         on the same physical link. The host MUST NOT send the packet to any         router for forwarding". */      if (!ip_addr_islinklocal(&iphdr->src))#endif /* LWIP_AUTOIP */      {        /* interface has default gateway? */        if (!ip_addr_isany(&netif->gw)) {          /* send to hardware address of default gateway IP address */          ipaddr = &(netif->gw);        /* no default gateway available */        } else {          /* no route to destination error (default gateway missing) */          return ERR_RTE;        }      }    }#if LWIP_NETIF_HWADDRHINT    if (netif->addr_hint != NULL) {      /* per-pcb cached entry was given */      u8_t etharp_cached_entry = *(netif->addr_hint);      if (etharp_cached_entry < ARP_TABLE_SIZE) {#endif /* LWIP_NETIF_HWADDRHINT */        if ((arp_table[etharp_cached_entry].state == ETHARP_STATE_STABLE) &&            (ip_addr_cmp(ipaddr, &arp_table[etharp_cached_entry].ipaddr))) {          /* the per-pcb-cached entry is stable and the right one! */          ETHARP_STATS_INC(etharp.cachehit);          return etharp_send_ip(netif, q, (struct eth_addr*)(netif->hwaddr),            &arp_table[etharp_cached_entry].ethaddr);        }#if LWIP_NETIF_HWADDRHINT      }    }#endif /* LWIP_NETIF_HWADDRHINT */    /* queue on destination Ethernet address belonging to ipaddr */    return etharp_query(netif, ipaddr, q);  }  /* continuation for multicast/broadcast destinations */  /* obtain source Ethernet address of the given interface */  /* send packet directly on the link */  return etharp_send_ip(netif, q, (struct eth_addr*)(netif->hwaddr), dest);}/** * Send an ARP request for the given IP address and/or queue a packet. * * If the IP address was not yet in the cache, a pending ARP cache entry * is added and an ARP request is sent for the given address. The packet * is queued on this entry. * * If the IP address was already pending in the cache, a new ARP request * is sent for the given address. The packet is queued on this entry. * * If the IP address was already stable in the cache, and a packet is * given, it is directly sent and no ARP request is sent out.  *  * If the IP address was already stable in the cache, and no packet is * given, an ARP request is sent out. *  * @param netif The lwIP network interface on which ipaddr * must be queried for. * @param ipaddr The IP address to be resolved. * @param q If non-NULL, a pbuf that must be delivered to the IP address. * q is not freed by this function. * * @note q must only be ONE packet, not a packet queue! * * @return * - ERR_BUF Could not make room for Ethernet header. * - ERR_MEM Hardware address unknown, and no more ARP entries available *   to query for address or queue the packet. * - ERR_MEM Could not queue packet due to memory shortage. * - ERR_RTE No route to destination (no gateway to external networks). * - ERR_ARG Non-unicast address given, those will not appear in ARP cache. * */err_tetharp_query(struct netif *netif, ip_addr_t *ipaddr, struct pbuf *q){  struct eth_addr * srcaddr = (struct eth_addr *)netif->hwaddr;  err_t result = ERR_MEM;  s8_t i; /* ARP entry index */  /* non-unicast address? */  if (ip_addr_isbroadcast(ipaddr, netif) ||      ip_addr_ismulticast(ipaddr) ||      ip_addr_isany(ipaddr)) {    LWIP_DEBUGF(ETHARP_DEBUG | LWIP_DBG_TRACE, ("etharp_query: will not add non-unicast IP address to ARP cache\n"));    return ERR_ARG;  }  /* find entry in ARP cache, ask to create entry if queueing packet */  i = find_entry(ipaddr, ETHARP_FLAG_TRY_HARD);  /* could not find or create entry? */  if (i < 0) {    LWIP_DEBUGF(ETHARP_DEBUG | LWIP_DBG_TRACE, ("etharp_query: could not create ARP entry\n"));    if (q) {      LWIP_DEBUGF(ETHARP_DEBUG | LWIP_DBG_TRACE, ("etharp_query: packet dropped\n"));      ETHARP_STATS_INC(etharp.memerr);    }    return (err_t)i;  }  /* mark a fresh entry as pending (we just sent a request) */  if (arp_table[i].state == ETHARP_STATE_EMPTY) {    arp_table[i].state = ETHARP_STATE_PENDING;  }  /* { i is either a STABLE or (new or existing) PENDING entry } */  LWIP_ASSERT("arp_table[i].state == PENDING or STABLE",

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -