valis / Reference / API reference

Network - API reference

Exported surface for the net subsystem. Part of the API reference.

Package valis/src/net/conditions

Conditions

dial-connect-error

Parent of the ways a resolved address did not yield a connection. ADDRESS is always populated on this branch, which is what separates it from the resolution branch above.

dial-connection-refused

Signalled when the peer answered and declined. A refusal is reported the moment it arrives rather than after a deadline elapses: a host that is down and a path that swallows packets want opposite operator responses, and a refusal reported as a timeout erases the difference.

dial-error

Root of every way an outbound connection can fail.

DESTINATION is the name or address literal exactly as the caller gave it, never a canonicalised or resolved form, so an operator reading a report sees the value they configured. ADDRESS is the address actually attempted and is NIL when the failure happened before any address existed, which is itself the distinction between a policy or resolution failure and a connection failure. BRANCH names the half that broke. CAUSE carries the underlying condition or errno.

dial-host-unreachable

Signalled when the network reported the address as unreachable. Distinct from a refusal, which proves something was listening at the far end, and from a deadline, which proves nothing at all.

dial-name-error

Parent of the ways a destination name did not become an address. A caller that only needs to know 'the name half failed' handles this one class; a caller that must respond differently to a missing name than to a misconfigured node handles the subclasses.

dial-name-not-found

Signalled when the name genuinely has no record. The fault is in the destination or in what configured it, not in this node.

dial-no-address-family

Signalled when the resolver refused because this network namespace holds no configured address of the requested family.

The operating system reports this identically to a name that does not exist, and it means the opposite. Keeping the two apart is the reason this hierarchy is worth its weight: read as 'no such name' it sends an operator to the zone data, when the fault is that this node was confined without an address of that family and cannot reach anything by that family at all.

dial-not-permitted

Signalled when the capability check refuses a dial.

Nothing observable leaves this process on this path: no query is emitted, no address is learned, no descriptor is created. That is the property the whole seam is built to have, and this condition is where it becomes visible. A refused dial that had already resolved the name would have published the destination to whoever watches this node's queries while still reporting a refusal to the caller, which is worse than no refusal at all.

dial-outside-the-seam

Signalled when code opens an outbound connection without passing through the seam. CALLER names the offending call site so the report identifies what to migrate rather than only that something needs migrating.

Defined alongside the rest of the vocabulary so the failure set is complete in one file and a reader learns the whole shape at once. The runtime check that signals it is built separately, and it refuses rather than resolving: a check that resolved on a caller's behalf and handed back an address would rebuild, one layer lower, exactly the resolve-then-connect-elsewhere path this seam removes.

dial-resolver-unreachable

Signalled when the configured nameserver could not be reached at all, so nothing was learned about the name either way. The fault is in this node's own configuration. This is never inferred from a name lookup failing: a failed lookup is ambiguous, and guessing between the branches here would lose the distinction the two classes above exist to preserve.

dial-source-address-unbound

Signalled when the outbound socket could not take the egress source address the caller required, or took a different one.

REQUESTED and BOUND are both carried because the two failures are not the same: an address that cannot be assigned means this node does not hold it, while a different address bound means the routing table chose, which is exactly the delegation an explicit source exists to prevent. A peer that authorises by source address drops traffic from anywhere else without replying, so this failure is otherwise silent.

dial-timed-out

Signalled when the connection deadline elapsed with no answer of any kind. This is the one connect outcome that carries no information about the peer, so it is kept apart from the two that do.

Generic functions

dial-error-address

(dial-error-address condition)

Undocumented: this exported symbol needs a docstring.

dial-error-branch

(dial-error-branch condition)

Undocumented: this exported symbol needs a docstring.

dial-error-cause

(dial-error-cause condition)

Undocumented: this exported symbol needs a docstring.

dial-error-destination

(dial-error-destination condition)

Undocumented: this exported symbol needs a docstring.

dial-error-family

(dial-error-family condition)

Undocumented: this exported symbol needs a docstring.

dial-error-port

(dial-error-port condition)

Undocumented: this exported symbol needs a docstring.

dial-outside-the-seam-caller

(dial-outside-the-seam-caller condition)

Undocumented: this exported symbol needs a docstring.

dial-source-address-unbound-bound

(dial-source-address-unbound-bound condition)

Undocumented: this exported symbol needs a docstring.

dial-source-address-unbound-requested

(dial-source-address-unbound-requested condition)

Undocumented: this exported symbol needs a docstring.

Package valis/src/net/dial

Functions

dial

