RXRPC(7)

๐Ÿ’– NAME ๐Ÿ’–

rxrpc โ€” the Linux RxRPC (AFS) protocol implementation, bestie. Yes, it's a real socket family. Yes, it slays. ๐Ÿฆ‹

This one lives in the kafs-client manual, section 7, so you already know it's the deep lore. โœจ


๐ŸŒธ SYNOPSIS ๐ŸŒธ

#include <sys/socket.h>
#include <linux/rxrpc.h>

socket = socket(AF_RXRPC, SOCK_DGRAM, PF_INET);
socket = socket(AF_RXRPC, SOCK_DGRAM, PF_INET6);

โœจ DESCRIPTION โœจ

Okay so Linux can implement the RxRPC transport protocol โ€” that's the one the AFS network filesystem rides on. And here's the iconic part: both the client end AND the server end are supported, even on the same socket, and authentication works at both ends too. Multi-talented. ๐Ÿ’…

You talk to it through the regular BSD socket interface, using sendmsg(2) and recvmsg(2) with control data โ€” that's how you multiplex a bunch of calls over one socket and how you hand over or pick up call metadata. And request_key(2) is what finds the authentication keys you wanna use, looking in the calling process's keyrings. ๐Ÿ”‘

Under the hood, the AF_RXRPC driver uses udp(7) sockets for transport โ€” either IPv4-only or IPv6 (with IPv4 hanging around too). And under certain circumstances, those underlying transport sockets may be shared between client-only sockets. But heads up: they are never shared if a socket is implementing a server. Nope. Not happening. ๐Ÿ™…โ€โ™€๏ธ

๐Ÿ—บ๏ธ Address format

struct sockaddr_rxrpc {
    sa_family_t     srx_family;     /* AF_RXRPC */
    uint16_t        srx_service;    /* The service identifier */
    uint16_t        transport_type; /* The type of transport */
    uint16_t        transport_len;  /* Transport address length */
    union {
        sa_family_t family;         /* Transport address family */
        struct sockaddr_in sin;     /* IPv4 transport address */
        struct sockaddr_in6 sin6;   /* IPv6 transport address */
    } transport;
};

So like, the rundown:

  • srx_family is always set to AF_RXRPC. Always. No debate.
  • srx_service is set to the service ID of the service you're after.
  • transport_type is set to the transport type, which for now is always SOCK_DGRAM.
  • transport_len says how big the address sitting in transport is.

Inside that transport address part, you set an address that actually makes sense for the underlying socket โ€” family, port, address, all the usual suspects as appropriate. And lowkey: it may be permissible to use IPv4 addresses on an IPv6 socket. ๐Ÿ‘€

๐ŸŽ€ Socket Options

AF_RXRPC serves up a whole lineup of socket options you can set with setsockopt(2) and read back with getsockopt(2). The socket option level for IPv6 is SOL_RXRPC.

  • RXRPC_SECURITY_KEY โ€” the option value is a string naming a key to hand to request_key(2) so it can go fetch an appropriate authentication key. Those keys are expected to be of rxrpc type. And if you never set this? AF_RXRPC will just do an unauthenticated, unencrypted call to the server. No key, no problem, no security either. ๐Ÿ˜ญ
  • RXRPC_SECURITY_KEYRING โ€” the option value is a string naming a keyring to pass to request_key(2), which is how you tell the server end which keys it should use to authenticate connections. The service keys inside that ring should be of type rxrpc_s, their descriptions should be of the form "<service-id>:<security-index>", and each one should be given an 8-byte secret. ๐Ÿ—๏ธ
  • RXRPC_EXCLUSIVE_CONNECTION โ€” the option value should be empty. What it does is make every single call on this socket get its own virtual connection, and therefore its own negotiated security context. Very main character, refuses to share. โœจ
  • RXRPC_MIN_SECURITY_LEVEL โ€” the option value should be a 4-byte unsigned integer, and it can be one of these constants: RXRPC_SECURITY_PLAIN, RXRPC_SECURITY_AUTH, or RXRPC_SECURITY_ENCRYPT. RXRPC_SECURITY_PLAIN means the packets should be securely checksummed only, RXRPC_SECURITY_AUTH means packets should be authenticated, and RXRPC_SECURITY_ENCRYPT means full encryption is employed. Pick your fighter. ๐Ÿ”ฅ
  • RXRPC_UPGRADEABLE_SERVICE โ€” the option value should be a 2-slot array of 2-byte unsigned integers. To use this the socket must be a server socket, and it must have been bound to more than one address with different srx_service specifiers. Slot[0] in the array is the service ID to upgrade from; slot[1] is the service ID to upgrade to. This lets a client find out whether there's a 'better' version of the service available on the same address but under a different service ID. And if the client follows the correct protocol for probing an upgradeable service, the kernel will automatically upgrade the service ID on the connection, and that'll show up in the address recvmsg(2) returns. Glow up, but for service IDs. ๐Ÿ‘‘
  • RXRPC_SUPPORTED_CMSG โ€” the option buffer should have room for a 4-byte integer. The maximum control buffer message type supported by the kernel gets written into that buffer. Why do you care? Because it lets an application find out which control messages it's actually allowed to use, so it can dodge an error instead of trying something unsupported and getting humbled. ๐Ÿ™ˆ

๐Ÿšฉ Message flags

