---
name: "cap_net"
section: "3"
platform: "freebsd"
package: "base"
version: "16.0-CURRENT-20261027-61c70dc16a79"
release: "FreeBSD 16.0-CURRENT (2026-10-27)"
platforms: ["freebsd"]
url: "https://new.carta.tech/cap_bind"
---

# cap\_net(3)

library for networking in capability mode

Part of [cap\_bind(3)](/cap_bind/3.md).

## NAME

**cap\_bind**, **cap\_connect**, **cap\_getaddrinfo**, **cap\_gethostbyaddr**, **cap\_gethostbyname**, **cap\_gethostbyname2**, **cap\_getnameinfo**, **cap\_net\_free**, **cap\_net\_limit**, **cap\_net\_limit\_addr2name**, **cap\_net\_limit\_addr2name\_family**, **cap\_net\_limit\_bind**, **cap\_net\_limit\_connect**, **cap\_net\_limit\_init**, **cap\_net\_limit\_name2addr**, **cap\_net\_limit\_name2addr\_family**, – library for networking in capability mode

## LIBRARY

library “libcap\_net”

## SYNOPSIS

**#include \<sys/nv.h\>**

**#include \<libcasper.h\>**

**#include \<casper/cap\_net.h\>**

*int*\

**cap\_bind**(*cap\_channel\_t \*chan*, *int s*, *const struct sockaddr \*addr*, *socklen\_t addrlen*);

*int*\

**cap\_connect**(*cap\_channel\_t \*chan*, *int s*, *const struct sockaddr \*name*, *socklen\_t namelen*);

*int*\

**cap\_getaddrinfo**(*cap\_channel\_t \*chan*, *const char \*hostname*, *const char \*servname*, *const struct addrinfo \*hints*, *struct addrinfo \*\*res*);

*int*\

**cap\_getnameinfo**(*cap\_channel\_t \*chan*, *const struct sockaddr \*sa*, *socklen\_t salen*, *char \*host*, *size\_t hostlen*, *char \*serv*, *size\_t servlen*, *int flags*);

*struct hostent \**\

**cap\_gethostbyname**(*const cap\_channel\_t \*chan*, *const char \*name*);

*struct hostent \**\

**cap\_gethostbyname2**(*const cap\_channel\_t \*chan*, *const char \*name*, *int af*);

*struct hostent \**\

**cap\_gethostbyaddr**(*const cap\_channel\_t \*chan*, *const void \*addr*, *socklen\_t len*, *int af*);

*cap\_net\_limit\_t \**\

**cap\_net\_limit\_init**(*cap\_channel\_t \*chan*, *uint64\_t mode*);

*int*\

**cap\_net\_limit**(*cap\_net\_limit\_t \*limit*);

*void*\

**cap\_net\_free**(*cap\_net\_limit\_t \*limit*);

*cap\_net\_limit\_t \**\

**cap\_net\_limit\_addr2name\_family**(*cap\_net\_limit\_t \*limit*, *int \*family*, *size\_t size*);

*cap\_net\_limit\_t \**\

**cap\_net\_limit\_addr2name**(*cap\_net\_limit\_t \*limit*, *const struct sockaddr \*sa*, *socklen\_t salen*);

*cap\_net\_limit\_t \**\

**cap\_net\_limit\_name2addr\_family**(*cap\_net\_limit\_t \*limit*, *int \*family*, *size\_t size*);

*cap\_net\_limit\_t \**\

**cap\_net\_limit\_name2addr**(*cap\_net\_limit\_t \*limit*, *const char \*name*, *const char \*serv*);

*cap\_net\_limit\_t \**\

**cap\_net\_limit\_connect**(*cap\_net\_limit\_t \*limit*, *const struct sockaddr \*sa*, *socklen\_t salen*);

*cap\_net\_limit\_t \**\

**cap\_net\_limit\_bind**(*cap\_net\_limit\_t \*limit*, *const struct sockaddr \*sa*, *socklen\_t salen*);

## DESCRIPTION

The functions **cap\_bind**(), **cap\_connect**(), **cap\_getaddrinfo**(), **cap\_getnameinfo**(), **cap\_gethostbyname**(), **cap\_gethostbyname2**(), and **cap\_gethostbyaddr**() provide a set of APIs equivalent to [bind(2)](/bind/2.md), [connect(2)](/connect/2.md), [getaddrinfo(3)](/getaddrinfo/3.md), [getnameinfo(3)](/getnameinfo/3.md), [gethostbyname(3)](/gethostbyname/3.md), [gethostbyname2(3)](/gethostbyname2/3.md), and [gethostbyaddr(3)](/gethostbyaddr/3.md) except that a connection to the **system.net** service needs to be provided.

These functions, as well as **cap\_net\_limit**(), are reentrant but not thread-safe. That is, they may be called from separate threads only with different *cap\_channel\_t* arguments or with synchronization.

## LIMITS

By default, the cap\_net capability provides unrestricted access to the network namespace. Applications typically only require access to a small portion of the network namespace: The **cap\_net\_limit**() function can be used to restrict access to the network. The **cap\_net\_limit\_init**() returns an opaque limit handle used to store a list of capabilities. The *mode* restricts the functionality of the service. Modes are encoded using the following flags:

