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

📄 etharp.c

📁 最新的lwip 1.3.0版本在ucos平台上的移植
💻 C
📖 第 1 页 / 共 3 页
字号:
  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 | 2, ("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))) {      /* interface has default gateway? */      if (netif->gw.addr != 0) {        /* 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;      }    }    /* 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, struct ip_addr *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 */#if LWIP_NETIF_HWADDRHINT  i = find_entry(ipaddr, ETHARP_TRY_HARD, netif);#else /* LWIP_NETIF_HWADDRHINT */  i = find_entry(ipaddr, ETHARP_TRY_HARD);#endif /* LWIP_NETIF_HWADDRHINT */  /* 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",  ((arp_table[i].state == ETHARP_STATE_PENDING) ||   (arp_table[i].state == ETHARP_STATE_STABLE)));  /* do we have a pending entry? or an implicit query request? */  if ((arp_table[i].state == ETHARP_STATE_PENDING) || (q == NULL)) {    /* try to resolve it; send out ARP request */    result = etharp_request(netif, ipaddr);    if (result != ERR_OK) {      /* ARP request couldn't be sent */      /* We don't re-send arp request in etharp_tmr, but we still queue packets,         since this failure could be temporary, and the next packet calling         etharp_query again could lead to sending the queued packets. */    }  }    /* packet given? */  if (q != NULL) {    /* stable entry? */    if (arp_table[i].state == ETHARP_STATE_STABLE) {      /* we have a valid IP->Ethernet address mapping */      /* send the packet */      result = etharp_send_ip(netif, q, srcaddr, &(arp_table[i].ethaddr));    /* pending entry? (either just created or already pending */    } else if (arp_table[i].state == ETHARP_STATE_PENDING) {#if ARP_QUEUEING /* queue the given q packet */      struct pbuf *p;      int copy_needed = 0;      /* IF q includes a PBUF_REF, PBUF_POOL or PBUF_RAM, we have no choice but       * to copy the whole queue into a new PBUF_RAM (see bug #11400)        * PBUF_ROMs can be left as they are, since ROM must not get changed. */      p = q;      while (p) {        LWIP_ASSERT("no packet queues allowed!", (p->len != p->tot_len) || (p->next == 0));        if(p->type != PBUF_ROM) {          copy_needed = 1;          break;        }        p = p->next;      }      if(copy_needed) {        /* copy the whole packet into new pbufs */        p = pbuf_alloc(PBUF_RAW, p->tot_len, PBUF_RAM);        if(p != NULL) {          if (pbuf_copy(p, q) != ERR_OK) {            pbuf_free(p);            p = NULL;          }        }      } else {        /* referencing the old pbuf is enough */        p = q;        pbuf_ref(p);      }      /* packet could be taken over? */      if (p != NULL) {        /* queue packet ... */        struct etharp_q_entry *new_entry;        /* allocate a new arp queue entry */        new_entry = memp_malloc(MEMP_ARP_QUEUE);        if (new_entry != NULL) {          new_entry->next = 0;          new_entry->p = p;          if(arp_table[i].q != NULL) {            /* queue was already existent, append the new entry to the end */            struct etharp_q_entry *r;            r = arp_table[i].q;            while (r->next != NULL) {              r = r->next;            }            r->next = new_entry;          } else {            /* queue did not exist, first item in queue */            arp_table[i].q = new_entry;          }          LWIP_DEBUGF(ETHARP_DEBUG | LWIP_DBG_TRACE, ("etharp_query: queued packet %p on ARP entry %"S16_F"\n", (void *)q, (s16_t)i));          result = ERR_OK;        } else {          /* the pool MEMP_ARP_QUEUE is empty */          pbuf_free(p);          LWIP_DEBUGF(ETHARP_DEBUG | LWIP_DBG_TRACE, ("etharp_query: could not queue a copy of PBUF_REF packet %p (out of memory)\n", (void *)q));          /* { result == ERR_MEM } through initialization */        }      } else {        ETHARP_STATS_INC(etharp.memerr);        LWIP_DEBUGF(ETHARP_DEBUG | LWIP_DBG_TRACE, ("etharp_query: could not queue a copy of PBUF_REF packet %p (out of memory)\n", (void *)q));        /* { result == ERR_MEM } through initialization */      }#else /* ARP_QUEUEING == 0 */      /* q && state == PENDING && ARP_QUEUEING == 0 => result = ERR_MEM */      /* { result == ERR_MEM } through initialization */      LWIP_DEBUGF(ETHARP_DEBUG | LWIP_DBG_TRACE, ("etharp_query: Ethernet destination address unknown, queueing disabled, packet %p dropped\n", (void *)q));#endif    }  }  return result;}/** * Send a raw ARP packet (opcode and all addresses can be modified) * * @param netif the lwip network interface on which to send the ARP packet * @param ethsrc_addr the source MAC address for the ethernet header * @param ethdst_addr the destination MAC address for the ethernet header * @param hwsrc_addr the source MAC address for the ARP protocol header * @param ipsrc_addr the source IP address for the ARP protocol header * @param hwdst_addr the destination MAC address for the ARP protocol header * @param ipdst_addr the destination IP address for the ARP protocol header * @param opcode the type of the ARP packet * @return ERR_OK if the ARP packet has been sent *         ERR_MEM if the ARP packet couldn't be allocated *         any other err_t on failure */#if !LWIP_AUTOIPstatic#endif /* LWIP_AUTOIP */err_tetharp_raw(struct netif *netif, const struct eth_addr *ethsrc_addr,           const struct eth_addr *ethdst_addr,           const struct eth_addr *hwsrc_addr, const struct ip_addr *ipsrc_addr,           const struct eth_addr *hwdst_addr, const struct ip_addr *ipdst_addr,           const u16_t opcode){  struct pbuf *p;  err_t result = ERR_OK;  u8_t k; /* ARP entry index */  struct etharp_hdr *hdr;#if LWIP_AUTOIP  const u8_t * ethdst_hwaddr;#endif /* LWIP_AUTOIP */  /* allocate a pbuf for the outgoing ARP request packet */  p = pbuf_alloc(PBUF_LINK, sizeof(struct etharp_hdr), PBUF_RAM);  /* could allocate a pbuf for an ARP request? */  if (p == NULL) {    LWIP_DEBUGF(ETHARP_DEBUG | LWIP_DBG_TRACE | 2, ("etharp_raw: could not allocate pbuf for ARP request.\n"));    ETHARP_STATS_INC(etharp.memerr);    return ERR_MEM;  }  LWIP_ASSERT("check that first pbuf can hold struct etharp_hdr",              (p->len >= sizeof(struct etharp_hdr)));  hdr = p->payload;  LWIP_DEBUGF(ETHARP_DEBUG | LWIP_DBG_TRACE, ("etharp_raw: sending raw ARP packet.\n"));  hdr->opcode = htons(opcode);  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;#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) : ethdst_addr->addr;#endif /* LWIP_AUTOIP */  /* Write MAC-Addresses (combined loop for both headers) */  while(k > 0) {    k--;    /* Write the ARP MAC-Addresses */    hdr->shwaddr.addr[k] = hwsrc_addr->addr[k];    hdr->dhwaddr.addr[k] = hwdst_addr->addr[k];    /* Write the Ethernet MAC-Addresses */#if LWIP_AUTOIP    hdr->ethhdr.dest.addr[k] = ethdst_hwaddr[k];#else  /* LWIP_AUTOIP */    hdr->ethhdr.dest.addr[k] = ethdst_addr->addr[k];#endif /* LWIP_AUTOIP */    hdr->ethhdr.src.addr[k]  = ethsrc_addr->addr[k];  }  hdr->sipaddr = *(struct ip_addr2 *)ipsrc_addr;  hdr->dipaddr = *(struct ip_addr2 *)ipdst_addr;  hdr->hwtype = htons(HWTYPE_ETHERNET);  hdr->proto = htons(ETHTYPE_IP);  /* set hwlen and protolen together */  hdr->_hwlen_protolen = htons((ETHARP_HWADDR_LEN << 8) | sizeof(struct ip_addr));  hdr->ethhdr.type = htons(ETHTYPE_ARP);  /* send ARP query */  result = netif->linkoutput(netif, p);  ETHARP_STATS_INC(etharp.xmit);  /* free ARP query packet */  pbuf_free(p);  p = NULL;  /* could not allocate pbuf for ARP request */  return result;}/** * Send an ARP request packet asking for ipaddr. * * @param netif the lwip network interface on which to send the request * @param ipaddr the IP address for which to ask * @return ERR_OK if the request has been sent *         ERR_MEM if the ARP packet couldn't be allocated *         any other err_t on failure */err_tetharp_request(struct netif *netif, struct ip_addr *ipaddr){  LWIP_DEBUGF(ETHARP_DEBUG | LWIP_DBG_TRACE, ("etharp_request: sending ARP request.\n"));  return etharp_raw(netif, (struct eth_addr *)netif->hwaddr, &ethbroadcast,                    (struct eth_addr *)netif->hwaddr, &netif->ip_addr, &ethzero,                    ipaddr, ARP_REQUEST);}/** * Process received ethernet frames. Using this function instead of directly * calling ip_input and passing ARP frames through etharp in ethernetif_input, * the ARP cache is protected from concurrent access. * * @param p the recevied packet, p->payload pointing to the ethernet header * @param netif the network interface on which the packet was received */err_tethernet_input(struct pbuf *p, struct netif *netif){  struct eth_hdr* ethhdr;  /* points to packet payload, which starts with an Ethernet header */  ethhdr = p->payload;    switch (htons(ethhdr->type)) {    /* IP packet? */    case ETHTYPE_IP:#if ETHARP_TRUST_IP_MAC      /* update ARP table */      etharp_ip_input(netif, p);#endif /* ETHARP_TRUST_IP_MAC */      /* skip Ethernet header */      if(pbuf_header(p, -(s16_t)sizeof(struct eth_hdr))) {        LWIP_ASSERT("Can't move over header in packet", 0);        pbuf_free(p);        p = NULL;      } else {        /* pass to IP layer */        ip_input(p, netif);      }      break;          case ETHTYPE_ARP:      /* pass p to ARP module */      etharp_arp_input(netif, (struct eth_addr*)(netif->hwaddr), p);      break;#if PPPOE_SUPPORT    case ETHTYPE_PPPOEDISC: /* PPP Over Ethernet Discovery Stage */      pppoe_disc_input(netif, p);      break;    case ETHTYPE_PPPOE: /* PPP Over Ethernet Session Stage */      pppoe_data_input(netif, p);      break;#endif /* PPPOE_SUPPORT */    default:      pbuf_free(p);      p = NULL;      break;  }  /* This means the pbuf is freed or consumed,     so the caller doesn't have to free it again */  return ERR_OK;}#endif /* LWIP_ARP */

⌨️ 快捷键说明

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