AF_RXRPC communicates certain information by way of the message flags passed to and received from sendmsg(2) and recvmsg(2).

  • MSG_MORE โ€” this is passed to sendmsg() to indicate that there's more data to be transmitted as part of the request phase of a client call, or the reply phase of a service operation.
  • MSG_EOR โ€” recvmsg() sets this to indicate that the call has been terminated (the control messages must be parsed for information as to why), and that the kernel has discarded the user call ID tag. That tag may now be reused. ๐ŸŽ€
  • MSG_PEEK โ€” this is passed to recvmsg() to look at the front of the message queue without removing any messages or changing the state of any outstanding calls.
  • MSG_WAITALL โ€” this is passed to sendmsg() to instruct it not to return for a signal if it's still loading up the message queue and progress is being made at the other side in emptying it. This works around the problem of sendmsg() getting interrupted after partially queuing its data, but not then being able to return how much it has consumed. ๐Ÿ˜ฎโ€๐Ÿ’จ
  • MSG_DONTWAIT โ€” this is passed to recvmsg() to indicate that it shouldn't wait if the message queue is empty.

๐Ÿ“ฆ Control messages

AF_RXRPC communicates metadata to the caller through the ancillary data buffer (msg_control) in the messages passed to and fro using sendmsg(2) and recvmsg(2). And when you're building a control message buffer for sendmsg(), you should consult the RXRPC_SUPPORTED_CMSG value to make sure that the control message type you're reaching for is actually supported. Check before you wreck. โœจ

  • RXRPC_USER_CALL_ID โ€” the data for this is an arbitrary long integer/pointer-sized tag that represents the call to the kernel. It may, for example, hold a pointer to some userspace structure representing the call to the process.
    • [sendmsg] This is passed to sendmsg() when the message proposed will create a client call. It must thereafter be included in all future sendmsg() calls pertaining to that call.
    • [recvmsg] recvmsg() includes the tag in all messages pertaining to a call until the final termination message is reached โ€” which recvmsg() will mark by setting MSG_EOR.
  • RXRPC_ABORT โ€” the data for this is a 32-bit integer that is the abort code.
    • [sendmsg] When passed to sendmsg(), this causes the operation matching the tag to be aborted; this will be followed up by recvmsg() indicating MSG_EOR and a local error of ECONNABORTED, thereby terminating the tag.
    • [recvmsg] When obtained from recvmsg(), this indicates that a remote abort was received from the peer, and the data gives the code for that abort.
  • RXRPC_ACK โ€” [recvmsg] this conveys no data. It indicates the final acknowledgement to a service call has been received. ๐Ÿ’–
  • RXRPC_NET_ERROR โ€” [recvmsg] this conveys a 32-bit integer into which the network error that terminated a call will have been placed.
  • RXRPC_BUSY โ€” [recvmsg] this conveys no data. It indicates that the operation has been rejected because the server is busy. ๐Ÿ˜ญ
  • RXRPC_LOCAL_ERROR โ€” [recvmsg] this conveys a 32-bit integer into which the local error that terminated a call will have been placed.
  • RXRPC_NEW_CALL โ€” [recvmsg] this conveys no data. It indicates that a new service call has arrived at a server socket and is in need of a tag. RXRPC_ACCEPT must be used for that.
  • RXRPC_ACCEPT โ€” the data for this is an arbitrary long integer/pointer-sized tag that represents the call to the kernel, with the same semantics as for RXRPC_USER_CALL_ID.
    • [sendmsg] Supply a user call ID tag to a new service call.
  • RXRPC_EXCLUSIVE_CALL โ€” [sendmsg] indicate that this particular call should be made on its own connection with an unshared negotiated security context. This requires no additional data. ๐Ÿฆ‹
  • RXRPC_UPGRADE_SERVICE โ€” [sendmsg] indicate that this call should attempt to probe the service ID on the other side to see if it gets upgraded. The answer can be found in the srx_service value of the peer address recvmsg() returns for this call. This requires no additional data.
  • RXRPC_TX_LENGTH โ€” the data for this is a signed 64-bit integer.
    • [sendmsg] Specify the exact total transmit size. This allows AF_RXRPC to work out in advance how big encrypted packets are going to be (under some circumstances, there's a data length encrypted inside the packet).
    • If this is set, it may allow AF_RXRPC to be more efficient at filling packets. But listen: if the wrong amount of data is given โ€” too little or too much โ€” then the call will be aborted. Get your math right, bestie. ๐Ÿ’€
  • RXRPC_SET_CALL_TIMEOUT โ€” the data for this is an array of 1-3 32-bit integers.
    • [sendmsg] Specify various call timeouts.
    • The first timeout is the hard timeout for the call, in seconds: the call will be aborted if it takes longer than this amount of time in total.
    • The second timeout is the idle timeout for the call, in milliseconds: the call will be aborted if we don't receive the next DATA packet within that amount of time during the reception phase.
    • The third timeout is the normal timeout for the call, in milliseconds: the call will be aborted if we go for that amount of time without receiving any type of packet pertaining to the call.

๐Ÿ‘€ SEE ALSO ๐Ÿ‘€

kafs(7), request_key(2)


Copyright (C) 2019 Red Hat, Inc. All Rights Reserved.

Written by David Howells (dhowells@redhat.com) โ€” thank you king, we owe you everything ๐Ÿซถ

This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version.


And that's the whole page, no cap. This version is 0.9, dated 2026-08-27, and it came straight from the RXRPC(7) manual. Slay, stay socket-safe, and remember: check RXRPC_SUPPORTED_CMSG before you send. ๐Ÿ’…โœจ๐ŸŽ€

๐Ÿ“ฆ where this page comes from