(dial grant destination port &key (type :stream) (family :internet) source (deadline *dial-deadline*))

Open a connection to DESTINATION at PORT under GRANT.

Answers three values: an integer file descriptor, the peer that answered as text, and its address family.

GRANT is required and positional. Calling without one is a program error at the call site rather than a dial that happens to be unchecked, which is the property that makes this the only door.

The first value is pinned as an integer descriptor and is meant to stay one. A consumer that wraps the connection in transport security takes an integer descriptor or a stream, and accepts neither of the socket objects the socket libraries hand out, so answering an object here would push a conversion into every caller and the mistake would only be discovered at the far end of the stack.

The caller owns the descriptor and its close from the moment this returns. Nothing here holds a reference to it, and nothing closes it later.

TYPE :DATAGRAM answers a socket already fixed to the one destination, so the caller sends without naming a recipient. SOURCE names the egress address to leave from, which is bound and proved before the connection is attempted, and a source naming no interface is refused before any socket is opened. DEADLINE bounds each address attempt rather than the dial as a whole.

Variables

*dial-deadline*

Seconds a single address is given to answer before the attempt is abandoned.

Applies per address rather than per dial, so a destination with several addresses can cost this much for each of them. A caller with a tighter budget passes its own; the default is chosen to outlast an ordinary intercontinental round trip and a retransmit, and to be well short of the kernel's own connect timeout, which runs into minutes and is far past the point any caller still wants the answer.

*wildcard-source-addresses*

Source addresses that name no interface. Binding one of these succeeds and leaves the routing table to choose, which is the delegation an explicit source exists to prevent, so they are refused before a socket is opened.

Package valis/src/net/exemptions

Classes

outbound-exemption

One place permitted to reach the network without passing through the seam.

Functions

make-outbound-exemption

(make-outbound-exemption &key ((:path path) nil) ((:caller caller) nil) ((:reason reason) "") ((:disposition disposition) :by-design) ((:escapes escapes) 0))

Undocumented: this exported symbol needs a docstring.

note-outbound-escape

(note-outbound-escape caller)

Count one connection CALLER was let through on, and answer the entry it matched.

outbound-exemption-caller

(outbound-exemption-caller instance)

Undocumented: this exported symbol needs a docstring.

outbound-exemption-callers

(outbound-exemption-callers)

The package-qualified function names permitted to dial outside the seam.

outbound-exemption-disposition

(outbound-exemption-disposition instance)

Undocumented: this exported symbol needs a docstring.

outbound-exemption-escapes

(outbound-exemption-escapes instance)

Undocumented: this exported symbol needs a docstring.

outbound-exemption-p

(outbound-exemption-p object)

Undocumented: this exported symbol needs a docstring.

outbound-exemption-path

(outbound-exemption-path instance)

Undocumented: this exported symbol needs a docstring.

outbound-exemption-paths

(outbound-exemption-paths)

The repo-relative paths the outbound sweep does not read.

outbound-exemption-reason

(outbound-exemption-reason instance)

Undocumented: this exported symbol needs a docstring.

outbound-exemptions-by-disposition

(outbound-exemptions-by-disposition)

The registry as an alist of disposition to entries, unmigrated debt first.

outbound-exemptions-with-disposition

(outbound-exemptions-with-disposition disposition)

The entries carrying DISPOSITION, in registry order.

report-outbound-exemptions

(report-outbound-exemptions &optional (stream *standard-output*))

Print what still reaches the network outside the seam, unmigrated first, and answer the registry grouped by disposition.

reset-outbound-escape-counts

(reset-outbound-escape-counts)

Clear every entry's escape count, so a later count is read against a known start.

Variables

*outbound-exemptions*

Every place permitted to reach the network outside the seam, with its reason.

*unswept-tree*

The one tracked tree of Lisp sources the outbound sweep deliberately skips.

Package valis/src/net/http

Conditions

redirect-limit-exceeded

Signalled when a chain of redirects outruns its bound.

A redirect chain is destination changes chosen by the responses rather than by the caller, so an unbounded walk is a loop somebody else controls. Abandoning the chain is the only answer that ends.

unsupported-request-scheme

Signalled for a URL whose scheme is neither http nor https.

Refused rather than guessed at. A scheme nobody wrote a meaning for would otherwise take the port of one that was written, and reach a destination the caller did not name.

Generic functions

redirect-limit-exceeded-hops

(redirect-limit-exceeded-hops condition)

Undocumented: this exported symbol needs a docstring.

redirect-limit-exceeded-url

(redirect-limit-exceeded-url condition)

