Common functions

Headers in include/common, in the global namespace.

bypass.h

Functions

bool parse_bypass(const std::string &text, const std::string &overlay_cidr, std::vector<BypassRule> &rules, const char *tag)

Parse the text of a bypass file.

Every line must parse for the call to succeed; the first bad line is reported on stderr with its number. A route prefix must not be 0.0.0.0/0 (that would undo the default route through the TUN) and must not overlap the overlay prefix (that would take the overlay off the TUN).

Parameters:
  • text – The whole file.

  • overlay_cidr – The overlay prefix, a.b.c.d/n.

  • rules – Receives the rules, in file order, on success.

  • tag – Log prefix such as “[Agent]”.

Returns:

true when every line parsed.

bool load_bypass_file(const std::string &path, const std::string &overlay_cidr, std::vector<BypassRule> &rules, const char *tag)

Read and parse a bypass file.

A file that cannot be opened is an error, so a wrong path cannot silently leave a machine without its exceptions.

struct BypassRule
#include <bypass.h>

The bypass file of an agent (VNET_BYPASS_FILE): what stays on the physical network while the agent is joined.

Blank lines and lines starting with ‘#’ are ignored. Three kinds of lines:

*   route a.b.c.d/n
*     The prefix keeps going through the physical gateway instead of the
*     TUN, and under lockdown it is allowed in both directions on every
*     port. A bare address is a /32.
*
*   out <iptables arguments>
*   in  <iptables arguments>
*     A rule appended to the lockdown chain VNET_OUT or VNET_IN, before
*     the final DROP, exactly as written: "in -p tcp -s 10.20.0.0/16
*     --dport 22443 -j ACCEPT". The arguments are split on whitespace and
*     handed to iptables without a shell. Without lockdown they do
*     nothing.
*
*   out6 <ip6tables arguments>
*   in6  <ip6tables arguments>
*     The same for IPv6, which lockdown otherwise blocks entirely.
*

Public Types

enum Kind

Values:

enumerator ROUTE
enumerator IN
enumerator OUT
enumerator IN6
enumerator OUT6

Public Members

Kind kind
std::string cidr

ROUTE: the prefix as written, normalized to a.b.c.d/n.

uint32_t addr = 0

ROUTE: the prefix in network order and its length.

int prefix = 0
std::vector<std::string> args

IN, OUT, IN6, OUT6: the iptables arguments.

config.h

struct MachineConfig
#include <config.h>

Generic machine configuration (IP + port).

Public Members

std::string ip

The IP address of the conductor.

uint16_t port

The port number of the conductor.

socket_utils.h

Functions

int connect_to(const MachineConfig &mc)

Connect to another machine using MachineConfig (blocking).

Returns:

socket fd on success, -1 on failure.

int connect_start(const std::string &host, uint16_t port)

Start a non-blocking connect to host:port (IPv4; host may be a name).

The connect may still be in progress when this returns; NetQueue::put_sck_connecting finishes it.

Returns:

the socket fd, or -1 when the name does not resolve or the connect fails at once.

uint32_t resolve_ipv4(const std::string &host)

Resolve an IPv4 address or host name to an address in network order; 0 when it does not resolve.

bool set_nonblocking(int fd)

Set a file descriptor to non-blocking mode.

Returns:

true on success.

bool set_blocking(int fd)

Clear O_NONBLOCK so a TLS handshake can run to completion.

bool set_socket_timeout(int fd, int ms)

Bound each blocking read and write on fd to ms milliseconds; 0 removes the bound.

Used around blocking TLS handshakes so a silent peer cannot hold an event loop.

Returns:

true on success.

bool read_n_bytes(int sock, void *buffer, size_t n, struct ssl_st *ssl = nullptr)

Read exactly n bytes from a socket (blocking).

ssl, when set, reads through that finished TLS session.

bool write_n_bytes(int sock, const void *buffer, size_t n, struct ssl_st *ssl = nullptr)

Write exactly n bytes to a socket.

Handles EAGAIN for non-blocking fds via retry. ssl, when set, writes through that finished TLS session.

bool send_protobuf_packet(int sock, vnet::protocol::PacketType type, const google::protobuf::Message &msg, struct ssl_st *ssl = nullptr)

