drivers/net/ovpn/netlink.c

Source file repositories/reference/linux-study-clean/drivers/net/ovpn/netlink.c

File Facts

System
Linux kernel
Corpus path
drivers/net/ovpn/netlink.c
Extension
.c
Size
36874 bytes
Lines
1388
Domain
Driver Families
Bucket
drivers/net
Inferred role
Driver Families: implementation source
Status
source implementation candidate

Why This File Exists

Repeatable hardware-adapter layer. Deep compatibility for every driver is out of scope; this atlas records patterns, probe lifecycles, bus glue, IRQ/DMA usage, and links back to core abstractions.

Dependency Surface

Detected Declarations

Annotated Snippet

if (!ipv6_addr_v4mapped(in6)) {
			sin6 = (struct sockaddr_in6 *)ss;
			sin6->sin6_port = port;
			memcpy(&sin6->sin6_addr, in6, sizeof(*in6));
			break;
		}

		/* v4-mapped-v6 address */
		ss->ss_family = AF_INET;
		in = &in6->s6_addr32[3];
		fallthrough;
	case AF_INET:
		sin = (struct sockaddr_in *)ss;
		sin->sin_port = port;
		sin->sin_addr.s_addr = *in;
		break;
	}

	return true;
}

static u8 *ovpn_nl_attr_local_ip(struct nlattr **attrs)
{
	u8 *addr6;

	if (!attrs[OVPN_A_PEER_LOCAL_IPV4] && !attrs[OVPN_A_PEER_LOCAL_IPV6])
		return NULL;

	if (attrs[OVPN_A_PEER_LOCAL_IPV4])
		return nla_data(attrs[OVPN_A_PEER_LOCAL_IPV4]);

	addr6 = nla_data(attrs[OVPN_A_PEER_LOCAL_IPV6]);
	/* this is an IPv4-mapped IPv6 address, therefore extract the actual
	 * v4 address from the last 4 bytes
	 */
	if (ipv6_addr_v4mapped((struct in6_addr *)addr6))
		return addr6 + 12;

	return addr6;
}

static sa_family_t ovpn_nl_family_get(struct nlattr *addr4,
				      struct nlattr *addr6)
{
	if (addr4)
		return AF_INET;

	if (addr6) {
		if (ipv6_addr_v4mapped((struct in6_addr *)nla_data(addr6)))
			return AF_INET;
		return AF_INET6;
	}

	return AF_UNSPEC;
}

static int ovpn_nl_peer_precheck(struct ovpn_priv *ovpn,
				 struct genl_info *info,
				 struct nlattr **attrs)
{
	sa_family_t local_fam, remote_fam;

	if (NL_REQ_ATTR_CHECK(info->extack, info->attrs[OVPN_A_PEER], attrs,
			      OVPN_A_PEER_ID))
		return -EINVAL;

	if (attrs[OVPN_A_PEER_REMOTE_IPV4] && attrs[OVPN_A_PEER_REMOTE_IPV6]) {
		NL_SET_ERR_MSG_MOD(info->extack,
				   "cannot specify both remote IPv4 or IPv6 address");
		return -EINVAL;
	}

	if (!attrs[OVPN_A_PEER_REMOTE_IPV4] &&
	    !attrs[OVPN_A_PEER_REMOTE_IPV6] && attrs[OVPN_A_PEER_REMOTE_PORT]) {
		NL_SET_ERR_MSG_MOD(info->extack,
				   "cannot specify remote port without IP address");
		return -EINVAL;
	}

	if ((attrs[OVPN_A_PEER_REMOTE_IPV4] ||
	     attrs[OVPN_A_PEER_REMOTE_IPV6]) &&
	    !attrs[OVPN_A_PEER_REMOTE_PORT]) {
		NL_SET_ERR_MSG_MOD(info->extack,
				   "cannot specify remote IP address without port");
		return -EINVAL;
	}

	if (!attrs[OVPN_A_PEER_REMOTE_IPV4] &&
	    attrs[OVPN_A_PEER_LOCAL_IPV4]) {
		NL_SET_ERR_MSG_MOD(info->extack,

Annotation

Implementation Notes