Undocumented: this exported symbol needs a docstring.

unsupported-request-scheme-scheme

(unsupported-request-scheme-scheme condition)

Undocumented: this exported symbol needs a docstring.

unsupported-request-scheme-url

(unsupported-request-scheme-url condition)

Undocumented: this exported symbol needs a docstring.

Functions

seam-http-request

(seam-http-request url &rest keys)

Fetch URL through the outbound seam and answer (values body status headers).

The three answers are what a certificate client reads: the status and the headers carry its replay nonce and its problem documents, so the shape is the HTTP client's own and is not a place to improve on it. The client's remaining answers describe a connection this seam has already given back, and are deliberately not passed on rather than handed over as something that is gone.

KEYS are the HTTP client's own request options. A :REDIRECT among them sets how far the chain here is followed, NIL answering a redirect rather than taking it; it is never passed on, because leaving the client to follow a redirect would put the next connection outside this seam entirely.

The connection comes from the seam under the capability bound at the time of the call, so an unauthorised destination is refused before any name is looked up. Every hop is dialled separately and decided separately, and every descriptor is given back on both the answering and the signalling path.

Variables

*dial-capability*

The outbound capability requests are made under, or NIL when none is held.

Bound for the extent of the order that was granted it rather than set once, so the authority sits on the path that holds it instead of standing in the image for whatever happens to make a request next. NIL refuses, which is what a request with no grant behind it has to do.

*redirect-hop-limit*

How many times a response may redirect before the chain is abandoned.

The same bound the HTTP client applies on its own, kept deliberately: taking its redirect handling away changes where the walk happens and must not quietly change how far it goes.

Package valis/src/net/policy

Classes

dial-decision

A permission that was granted, and the grant it rests on.

Answered rather than merely implied by returning normally, so what allowed a dial can be reported and audited instead of reconstructed by reading code.

dial-grant

The authority a principal presents to dial.

DESIGNATION names what the grant reaches. HASH identifies the grant itself and is what an owner names when withdrawing it, so a grant issued without one can never be withdrawn and its decisions are never held.

Functions

clear-dial-decisions

(clear-dial-decisions)

Drop every held decision. Returns no meaningful value.

dial-decision-designation

(dial-decision-designation instance)

Undocumented: this exported symbol needs a docstring.

dial-decision-destination

(dial-decision-destination instance)

Undocumented: this exported symbol needs a docstring.

dial-decision-p

(dial-decision-p object)

Undocumented: this exported symbol needs a docstring.

dial-decision-port

(dial-decision-port instance)

Undocumented: this exported symbol needs a docstring.

dial-grant-designation

(dial-grant-designation instance)

Undocumented: this exported symbol needs a docstring.

dial-grant-hash

(dial-grant-hash instance)

Undocumented: this exported symbol needs a docstring.

dial-grant-p

(dial-grant-p object)

Undocumented: this exported symbol needs a docstring.

dial-scope

(dial-scope designation)

What DESIGNATION reaches: :EVERY-DESTINATION, the one destination its trailing segment names, or NIL when it is not a designation this file recognises.

The trailing segment carries the reach in the shape the listener-bind designation already established for a parameter carried in a designation, so an operator reading a grant-set sees what a dial grant reaches in the designation itself rather than having to look it up somewhere else.

An unrecognised designation answers NIL rather than being treated as a harmless unknown, because a designation nobody wrote a meaning for is exactly the shape a mistake takes.

This is the one place the rule is written. A second reading of the same string somewhere else would be a second rule, and the two would drift apart quietly on a string that decides where a principal may go.

evaluate-dial

(evaluate-dial grant destination port)

Answer the decision that permits GRANT to dial DESTINATION at PORT, or refuse.

Refuses by signalling DIAL-NOT-PERMITTED rather than by answering NIL, so a caller cannot proceed by ignoring a value. The refusal carries a keyword naming which refusal happened, so an operator reading a report can tell a principal holding nothing from one holding a grant for somewhere else, and either from one whose grant the owner has since withdrawn: :NO-GRANT, :GRANT-WITHDRAWN, :UNRECOGNISED-DESIGNATION, :NAMED-SCOPE-UNWIRED, :OUTSIDE-GRANT-SCOPE, or :REFUSED-BY-OPERATOR-POLICY. A keyword rather than a sentence, because a caller can dispatch on the first and can only print the second.

A grant naming a set rather than a destination is decided against the members this node works out at this moment, and its decision is never held: membership follows the operator's configuration, which changes without any grant being withdrawn, so a held decision would go on permitting a destination the operator had already removed.