Send a protobuf message with the 6-byte packet header.

Wire format: [4-byte payload_size (network order)] [2-byte packet_type (network order)] [protobuf payload bytes]

payload_size = sizeof(packet_type) + protobuf_size but we store it as just protobuf_size since the header struct stores both fields and NetQueue reads header first.

IMPORTANT: payload_size in the header is the number of bytes AFTER the 6-byte header, matching NetQueue::process().

bool read_protobuf_packet(int sock, vnet::protocol::PacketType expected_type, google::protobuf::Message &msg, struct ssl_st *ssl = nullptr)

Read a protobuf message with the 6-byte packet header (blocking).

Reads the full header, skips heartbeats, verifies the packet type, then reads and parses the protobuf payload.

Parameters:
  • sock – The connected socket.

  • expected_type – The type the packet must have; any other type makes the call fail.

  • msg – Receives the parsed payload.

  • ssl – The TLS session of the socket, or nullptr.

Returns:

true when a packet of expected_type was read and parsed.

bool read_raw_packet(int sock, vnet::protocol::PacketType &type, std::vector<char> &buffer)

Read a packet header and payload, returning the type.

Useful when you don’t know the packet type in advance.

Parameters:
  • sock – The connected socket.

  • type – Receives the packet type.

  • buffer – Receives the payload bytes; its size is the payload size.

Returns:

true on success.

bool send_heartbeat(int sock)

Send a heartbeat (header-only, zero-length payload).

std::string ipv4_to_string(uint32_t ipv4)

Convert a network-order uint32_t IPv4 to string.

uint32_t string_to_ipv4(const std::string &ip)

Convert an IPv4 string to network-order uint32_t.

bool read_default_route(std::string &iface, uint32_t &gateway_nbo)

Read the IPv4 default route from /proc/net/route.

Parameters:
  • iface – Receives the outbound interface name.

  • gateway_nbo – Receives the gateway address in network order.

Returns:

true when a default route exists.

sysutil.h

Functions

bool run_program(const std::vector<std::string> &argv, const char *tag, bool quiet = false)

Run a program with the given argument vector and wait for it.

The program is found through PATH; no shell is involved, so the arguments are never interpreted.

Parameters:
  • argv – Program name followed by its arguments.

  • tag – Log prefix such as “[Agent]” for the failure message.

  • quiet – Discard the program’s output and log nothing on failure; for probes whose failure is an expected answer.

Returns:

true when the program exited with status 0.

bool env_int(const char *name, long min, long max, long &value)

Read an integer setting from the environment.

Unset: value is left unchanged and true is returned. Set and within [min, max]: value is updated and true is returned. Otherwise an error naming the variable is printed and false is returned.

std::string env_or(const char *name, const std::string &def)

Read a string setting from the environment, or def when unset.

bool valid_name(const std::string &name, size_t max_len)

A machine name: 1 to max_len characters from [A-Za-z0-9_-].

Agent names are limited to 10 characters, since “vnet-” plus the name must fit the 15-character interface name limit.

bool parse_cidr(const std::string &text, uint32_t &addr, int &prefix)

Parse “a.b.c.d/n”.

addr is returned in network order, prefix in [0, 32]. A bare address is accepted as /32.

std::string load_auth_key(const char *argv_key, const char *tag)

The shared secret of this machine: VNET_AUTH_KEY, or the first line of the file named by VNET_AUTH_KEY_FILE, or the command-line fallback.

Empty when none is available.

Variables

const size_t AGENT_NAME_MAX = 10
const size_t SWITCH_NAME_MAX = 32

tun.h

Functions

int tun_open(const std::string &name, uint32_t ipv4, uint8_t prefix_len = 24)

Open a TUN device and configure it.

Creates a TUN interface with the given name, assigns the given IPv4 address with a /24 prefix, and brings the interface up.

Parameters:
  • name – Interface name (e.g. “vnet0”). Max 15 chars.

  • ipv4 – Virtual IPv4 address in network order.

  • prefix_len – Subnet prefix length (default 24 = /24).

Returns:

File descriptor for the TUN device, or -1 on failure.

void tun_close(int fd, const std::string &name)

Bring the interface down and close the TUN device.

Pass fd < 0 when something else owns and closes the descriptor.