---
name: "frame"
section: "4"
platform: "openbsd"
package: "man"
version: "8.0-current-20261101"
release: "OpenBSD 8.0-current (2026-11-01)"
platforms: ["openbsd"]
url: "https://new.carta.tech/frame/4"
---

# frame(4)

frame protocol family

## NAME

**frame** – frame protocol family

## SYNOPSIS

**pseudo-device af\_frame**

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

**#include \<net/frame.h\>**

## DESCRIPTION

The **frame** protocol family provides an interface for sending and receiving low level network interface frames through the normal [socket(2)](/socket/2.md) mechanisms.

The **frame** protocol family supports the SOCK\_DGRAM socket type. Only root may create **frame** protocol family sockets.

**frame** protocol family sockets are designed as an alternative to [bpf(4)](/bpf/4.md) for handling low data and packet rate communication protocols. Rather than filtering every frame entering the system before the network stack, like [bpf(4)](/bpf/4.md), processing of the **frame** protocol family runs after the built in protocol handlers in the kernel, thus avoiding the overhead. For this reason, it is not possible to handle IPv4 or IPv6 packets with **frame** protocol sockets because the kernel network stack consumes them before the receive handling for **frame** sockets is run.

Sockets can be created in the **frame** protocol family by using AF\_FRAME as the *domain* argument to [socket(2)](/socket/2.md). The type of interface, as per ⟨net/if\_types.h⟩, is specified as the socket *protocol*. Currently only Ethernet interfaces are supported.

Sockets bound to the **frame** family use the following address structure:

```
#define FRAME_ADDRLEN	8
#define FRAME_DATALEN	32
struct sockaddr_frame {
	uint8_t		sfrm_len;
	uint8_t		sfrm_family;
	uint16_t	sfrm_proto;
	unsigned int	sfrm_ifindex;
	uint8_t		sfrm_addr[FRAME_ADDRLEN];
	char		sfrm_ifname[IFNAMSIZ];
	uint8_t		sfrm_data[FRAME_DATALEN];
};
```

The interface used for transmitting or receiving frames with a **frame** domain socket may be specified by using an interface index with *sfrm\_ifindex*, or by name with *sfrm\_ifname*. The use of other *struct* *sockaddr\_frame* fields depends on the type of interface.

### Ethernet frame sockets

A **frame** socket for use with Ethernet interfaces can be created using IFT\_ETHER as the *protocol* argument to [socket(2)](/socket/2.md):

```
int sock = socket(AF_FRAME, SOCK_DGRAM, IFT_ETHER);
```

The Ethernet protocol is specified with *sfrm\_proto* in network byte order. Ethernet addresses are specified using the first 6 bytes of *sfrm\_addr*.

Ethernet **frame** sockets may receive frames on all interfaces by specifying 0 for *sfrm\_ifindex* when using [bind(2)](/bind/2.md). Similarly, a “wildcard” local address of all zeros can be specified in *sfrm\_addr*.

An interface and address must be specified when sending Ethernet frames.

Ethernet sockets support the following **frame** socket options using IFT\_ETHER as the *level* argument with [setsockopt(2)](/setsockopt/2.md) and [getsockopt(2)](/getsockopt/2.md):

- FRAME\_RECVDSTADDR *int*

  Enable or disable the reception of the Ethernet destination address as a *struct* *ether\_addr* control message for frames received with [recvmsg(2)](/recvmsg/2.md).

- FRAME\_RECVPRIO *int*

  Enable or disable the reception of the mbuf packet priority field as an *int* sized control message for frames received with [recvmsg(2)](/recvmsg/2.md).

- FRAME\_ADD\_MEMBERSHIP *struct* *frame\_mreq*

  Configure an Ethernet interface to enable reception of frames destined to the specified multicast Ethernet address.

  ```
  struct frame_mreq {
  	unsigned int	fmr_ifindex;
  	uint8_t		fmr_addr[FRAME_ADDRLEN];
  	char		fmr_ifname[IFNAMSIZ];
  };
  ```

  An interface must be specified using either *fmr\_ifindex* or *fmr\_ifname*. The multicast Ethernet address is specified in the first 6 bytes of *fmr\_addr*.

- FRAME\_DEL\_MEMBERSHIP *struct* *frame\_mreq*

  Configure an Ethernet interface to disable reception of frames destined to the specified multicast Ethernet address.

- FRAME\_SENDPRIO *int*

  Specify an mbuf priority value between IF\_HDRPRIO\_MIN (0) and IF\_HDRPRIO\_MAX (7) for frames sent with the Ethernet **frame** socket, or IF\_HDRPRIO\_PACKET to use the existing mbuf priority value. The default is IF\_HDRPRIO\_PACKET.

## EXAMPLES

To receive LLDP frames on the em0 Ethernet interface:

```
struct sockaddr_frame sfrm = {
	.sfrm_family = AF_FRAME,
	.sfrm_ifname = "em0",
	.sfrm_proto = htons(ETHERTYPE_LLDP),
};
struct frame_mreq fmr = {
	.fmr_ifname = "em0",
	.fmr_addr = { 0x01, 0x80, 0xc2, 0x00, 0x00, 0x0e },
};
int sock;
sock = socket(AF_FRAME, SOCK_DGRAM, IFT_ETHER);
if (sock == -1)
	err(1, "ethernet frame socket");
if (bind(sock, (struct sockaddr *)&sfrm, sizeof(sfrm)) == -1)
	err(1, "bind");
if (setsockopt(sock, IFT_ETHER, FRAME_ADD_MEMBERSHIP,
    &fmr, sizeof(fmr)) == -1)
	err(1, "join lldp multicast group");
for (;;) {
	socklen_t sfrmlen = sizeof(sfrm);
	uint8_t frame[2048];
	ssize_t rv;
	rv = recvfrom(sock, frame, sizeof(frame), 0,
	    (struct sockaddr *)&sfrm, &sfrmlen);
	if (rv == -1)
		err(1, "lldp recv");
	printf("received %zd bytes from %s", rv,
	    ether_ntoa((struct ether_addr *)sfrm.sfrm_addr));
}
```

## SEE ALSO

[socket(2)](/socket/2.md), [netintro(4)](/netintro/4.md)

## HISTORY

**frame** domain sockets appeared in OpenBSD 7.7.

## AUTHORS

David Gwynne ⟨*dlg@openbsd.org*⟩.