Called from inside the dial verb before any name is looked up and before any socket exists.

The withdrawal is consulted ahead of the held decisions rather than behind them. The owner's withdrawal already empties what it named through the eviction the fabric chains onto it, and asking again here costs one lookup and means the answer does not depend on that wiring having been installed.

evict-dial-decisions-by-hash

(evict-dial-decisions-by-hash hash-32-bytes)

Drop every decision held for the grant HASH-32-BYTES names.

The fabric chains this onto the same hook the owner's revocation already calls, so withdrawing a grant empties its decisions as part of the withdrawal rather than as a second act somebody has to remember. Returns no meaningful value.

make-dial-grant

(make-dial-grant &key ((:designation designation) nil) ((:hash hash) nil))

Undocumented: this exported symbol needs a docstring.

named-scope-p

(named-scope-p scope)

Whether SCOPE names a set the node works out rather than a single destination.

register-named-scope

(register-named-scope name function)

Answer NAME's members through FUNCTION, called with the dial's subject. NIL unwires NAME.

Variables

*dial-policy-function*

An operator narrowing of what a grant reaches, or NIL for none.

A function of the grant, the destination and the port, answering true to let a dial proceed. It runs in addition to the grant's own scope and never in place of it, so it can only refuse what the grant already permitted. A hook able to widen would move the reach of a grant off the grant structure the owner controls and onto a function somebody installed, which the owner could not see by reading the grant.

Changing it does not reach decisions already held. A narrowing is an operator's configuration act, so an operator who wants it to bite on what is already held empties the cache with CLEAR-DIAL-DECISIONS.

*dial-revocation-store*

The record of the grants the owner has withdrawn, or NIL when none is wired.

The fabric installs the node's own store here at start, the same append-only store the capability verifier consults, so a grant withdrawn once is withdrawn everywhere rather than separately in each seam that honours it.

NIL means this image holds no such record: the case in a unit test and on a node that has not started. Nothing has been withdrawn there because there is nowhere to have withdrawn it.

*dial-scope-subject*

What the dial being evaluated is made on behalf of, offered to a named scope.

*named-scope-functions*

Scope name to the function this node answers that scope's members with.

+dial-designation+

The designation of a grant that reaches every destination.

+dial-prefix+

The prefix of a grant whose reach is narrowed by its trailing segment, in the shape the listener-bind designation already established for a parameter carried in a designation.

+dns-secondaries-designation+

The designation held by something permitted to reach those secondaries and nothing else.

+dns-secondaries-scope+

The scope naming the secondaries this node's zones are configured to notify.

+named-scopes+

Every trailing segment that names a set of destinations rather than one destination.

Package valis/src/net/resolve

Functions

%resolve-destination

(%resolve-destination destination &key (family :internet) port)

The addresses to try for DESTINATION, in the order they should be tried, as conses of address and family.

An address literal is answered as it was given and no resolver is consulted: a literal was never a name, and querying for one would put a destination on the wire that valis had no reason to ask about.

PORT is carried only so a failure names the whole destination the caller meant. Signals a subtype of the resolution failure when no address results.

clear-name-cache

(clear-name-cache)

Drop every cached answer.

Variables

*default-name-ttl*

Seconds an answer is held when the answer carries no lifetime of its own. The system resolver reports none, so one is supplied here; a resolver that does report one passes it through instead.

*family-probe-function*

The function that answers whether this namespace holds an address of a family. A seam for the same reason as the resolver above: a development host holds addresses of both families, so the interesting answer cannot occur there.

*resolver-function*

The function a name is resolved through. A seam, so the two outcomes the system reports identically can be presented to a test directly. Without it the distinction this file draws could not be exercised anywhere but on a confined node, and a passing suite would imply a check that had never run.

Package valis/src/net/tripwire

Functions

install-outbound-tripwire

(install-outbound-tripwire)

Put the refusing check in front of the socket libraries' connect verbs. Idempotent.

outbound-tripwire-escape-list

(outbound-tripwire-escape-list)

The call sites this check lets through, as package-qualified function names.

outbound-tripwire-installed-p

(outbound-tripwire-installed-p)

True while the check stands in front of the socket libraries.

uninstall-outbound-tripwire

(uninstall-outbound-tripwire)

Put the socket libraries' own connect verbs back as they were. Idempotent.

Variables

*caller-walk-depth*

How many stack frames the walk reads before giving up, in which case the connection is refused.

*dialling-through-the-seam*

True for the extent of the seam's own connection attempt, and no longer.