net/sunrpc/addr.c

Source file repositories/reference/linux-study-clean/net/sunrpc/addr.c

File Facts

System
Linux kernel
Corpus path
net/sunrpc/addr.c
Extension
.c
Size
8949 bytes
Lines
355
Domain
Networking Core
Bucket
Sockets, Protocols, Packet Path, And Network Policy
Inferred role
Networking Core: exported/initcall integration point
Status
integration implementation candidate

Why This File Exists

Networking stack implementation surface: socket APIs, protocol dispatch, packet flow, routing, filtering, and network namespaces.

Dependency Surface

Detected Declarations

Annotated Snippet

// SPDX-License-Identifier: GPL-2.0-only
/*
 * Copyright 2009, Oracle.  All rights reserved.
 *
 * Convert socket addresses to presentation addresses and universal
 * addresses, and vice versa.
 *
 * Universal addresses are introduced by RFC 1833 and further refined by
 * recent RFCs describing NFSv4.  The universal address format is part
 * of the external (network) interface provided by rpcbind version 3
 * and 4, and by NFSv4.  Such an address is a string containing a
 * presentation format IP address followed by a port number in
 * "hibyte.lobyte" format.
 *
 * IPv6 addresses can also include a scope ID, typically denoted by
 * a '%' followed by a device name or a non-negative integer.  Refer to
 * RFC 4291, Section 2.2 for details on IPv6 presentation formats.
 */

#include <net/ipv6.h>
#include <linux/sunrpc/addr.h>
#include <linux/sunrpc/msg_prot.h>
#include <linux/slab.h>
#include <linux/export.h>

#if IS_ENABLED(CONFIG_IPV6)

static size_t rpc_ntop6_noscopeid(const struct sockaddr *sap,
				  char *buf, const int buflen)
{
	const struct sockaddr_in6 *sin6 = (struct sockaddr_in6 *)sap;
	const struct in6_addr *addr = &sin6->sin6_addr;

	/*
	 * RFC 4291, Section 2.2.2
	 *
	 * Shorthanded ANY address
	 */
	if (ipv6_addr_any(addr))
		return snprintf(buf, buflen, "::");

	/*
	 * RFC 4291, Section 2.2.2
	 *
	 * Shorthanded loopback address
	 */
	if (ipv6_addr_loopback(addr))
		return snprintf(buf, buflen, "::1");

	/*
	 * RFC 4291, Section 2.2.3
	 *
	 * Special presentation address format for mapped v4
	 * addresses.
	 */
	if (ipv6_addr_v4mapped(addr))
		return snprintf(buf, buflen, "::ffff:%pI4",
					&addr->s6_addr32[3]);

	/*
	 * RFC 4291, Section 2.2.1
	 */
	return snprintf(buf, buflen, "%pI6c", addr);
}

static size_t rpc_ntop6(const struct sockaddr *sap,
			char *buf, const size_t buflen)
{
	const struct sockaddr_in6 *sin6 = (struct sockaddr_in6 *)sap;
	char scopebuf[IPV6_SCOPE_ID_LEN];
	size_t len;
	int rc;

	len = rpc_ntop6_noscopeid(sap, buf, buflen);
	if (unlikely(len == 0))
		return len;

	if (!(ipv6_addr_type(&sin6->sin6_addr) & IPV6_ADDR_LINKLOCAL))
		return len;
	if (sin6->sin6_scope_id == 0)
		return len;

	rc = snprintf(scopebuf, sizeof(scopebuf), "%c%u",
			IPV6_SCOPE_DELIMITER, sin6->sin6_scope_id);
	if (unlikely((size_t)rc >= sizeof(scopebuf)))
		return 0;

	len += rc;
	if (unlikely(len >= buflen))
		return 0;

Annotation

Implementation Notes