void etharp_ip_input(struct netif *netif, struct pbuf *p) { struct ethip_hdr *hdr; /* 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 on local network? */ //Receive another network IP packet. #if 0 //20090224 if (!ip_addr_maskcmp(&(hdr->ip.src), &(netif->ip_addr), &(netif->netmask)) #if 0 //ZOT716u2 #ifdef O_AXIS /* Open TCP/IP layer hole */ && !TCP_HOLE_FLAG //615wu #endif// O_AXIS #endif //ZOT716u2 #ifdef RENDEZVOUS && !mRENVEnable #endif//RENDEZVOUS ) { /* do nothing */ return; } #endif //0 //20090224 LWIP_DEBUGF(ETHARP_DEBUG | DBG_TRACE, ("etharp_ip_input: updating ETHARP table.\n")); /* update ARP table, ask to insert entry */ update_arp_entry(netif, &(hdr->ip.src), &(hdr->eth.src), ETHARP_CREATE); }
/*-----------------------------------------------------------------------------------*/ struct pbuf * etharp_ip_input(struct netif *netif, struct pbuf *p) { struct ethip_hdr *hdr; hdr = p->payload; /* Only insert/update an entry if the source IP address of the incoming IP packet comes from a host on the local network. */ if(!ip_addr_maskcmp(&(hdr->ip.src), &(netif->ip_addr), &(netif->netmask))) { return NULL; } if(ip_addr_isbroadcast(&(hdr->ip.src), &(netif->netmask))) { return NULL; } DEBUGF(ETHARP_DEBUG, ("etharp_ip_input: updating ETHARP table.\n")); if (ip_addr_isbroadcast(&(hdr->ip.dest), &(netif->netmask))) return update_arp_entry(&(hdr->ip.src), &(hdr->eth.src), 0); else return update_arp_entry(&(hdr->ip.src), &(hdr->eth.src), 1); }
/** Add a new static entry to the ARP table. If an entry exists for the * specified IP address, this entry is overwritten. * If packets are queued for the specified IP address, they are sent out. * * @param ipaddr IP address for the new static entry * @param ethaddr ethernet address for the new static entry * @return @see return values of etharp_add_static_entry */ err_t etharp_add_static_entry(ip_addr_t *ipaddr, struct eth_addr *ethaddr) { struct netif *netif; LWIP_DEBUGF(ETHARP_DEBUG | LWIP_DBG_TRACE, ("etharp_add_static_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_16(ipaddr), ip4_addr2_16(ipaddr), ip4_addr3_16(ipaddr), ip4_addr4_16(ipaddr), ethaddr->addr[0], ethaddr->addr[1], ethaddr->addr[2], ethaddr->addr[3], ethaddr->addr[4], ethaddr->addr[5])); netif = ip_route(ipaddr); if (netif == NULL) { return ERR_RTE; } return update_arp_entry(netif, ipaddr, ethaddr, ETHARP_FLAG_TRY_HARD | ETHARP_FLAG_STATIC_ENTRY); }
/** * Updates the ARP table using the given 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() */ struct pbuf * etharp_ip_input(struct netif *netif, struct pbuf *p) { struct ethip_hdr *hdr; /* 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 on local network? */ if (!ip_addr_maskcmp(&(hdr->ip.src), &(netif->ip_addr), &(netif->netmask))) { /* do nothing */ return NULL; } DEBUGF(ETHARP_DEBUG | DBG_TRACE, ("etharp_ip_input: updating ETHARP table.\n")); /* update ARP table, ask to insert entry */ update_arp_entry(netif, &(hdr->ip.src), &(hdr->eth.src), ARP_INSERT_FLAG); return NULL; }
/** * 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() */ void etharp_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); }
/** * 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() */ static void etharp_ip4_input(struct netif *netif, struct pbuf *p) { struct ethip4_hdr *hdr; struct ip_addr src4; /* 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; IP64_CONV(&src4,&(hdr->ip.src)); if (!ip_addr_list_maskfind(netif->addrs, &(src4))) { /* do nothing */ return; } LWIP_DEBUGF(ETHARP_DEBUG | DBG_TRACE, ("etharp_ip4_input: updating ETHARP table.\n")); /* update ARP table, ask to insert entry */ update_arp_entry(netif, &(src4), &(hdr->eth.src), ARP_INSERT_FLAG); return; }
void handle_frame(struct eth_dev *e, struct net_dev *nd, struct pcnet_rx_32 *f) { //int i; uint8 *b = (uint8 *)(0L + f->RBADR); struct eth_frame *tmp; struct ip_hdr *iph; /* printf("handle_frame:\n" "ENP:%x STP:%x BUFF:%x CRC:%x OFLO:%x FRAM:%x\n" "ERR:%x OWN:%x BCNT:%x MCNT:%x\n", f->ENP, f->STP, f->BUFF, f->CRC, f->OFLO, f->FRAM, f->ERR, f->OWN, f->BCNT, f->MCNT); */ tmp = kmalloc(f->BCNT, "eth_frame", NULL); memcpy(tmp, b, f->BCNT); tmp->len = ntohs(tmp->len); // printf("src: "); // print_mac(tmp->src); // printf(" dst: "); // print_mac(tmp->dst), // printf(" len: %lx\n", tmp->len); // printf("nd->upper: %x\n", nd->upper); switch(tmp->len) { case ETHPROTO_IP: iph = (struct ip_hdr *)&tmp->data; update_arp_entry( ntohl(iph->src), tmp->src, nd ); break; case ETHPROTO_ARP: arp_handle(nd, (uint8 *)&tmp->data, f->MCNT-(6+6+2)); break; } nd->upper->ops->recv(nd, nd->upper, (uint8 *)&tmp->data, f->MCNT-(6+6+2)); kfree(tmp); }
/** * 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 netif netif related to this entry (used for NETIF_ADDRHINT) * @param ipaddr IP address of the inserted ARP entry. * @param ethaddr Ethernet address of the inserted ARP entry. * @param flags @see definition of ETHARP_FLAG_* * * @return * - ERR_OK Succesfully updated ARP cache. * - ERR_MEM If we could not add a new ARP entry when ETHARP_FLAG_TRY_HARD was set. * - ERR_ARG Non-unicast address given, those will not appear in ARP cache. * * @see pbuf_free() */ static err_t update_arp_entry(struct netif *netif, ip_addr_t *ipaddr, struct eth_addr *ethaddr, u8_t flags) { s8_t i; 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_16(ipaddr), ip4_addr2_16(ipaddr), ip4_addr3_16(ipaddr), ip4_addr4_16(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 */ i = find_entry(ipaddr, flags); /* bail out if no entry could be found */ if (i < 0) { return (err_t)i; } #if ETHARP_SUPPORT_STATIC_ENTRIES if (flags & ETHARP_FLAG_STATIC_ENTRY) { /* record static type */ arp_table[i].static_entry = 1; } #endif /* ETHARP_SUPPORT_STATIC_ENTRIES */ /* mark it stable */ arp_table[i].state = ETHARP_STATE_STABLE; #if LWIP_SNMP /* record network interface */ arp_table[i].netif = netif; #endif /* LWIP_SNMP */ /* 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 */ ETHADDR32_COPY(&arp_table[i].ethaddr, ethaddr); /* reset time stamp */ arp_table[i].ctime = 0; /* this is where we will send out queued packets! */ #if ARP_QUEUEING 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); #else /* ARP_QUEUEING */ if (arp_table[i].q != NULL) { struct pbuf *p = arp_table[i].q; arp_table[i].q = NULL; #endif /* ARP_QUEUEING */ /* send the queued IP packet */ etharp_send_ip(netif, p, (struct eth_addr*)(netif->hwaddr), ethaddr); /* free the queued IP packet */ pbuf_free(p); } return ERR_OK; } #if ETHARP_SUPPORT_STATIC_ENTRIES /** Add a new static entry to the ARP table. If an entry exists for the * specified IP address, this entry is overwritten. * If packets are queued for the specified IP address, they are sent out. * * @param ipaddr IP address for the new static entry * @param ethaddr ethernet address for the new static entry * @return @see return values of etharp_add_static_entry */ err_t etharp_add_static_entry(ip_addr_t *ipaddr, struct eth_addr *ethaddr) { struct netif *netif; LWIP_DEBUGF(ETHARP_DEBUG | LWIP_DBG_TRACE, ("etharp_add_static_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_16(ipaddr), ip4_addr2_16(ipaddr), ip4_addr3_16(ipaddr), ip4_addr4_16(ipaddr), ethaddr->addr[0], ethaddr->addr[1], ethaddr->addr[2], ethaddr->addr[3], ethaddr->addr[4], ethaddr->addr[5])); netif = ip_route(ipaddr); if (netif == NULL) { return ERR_RTE; } return update_arp_entry(netif, ipaddr, ethaddr, ETHARP_FLAG_TRY_HARD | ETHARP_FLAG_STATIC_ENTRY); } /** Remove a static entry from the ARP table previously added with a call to * etharp_add_static_entry. * * @param ipaddr IP address of the static entry to remove * @return ERR_OK: entry removed * ERR_MEM: entry wasn't found * ERR_ARG: entry wasn't a static entry but a dynamic one */ err_t etharp_remove_static_entry(ip_addr_t *ipaddr) { s8_t i; LWIP_DEBUGF(ETHARP_DEBUG | LWIP_DBG_TRACE, ("etharp_remove_static_entry: %"U16_F".%"U16_F".%"U16_F".%"U16_F"\n", ip4_addr1_16(ipaddr), ip4_addr2_16(ipaddr), ip4_addr3_16(ipaddr), ip4_addr4_16(ipaddr))); /* find or create ARP entry */ i = find_entry(ipaddr, ETHARP_FLAG_FIND_ONLY); /* bail out if no entry could be found */ if (i < 0) { return (err_t)i; } if ((arp_table[i].state != ETHARP_STATE_STABLE) || (arp_table[i].static_entry == 0)) { /* entry wasn't a static entry, cannot remove it */ return ERR_ARG; } /* entry found, free it */ free_entry(i); return ERR_OK; }
/** * 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() */ void etharp_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, sizeof(struct etharp_hdr))); pbuf_free(p); return; } hdr = p->payload; /* get aligned copies of addresses */ *(struct ip_addr2 *)&sipaddr = hdr->sipaddr; *(struct ip_addr2 *)&dipaddr = hdr->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; for(i = 0; i < netif->hwaddr_len; ++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)); hdr->ethhdr.type = htons(ETHTYPE_ARP); /* 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 | 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 | 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 | 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 | DBG_TRACE, ("etharp_arp_input: ARP unknown opcode type %"S16_F"\n", htons(hdr->opcode))); break; } /* free ARP packet */ pbuf_free(p); }
/*-----------------------------------------------------------------------------------*/ struct pbuf * etharp_arp_input(struct netif *netif, struct eth_addr *ethaddr, struct pbuf *p, struct pbuf **queued) { struct etharp_hdr *hdr; u8_t i; if(p->tot_len < sizeof(struct etharp_hdr)) { DEBUGF(ETHARP_DEBUG, ("etharp_etharp_input: packet too short (%d/%d)\n", (int) p->tot_len, (int) sizeof(struct etharp_hdr))); return NULL; } hdr = p->payload; switch(htons(hdr->opcode)) { case ARP_REQUEST: *queued = update_arp_entry(&(hdr->sipaddr), &(hdr->shwaddr), 0); /* ARP request. If it asked for our address, we send out a reply. */ DEBUGF(ETHARP_DEBUG, ("etharp_arp_input: ARP request\n")); if(!memcmp(&(hdr->dipaddr), &(netif->ip_addr), sizeof (hdr->dipaddr))) { pbuf_ref(p); hdr->opcode = htons(ARP_REPLY); memcpy (&(hdr->dipaddr), &(hdr->sipaddr), sizeof (hdr->dipaddr)); memcpy (&(hdr->sipaddr), &(netif->ip_addr), sizeof (hdr->sipaddr)); for(i = 0; i < 6; ++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, 6); hdr->proto = htons(ETHTYPE_IP); ARPH_PROTOLEN_SET(hdr, sizeof(struct ip_addr)); hdr->ethhdr.type = htons(ETHTYPE_ARP); return p; } break; case ARP_REPLY: /* ARP reply. We insert or update the ARP table. */ DEBUGF(ETHARP_DEBUG, ("etharp_arp_input: ARP reply\n")); if(!memcmp (&(hdr->dipaddr), &(netif->ip_addr), sizeof (hdr->dipaddr))) { #if (LWIP_DHCP && DHCP_DOES_ARP_CHECK) dhcp_arp_reply(&hdr->sipaddr); #endif /* add_arp_entry() will return a pbuf that has previously been queued waiting for an ARP reply. */ } /* whether its destined for us or not, we update the arp table */ return add_arp_entry(&(hdr->sipaddr), &(hdr->shwaddr)); break; default: DEBUGF(ETHARP_DEBUG, ("etharp_arp_input: unknown type %d\n", htons(hdr->opcode))); break; } return NULL; }
/** * Responds to ARP requests, updates ARP entries and sends queued IP packets. * * 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() */ struct pbuf * etharp_arp_input(struct netif *netif, struct eth_addr *ethaddr, struct pbuf *p) { struct etharp_hdr *hdr; u8_t i; /* drop short ARP packets */ if (p->tot_len < sizeof(struct etharp_hdr)) { DEBUGF(ETHARP_DEBUG | DBG_TRACE | 1, ("etharp_arp_input: packet too short (%ld/%u)\n", p->tot_len, sizeof(struct etharp_hdr))); pbuf_free(p); return NULL; } hdr = p->payload; 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. */ DEBUGF (ETHARP_DEBUG | DBG_TRACE, ("etharp_arp_input: incoming ARP request\n")); /* we are not configured? */ if (netif->ip_addr.addr == 0) { DEBUGF(ETHARP_DEBUG | DBG_TRACE, ("etharp_arp_input: we are unconfigured, ARP request ignored.\n")); pbuf_free(p); return NULL; } /* update the ARP cache */ update_arp_entry(netif, &(hdr->sipaddr), &(hdr->shwaddr), 0); /* ARP request for our address? */ if (ip_addr_cmp(&(hdr->dipaddr), &(netif->ip_addr))) { 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); ip_addr_set(&(hdr->dipaddr), &(hdr->sipaddr)); ip_addr_set(&(hdr->sipaddr), &(netif->ip_addr)); for(i = 0; i < netif->hwaddr_len; ++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)); hdr->ethhdr.type = htons(ETHTYPE_ARP); /* return ARP reply */ netif->linkoutput(netif, p); } else { DEBUGF(ETHARP_DEBUG | DBG_TRACE, ("etharp_arp_input: incoming ARP request was not for us.\n")); } break; case ARP_REPLY: /* ARP reply. We insert or update the ARP table. */ DEBUGF(ETHARP_DEBUG | DBG_TRACE, ("etharp_arp_input: incoming ARP reply\n")); #if (LWIP_DHCP && DHCP_DOES_ARP_CHECK) /* DHCP needs to know about ARP replies */ dhcp_arp_reply(netif, &hdr->sipaddr); #endif /* ARP reply directed to us? */ if (ip_addr_cmp(&(hdr->dipaddr), &(netif->ip_addr))) { DEBUGF(ETHARP_DEBUG | DBG_TRACE, ("etharp_arp_input: incoming ARP reply is for us\n")); /* update_the ARP cache, ask to insert */ update_arp_entry(netif, &(hdr->sipaddr), &(hdr->shwaddr), ARP_INSERT_FLAG); /* ARP reply not directed to us */ } else { DEBUGF(ETHARP_DEBUG | DBG_TRACE, ("etharp_arp_input: incoming ARP reply is not for us\n")); /* update the destination address pair */ update_arp_entry(netif, &(hdr->sipaddr), &(hdr->shwaddr), 0); /* update the destination address pair */ update_arp_entry(netif, &(hdr->dipaddr), &(hdr->dhwaddr), 0); } break; default: DEBUGF(ETHARP_DEBUG | DBG_TRACE, ("etharp_arp_input: ARP unknown opcode type %d\n", htons(hdr->opcode))); break; } /* free ARP packet */ pbuf_free(p); p = NULL; /* nothing to send, we did it! */ return NULL; }
/** * 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() */ void etharp_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; /* 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 (%d/%d)\n", p->tot_len, sizeof(struct etharp_hdr))); pbuf_free(p); return; } hdr = p->payload; /* get aligned copies of addresses */ *(struct ip_addr2 *)&sipaddr = hdr->sipaddr; *(struct ip_addr2 *)&dipaddr = hdr->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_CREATE); /* 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; for(i = 0; i < netif->hwaddr_len; ++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)); hdr->ethhdr.type = htons(ETHTYPE_ARP); /* return ARP reply */ netif->linkoutput(netif, p); #ifdef LINKLOCAL_IP //Ron Add for Rendzvous 12/10/04 if( mRENVEnable && (LinkLocal_get_current_state() != NO_USE ) && is_linklocal_ip( dipaddr.addr ) ) { if( (LinkLocal_get_current_state() != IDLE) && ip_conflict_cnt++ == 0 ) linklocal_alarm(); else if( (LinkLocal_get_current_state() == IDLE) && ip_conflict_cnt++ == 0) { linklocal_alarm(); } } #endif /* we are not configured? */ } else if (netif->ip_addr.addr == 0) { /* { for_us == 0 and netif->ip_addr.addr == 0 } */ #ifdef LINKLOCAL_IP //Ron Add for Rendzvous 12/10/04 if( mRENVEnable && (LinkLocal_get_current_state() != NO_USE ) && is_linklocal_ip( dipaddr.addr ) ) { if( (LinkLocal_get_current_state() != IDLE) && ip_conflict_cnt++ == 0 ) linklocal_alarm(); else if( (LinkLocal_get_current_state() == IDLE) && ip_conflict_cnt++ == 0) { linklocal_alarm(); } hdr->opcode = htons(ARP_REPLY); hdr->sipaddr = hdr->dipaddr; hdr->dipaddr = *(struct ip_addr2 *)&netif->ip_addr; // hdr->dipaddr = hdr->sipaddr; // hdr->sipaddr = *(struct ip_addr2 *)&netif->ip_addr; for(i = 0; i < netif->hwaddr_len; ++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)); hdr->ethhdr.type = htons(ETHTYPE_ARP); netif->linkoutput(netif, p); } #endif LWIP_DEBUGF(ETHARP_DEBUG | 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 | 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 | DBG_TRACE, ("etharp_arp_input: incoming ARP reply\n")); #if (LWIP_DHCP && DHCP_DOES_ARP_CHECK) /* DHCP wants to know about ARP replies to our wanna-have-address */ if (for_us){ dhcp_arp_reply(netif, &sipaddr); } #endif #ifdef LINKLOCAL_IP //Ron Add for Rendzvous 12/10/04 if( mRENVEnable && (LinkLocal_get_current_state() != NO_USE ) && is_linklocal_ip( sipaddr.addr ) ) { if( (LinkLocal_get_current_state() != IDLE) && ip_conflict_cnt++ == 0 ) linklocal_alarm(); else if( (LinkLocal_get_current_state() == IDLE) && ip_conflict_cnt++ == 0) { linklocal_alarm(); } } #endif break; default: LWIP_DEBUGF(ETHARP_DEBUG | DBG_TRACE, ("etharp_arp_input: ARP unknown opcode type %d\n", htons(hdr->opcode))); break; } /* free ARP packet */ pbuf_free(p); }
/** * 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() */ struct pbuf * etharp_arp_input(struct netif *netif, struct eth_addr *ethaddr, struct pbuf *p) { struct etharp_hdr *hdr; u8_t i; u8_t for_us; /* 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 (%d/%d)\n", p->tot_len, sizeof(struct etharp_hdr))); pbuf_free(p); return NULL; } hdr = p->payload; /* 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(&(hdr->dipaddr), &(netif->ip_addr)); } /* add or update entries in the ARP cache */ if (for_us) { /* insert IP address in ARP cache (assume requester wants to talk to us) * we might even send out a queued packet to this host */ update_arp_entry(netif, &(hdr->sipaddr), &(hdr->shwaddr), ARP_INSERT_FLAG); /* request was not directed to us, but snoop anyway */ } else { /* update the source IP address in the cache */ update_arp_entry(netif, &(hdr->sipaddr), &(hdr->shwaddr), 0); } 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")); /* we are not configured? */ if (netif->ip_addr.addr == 0) { LWIP_DEBUGF(ETHARP_DEBUG | DBG_TRACE, ("etharp_arp_input: we are unconfigured, ARP request ignored.\n")); pbuf_free(p); return NULL; } /* 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); ip_addr_set(&(hdr->dipaddr), &(hdr->sipaddr)); ip_addr_set(&(hdr->sipaddr), &(netif->ip_addr)); for(i = 0; i < netif->hwaddr_len; ++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)); hdr->ethhdr.type = htons(ETHTYPE_ARP); /* return ARP reply */ netif->linkoutput(netif, p); /* request was not directed to us */ } else { LWIP_DEBUGF(ETHARP_DEBUG | DBG_TRACE, ("etharp_arp_input: incoming ARP request was not for us.\n")); } break; case ARP_REPLY: /* ARP reply. We insert or update the ARP table later. */ LWIP_DEBUGF(ETHARP_DEBUG | DBG_TRACE, ("etharp_arp_input: incoming ARP reply\n")); #if (LWIP_DHCP && DHCP_DOES_ARP_CHECK) /* DHCP wants to know about ARP replies to our wanna-have-address */ if (for_us) dhcp_arp_reply(netif, &hdr->sipaddr); #endif break; default: LWIP_DEBUGF(ETHARP_DEBUG | DBG_TRACE, ("etharp_arp_input: ARP unknown opcode type %d\n", htons(hdr->opcode))); break; } /* free ARP packet */ pbuf_free(p); p = NULL; /* nothing to send, we did it! */ return NULL; }
NDIS_STATUS WAN_AddRasLink ( IN PKIP_NDIS_ADAPTER pAdapter, IN PNDIS_WAN_LINE_UP pWanLineUp ) { NDIS_STATUS nStatus = NDIS_STATUS_SUCCESS; PKIP_RAS_LINK RasLink = NULL; ULONG OsVersion = OsGetMajorVersion(); DBGLOG(( LTrace, "Local MAC: %.2X%.2X%.2X%.2X%.2X%.2X Remote MAC: %.2X%.2X%.2X%.2X%.2X%.2X\n", pWanLineUp->LocalAddress[0], pWanLineUp->LocalAddress[1], pWanLineUp->LocalAddress[2], pWanLineUp->LocalAddress[3], pWanLineUp->LocalAddress[4], pWanLineUp->LocalAddress[5], pWanLineUp->RemoteAddress[0], pWanLineUp->RemoteAddress[1], pWanLineUp->RemoteAddress[2], pWanLineUp->RemoteAddress[3], pWanLineUp->RemoteAddress[4], pWanLineUp->RemoteAddress[5] )); if ( pWanLineUp->ProtocolType != ETHTYPE_IP ){ return NDIS_STATUS_SUCCESS; } if ( OsVersion < 5 ){ if ( pWanLineUp->ProtocolBufferLength < sizeof(WAN_IP_INFO_NT)){ return NDIS_STATUS_SUCCESS; } }else if ( OsVersion < 6 ){ if ( pWanLineUp->ProtocolBufferLength < sizeof(WAN_IP_INFO_W2K)){ return NDIS_STATUS_SUCCESS; } }else if ( OsVersion < 7 ){ if ( pWanLineUp->ProtocolBufferLength < sizeof(WAN_IP_INFO_VISTA)){ return NDIS_STATUS_SUCCESS; } } // To avoid RAS entries duplications if (WAN_CheckForContext(pAdapter, &pWanLineUp->LocalAddress[2]) == FALSE ) { RasLink = NDIS_AllocateRasLink( pAdapter, pWanLineUp ); if ( RasLink == NULL ) { nStatus = NDIS_STATUS_RESOURCES; }else{ if ( OsVersion < 5 ){ PWAN_IP_INFO_NT WanIpInfo = (PWAN_IP_INFO_NT)pWanLineUp->ProtocolBuffer; ip4_addr_set_u32(&RasLink->IpAddr,WanIpInfo->IpAddress); ip4_addr_set_u32(&RasLink->IpMask,IPADDR_BROADCAST); }else if ( OsVersion < 6 ){ PWAN_IP_INFO_W2K WanIpInfo = (PWAN_IP_INFO_W2K)pWanLineUp->ProtocolBuffer; ip4_addr_set_u32(&RasLink->IpAddr,WanIpInfo->LocalIpAddress); ip4_addr_set_u32(&RasLink->IpMask,WanIpInfo->IpSubnetMask); ip4_addr_set_u32(&RasLink->RemoteIpAddr,WanIpInfo->RemoteIpAddress); }else if ( OsVersion < 7 ){ PWAN_IP_INFO_VISTA WanIpInfo = (PWAN_IP_INFO_VISTA)pWanLineUp->ProtocolBuffer; ip4_addr_set_u32(&RasLink->IpAddr,WanIpInfo->LocalIpAddress); ip4_addr_set_u32(&RasLink->IpMask,WanIpInfo->IpSubnetMask); ip4_addr_set_u32(&RasLink->RemoteIpAddr,WanIpInfo->RemoteIpAddress); } ProtocolBindAdapter( (PKIP_NDIS_INTERFACE)RasLink, RasLink->IpAddr.addr, RasLink->IpMask.addr, RasLink->IpAddr.addr, TRUE ); // update arp table update_arp_entry( &RasLink->Interface.Protocol.IIF, &RasLink->RemoteIpAddr, (struct eth_addr*)RasLink->RemoteAddress, ETHARP_FLAG_STATIC_ENTRY ); update_arp_entry( &RasLink->Interface.Protocol.IIF, &RasLink->IpAddr, (struct eth_addr*)RasLink->RemoteAddress, ETHARP_FLAG_STATIC_ENTRY ); } } return nStatus; }