void IP4::transmit(Packet_ptr pckt) { assert(pckt->size() > sizeof(IP4::full_header)); auto ip4_pckt = std::static_pointer_cast<PacketIP4>(pckt); ip4_pckt->make_flight_ready(); IP4::ip_header& hdr = ip4_pckt->ip4_header(); // Create local and target subnets addr target = hdr.daddr & stack_.netmask(); addr local = stack_.ip_addr() & stack_.netmask(); // Compare subnets to know where to send packet pckt->next_hop(target == local ? hdr.daddr : stack_.router()); debug("<IP4 TOP> Next hop for %s, (netmask %s, local IP: %s, gateway: %s) == %s\n", hdr.daddr.str().c_str(), stack_.netmask().str().c_str(), stack_.ip_addr().str().c_str(), stack_.router().str().c_str(), target == local ? "DIRECT" : "GATEWAY"); debug("<IP4 transmit> my ip: %s, Next hop: %s, Packet size: %i IP4-size: %i\n", stack_.ip_addr().str().c_str(), pckt->next_hop().str().c_str(), pckt->size(), ip4_pckt->ip4_segment_size() ); linklayer_out_(pckt); }
void Arp::arp_resolve(IP4::addr next_hop) { PRINT("<ARP RESOLVE> %s\n", next_hop.str().c_str()); auto req = static_unique_ptr_cast<PacketArp>(inet_.create_packet()); req->init(mac_, inet_.ip_addr(), next_hop); req->set_dest_mac(MAC::BROADCAST); req->set_opcode(H_request); // Stat increment requests sent requests_tx_++; linklayer_out_(std::move(req), MAC::BROADCAST, Ethertype::ARP); }
void Arp::arp_resolve(Packet_ptr pckt) { debug("<ARP RESOLVE> %s\n", pckt->next_hop().str().c_str()); const auto next_hop = pckt->next_hop(); await_resolution(std::move(pckt), next_hop); auto req = static_unique_ptr_cast<PacketArp>(inet_.create_packet(sizeof(header))); req->init(mac_, inet_.ip_addr()); req->set_dest_mac(Ethernet::BROADCAST_FRAME); req->set_dest_ip(next_hop); req->set_opcode(H_request); // Stat increment requests sent requests_tx_++; linklayer_out_(std::move(req)); }
void Arp::arp_respond(header* hdr_in) { debug2("\t IP Match. Constructing ARP Reply\n"); // Stat increment replies sent replies_tx_++; // Populate ARP-header auto res = static_unique_ptr_cast<PacketArp>(inet_.create_packet(sizeof(header))); res->init(mac_, inet_.ip_addr()); res->set_dest_mac(hdr_in->shwaddr); res->set_dest_ip(hdr_in->sipaddr); res->set_opcode(H_reply); debug2("\t My IP: %s belongs to My Mac: %s\n", res->source_ip().str().c_str(), res->source_mac().str().c_str()); linklayer_out_(std::move(res)); }
void Arp::arp_respond(header* hdr_in, IP4::addr ack_ip) { PRINT("\t IP Match. Constructing ARP Reply\n"); // Stat increment replies sent replies_tx_++; // Populate ARP-header auto res = static_unique_ptr_cast<PacketArp>(inet_.create_packet()); res->init(mac_, ack_ip, hdr_in->sipaddr); res->set_dest_mac(hdr_in->shwaddr); res->set_opcode(H_reply); PRINT("\t IP: %s is at My Mac: %s\n", res->source_ip().str().c_str(), res->source_mac().str().c_str()); MAC::Addr dest = hdr_in->shwaddr; PRINT("<ARP -> physical> Sending response to %s. Linklayer begin: buf + %i \n", dest.str().c_str(), res->layer_begin() - res->buf() ); linklayer_out_(std::move(res), dest, Ethertype::ARP); }
void Arp::transmit(Packet_ptr pckt, IP4::addr next_hop) { Expects(pckt->size()); PRINT("<ARP -> physical> Transmitting %u bytes to %s\n", (uint32_t) pckt->size(), next_hop.str().c_str()); MAC::Addr dest_mac; if (next_hop == IP4::ADDR_BCAST) { dest_mac = MAC::BROADCAST; } else { #ifdef ARP_PASSTHROUGH extern MAC::Addr linux_tap_device; dest_mac = linux_tap_device; #else // If we don't have a cached IP, perform address resolution auto cache_entry = cache_.find(next_hop); if (UNLIKELY(cache_entry == cache_.end())) { PRINT("<ARP> No cache entry for IP %s. Resolving. \n", next_hop.to_string().c_str()); await_resolution(std::move(pckt), next_hop); return; } // Get MAC from cache dest_mac = cache_[next_hop].mac(); #endif PRINT("<ARP> Found cache entry for IP %s -> %s \n", next_hop.to_string().c_str(), dest_mac.to_string().c_str()); } // Move chain to linklayer linklayer_out_(std::move(pckt), dest_mac, Ethertype::IP4); }
void Arp::transmit(Packet_ptr pckt) { assert(pckt->size()); /** Get destination IP from IP header */ IP4::ip_header* iphdr = reinterpret_cast<IP4::ip_header*>(pckt->buffer() + sizeof(Ethernet::header)); IP4::addr sip = iphdr->saddr; IP4::addr dip = pckt->next_hop(); debug2("<ARP -> physical> Transmitting %i bytes to %s\n", pckt->size(), dip.str().c_str()); Ethernet::addr dest_mac; if (iphdr->daddr == IP4::INADDR_BCAST) { // When broadcasting our source IP should be either // our own IP or 0.0.0.0 if (sip != inet_.ip_addr() && sip != IP4::INADDR_ANY) { debug2("<ARP> Dropping outbound broadcast packet due to " "invalid source IP %s\n", sip.str().c_str()); return; } // mui importante dest_mac = Ethernet::BROADCAST_FRAME; } else { if (sip != inet_.ip_addr()) { debug2("<ARP -> physical> Not bound to source IP %s. My IP is %s. DROP!\n", sip.str().c_str(), inet_.ip_addr().str().c_str()); return; } // If we don't have a cached IP, perform address resolution if (!is_valid_cached(dip)) { arp_resolver_(std::move(pckt)); return; } // Get MAC from cache dest_mac = cache_[dip].mac_; } /** Attach next-hop mac and ethertype to ethernet header */ auto* ethhdr = reinterpret_cast<Ethernet::header*>(pckt->buffer()); ethhdr->src = mac_; ethhdr->dest = dest_mac; ethhdr->type = Ethernet::ETH_IP4; /** Update chain as well */ auto* next = pckt->tail(); while(next) { auto* headur = reinterpret_cast<Ethernet::header*>(next->buffer()); headur->src = mac_; headur->dest = dest_mac; headur->type = Ethernet::ETH_IP4; next = next->tail(); } debug2("<ARP -> physical> Sending packet to %s\n", mac_.str().c_str()); linklayer_out_(std::move(pckt)); }