<commit_before>// This file is a part of the IncludeOS unikernel - www.includeos.org
//
// Copyright 2015 Oslo and Akershus University College of Applied Sciences
// and <NAME>
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

// #define DEBUG
#include <net/ip4/icmp4.hpp>

namespace net {

  int ICMPv4::request_id_ = 0;

  ICMPv4::ICMPv4(Stack& inet) :
    inet_{inet}
  {}

  void ICMPv4::receive(Packet_ptr pckt) {
    if ((size_t)pckt->size() < sizeof(IP4::header) + icmp4::Packet::header_size()) // Drop if not a full header
      return;

    auto pckt_ip4 = static_unique_ptr_cast<PacketIP4>(std::move(pckt));
    auto req = icmp4::Packet(std::move(pckt_ip4));
    std::map<Tuple, ICMP_callback>::iterator it;

    switch(req.type()) {
    case (icmp4::Type::ECHO_REPLY):
      debug("<ICMP> PING Reply from %s\n", req.ip().src().str().c_str());
      // Find callback matching the reply
      it = ping_callbacks_.find(std::make_pair(req.id(), req.sequence()));
      if (it != ping_callbacks_.end()) {
        it->second.callback(ICMP_packet{req.id(), req.sequence(), req.ip().src(), req.ip().dst(), req.type(), req.code(),
          req.checksum(), req.payload()});

        // Timers::stop(it->second.timer_id);

        ping_callbacks_.erase(it);
      }
      break;
    case (icmp4::Type::DEST_UNREACHABLE):
      debug("<ICMP> DESTINATION UNREACHABLE from %s\n", req.ip().src().str().c_str());
      // TODO
      // Send to transport layer
      break;
    case (icmp4::Type::REDIRECT):
      debug("<ICMP> REDIRECT from %s\n", req.ip().src().str().c_str());
      // TODO
      // Only sent by gateways. Incoming: Update routing information based on the message
      break;
    case (icmp4::Type::ECHO):
      debug("<ICMP> PING from %s\n", req.ip().src().str().c_str());
      ping_reply(req);
      break;
    case (icmp4::Type::TIME_EXCEEDED):
      debug("<ICMP> TIME EXCEEDED from %s\n", req.ip().src().str().c_str());
      // TODO
      // Send to transport layer
      break;
    case (icmp4::Type::PARAMETER_PROBLEM):
      debug("<ICMP> PARAMETER PROBLEM from %s\n", req.ip().src().str().c_str());
      // TODO
      // Send to transport layer
      break;
    case (icmp4::Type::TIMESTAMP):
      debug("<ICMP> TIMESTAMP from %s\n", req.ip().src().str().c_str());
      // TODO May
      // timestamp_reply(req);
      break;
    case (icmp4::Type::TIMESTAMP_REPLY):
      debug("<ICMP> TIMESTAMP REPLY from %s\n", req.ip().src().str().c_str());
      // TODO May
      break;
    }
  }

  void ICMPv4::destination_unreachable(Packet_ptr pckt, icmp4::code::Dest_unreachable code) {
    if ((size_t)pckt->size() < sizeof(IP4::header) + icmp4::Packet::header_size()) // Drop if not a full header
      return;
    auto pckt_ip4 = static_unique_ptr_cast<PacketIP4>(std::move(pckt));
    auto pckt_icmp4 = icmp4::Packet(std::move(pckt_ip4));
    send_response(pckt_icmp4, icmp4::Type::DEST_UNREACHABLE, (uint8_t) code, pckt_icmp4.header_and_data());
  }

  void ICMPv4::redirect(icmp4::Packet& /* req */, icmp4::code::Redirect /* code */) {
    // send_response(req, icmp4::Type::REDIRECT, (uint8_t) code, icmp4::Packet::Span(, ));
  }

  void ICMPv4::time_exceeded(icmp4::Packet& /* req */, icmp4::code::Time_exceeded /* code */) {
    // send_response(req, icmp4::Type::TIME_EXCEEDED, (uint8_t) code, icmp4::Packet::Span(, ));
  }

  void ICMPv4::parameter_problem(icmp4::Packet& /* req */) {
    // send_response(req, icmp4::Type::PARAMETER_PROBLEM, 0, icmp4::Packet::Span(, ));
  }

  void ICMPv4::timestamp_request(IP4::addr /* ip */) {
    // TODO
    // send_request(ip, icmp4::Type::TIMESTAMP, 0, icmp4::Packet::Span(, ));
  }

  void ICMPv4::timestamp_reply(icmp4::Packet& /* req */) {
    // TODO
    // send_response(req, icmp4::Type::TIMESTAMP_REPLY, 0, icmp4::Packet::Span(, ));
  }

  void ICMPv4::ping(IP4::addr ip) {
    send_request(ip, icmp4::Type::ECHO, 0, icmp4::Packet::Span(includeos_payload_, 48));
  }
  void ICMPv4::ping(IP4::addr ip, icmp_func callback) {
    send_request(ip, icmp4::Type::ECHO, 0, icmp4::Packet::Span(includeos_payload_, 48), callback);
  }

  void ICMPv4::ping_reply(icmp4::Packet& req) {
    send_response(req, icmp4::Type::ECHO_REPLY, 0, req.payload());
  }

