aboutsummaryrefslogtreecommitdiff
path: root/include/tst_netlink.h
blob: 7d96fd711e6cfdb0314d13b6eb410046b85fdb86 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
/* SPDX-License-Identifier: GPL-2.0-or-later
 * Copyright (c) 2021 Linux Test Project
 */

#ifndef TST_NETLINK_H
#define TST_NETLINK_H

#include <linux/netlink.h>

struct tst_netlink_context;

struct tst_netlink_attr_list {
	unsigned short type;
	const void *data;
	ssize_t len;
	const struct tst_netlink_attr_list *sublist;
};

struct tst_netlink_message {
	struct nlmsghdr *header;
	struct nlmsgerr *err;
	void *payload;
	size_t payload_size;
};

extern int tst_netlink_errno;

/* Open a netlink socket */
struct tst_netlink_context *tst_netlink_create_context(const char *file,
	const int lineno, int protocol);
#define NETLINK_CREATE_CONTEXT(protocol) \
	tst_netlink_create_context(__FILE__, __LINE__, (protocol))

/* Free a tst_netlink_message array returned by tst_netlink_recv() */
void tst_netlink_free_message(struct tst_netlink_message *msg);
#define NETLINK_FREE_MESSAGE tst_netlink_free_message

/* Close netlink socket */
void tst_netlink_destroy_context(const char *file, const int lineno,
	struct tst_netlink_context *ctx);
#define NETLINK_DESTROY_CONTEXT(ctx) \
	tst_netlink_destroy_context(__FILE__, __LINE__, (ctx))

/* Send all messages in given buffer */
int tst_netlink_send(const char *file, const int lineno,
	struct tst_netlink_context *ctx);
#define NETLINK_SEND(ctx) tst_netlink_send(__FILE__, __LINE__, (ctx))

/* Send all messages in given buffer and validate kernel response */
int tst_netlink_send_validate(const char *file, const int lineno,
	struct tst_netlink_context *ctx);
#define NETLINK_SEND_VALIDATE(ctx) \
	tst_netlink_send_validate(__FILE__, __LINE__, (ctx))

/* Wait until data is available for reading from the netlink socket */
int tst_netlink_wait(struct tst_netlink_context *ctx);
#define NETLINK_WAIT tst_netlink_wait

/*
 * Read from netlink socket and return an array of partially parsed messages.
 * header == NULL indicates end of array.
 */
struct tst_netlink_message *tst_netlink_recv(const char *file, const int lineno,
	struct tst_netlink_context *ctx);
#define NETLINK_RECV(ctx) tst_netlink_recv(__FILE__, __LINE__, (ctx))

/* Add new message to buffer */
int tst_netlink_add_message(const char *file, const int lineno,
	struct tst_netlink_context *ctx, const struct nlmsghdr *header,
	const void *payload, size_t payload_size);
#define NETLINK_ADD_MESSAGE(ctx, header, payload, psize) \
	tst_netlink_add_message(__FILE__, __LINE__, (ctx), (header), \
		(payload), (psize))

/* Add arbitrary nlattr attribute to last message */
int tst_netlink_add_attr(const char *file, const int lineno,
	struct tst_netlink_context *ctx, unsigned short type, const void *data,
	unsigned short len);
#define NETLINK_ADD_ATTR(ctx, type, data, len) \
	tst_netlink_add_attr(__FILE__, __LINE__, (ctx), (type), (data), (len))

/* Add string nlattr attribute to last message */
int tst_netlink_add_attr_string(const char *file, const int lineno,
	struct tst_netlink_context *ctx, unsigned short type, const char *data);
#define NETLINK_ADD_ATTR_STRING(ctx, type, data) \
	tst_netlink_add_attr_string(__FILE__, __LINE__, (ctx), (type), (data))

/*
 * Add list of arbitrary nlattr attributes to last message. The list is
 * terminated by attribute with negative length. Nested sublists are supported.
 */
int tst_netlink_add_attr_list(const char *file, const int lineno,
	struct tst_netlink_context *ctx,
	const struct tst_netlink_attr_list *list);
#define NETLINK_ADD_ATTR_LIST(ctx, list) \
	tst_netlink_add_attr_list(__FILE__, __LINE__, (ctx), (list))

/* Add arbitrary rtattr attribute to last message */
int tst_rtnl_add_attr(const char *file, const int lineno,
	struct tst_netlink_context *ctx, unsigned short type, const void *data,
	unsigned short len);
#define RTNL_ADD_ATTR(ctx, type, data, len) \
	tst_rtnl_add_attr(__FILE__, __LINE__, (ctx), (type), (data), (len))

/* Add string rtattr attribute to last message */
int tst_rtnl_add_attr_string(const char *file, const int lineno,
	struct tst_netlink_context *ctx, unsigned short type, const char *data);
#define RTNL_ADD_ATTR_STRING(ctx, type, data) \
	tst_rtnl_add_attr_string(__FILE__, __LINE__, (ctx), (type), (data))

/*
 * Add list of arbitrary rtattr attributes to last message. The list is
 * terminated by attribute with negative length. Nested sublists are supported.
 */
int tst_rtnl_add_attr_list(const char *file, const int lineno,
	struct tst_netlink_context *ctx,
	const struct tst_netlink_attr_list *list);
#define RTNL_ADD_ATTR_LIST(ctx, list) \
	tst_rtnl_add_attr_list(__FILE__, __LINE__, (ctx), (list))

/* Check that all sent messages with NLM_F_ACK flag have been acked without
 * error. Usage:
 *
 * tst_netlink_send(ctx);
 * tst_netlink_wait(ctx);
 * response = tst_netlink_recv(ctx);
 * if (!tst_netlink_check_acks(ctx, response)) { ... }
 * tst_netlink_free_message(response);
 */
int tst_netlink_check_acks(const char *file, const int lineno,
	struct tst_netlink_context *ctx, struct tst_netlink_message *response);
#define NETLINK_CHECK_ACKS(ctx, response) \
	tst_netlink_check_acks(__FILE__, __LINE__, (ctx), (response))

#endif /* TST_NETLINK_H */