Esempio n. 1
0
Result<basic::Classifier> decode<basic::Classifier>(
    const Netlink<struct rtnl_cls>& cls)
{
  if (rtnl_tc_get_kind(TC_CAST(cls.get())) != string("basic")) {
    return None();
  }

  return basic::Classifier(rtnl_cls_get_protocol(cls.get()));
}
Esempio n. 2
0
Result<ingress::Discipline> decode<ingress::Discipline>(
    const Netlink<struct rtnl_qdisc>& qdisc)
{
  if (rtnl_tc_get_kind(TC_CAST(qdisc.get())) != string("ingress") ||
      rtnl_tc_get_parent(TC_CAST(qdisc.get())) != INGRESS_ROOT.get() ||
      rtnl_tc_get_handle(TC_CAST(qdisc.get())) != ingress::HANDLE.get()) {
    return None();
  }

  return ingress::Discipline();
}
Esempio n. 3
0
Try<Nothing> encode<basic::Classifier>(
    const Netlink<struct rtnl_cls>& cls,
    const basic::Classifier& classifier)
{
  rtnl_cls_set_protocol(cls.get(), classifier.protocol());

  int error = rtnl_tc_set_kind(TC_CAST(cls.get()), "basic");
  if (error != 0) {
    return Error(
        "Failed to set the kind of the classifier: " +
        string(nl_geterror(error)));
  }

  return Nothing();
}
Esempio n. 4
0
Try<Nothing> encode<ingress::Discipline>(
    const Netlink<struct rtnl_qdisc>& qdisc,
    const ingress::Discipline& discipline)
{
  int error = rtnl_tc_set_kind(TC_CAST(qdisc.get()), "ingress");
  if (error != 0) {
    return Error(
        "Failed to set the kind of the queueing discipline: " +
        string(nl_geterror(error)));
  }

  rtnl_tc_set_parent(TC_CAST(qdisc.get()), INGRESS_ROOT.get());
  rtnl_tc_set_handle(TC_CAST(qdisc.get()), ingress::HANDLE.get());

  return Nothing();
}
Esempio n. 5
0
Result<htb::Config> decode<htb::Config>(
    const Netlink<struct rtnl_qdisc>& qdisc)
{
  if (rtnl_tc_get_kind(TC_CAST(qdisc.get())) != htb::KIND) {
    return None();
  }

  return htb::Config();
}
Esempio n. 6
0
Try<Nothing> encode<icmp::Classifier>(
    const Netlink<struct rtnl_cls>& cls,
    const icmp::Classifier& classifier)
{
  // ICMP packets are one type of IP packets.
  rtnl_cls_set_protocol(cls.get(), ETH_P_IP);

  int error = rtnl_tc_set_kind(TC_CAST(cls.get()), "u32");
  if (error != 0) {
    return Error(
        "Failed to set the kind of the classifier: " +
        string(nl_geterror(error)));
  }

  // To avoid confusion, we only use u32 selectors which are used to
  // match arbitrary 32-bit content in a packet.

  // Format of an IP packet at offset 8. The IP protocol field is at
  // offset 9. ICMP has protocol = 1.
  //        +--------+--------+--------+--------+
  //        |   X    | Proto. |   X    |   X    |
  //        +--------+--------+--------+--------+
  // Offset:    8        9        10       11
  uint32_t protocol = 0x00010000;
  uint32_t mask = 0x00ff0000; // Ignore offset 8, 10, 11.

  // To match ICMP packets (protocol = 1).
  error = rtnl_u32_add_key(
      cls.get(),
      htonl(protocol),
      htonl(mask),
      8, // Offset from which to start matching.
      0);

  if (error != 0) {
    return Error(
        "Failed to add selector for IP protocol: " +
        string(nl_geterror(error)));
  }

  if (classifier.destinationIP.isSome()) {
    Try<struct in_addr> in = classifier.destinationIP.get().in();
    if (in.isError()) {
      return Error("Destination IP is not an IPv4 address");
    }

    // To match those IP packets that have the given destination IP.
    error = rtnl_u32_add_key(
        cls.get(),
        in.get().s_addr,
        htonl(0xffffffff),
        16, // Offset from which to start matching.
        0);

    if (error != 0) {
      return Error(
          "Failed to add selector for destination IP address: " +
           string(nl_geterror(error)));
    }
  }

  return Nothing();
}
Esempio n. 7
0
Result<icmp::Classifier> decode<icmp::Classifier>(
    const Netlink<struct rtnl_cls>& cls)
{
  if (rtnl_cls_get_protocol(cls.get()) != ETH_P_IP ||
      rtnl_tc_get_kind(TC_CAST(cls.get())) != string("u32")) {
    return None();
  }

  // Raw values.
  Option<uint32_t> protocol;
  Option<net::IP> destinationIP;

  // There are at most 0xff keys.
  for (uint8_t i = 0; i <= 0xff; i++) {
    uint32_t value;
    uint32_t mask;
    int offset;
    int offsetmask;

    // Decode a selector from the libnl filter 'cls'.
    int error = rtnl_u32_get_key(
        cls.get(),
        i,
        &value,
        &mask,
        &offset,
        &offsetmask);

    if (error != 0) {
      if (error == -NLE_INVAL) {
        // This is the case where cls does not have a u32 selector. In
        // that case, we just return None.
        return None();
      } else if (error == -NLE_RANGE) {
        break;
      } else {
        return Error(
            "Failed to decode a u32 selector: " +
            string(nl_geterror(error)));
      }
    }

    // The function "rtnl_u32_get_key" sets value and mask in network
    // order. Convert them back to host order.
    value = ntohl(value);
    mask = ntohl(mask);

    // IP protocol field.
    if (offset == 8 && value == 0x00010000 && mask == 0x00ff0000) {
      protocol = value;
    }

    // Destination IP address.
    if (offset == 16 && mask == 0xffffffff) {
      destinationIP = net::IP(value);
    }
  }

  if (protocol.isSome()) {
    return icmp::Classifier(destinationIP);
  }

  return None();
}