  void ICMPv4::send_request(IP4::addr dest_ip, icmp4::Type type, uint8_t code, icmp4::Packet::Span payload,
    icmp_func callback, uint16_t sequence) {<commit_msg>ICMP4 ping reply: Calling new method send_response_with_id when responding to incoming ping requests<commit_after>// This file is a part of the IncludeOS unikernel - www.includeos.org
//
// Copyright 2015 Oslo and Akershus University College of Applied Sciences
// and <NAME>
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

// #define DEBUG
#include <net/ip4/icmp4.hpp>

namespace net {

  int ICMPv4::request_id_ = 0;

  ICMPv4::ICMPv4(Stack& inet) :
    inet_{inet}
  {}

  void ICMPv4::receive(Packet_ptr pckt) {
    if ((size_t)pckt->size() < sizeof(IP4::header) + icmp4::Packet::header_size()) // Drop if not a full header
      return;

    auto pckt_ip4 = static_unique_ptr_cast<PacketIP4>(std::move(pckt));
    auto req = icmp4::Packet(std::move(pckt_ip4));
    std::map<Tuple, ICMP_callback>::iterator it;

    switch(req.type()) {
    case (icmp4::Type::ECHO_REPLY):
      debug("<ICMP> PING Reply from %s\n", req.ip().src().str().c_str());
      // Find callback matching the reply
      it = ping_callbacks_.find(std::make_pair(req.id(), req.sequence()));
      if (it != ping_callbacks_.end()) {
        it->second.callback(ICMP_packet{req.id(), req.sequence(), req.ip().src(), req.ip().dst(), req.type(), req.code(),
          req.checksum(), req.payload()});

        // Timers::stop(it->second.timer_id);

        ping_callbacks_.erase(it);
      }
      break;
    case (icmp4::Type::DEST_UNREACHABLE):
      debug("<ICMP> DESTINATION UNREACHABLE from %s\n", req.ip().src().str().c_str());
      // TODO
      // Send to transport layer
      break;
    case (icmp4::Type::REDIRECT):
      debug("<ICMP> REDIRECT from %s\n", req.ip().src().str().c_str());
      // TODO
      // Only sent by gateways. Incoming: Update routing information based on the message
      break;
    case (icmp4::Type::ECHO):
      printf("<ICMP> PING from %s\n", req.ip().src().str().c_str());
      ping_reply(req);
      break;
    case (icmp4::Type::TIME_EXCEEDED):
      debug("<ICMP> TIME EXCEEDED from %s\n", req.ip().src().str().c_str());
      // TODO
      // Send to transport layer
      break;
    case (icmp4::Type::PARAMETER_PROBLEM):
      debug("<ICMP> PARAMETER PROBLEM from %s\n", req.ip().src().str().c_str());
      // TODO
      // Send to transport layer
      break;
    case (icmp4::Type::TIMESTAMP):
      debug("<ICMP> TIMESTAMP from %s\n", req.ip().src().str().c_str());
      // TODO May
      // timestamp_reply(req);
      break;
    case (icmp4::Type::TIMESTAMP_REPLY):
      debug("<ICMP> TIMESTAMP REPLY from %s\n", req.ip().src().str().c_str());
      // TODO May
      break;
    }
  }

  void ICMPv4::destination_unreachable(Packet_ptr pckt, icmp4::code::Dest_unreachable code) {
    if ((size_t)pckt->size() < sizeof(IP4::header) + icmp4::Packet::header_size()) // Drop if not a full header
      return;
    auto pckt_ip4 = static_unique_ptr_cast<PacketIP4>(std::move(pckt));
    auto pckt_icmp4 = icmp4::Packet(std::move(pckt_ip4));
    send_response(pckt_icmp4, icmp4::Type::DEST_UNREACHABLE, (uint8_t) code, pckt_icmp4.header_and_data());
  }

  void ICMPv4::redirect(icmp4::Packet& /* req */, icmp4::code::Redirect /* code */) {
    // send_response(req, icmp4::Type::REDIRECT, (uint8_t) code, icmp4::Packet::Span(, ));
  }

  void ICMPv4::time_exceeded(icmp4::Packet& /* req */, icmp4::code::Time_exceeded /* code */) {
    // send_response(req, icmp4::Type::TIME_EXCEEDED, (uint8_t) code, icmp4::Packet::Span(, ));
  }

  void ICMPv4::parameter_problem(icmp4::Packet& /* req */) {
    // send_response(req, icmp4::Type::PARAMETER_PROBLEM, 0, icmp4::Packet::Span(, ));
  }

  void ICMPv4::timestamp_request(IP4::addr /* ip */) {
    // TODO
    // send_request(ip, icmp4::Type::TIMESTAMP, 0, icmp4::Packet::Span(, ));
  }

  void ICMPv4::timestamp_reply(icmp4::Packet& /* req */) {
    // TODO
    // send_response(req, icmp4::Type::TIMESTAMP_REPLY, 0, icmp4::Packet::Span(, ));
  }

  void ICMPv4::ping(IP4::addr ip) {
    send_request(ip, icmp4::Type::ECHO, 0, icmp4::Packet::Span(includeos_payload_, 48));
  }
  void ICMPv4::ping(IP4::addr ip, icmp_func callback) {
    send_request(ip, icmp4::Type::ECHO, 0, icmp4::Packet::Span(includeos_payload_, 48), callback);
  }

  void ICMPv4::ping_reply(icmp4::Packet& req) {
    send_response_with_id(req, icmp4::Type::ECHO_REPLY, 0, req.payload());
  }

  void ICMPv4::send_request(IP4::addr dest_ip, icmp4::Type type, uint8_t code, icmp4::Packet::Span payload,
    icmp_func callback, uint16_t sequence) {
{'fraction_non_alphanumeric': 0.17248687928946305, 'fraction_numerical': 0.0190754945498587, 'mean_word_length': 3.6066945606694563, 'pattern_counts': {'":': 0, '<': 33, '<?xml version=': 0, '>': 37, 'https://': 0, 'lorem ipsum': 0, 'www.': 4, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '3789055', 'n_tokens_mistral': 3635, 'n_tokens_neox': 3554, 'n_words': 752}