Example #1
0
  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);
  }
Example #2
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);
  }
Example #3
0
  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));
  }
Example #4
0
  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));
  }
Example #5
0
  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);
  }
Example #6
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);
  }
Example #7
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));
  }