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

📄 etharp.c

📁 《嵌入式网络系统设计-基于Atmel ARM7 系列》这个本书的光盘资料
💻 C
📖 第 1 页 / 共 3 页
字号:
  }  /* 2) found recyclable stable entry? */  else if (old_stable < ARP_TABLE_SIZE) {    /* recycle oldest stable*/    i = old_stable;    LWIP_DEBUGF(ETHARP_DEBUG | DBG_TRACE, ("find_entry: selecting oldest stable entry %"U16_F"\n", (u16_t)i));#if ARP_QUEUEING    /* no queued packets should exist on stable entries */    LWIP_ASSERT("arp_table[i].p == NULL", arp_table[i].p == NULL);#endif  /* 3) found recyclable pending entry without queued packets? */  } else if (old_pending < ARP_TABLE_SIZE) {    /* recycle oldest pending */    i = old_pending;    LWIP_DEBUGF(ETHARP_DEBUG | DBG_TRACE, ("find_entry: selecting oldest pending entry %"U16_F" (without queue)\n", (u16_t)i));#if ARP_QUEUEING  /* 4) found recyclable pending entry with queued packets? */  } else if (old_queue < ARP_TABLE_SIZE) {    /* recycle oldest pending */    i = old_queue;    LWIP_DEBUGF(ETHARP_DEBUG | DBG_TRACE, ("find_entry: selecting oldest pending entry %"U16_F", freeing packet queue %p\n", (u16_t)i, (void *)(arp_table[i].p)));    pbuf_free(arp_table[i].p);    arp_table[i].p = NULL;#endif    /* no empty or recyclable entries found */  } else {    return (s8_t)ERR_MEM;  }  /* { 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;  return (err_t)i;}/** * 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 | DBG_TRACE | 3, ("update_arp_entry()\n"));  LWIP_ASSERT("netif->hwaddr_len != 0", netif->hwaddr_len != 0);  LWIP_DEBUGF(ETHARP_DEBUG | 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 | DBG_TRACE, ("update_arp_entry: will not add non-unicast IP address to ARP cache\n"));    return ERR_ARG;  }  /* find or create ARP entry */  i = find_entry(ipaddr, flags);  /* 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 | DBG_TRACE, ("update_arp_entry: updating stable entry %"S16_F"\n", (s16_t)i));  /* update address */  k = netif->hwaddr_len;  while (k > 0) {    k--;    arp_table[i].ethaddr.addr[k] = ethaddr->addr[k];  }  /* reset time stamp */  arp_table[i].ctime = 0;/* this is where we will send out queued packets! */#if ARP_QUEUEING  while (arp_table[i].p != NULL) {    /* get the first packet on the queue */    struct pbuf *p = arp_table[i].p;    /* Ethernet header */    struct eth_hdr *ethhdr = p->payload;    /* remember (and reference) remainder of queue */    /* note: this will also terminate the p pbuf chain */    arp_table[i].p = pbuf_dequeue(p);    /* fill-in Ethernet header */    k = netif->hwaddr_len;    while(k > 0) {      k--;      ethhdr->dest.addr[k] = ethaddr->addr[k];      ethhdr->src.addr[k] = netif->hwaddr[k];    }    ethhdr->type = htons(ETHTYPE_IP);    LWIP_DEBUGF(ETHARP_DEBUG | DBG_TRACE, ("update_arp_entry: sending queued IP packet %p.\n", (void *)p));    /* send the queued IP packet */    netif->linkoutput(netif, p);    /* 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;  i = 0;  while (i < ARP_TABLE_SIZE)  {    if ((arp_table[i].state == ETHARP_STATE_STABLE) &&        (arp_table[i].netif == netif) &&         ip_addr_cmp(ipaddr, &arp_table[i].ipaddr) )    {      *eth_ret = &arp_table[i].ethaddr;      *ip_ret = &arp_table[i].ipaddr;      return i;    }    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 pbuf 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_ASSERT("netif != NULL", netif != NULL);  /* 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 | 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 pbuf The ARP packet that arrived on netif. Is freed by this function. * @param ethaddr Ethernet address of netif. * * @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;  LWIP_ASSERT("netif != NULL", netif != NULL);    /* drop short ARP packets */  if (p->tot_len < sizeof(struct etharp_hdr)) {    LWIP_DEBUGF(ETHARP_DEBUG | DBG_TRACE | 1, ("etharp_arp_input: packet dropped, too short (%"S16_F"/%"S16_F")\n", p->tot_len, (s16_t)sizeof(struct etharp_hdr)));    pbuf_free(p);    return;  }  hdr = p->payload;   /* Copy struct ip_addr2 to aligned ip_addr, to support compilers without   * structure packing (not using structure copy which breaks strict-aliasing rules). */  memcpy(&sipaddr, &hdr->sipaddr, sizeof(sipaddr));  memcpy(&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 | DBG_TRACE, ("etharp_arp_input: incoming ARP request\n"));    /* ARP request for our address? */    if (for_us) {      LWIP_DEBUGF(ETHARP_DEBUG | DBG_TRACE, ("etharp_arp_input: replying to ARP request for our IP address\n"));      /* re-use pbuf to send ARP reply */      hdr->opcode = htons(ARP_REPLY);      hdr->dipaddr = hdr->sipaddr;      hdr->sipaddr = *(struct ip_addr2 *)&netif->ip_addr;      i = netif->hwaddr_len;      while(i > 0) {        i--;        hdr->dhwaddr.addr[i] = hdr->shwaddr.addr[i];        hdr->shwaddr.addr[i] = ethaddr->addr[i];        hdr->ethhdr.dest.addr[i] = hdr->dhwaddr.addr[i];        hdr->ethhdr.src.addr[i] = ethaddr->addr[i];      }      hdr->hwtype = htons(HWTYPE_ETHERNET);      ARPH_HWLEN_SET(hdr, netif->hwaddr_len);      hdr->proto = htons(ETHTYPE_IP);      ARPH_PROTOLEN_SET(hdr, sizeof(struct ip_addr));

⌨️ 快捷键说明

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