net/tipc/netlink_compat.c

Source file repositories/reference/linux-study-clean/net/tipc/netlink_compat.c

File Facts

System
Linux kernel
Corpus path
net/tipc/netlink_compat.c
Extension
.c
Size
35484 bytes
Lines
1374
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

struct tipc_nl_compat_msg {
	u16 cmd;
	int rep_type;
	int rep_size;
	int req_type;
	int req_size;
	struct net *net;
	struct sk_buff *rep;
	struct tlv_desc *req;
	struct sock *dst_sk;
};

struct tipc_nl_compat_cmd_dump {
	int (*header)(struct tipc_nl_compat_msg *);
	int (*dumpit)(struct sk_buff *, struct netlink_callback *);
	int (*format)(struct tipc_nl_compat_msg *msg, struct nlattr **attrs);
};

struct tipc_nl_compat_cmd_doit {
	int (*doit)(struct sk_buff *skb, struct genl_info *info);
	int (*transcode)(struct tipc_nl_compat_cmd_doit *cmd,
			 struct sk_buff *skb, struct tipc_nl_compat_msg *msg);
};

static int tipc_skb_tailroom(struct sk_buff *skb)
{
	int tailroom;
	int limit;

	tailroom = skb_tailroom(skb);
	limit = TIPC_SKB_MAX - skb->len;

	if (tailroom < limit)
		return tailroom;

	return limit;
}

static inline int TLV_GET_DATA_LEN(struct tlv_desc *tlv)
{
	return TLV_GET_LEN(tlv) - TLV_SPACE(0);
}

static int tipc_add_tlv(struct sk_buff *skb, u16 type, void *data, u16 len)
{
	struct tlv_desc *tlv = (struct tlv_desc *)skb_tail_pointer(skb);

	if (tipc_skb_tailroom(skb) < TLV_SPACE(len))
		return -EMSGSIZE;

	skb_put(skb, TLV_SPACE(len));
	memset(tlv, 0, TLV_SPACE(len));
	tlv->tlv_type = htons(type);
	tlv->tlv_len = htons(TLV_LENGTH(len));
	if (len && data)
		memcpy(TLV_DATA(tlv), data, len);

	return 0;
}

static void tipc_tlv_init(struct sk_buff *skb, u16 type)
{
	struct tlv_desc *tlv = (struct tlv_desc *)skb->data;

	TLV_SET_LEN(tlv, 0);
	TLV_SET_TYPE(tlv, type);
	skb_put(skb, sizeof(struct tlv_desc));
}

static __printf(2, 3) int tipc_tlv_sprintf(struct sk_buff *skb,
					   const char *fmt, ...)
{
	int n;
	u16 len;
	u32 rem;
	char *buf;
	struct tlv_desc *tlv;
	va_list args;

	rem = tipc_skb_tailroom(skb);

	tlv = (struct tlv_desc *)skb->data;
	len = TLV_GET_LEN(tlv);
	buf = TLV_DATA(tlv) + len;

	va_start(args, fmt);
	n = vscnprintf(buf, rem, fmt, args);
	va_end(args);

	TLV_SET_LEN(tlv, n + len);

Annotation

Implementation Notes