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

📄 etharp.c

📁 最新的lwip 1.3.0版本在ucos平台上的移植
💻 C
📖 第 1 页 / 共 3 页
字号:
  /* { empty or recyclable entry found } */  LWIP_ASSERT("i < ARP_TABLE_SIZE", i < ARP_TABLE_SIZE);  if (arp_table[i].state != ETHARP_STATE_EMPTY)  {    snmp_delete_arpidx_tree(arp_table[i].netif, &arp_table[i].ipaddr);  }  /* recycle entry (no-op for an already empty entry) */  arp_table[i].state = ETHARP_STATE_EMPTY;  /* IP address given? */  if (ipaddr != NULL) {    /* set IP address */    ip_addr_set(&arp_table[i].ipaddr, ipaddr);  }  arp_table[i].ctime = 0;#if LWIP_NETIF_HWADDRHINT  NETIF_SET_HINT(netif, i);#else /* #if LWIP_NETIF_HWADDRHINT */  etharp_cached_entry = i;#endif /* #if LWIP_NETIF_HWADDRHINT */  return (err_t)i;}/** * Send an IP packet on the network using netif->linkoutput * The ethernet header is filled in before sending. * * @params netif the lwIP network interface on which to send the packet * @params p the packet to send, p->payload pointing to the (uninitialized) ethernet header * @params src the source MAC address to be copied into the ethernet header * @params dst the destination MAC address to be copied into the ethernet header * @return ERR_OK if the packet was sent, any other err_t on failure */static err_tetharp_send_ip(struct netif *netif, struct pbuf *p, struct eth_addr *src, struct eth_addr *dst){  struct eth_hdr *ethhdr = p->payload;  u8_t k;  LWIP_ASSERT("netif->hwaddr_len must be the same as ETHARP_HWADDR_LEN for etharp!",              (netif->hwaddr_len == ETHARP_HWADDR_LEN));  k = ETHARP_HWADDR_LEN;  while(k > 0) {    k--;    ethhdr->dest.addr[k] = dst->addr[k];    ethhdr->src.addr[k]  = src->addr[k];  }  ethhdr->type = htons(ETHTYPE_IP);  LWIP_DEBUGF(ETHARP_DEBUG | LWIP_DBG_TRACE, ("etharp_send_ip: sending packet %p\n", (void *)p));  /* send the packet */  return netif->linkoutput(netif, p);}/** * Update (or insert) a IP/MAC address pair in the ARP cache. * * If a pending entry is resolved, any queued packets will be sent * at this point. *  * @param ipaddr IP address of the inserted ARP entry. * @param ethaddr Ethernet address of the inserted ARP entry. * @param flags Defines behaviour: * - ETHARP_TRY_HARD Allows ARP to insert this as a new item. If not specified, * only existing ARP entries will be updated. * * @return * - ERR_OK Succesfully updated ARP cache. * - ERR_MEM If we could not add a new ARP entry when ETHARP_TRY_HARD was set. * - ERR_ARG Non-unicast address given, those will not appear in ARP cache. * * @see pbuf_free() */static err_tupdate_arp_entry(struct netif *netif, struct ip_addr *ipaddr, struct eth_addr *ethaddr, u8_t flags){  s8_t i;  u8_t k;  LWIP_DEBUGF(ETHARP_DEBUG | LWIP_DBG_TRACE | 3, ("update_arp_entry()\n"));  LWIP_ASSERT("netif->hwaddr_len == ETHARP_HWADDR_LEN", netif->hwaddr_len == ETHARP_HWADDR_LEN);  LWIP_DEBUGF(ETHARP_DEBUG | LWIP_DBG_TRACE, ("update_arp_entry: %"U16_F".%"U16_F".%"U16_F".%"U16_F" - %02"X16_F":%02"X16_F":%02"X16_F":%02"X16_F":%02"X16_F":%02"X16_F"\n",                                        ip4_addr1(ipaddr), ip4_addr2(ipaddr), ip4_addr3(ipaddr), ip4_addr4(ipaddr),                                         ethaddr->addr[0], ethaddr->addr[1], ethaddr->addr[2],                                        ethaddr->addr[3], ethaddr->addr[4], ethaddr->addr[5]));  /* non-unicast address? */  if (ip_addr_isany(ipaddr) ||      ip_addr_isbroadcast(ipaddr, netif) ||      ip_addr_ismulticast(ipaddr)) {    LWIP_DEBUGF(ETHARP_DEBUG | LWIP_DBG_TRACE, ("update_arp_entry: will not add non-unicast IP address to ARP cache\n"));    return ERR_ARG;  }  /* find or create ARP entry */#if LWIP_NETIF_HWADDRHINT  i = find_entry(ipaddr, flags, netif);#else /* LWIP_NETIF_HWADDRHINT */  i = find_entry(ipaddr, flags);#endif /* LWIP_NETIF_HWADDRHINT */  /* bail out if no entry could be found */  if (i < 0)    return (err_t)i;    /* mark it stable */  arp_table[i].state = ETHARP_STATE_STABLE;  /* record network interface */  arp_table[i].netif = netif;  /* insert in SNMP ARP index tree */  snmp_insert_arpidx_tree(netif, &arp_table[i].ipaddr);  LWIP_DEBUGF(ETHARP_DEBUG | LWIP_DBG_TRACE, ("update_arp_entry: updating stable entry %"S16_F"\n", (s16_t)i));  /* update address */  k = ETHARP_HWADDR_LEN;  while (k > 0) {    k--;    arp_table[i].ethaddr.addr[k] = ethaddr->addr[k];  }  /* reset time stamp */  arp_table[i].ctime = 0;#if ARP_QUEUEING  /* this is where we will send out queued packets! */  while (arp_table[i].q != NULL) {    struct pbuf *p;    /* remember remainder of queue */    struct etharp_q_entry *q = arp_table[i].q;    /* pop first item off the queue */    arp_table[i].q = q->next;    /* get the packet pointer */    p = q->p;    /* now queue entry can be freed */    memp_free(MEMP_ARP_QUEUE, q);    /* send the queued IP packet */    etharp_send_ip(netif, p, (struct eth_addr*)(netif->hwaddr), ethaddr);    /* free the queued IP packet */    pbuf_free(p);  }#endif  return ERR_OK;}/** * Finds (stable) ethernet/IP address pair from ARP table * using interface and IP address index. * @note the addresses in the ARP table are in network order! * * @param netif points to interface index * @param ipaddr points to the (network order) IP address index * @param eth_ret points to return pointer * @param ip_ret points to return pointer * @return table index if found, -1 otherwise */s8_tetharp_find_addr(struct netif *netif, struct ip_addr *ipaddr,         struct eth_addr **eth_ret, struct ip_addr **ip_ret){  s8_t i;  LWIP_UNUSED_ARG(netif);#if LWIP_NETIF_HWADDRHINT  i = find_entry(ipaddr, ETHARP_FIND_ONLY, NULL);#else /* LWIP_NETIF_HWADDRHINT */  i = find_entry(ipaddr, ETHARP_FIND_ONLY);#endif /* LWIP_NETIF_HWADDRHINT */  if((i >= 0) && arp_table[i].state == ETHARP_STATE_STABLE) {      *eth_ret = &arp_table[i].ethaddr;      *ip_ret = &arp_table[i].ipaddr;      return i;  }  return -1;}/** * Updates the ARP table using the given IP packet. * * Uses the incoming IP packet's source address to update the * ARP cache for the local network. The function does not alter * or free the packet. This function must be called before the * packet p is passed to the IP layer. * * @param netif The lwIP network interface on which the IP packet pbuf arrived. * @param p The IP packet that arrived on netif. * * @return NULL * * @see pbuf_free() */voidetharp_ip_input(struct netif *netif, struct pbuf *p){  struct ethip_hdr *hdr;  LWIP_ERROR("netif != NULL", (netif != NULL), return;);  /* Only insert an entry if the source IP address of the     incoming IP packet comes from a host on the local network. */  hdr = p->payload;  /* source is not on the local network? */  if (!ip_addr_netcmp(&(hdr->ip.src), &(netif->ip_addr), &(netif->netmask))) {    /* do nothing */    return;  }  LWIP_DEBUGF(ETHARP_DEBUG | LWIP_DBG_TRACE, ("etharp_ip_input: updating ETHARP table.\n"));  /* update ARP table */  /* @todo We could use ETHARP_TRY_HARD if we think we are going to talk   * back soon (for example, if the destination IP address is ours. */  update_arp_entry(netif, &(hdr->ip.src), &(hdr->eth.src), 0);}/** * Responds to ARP requests to us. Upon ARP replies to us, add entry to cache   * send out queued IP packets. Updates cache with snooped address pairs. * * Should be called for incoming ARP packets. The pbuf in the argument * is freed by this function. * * @param netif The lwIP network interface on which the ARP packet pbuf arrived. * @param ethaddr Ethernet address of netif. * @param p The ARP packet that arrived on netif. Is freed by this function. * * @return NULL * * @see pbuf_free() */voidetharp_arp_input(struct netif *netif, struct eth_addr *ethaddr, struct pbuf *p){  struct etharp_hdr *hdr;  /* these are aligned properly, whereas the ARP header fields might not be */  struct ip_addr sipaddr, dipaddr;  u8_t i;  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(struct etharp_hdr)) {    LWIP_DEBUGF(ETHARP_DEBUG | LWIP_DBG_TRACE | 1, ("etharp_arp_input: packet dropped, too short (%"S16_F"/%"S16_F")\n", p->tot_len, (s16_t)sizeof(struct etharp_hdr)));    ETHARP_STATS_INC(etharp.lenerr);    ETHARP_STATS_INC(etharp.drop);    pbuf_free(p);    return;  }  hdr = p->payload;  /* RFC 826 "Packet Reception": */  if ((hdr->hwtype != htons(HWTYPE_ETHERNET)) ||      (hdr->_hwlen_protolen != htons((ETHARP_HWADDR_LEN << 8) | sizeof(struct ip_addr))) ||      (hdr->proto != htons(ETHTYPE_IP)) ||      (hdr->ethhdr.type != htons(ETHTYPE_ARP)))  {    LWIP_DEBUGF(ETHARP_DEBUG | LWIP_DBG_TRACE | 1,      ("etharp_arp_input: packet dropped, wrong hw type, hwlen, proto, protolen or ethernet type (%"U16_F"/%"U16_F"/%"U16_F"/%"U16_F"/%"U16_F")\n",      hdr->hwtype, ARPH_HWLEN(hdr), hdr->proto, ARPH_PROTOLEN(hdr), hdr->ethhdr.type));    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). */  SMEMCPY(&sipaddr, &hdr->sipaddr, sizeof(sipaddr));  SMEMCPY(&dipaddr, &hdr->dipaddr, sizeof(dipaddr));  /* this interface is not configured? */  if (netif->ip_addr.addr == 0) {    for_us = 0;  } else {    /* ARP packet directed to us? */    for_us = ip_addr_cmp(&dipaddr, &(netif->ip_addr));  }  /* ARP message directed to us? */  if (for_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. */    update_arp_entry(netif, &sipaddr, &(hdr->shwaddr), ETHARP_TRY_HARD);  /* ARP message not directed to us? */  } else {    /* update the source IP address in the cache, if present */    update_arp_entry(netif, &sipaddr, &(hdr->shwaddr), 0);  }  /* now act on the message itself */  switch (htons(hdr->opcode)) {  /* ARP request? */  case 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);      hdr->dipaddr = hdr->sipaddr;      hdr->sipaddr = *(struct ip_addr2 *)&netif->ip_addr;      LWIP_ASSERT("netif->hwaddr_len must be the same as ETHARP_HWADDR_LEN for etharp!",                  (netif->hwaddr_len == ETHARP_HWADDR_LEN));      i = ETHARP_HWADDR_LEN;#if LWIP_AUTOIP      /* If we are using Link-Local, ARP packets must be broadcast on the       * link layer. (See RFC3927 Section 2.5) */      ethdst_hwaddr = ((netif->autoip != NULL) && (netif->autoip->state != AUTOIP_STATE_OFF)) ? (u8_t*)(ethbroadcast.addr) : hdr->shwaddr.addr;#endif /* LWIP_AUTOIP */      while(i > 0) {        i--;        hdr->dhwaddr.addr[i] = hdr->shwaddr.addr[i];#if LWIP_AUTOIP        hdr->ethhdr.dest.addr[i] = ethdst_hwaddr[i];#else  /* LWIP_AUTOIP */        hdr->ethhdr.dest.addr[i] = hdr->shwaddr.addr[i];#endif /* LWIP_AUTOIP */        hdr->shwaddr.addr[i] = ethaddr->addr[i];        hdr->ethhdr.src.addr[i] = ethaddr->addr[i];      }      /* 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 (netif->ip_addr.addr == 0) {      /* { 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 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    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, struct ip_addr *ipaddr){

⌨️ 快捷键说明

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