---
title: llarp/net/ip_packet.hpp

---

# llarp/net/ip_packet.hpp



## Namespaces

| Name           |
| -------------- |
| **[llarp](Namespaces/namespacellarp.md)** <br>[crypto.hpp] |
| **[llarp::net](Namespaces/namespacellarp_1_1net.md)**  |

## Classes

|                | Name           |
| -------------- | -------------- |
| struct | **[llarp::net::ip_header_le](Classes/structllarp_1_1net_1_1ip__header__le.md)**  |
| struct | **[llarp::net::ip_header_be](Classes/structllarp_1_1net_1_1ip__header__be.md)**  |
| struct | **[llarp::net::ipv6_header_preamble_le](Classes/structllarp_1_1net_1_1ipv6__header__preamble__le.md)**  |
| struct | **[llarp::net::ipv6_header_preamble_be](Classes/structllarp_1_1net_1_1ipv6__header__preamble__be.md)**  |
| struct | **[llarp::net::ipv6_header](Classes/structllarp_1_1net_1_1ipv6__header.md)**  |
| struct | **[llarp::net::IPPacket](Classes/structllarp_1_1net_1_1IPPacket.md)** <br>an Packet  |
| struct | **[llarp::net::IPPacket::CompareSize](Classes/structllarp_1_1net_1_1IPPacket_1_1CompareSize.md)**  |
| struct | **[llarp::net::IPPacket::CompareOrder](Classes/structllarp_1_1net_1_1IPPacket_1_1CompareOrder.md)**  |




## Source code

