Пример #1
0
int Arp::transmit(Packet_ptr pckt){
  
  assert(pckt->size());
  
  /** Get destination IP from IP header   */
  IP4::ip_header* iphdr = (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 mac;
  
  if (iphdr->daddr == IP4::INADDR_BCAST)
  {
    // when broadcasting our source IP should be either
    // our own IP or 0.0.0.0
    static const IP4::addr INADDR_NONE  {{0}};
    if (sip != ip_ && sip != INADDR_NONE)
    {
      debug2("<ARP> Dropping outbound broadcast packet due to "
             "invalid source IP %s\n",  sip.str().c_str());
      return -1;
    }
    mac = Ethernet::addr::BROADCAST_FRAME;
  }
  else
  {
    if (sip != ip_)
    {
      debug2("<ARP -> physical> Not bound to source IP %s. My IP is %s. DROP!\n",
            sip.str().c_str(), ip_.str().c_str());
      return -1;
    }
    
    // If we don't have a cached IP, get mac from next-hop (Håreks c001 hack)
    if (!is_valid_cached(dip))  
        return arp_resolver_(pckt);
    
    // Get mac from cache
    mac = cache_[dip].mac_;
  }
  
  /** Attach next-hop mac and ethertype to ethernet header  */  
  Ethernet::header* ethhdr = (Ethernet::header*)pckt->buffer();    
  ethhdr->src = mac_;
  ethhdr->dest.major = mac.major;
  ethhdr->dest.minor = mac.minor;
  ethhdr->type = Ethernet::ETH_IP4;
  
  debug2("<ARP -> physical> Sending packet to %s \n",mac.str().c_str());
  return linklayer_out_(pckt);
}
Пример #2
0
 virtual void
 network_config(IP4::addr addr, IP4::addr nmask, IP4::addr router, IP4::addr dns) override
 {
   INFO("Inet4", "Reconfiguring network. New IP: %s", addr.str().c_str());
   this->ip4_addr_  = addr;
   this->netmask_   = nmask;
   this->router_    = router;
   this->dns_server = dns;
 }
Пример #3
0
void print_error(const std::string& hostname, IP4::addr server, const Error& err) {
  printf("Error occurred when resolving IP address of %s with DNS server %s: %s\n", hostname.c_str(),
        server.to_string().c_str(), err.what());

  if (err.is_icmp()) {
    auto* pd = dynamic_cast<const ICMP_error*>(&err);
    printf("ICMP error type received when resolving %s: %s\n", hostname.c_str(), pd->icmp_type_str().c_str());
    printf("ICMP error code received when resolving %s: %s\n", hostname.c_str(), pd->icmp_code_str().c_str());
  }
}
Пример #4
0
  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);
  }
Пример #5
0
  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);
  }
Пример #6
0
void Arp::cache(IP4::addr& ip, Ethernet::addr& mac){
  
  debug2("Caching IP %s for %s \n",ip.str().c_str(),mac.str().c_str());
  
  auto entry = cache_.find(ip);
  if (entry != cache_.end()){
    
    debug2("Cached entry found: %s recorded @ %llu. Updating timestamp \n",
          entry->second.mac_.str().c_str(), entry->second.t_);
    
    // Update
    entry->second.update();
    
  }else cache_[ip] = mac; // Insert
  
}
Пример #7
0
  void Arp::await_resolution(Packet_ptr pckt, IP4::addr next_hop) {
    auto queue =  waiting_packets_.find(next_hop);
    PRINT("<ARP await> Waiting for resolution of %s\n", next_hop.str().c_str());
    if (queue != waiting_packets_.end()) {
      PRINT("\t * Packets already queueing for this IP\n");
      queue->second.pckt->chain(std::move(pckt));
    } else {
      PRINT("\t *This is the first packet going to that IP\n");
      waiting_packets_.emplace(std::make_pair(next_hop, Queue_entry{std::move(pckt)}));

      // Try resolution immediately
      arp_resolver_(next_hop);

      // Retry later
      resolve_timer_.start(1s);
    }
  }
Пример #8
0
  void Arp::cache(IP4::addr ip, MAC::Addr mac) {
    PRINT("<Arp> Caching IP %s for %s\n", ip.str().c_str(), mac.str().c_str());

    auto entry = cache_.find(ip);

    if (entry != cache_.end()) {
      PRINT("Cached entry found: %s recorded @ %llu. Updating timestamp\n",
             entry->second.mac().str().c_str(), entry->second.timestamp());

      if (entry->second.mac() != mac) {
        cache_.erase(entry);
        cache_[ip] = mac;
      } else {
        entry->second.update();
      }

    } else {
      cache_[ip] = mac; // Insert
      if (UNLIKELY(not flush_timer_.is_running())) {
        flush_timer_.start(flush_interval_);
      }
    }
  }
Пример #9
0
  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));
  }
Пример #10
0
void print_success(const std::string& hostname, IP4::addr server, IP4::addr res) {
  printf("Resolved IP address of %s with DNS server %s: %s\n", hostname.c_str(),
          server.to_string().c_str(), res.to_string().c_str());
}