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

📄 etharp.c

📁 lwip-1.4.0
💻 C
📖 第 1 页 / 共 4 页
字号:
  ((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. */    }    if (q == NULL) {      return result;    }  }  /* packet given? */  LWIP_ASSERT("q != NULL", q != NULL);  /* stable entry? */  if (arp_table[i].state == ETHARP_STATE_STABLE) {    /* we have a valid IP->Ethernet address mapping */    ETHARP_SET_HINT(netif, i);    /* 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) {    /* entry is still pending, queue the given packet 'q' */    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 ... */#if ARP_QUEUEING      struct etharp_q_entry *new_entry;      /* allocate a new arp queue entry */      new_entry = (struct etharp_q_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;      }#else /* ARP_QUEUEING */      /* always queue one packet per ARP request only, freeing a previously queued packet */      if (arp_table[i].q != NULL) {        LWIP_DEBUGF(ETHARP_DEBUG | LWIP_DBG_TRACE, ("etharp_query: dropped previously queued packet %p for ARP entry %"S16_F"\n", (void *)q, (s16_t)i));        pbuf_free(arp_table[i].q);      }      arp_table[i].q = p;      result = ERR_OK;      LWIP_DEBUGF(ETHARP_DEBUG | LWIP_DBG_TRACE, ("etharp_query: queued packet %p on ARP entry %"S16_F"\n", (void *)q, (s16_t)i));#endif /* ARP_QUEUEING */    } 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;    }  }  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 ip_addr_t *ipsrc_addr,           const struct eth_addr *hwdst_addr, const ip_addr_t *ipdst_addr,           const u16_t opcode){  struct pbuf *p;  err_t result = ERR_OK;  struct eth_hdr *ethhdr;  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_RAW, SIZEOF_ETHARP_PACKET, PBUF_RAM);  /* could allocate a pbuf for an ARP request? */  if (p == NULL) {    LWIP_DEBUGF(ETHARP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_LEVEL_SERIOUS,      ("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_ETHARP_PACKET));  ethhdr = (struct eth_hdr *)p->payload;  hdr = (struct etharp_hdr *)((u8_t*)ethhdr + SIZEOF_ETH_HDR);  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));#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(ipsrc_addr) ? (u8_t*)(ethbroadcast.addr) : ethdst_addr->addr;#endif /* LWIP_AUTOIP */  /* Write the ARP MAC-Addresses */  ETHADDR16_COPY(&hdr->shwaddr, hwsrc_addr);  ETHADDR16_COPY(&hdr->dhwaddr, hwdst_addr);  /* Write the Ethernet MAC-Addresses */#if LWIP_AUTOIP  ETHADDR16_COPY(&ethhdr->dest, ethdst_hwaddr);#else  /* LWIP_AUTOIP */  ETHADDR16_COPY(&ethhdr->dest, ethdst_addr);#endif /* LWIP_AUTOIP */  ETHADDR16_COPY(&ethhdr->src, ethsrc_addr);  /* Copy struct ip_addr2 to aligned ip_addr, to support compilers without   * structure packing. */   IPADDR2_COPY(&hdr->sipaddr, ipsrc_addr);  IPADDR2_COPY(&hdr->dipaddr, ipdst_addr);  hdr->hwtype = PP_HTONS(HWTYPE_ETHERNET);  hdr->proto = PP_HTONS(ETHTYPE_IP);  /* set hwlen and protolen */  hdr->hwlen = ETHARP_HWADDR_LEN;  hdr->protolen = sizeof(ip_addr_t);  ethhdr->type = PP_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, ip_addr_t *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);}#endif /* LWIP_ARP *//** * 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;  u16_t type;  s16_t ip_hdr_offset = SIZEOF_ETH_HDR;  if (p->len <= SIZEOF_ETH_HDR) {    /* a packet with only an ethernet header (or less) is not valid for us */    ETHARP_STATS_INC(etharp.proterr);    ETHARP_STATS_INC(etharp.drop);    goto free_and_return;  }  /* points to packet payload, which starts with an Ethernet header */  ethhdr = (struct eth_hdr *)p->payload;  LWIP_DEBUGF(ETHARP_DEBUG | LWIP_DBG_TRACE,    ("ethernet_input: dest:%"X8_F":%"X8_F":%"X8_F":%"X8_F":%"X8_F":%"X8_F", src:%"X8_F":%"X8_F":%"X8_F":%"X8_F":%"X8_F":%"X8_F", type:%"X16_F"\n",     (unsigned)ethhdr->dest.addr[0], (unsigned)ethhdr->dest.addr[1], (unsigned)ethhdr->dest.addr[2],     (unsigned)ethhdr->dest.addr[3], (unsigned)ethhdr->dest.addr[4], (unsigned)ethhdr->dest.addr[5],     (unsigned)ethhdr->src.addr[0], (unsigned)ethhdr->src.addr[1], (unsigned)ethhdr->src.addr[2],     (unsigned)ethhdr->src.addr[3], (unsigned)ethhdr->src.addr[4], (unsigned)ethhdr->src.addr[5],     (unsigned)htons(ethhdr->type)));  type = ethhdr->type;#if ETHARP_SUPPORT_VLAN  if (type == PP_HTONS(ETHTYPE_VLAN)) {    struct eth_vlan_hdr *vlan = (struct eth_vlan_hdr*)(((char*)ethhdr) + SIZEOF_ETH_HDR);    if (p->len <= SIZEOF_ETH_HDR + SIZEOF_VLAN_HDR) {      /* a packet with only an ethernet/vlan header (or less) is not valid for us */      ETHARP_STATS_INC(etharp.proterr);      ETHARP_STATS_INC(etharp.drop);      goto free_and_return;    }#ifdef ETHARP_VLAN_CHECK /* if not, allow all VLANs */    if (VLAN_ID(vlan) != ETHARP_VLAN_CHECK) {      /* silently ignore this packet: not for our VLAN */      pbuf_free(p);      return ERR_OK;    }#endif /* ETHARP_VLAN_CHECK */    type = vlan->tpid;    ip_hdr_offset = SIZEOF_ETH_HDR + SIZEOF_VLAN_HDR;  }#endif /* ETHARP_SUPPORT_VLAN */#if LWIP_ARP_FILTER_NETIF  netif = LWIP_ARP_FILTER_NETIF_FN(p, netif, htons(type));#endif /* LWIP_ARP_FILTER_NETIF*/  switch (type) {#if LWIP_ARP    /* IP packet? */    case PP_HTONS(ETHTYPE_IP):      if (!(netif->flags & NETIF_FLAG_ETHARP)) {        goto free_and_return;      }#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, -ip_hdr_offset)) {        LWIP_ASSERT("Can't move over header in packet", 0);        goto free_and_return;      } else {        /* pass to IP layer */        ip_input(p, netif);      }      break;          case PP_HTONS(ETHTYPE_ARP):      if (!(netif->flags & NETIF_FLAG_ETHARP)) {        goto free_and_return;      }      /* pass p to ARP module */      etharp_arp_input(netif, (struct eth_addr*)(netif->hwaddr), p);      break;#endif /* LWIP_ARP */#if PPPOE_SUPPORT    case PP_HTONS(ETHTYPE_PPPOEDISC): /* PPP Over Ethernet Discovery Stage */      pppoe_disc_input(netif, p);      break;    case PP_HTONS(ETHTYPE_PPPOE): /* PPP Over Ethernet Session Stage */      pppoe_data_input(netif, p);      break;#endif /* PPPOE_SUPPORT */    default:      ETHARP_STATS_INC(etharp.proterr);      ETHARP_STATS_INC(etharp.drop);      goto free_and_return;  }  /* This means the pbuf is freed or consumed,     so the caller doesn't have to free it again */  return ERR_OK;free_and_return:  pbuf_free(p);  return ERR_OK;}#endif /* LWIP_ARP || LWIP_ETHERNET */

⌨️ 快捷键说明

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