void arp_handle() { //cprintf("receive arp .............................\n"); int * data = ethernet_rx_data + ETHERNET_HDR_LEN; if(data[ARP_TYPE] == ARP_TYPE_REPLY) { if(eth_memcmp(data + ARP_TARGET_IP, IP_ADDR, 4) != 0); return; int i=0; for (i=0; i<4; i++) cprintf("%d\n", *(data+ARP_SENDER_IP+i)); //tcp_request(); for (i = 0; i < 6; i++) remote_mac[i] = *(data+ARP_SENDER_MAC+i); } else if (data[ARP_TYPE] == ARP_TYPE_REQUEST && data[ARP_TARGET_IP] == IP_ADDR[0] && data[ARP_TARGET_IP + 1] == IP_ADDR[1] && data[ARP_TARGET_IP + 2] == IP_ADDR[2] && data[ARP_TARGET_IP + 3] == IP_ADDR[3]) { ethernet_tx_len = ETHERNET_HDR_LEN + ARP_BODY_LEN; ethernet_set_tx(ethernet_rx_src, ETHERNET_TYPE_ARP); int * buf = ethernet_tx_data + ETHERNET_HDR_LEN; eth_memcpy(buf, ARP_FIX_HDR, 6 + 1); buf[ARP_TYPE] = ARP_TYPE_REPLY; eth_memcpy(buf + ARP_SENDER_MAC, MAC_ADDR, 6); eth_memcpy(buf + ARP_SENDER_IP, IP_ADDR, 4); eth_memcpy(buf + ARP_TARGET_MAC, data + ARP_SENDER_MAC, 6); eth_memcpy(buf + ARP_TARGET_IP, data + ARP_SENDER_IP, 4); cprintf("send arp response...\n"); ethernet_send(); } else if (data[ARP_TYPE] == ARP_TYPE_REQUEST && data[ARP_TARGET_IP] == data[ARP_SENDER_IP] && data[ARP_TARGET_IP + 1] == data[ARP_SENDER_IP + 1] && data[ARP_TARGET_IP + 2] == data[ARP_SENDER_IP + 2] && data[ARP_TARGET_IP + 3] == data[ARP_SENDER_IP + 3]) //Is gratuitous = true { if (data[ARP_TARGET_IP] == tcp_dst_addr[0] && data[ARP_TARGET_IP + 1] == tcp_dst_addr[1] && data[ARP_TARGET_IP + 2] == tcp_dst_addr[2] && data[ARP_TARGET_IP + 3] == tcp_dst_addr[3]) { int i; for (i = 0; i < 6; i++) remote_mac[i] = *(data+ARP_SENDER_MAC+i); arp_request(); tcp_request(); } } }
/*! * Function name: eth_build_frame * \return length of the ethernet frame. * \param dest_mac_addr : [in] Destination MAC address expected in the the ethernet frame (1st elt of the ethernet frame). * \param source_mac_addr : [in] Source MAC address expected in the the ethernet frame (2nd elt of the ethernet frame). * \param dest_ip_addr : [in] Destination IP address expected in the the IP frame (10th elt of the IP frame). * \param source_ip_addr : [in] Source IP address expected in the the IP frame (9th elt of the IP frame). * \param output_frame : [out] Ethernet Frame generated. * \param protocol : [in] protocol of interest. * \brief Build the ethernet frame. * *******************************************************************/ u32_t eth_build_frame(const u8_t* const dest_mac_addr, const u8_t* const source_mac_addr, const u32_t dest_ip_addr, const u32_t source_ip_addr, u8_t* const output_frame, u32_t const protocol) { ETHER_HEADER_T* ether; u32_t length = 0; //Ethernet header ether = (ETHER_HEADER_T *)output_frame; (void)eth_memcpy(ether->destination_addr,dest_mac_addr); (void)eth_memcpy(ether->source_addr,source_mac_addr); switch(protocol) { case ETH_ETHERNET: ether->frame_type = htons(ETHERTYPE_IP); break; case ETH_ARP_REQUEST: //cIPS sent an arp request to a peer. The peer replied and here is the reply case. ether->frame_type = htons(ETHERTYPE_ARP); (void)eth_memcpy(ether->destination_addr,BROADCAST_ADDR); length = arp_build_frame(BLANK_ADDR, source_mac_addr,dest_ip_addr,source_ip_addr,ARP_REQUEST,output_frame+ sizeof(ETHER_HEADER_T)); break; case ETH_ARP_REPLY: //The peer sends an arp request to cIPS. cIPS replies in this case. ether->frame_type = htons(ETHERTYPE_ARP); length = arp_build_frame(dest_mac_addr, source_mac_addr,dest_ip_addr,source_ip_addr,ARP_RESPONSE,output_frame+ sizeof(ETHER_HEADER_T)); break; default: break; }; length+= sizeof(ETHER_HEADER_T); return length ; }
void ip_send_packet(int * macdst, int proto, int length) { length += 20; // ip header ethernet_set_tx(macdst, ETHERNET_TYPE_IP); int * data = ethernet_tx_data + ETHERNET_HDR_LEN; data[IP_VERSION] = IP_VERSION_VAL; data[IP_TOTAL_LEN] = MSB(length); data[IP_TOTAL_LEN + 1] = LSB(length); data[IP_FLAGS] = 0; data[IP_FLAGS + 1] = 0; data[IP_TTL] = 64; data[IP_PROTOCAL] = proto; eth_memcpy(data + IP_SRC, IP_ADDR, 4); eth_memcpy(data + IP_DST, tcp_dst_addr, 4); }
void ip_make_reply(int proto, int length) { length += 20; // ip header ethernet_set_tx(ethernet_rx_src, ETHERNET_TYPE_IP); int * data = ethernet_tx_data + ETHERNET_HDR_LEN; data[IP_VERSION] = IP_VERSION_VAL; data[IP_TOTAL_LEN] = MSB(length); data[IP_TOTAL_LEN + 1] = LSB(length); data[IP_FLAGS] = 0; data[IP_FLAGS + 1] = 0; data[IP_TTL] = 64; data[IP_PROTOCAL] = proto; eth_memcpy(data + IP_SRC, IP_ADDR, 4); eth_memcpy(data + IP_DST, ethernet_rx_data + ETHERNET_HDR_LEN + IP_SRC, 4); }
/*! * Function name: arp_query_cache * \return ERR_OK if found, ERR_VAL othewise. * \param cache : [in/out] cache of interest. * \param ip_addr : [in] IP address of the adapter looked for. * \param destination_mac_addr : [out] MAC address associated to the IP address. * \param ip_mask : [in] IP mask. * \brief Look for the MAC address associated to an IP address. * *******************************************************************/ err_t arp_query_cache(ARP_CACHE_T* const cache, const u32_t ip_addr, u8_t* const destination_mac_addr, const u32_t ip_mask) { u32_t i; err_t err = ERR_OK; bool_t found = FALSE; T_DEBUGF(ETHARP_DEBUG,("ip_addr = %ld.%ld.%ld.%ld ", (ip_addr >> 24) & 0xff, (ip_addr >> 16) & 0xff, (ip_addr >> 8) & 0xff, ip_addr & 0xff)); T_DEBUGF(ETHARP_DEBUG,("(0x%lx) ", ip_addr)); T_DEBUGF(ETHARP_DEBUG,("%s \r\n",__func__)); //Scan the list of adapter to update the MAC address. for( i = 0; i < ARP_TABLE_SIZE; i++ ) { if( cache->table[i].ip_addr == ip_addr ) { (void)eth_memcpy(destination_mac_addr, cache->table[i].ether_addr); found = TRUE; i = ARP_TABLE_SIZE; //exit loop } } if( !found ) { //!<If broadcast address then this is not a "not found" and return the broadcast MAC address. if( (ip_addr & (~ip_mask)) != (IP_BROADCAST & (~ip_mask))) {err = ERR_VAL;} memset(destination_mac_addr, 0xFF ,MAC_ADDRESS_LENGTH); arp_print_cache(cache); } return err; }
void ip_send(int proto, int length) { length += IP_HDR_LEN; // ip header ethernet_set_tx(ETHERNET_TYPE_IP); int * data = ethernet_tx_data + ETHERNET_HDR_LEN; data[IP_VERSION] = IP_VERSION_VAL; data[IP_TOTAL_LEN] = MSB(length); data[IP_TOTAL_LEN + 1] = LSB(length); data[IP_FLAGS] = 0; data[IP_FLAGS + 1] = 0; data[IP_TTL] = 64; data[IP_PROTOCAL] = proto; eth_memcpy(data + IP_SRC, IP_ADDR, 4); eth_memcpy(data + IP_DST, REMOTE_IP_ADDR, 4); ethernet_tx_len = ETHERNET_HDR_LEN + length; ethernet_send(); }
void arp_request(){ ethernet_tx_len = ETHERNET_HDR_LEN + ARP_BODY_LEN; ethernet_set_tx(BROADCAST, ETHERNET_TYPE_ARP); int * buf = ethernet_tx_data + ETHERNET_HDR_LEN; eth_memcpy(buf, ARP_FIX_HDR, 6 + 1); buf[ARP_TYPE] = ARP_TYPE_REQUEST; eth_memcpy(buf + ARP_SENDER_MAC, MAC_ADDR, 6); eth_memcpy(buf + ARP_SENDER_IP, IP_ADDR, 4); eth_memcpy(buf + ARP_TARGET_MAC, DEFAULT, 6); eth_memcpy(buf + ARP_TARGET_IP, tcp_dst_addr, 4); intr_disable(); ethernet_send(); intr_enable(); //cprintf("send arp ...........................\n"); }
void arp_handle() { int * data = ethernet_rx_data + ETHERNET_HDR_LEN; if(data[ARP_TYPE] == ARP_TYPE_REQUEST) { if(eth_memcmp(data + ARP_TARGET_IP, IP_ADDR, 4) != 0) return; ethernet_tx_len = ETHERNET_HDR_LEN + ARP_BODY_LEN; ethernet_set_tx(ethernet_rx_src, ETHERNET_TYPE_ARP); int * buf = ethernet_tx_data + ETHERNET_HDR_LEN; eth_memcpy(buf, ARP_FIX_HDR, 6 + 1); buf[ARP_TYPE] = ARP_TYPE_REPLY; eth_memcpy(buf + ARP_SENDER_MAC, MAC_ADDR, 6); eth_memcpy(buf + ARP_SENDER_IP, IP_ADDR, 4); eth_memcpy(buf + ARP_TARGET_MAC, data + ARP_SENDER_MAC, 6); eth_memcpy(buf + ARP_TARGET_IP, data + ARP_SENDER_IP, 4); ethernet_send(); } }
/*! * Function name: arp_build_frame * \return length of the arp frame. * \param dest_mac_addr : [in] Destination MAC address expected in the the ethernet frame (1st elt of the ethernet frame). * \param source_mac_addr : [in] Source MAC address expected in the the ethernet frame (2nd elt of the ethernet frame). * \param dest_ip_addr : [in] Destination IP address expected in the the IP frame (10th elt of the IP frame). * \param source_ip_addr : [in] Source IP address expected in the the IP frame (9th elt of the IP frame). * \param arp_service : [in] ARP_REQUEST or ARP_RESPONSE * \param output_frame : [out] Ethernet Frame generated. * \brief Build the ARP frame. * *******************************************************************/ u32_t arp_build_frame(const u8_t* const dest_mac_addr, const u8_t* const source_mac_addr, const u32_t dest_ip_addr, const u32_t source_ip_addr, const u16_t arp_service, u8_t* const output_frame) { ARP_HEADER_T* arp; //Arp header arp = (ARP_HEADER_T*) output_frame; arp->hardware = htons(ETHERTYPE_ETHERNET); arp->protocol = htons(ETHERTYPE_IP); arp->hw_size = (u8_t) MAC_ADDRESS_LENGTH; arp->protocol_size = (u8_t)IP_ADDRESS_LENGTH ; arp->operation = htons(arp_service); (void)eth_memcpy(arp->sender_hw_addr,source_mac_addr); arp->sender_ip_addr = htonl(source_ip_addr); (void)eth_memcpy(arp->target_hw_addr,dest_mac_addr); arp->target_ip_addr = htonl(dest_ip_addr); return sizeof(ARP_HEADER_T); }
/*! * Function name: arp_update_cache * \return ERR_OK. * \param cache : [out] cache of interest. * \param ip_addr : [in] IP address of the adapter looked for. * \param source_mac_addr : [in] MAC address associated to the IP address. * \brief <br> * 1. Update the MAC address if the IP address already exists in the list. * 2. Otherwise, add the couple (IP addr, MAC addr) in the list * *******************************************************************/ err_t arp_update_cache(ARP_CACHE_T* const cache, const u32_t ip_addr, const u8_t* const source_mac_addr) { u32_t i; err_t err = ERR_OK; bool_t found = FALSE; T_DEBUGF(ETHARP_DEBUG,("%s\r\n",__func__)); T_DEBUGF(ETHARP_DEBUG,("ip_addr = %ld.%ld.%ld.%ld (0x%lx) ", (ip_addr >> 24) & 0xff, (ip_addr >> 16) & 0xff, (ip_addr >> 8) & 0xff, ip_addr & 0xff, ip_addr)); T_DEBUGF(ETHARP_DEBUG,("mac %x.%x.%x.%x.%x.%x ",source_mac_addr[0],source_mac_addr[1],source_mac_addr[2],source_mac_addr[3],source_mac_addr[4],source_mac_addr[5])); T_DEBUGF(ETHARP_DEBUG,("%s \r\n",__func__)); //Filter: check that the MAC addr is not a boadcast addr. i=0; while( (i < MAC_ADDRESS_LENGTH) && (source_mac_addr[i] == BROADCAST_ADDR[i])) { i++; } if( i != MAC_ADDRESS_LENGTH ) //!<If not a broadcast address. { //Scan the list of adapter to update the MAC address. for( i = 0; i < ARP_TABLE_SIZE; i++ ) { if( cache->table[i].ip_addr == ip_addr ) { (void)eth_memcpy(cache->table[i].ether_addr,source_mac_addr); found = TRUE; i = ARP_TABLE_SIZE; //exit loop } } if( !found )//If the IP address is not in the list then insert it. { for( i = 0; i < ARP_TABLE_SIZE; i++ ) { if( cache->table[i].state == ARP_UNUSED ) { (void)eth_memcpy(cache->table[i].ether_addr,source_mac_addr); cache->table[i].state = i; cache->table[i].ip_addr = ip_addr; found = TRUE; i = ARP_TABLE_SIZE; //exit loop } } if( !found ) //The table is full, an entry has to be replaced. { //Replace the oldest entry i = cache->older_index; (void)eth_memcpy(cache->table[i].ether_addr,source_mac_addr); cache->table[i].state = i; cache->table[i].ip_addr = ip_addr; (cache->older_index)++; if( cache->older_index == ARP_TABLE_SIZE){ //The table is a round buffer. Go back to the beginning when the index reaches the end. cache->older_index = 0; } } } } arp_print_cache(cache); return err; }