```cpp
#pragma once

#include <oxenc/endian.h>
#include <llarp/ev/ev.hpp>
#include "net.hpp"
#include <llarp/util/buffer.hpp>
#include <llarp/util/time.hpp>
#include <memory>
#include <llarp/service/protocol_type.hpp>
#include <utility>
#include <vector>

namespace llarp::net
{
  struct ip_header_le
  {
    uint8_t ihl : 4;
    uint8_t version : 4;
    uint8_t tos;
    uint16_t tot_len;
    uint16_t id;
    uint16_t frag_off;
    uint8_t ttl;
    uint8_t protocol;
    uint16_t check;
    uint32_t saddr;
    uint32_t daddr;
  };

  struct ip_header_be
  {
    uint8_t version : 4;
    uint8_t ihl : 4;
    uint8_t tos;
    uint16_t tot_len;
    uint16_t id;
    uint16_t frag_off;
    uint8_t ttl;
    uint8_t protocol;
    uint16_t check;
    uint32_t saddr;
    uint32_t daddr;
  };

  using ip_header = std::conditional_t<oxenc::little_endian, ip_header_le, ip_header_be>;

  static_assert(sizeof(ip_header) == 20);

  struct ipv6_header_preamble_le
  {
    unsigned char pad_small : 4;
    unsigned char version : 4;
    uint8_t pad[3];
  };

  struct ipv6_header_preamble_be
  {
    unsigned char version : 4;
    unsigned char pad_small : 4;
    uint8_t pad[3];
  };

  using ipv6_header_preamble =
      std::conditional_t<oxenc::little_endian, ipv6_header_preamble_le, ipv6_header_preamble_be>;

  static_assert(sizeof(ipv6_header_preamble) == 4);

  struct ipv6_header
  {
    union
    {
      ipv6_header_preamble preamble;
      uint32_t flowlabel;
    } preamble;

    uint16_t payload_len;
    uint8_t protocol;
    uint8_t hoplimit;
    in6_addr srcaddr;
    in6_addr dstaddr;
    llarp::nuint32_t
    FlowLabel() const;

    void
    FlowLabel(llarp::nuint32_t label);
  };

  static_assert(sizeof(ipv6_header) == 40);

  enum class IPProtocol : uint8_t
  {
    ICMP = 0x01,
    IGMP = 0x02,
    IPIP = 0x04,
    TCP = 0x06,
    UDP = 0x11,
    GRE = 0x2F,
    ICMP6 = 0x3A,
    OSFP = 0x59,
    PGM = 0x71,
  };

  std::string
  IPProtocolName(IPProtocol proto);

  IPProtocol
  ParseIPProtocol(std::string data);

  struct IPPacket
  {
    static constexpr size_t _max_size = 1500;
    llarp_time_t timestamp;
    std::vector<byte_t> _buf;

   public:
    IPPacket() : IPPacket{size_t{}}
    {}
    explicit IPPacket(size_t sz);
    explicit IPPacket(byte_view_t);
    IPPacket(std::vector<byte_t>&&);

    ~IPPacket() = default;

    static constexpr size_t MaxSize = _max_size;
    static constexpr size_t MinSize = 20;

    [[deprecated("deprecated because of llarp_buffer_t")]] static IPPacket
    UDP(nuint32_t srcaddr,
        nuint16_t srcport,
        nuint32_t dstaddr,
        nuint16_t dstport,
        const llarp_buffer_t& data)
    {
      return make_udp(srcaddr, srcport, dstaddr, dstport, data.copy());
    }

    static IPPacket
    make_udp(
        net::ipaddr_t srcaddr,
        net::port_t srcport,
        net::ipaddr_t dstaddr,
        net::port_t dstport,
        std::vector<byte_t> udp_body);

    static inline IPPacket
    make_udp(SockAddr src, SockAddr dst, std::variant<OwnedBuffer, std::vector<byte_t>> udp_body)
    {
      if (auto* vec = std::get_if<std::vector<byte_t>>(&udp_body))
        return make_udp(src.getIP(), src.port(), dst.getIP(), dst.port(), std::move(*vec));
      else if (auto* buf = std::get_if<OwnedBuffer>(&udp_body))
        return make_udp(src, dst, buf->copy());
      else
        return net::IPPacket{size_t{}};
    }

    [[deprecated("deprecated because of llarp_buffer_t")]] inline bool
    Load(const llarp_buffer_t& buf)
    {
      _buf = buf.copy();
      if (size() >= MinSize)
        return true;
      _buf.resize(0);
      return false;
    }

    [[deprecated("deprecated because of llarp_buffer_t")]] inline llarp_buffer_t
    ConstBuffer() const
    {
      return llarp_buffer_t{_buf};
    }

    inline std::vector<byte_t>
    steal()
    {
      std::vector<byte_t> buf;
      buf.resize(0);
      std::swap(_buf, buf);
      return buf;
    }

    inline byte_t*
    data()
    {
      return _buf.data();
    }

    inline const byte_t*
    data() const
    {
      return _buf.data();
    }

    constexpr size_t
    capacity() const
    {
      return _max_size;
    }

    inline size_t
    size() const
    {
      return _buf.size();
    }

    inline bool
    empty() const
    {
      return _buf.empty();
    }

    byte_view_t
    view() const;

    struct CompareSize
    {
      bool
      operator()(const IPPacket& left, const IPPacket& right)
      {
        return left.size() < right.size();
      }
    };

    struct CompareOrder
    {
      bool
      operator()(const IPPacket& left, const IPPacket& right)
      {
        return left.timestamp < right.timestamp;
      }
    };

    inline ip_header*
    Header()
    {
      return reinterpret_cast<ip_header*>(data());
    }

    inline const ip_header*
    Header() const
    {
      return reinterpret_cast<const ip_header*>(data());
    }

    inline ipv6_header*
    HeaderV6()
    {
      return reinterpret_cast<ipv6_header*>(data());
    }

    inline const ipv6_header*
    HeaderV6() const
    {
      return reinterpret_cast<const ipv6_header*>(data());
    }

    inline int
    Version() const
    {
      return Header()->version;
    }

    inline byte_t
    protocol() const
    {
      if (IsV4())
        return Header()->protocol;
      else
        return HeaderV6()->protocol;
    }

    inline bool
    IsV4() const
    {
      return Version() == 4;
    }

    inline bool
    IsV6() const
    {
      return Version() == 6;
    }

    inline service::ProtocolType
    ServiceProtocol() const
    {
      if (IsV4())
        return service::ProtocolType::TrafficV4;
      if (IsV6())
        return service::ProtocolType::TrafficV6;

      return service::ProtocolType::Control;
    }

    huint128_t
    srcv6() const;

    huint128_t
    dstv6() const;

    huint32_t
    srcv4() const;

    huint32_t
    dstv4() const;

    huint128_t
    src4to6() const;

    huint128_t
    dst4to6() const;

    huint128_t
    src4to6Lan() const;

    huint128_t
    dst4to6Lan() const;

    SockAddr
    src() const;

    SockAddr
    dst() const;

    std::optional<nuint16_t>
    DstPort() const;

    std::optional<nuint16_t>
    SrcPort() const;

    std::optional<std::pair<const char*, size_t>>
    L4Data() const;

    inline std::optional<OwnedBuffer>
    L4OwnedBuffer() const
    {
      if (auto data = L4Data())
        return OwnedBuffer{reinterpret_cast<const byte_t*>(data->first), data->second};
      return std::nullopt;
    }

    void
    UpdateIPv4Address(nuint32_t src, nuint32_t dst);

    void
    UpdateIPv6Address(
        huint128_t src, huint128_t dst, std::optional<nuint32_t> flowlabel = std::nullopt);

    void
    ZeroAddresses(std::optional<nuint32_t> flowlabel = std::nullopt);

    void
    ZeroSourceAddress(std::optional<nuint32_t> flowlabel = std::nullopt);

    std::optional<IPPacket>
    MakeICMPUnreachable() const;

    std::function<void(net::IPPacket)> reply;

    void
    recompute_checksums();

    static std::vector<byte_t>
    make_icmp(std::vector<byte_t>&& pkt, net::ipaddr_t our_ip, int type, int code);
  };

  uint16_t
  ipchksum(const byte_t* buf, size_t sz, uint32_t sum = 0);

}  // namespace llarp::net
```


-------------------------------

Updated on 2023-03-06 at 20:36:34 +0000
