net/psp/psp_nl.c

Source file repositories/reference/linux-study-clean/net/psp/psp_nl.c

File Facts

System
Linux kernel
Corpus path
net/psp/psp_nl.c
Extension
.c
Size
22569 bytes
Lines
952
Domain
Networking Core
Bucket
Sockets, Protocols, Packet Path, And Network Policy
Inferred role
Networking Core: implementation source
Status
source 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

if (dev_net(psd->main_netdev) != genl_info_net(info)) {
			NL_SET_BAD_ATTR(info->extack,
					info->attrs[PSP_A_DEV_NSID]);
			return ERR_PTR(-EPERM);
		}

		nsid = nla_get_s32(info->attrs[PSP_A_DEV_NSID]);

		net = get_net_ns_by_id(genl_info_net(info), nsid);
		if (!net) {
			NL_SET_BAD_ATTR(info->extack,
					info->attrs[PSP_A_DEV_NSID]);
			return ERR_PTR(-EINVAL);
		}
	} else {
		net = get_net(genl_info_net(info));
	}

	return net;
}

void
psp_device_unlock(const struct genl_split_ops *ops, struct sk_buff *skb,
		  struct genl_info *info)
{
	struct socket *socket = info->user_ptr[1];
	struct psp_dev *psd = info->user_ptr[0];

	mutex_unlock(&psd->lock);
	if (socket)
		sockfd_put(socket);
}

bool psp_has_assoc_dev_in_ns(struct psp_dev *psd, struct net *net)
{
	struct psp_assoc_dev *entry;

	list_for_each_entry(entry, &psd->assoc_dev_list, dev_list) {
		if (dev_net(entry->assoc_dev) == net)
			return true;
	}

	return false;
}

static int psp_nl_fill_assoc_dev_list(struct psp_dev *psd, struct sk_buff *rsp,
				      struct net *cur_net,
				      struct net *filter_net)
{
	struct psp_assoc_dev *entry;
	struct net *dev_net_ns;
	struct nlattr *nest;
	int nsid;

	list_for_each_entry(entry, &psd->assoc_dev_list, dev_list) {
		dev_net_ns = dev_net(entry->assoc_dev);

		if (filter_net && dev_net_ns != filter_net)
			continue;

		/* When filtering by namespace, all devices are in the caller's
		 * namespace so nsid is always NETNSA_NSID_NOT_ASSIGNED (-1).
		 * Otherwise, calculate the nsid relative to cur_net.
		 */
		nsid = filter_net ? NETNSA_NSID_NOT_ASSIGNED :
				    peernet2id_alloc(cur_net, dev_net_ns,
						     GFP_KERNEL);

		nest = nla_nest_start(rsp, PSP_A_DEV_ASSOC_LIST);
		if (!nest)
			return -EMSGSIZE;

		if (nla_put_u32(rsp, PSP_A_ASSOC_DEV_INFO_IFINDEX,
				entry->assoc_dev->ifindex) ||
		    nla_put_s32(rsp, PSP_A_ASSOC_DEV_INFO_NSID, nsid)) {
			nla_nest_cancel(rsp, nest);
			return -EMSGSIZE;
		}

		nla_nest_end(rsp, nest);
	}

	return 0;
}

static int
psp_nl_dev_fill(struct psp_dev *psd, struct sk_buff *rsp,
		const struct genl_info *info)
{
	struct net *cur_net;

Annotation

Implementation Notes