```
CAPNET_ADDR2NAME		reverse DNS lookups are allowed with
				cap_getnameinfo
CAPNET_NAME2ADDR		name resolution is allowed with
				cap_getaddrinfo
CAPNET_DEPRECATED_ADDR2NAME	reverse DNS lookups are allowed with
				cap_gethostbyaddr
CAPNET_DEPRECATED_NAME2ADDR	name resolution is allowed with
				cap_gethostbyname and cap_gethostbyname2
CAPNET_BIND			bind syscall is allowed
CAPNET_CONNECT			connect syscall is allowed
CAPNET_CONNECTDNS		connect syscall is allowed to the values
				returned from previous call to
				the cap_getaddrinfo or cap_gethostbyname
```

**cap\_net\_limit\_addr2name\_family**() limits the **cap\_getnameinfo**() and **cap\_gethostbyaddr**() to do reverse DNS lookups to specific family (AF\_INET, AF\_INET6, etc.)

**cap\_net\_limit\_addr2name**() limits the **cap\_getnameinfo**() and **cap\_gethostbyaddr**() to do reverse DNS lookups only on those specific structures.

**cap\_net\_limit\_name2addr\_family**() limits the **cap\_getaddrinfo**(), **cap\_gethostbyname**() and **cap\_gethostbyname2**() to do the name resolution on specific family (AF\_INET, AF\_INET6, etc.)

**cap\_net\_limit\_addr2name**() restricts **cap\_getaddrinfo**(), **cap\_gethostbyname**() and **cap\_gethostbyname2**() to a set of domains.

**cap\_net\_limit\_bind**() limits **cap\_bind**() to bind only on those specific structures.

**cap\_net\_limit\_connect**() limits **cap\_connect**() to connect only on those specific structures. If the CAPNET\_CONNECTDNS is set the limits are extended to the values returned by **cap\_getaddrinfo**(), **cap\_gethostbyname**() and **cap\_gethostbyname2**() In case of the **cap\_getaddrinfo**() the restriction is strict. In case of the **cap\_gethostbyname**() and **cap\_gethostbyname2**() any port will be accepted in the **cap\_connect**() function.

The **cap\_net\_limit**() will consume and apply the limits.

Once a set of limits is applied, subsequent calls to **cap\_net\_limit**() may only further restrict the service. Any call that would grant operations not currently permitted will fail.

If the **cap\_net\_limit**() was not called the rights may be freed using **cap\_net\_free**(). Multiple calls to **cap\_net\_limit\_addr2name\_family**(), **cap\_net\_limit\_addr2name**(), **cap\_net\_limit\_name2addr\_family**(), **cap\_net\_limit\_name2addr**(), **cap\_net\_limit\_connect**(), and **cap\_net\_limit\_bind**() is supported, each call is extending previous capabilities.

## EXAMPLES

The following example first opens a capability to casper and then uses this capability to create the **system.net** casper service and uses it to resolve a host and connect to it.

```
cap_channel_t *capcas, *capnet;
cap_net_limit_t *limit;
int familylimit, error, s;
const char *host = "example.com";
struct addrinfo hints, *res;
/* Open capability to Casper. */
capcas = cap_init();
if (capcas == NULL)
	err(1, "Unable to contact Casper");
/* Cache NLA for gai_strerror. */
caph_cache_catpages();
/* Enter capability mode sandbox. */
if (caph_enter_casper() < 0)
	err(1, "Unable to enter capability mode");
/* Use Casper capability to create capability to the system.net service. */
capnet = cap_service_open(capcas, "system.net");
if (capnet == NULL)
	err(1, "Unable to open system.net service");
/* Close Casper capability. */
cap_close(capcas);
/* Limit system.net to resolve IPv4 addresses, to host example.com . */
limit = cap_net_limit_init(capnet, CAPNET_NAME2ADDR | CAPNET_CONNECTDNS);
if (limit == NULL)
	err(1, "Unable to create limits.");
cap_net_limit_name2addr(limit, host, "80");
familylimit = AF_INET;
cap_net_limit_name2addr_family(limit, &familylimit, 1);
if (cap_net_limit(limit) < 0)
	err(1, "Unable to apply limits.");
/* Find IP addresses for the given host. */
memset(&hints, 0, sizeof(hints));
hints.ai_family = AF_INET;
hints.ai_socktype = SOCK_STREAM;
error = cap_getaddrinfo(capnet, host, "80", &hints, &res);
if (error != 0)
	errx(1, "cap_getaddrinfo(): %s: %s", host, gai_strerror(error));
s = socket(res->ai_family, res->ai_socktype, res->ai_protocol);
if (s < 0)
	err(1, "Unable to create socket");
if (cap_connect(capnet, s, res->ai_addr,  res->ai_addrlen) < 0)
	err(1, "Unable to connect to host");
```

## SEE ALSO

[bind(2)](/bind/2.md), [cap\_enter(2)](/cap_enter/2.md), [connect(2)](/connect/2.md), [caph\_enter(3)](/caph_enter/3.md), [err(3)](/err/3.md), [gethostbyaddr(3)](/gethostbyaddr/3.md), [gethostbyname(3)](/gethostbyname/3.md), [gethostbyname2(3)](/gethostbyname2/3.md), [getnameinfo(3)](/getnameinfo/3.md), [capsicum(4)](/capsicum/4.md), [nv(9)](/nv/9.md)

## AUTHORS

Mariusz Zaborski ⟨*oshogbo@FreeBSD.org*⟩
