1 /*
2  * Copyright (c) 2018 Richard Palethorpe <rpalethorpe@suse.com>
3  *
4  * This program is free software: you can redistribute it and/or modify
5  * it under the terms of the GNU General Public License as published by
6  * the Free Software Foundation, either version 2 of the License, or
7  * (at your option) any later version.
8  *
9  * This program is distributed in the hope that it will be useful,
10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12  * GNU General Public License for more details.
13  *
14  * You should have received a copy of the GNU General Public License
15  * along with this program. If not, see <http://www.gnu.org/licenses/>.
16  */
17 /**
18  * @file tst_netlink.h
19  *
20  * Library for communicating with the kernel over the netlink interface.
21  */
22 
23 #ifndef TST_NETLINK_H
24 #define TST_NETLINK_H
25 
26 #include <linux/netlink.h>
27 
28 #ifndef NETLINK_CRYPTO
29 /**
30  * The netlink-crypto socket protocol.
31  */
32 #define NETLINK_CRYPTO 21
33 #endif
34 
35 /** @private */
safe_netlink_send(const char * file,const int lineno,int fd,const struct nlmsghdr * nh,const void * payload)36 static inline ssize_t safe_netlink_send(const char *file, const int lineno,
37 					int fd, const struct nlmsghdr *nh,
38 					const void *payload)
39 {
40 	struct sockaddr_nl sa = { .nl_family = AF_NETLINK };
41 	struct iovec iov[2] = {
42 		{(struct nlmsghdr *)nh, sizeof(*nh)},
43 		{(void *)payload, nh->nlmsg_len - sizeof(*nh)}
44 	};
45 	struct msghdr msg = {
46 		.msg_name = &sa,
47 		.msg_namelen = sizeof(sa),
48 		.msg_iov = iov,
49 		.msg_iovlen = 2
50 	};
51 
52 	return safe_sendmsg(file, lineno, nh->nlmsg_len, fd, &msg, 0);
53 }
54 
55 /**
56  * Sends a netlink message using safe_sendmsg().
57  *
58  * @param fd netlink socket file descriptor.
59  * @param nl_header netlink header structure describing the message.
60  * @param payload an opaque object containing the message data.
61  *
62  * You should set the message length, type and flags to appropriate values
63  * within the nl_header object. See lib/tst_crypto.c for an example.
64  *
65  * @return The number of bytes sent.
66  */
67 #define SAFE_NETLINK_SEND(fd, nl_header, payload)		\
68 	safe_netlink_send(__FILE__, __LINE__, fd, nl_header, payload)
69 
70 /** @private */
safe_netlink_recv(const char * file,const int lineno,int fd,char * nl_headers_buf,size_t buf_len)71 static inline ssize_t safe_netlink_recv(const char *file, const int lineno,
72 					int fd, char *nl_headers_buf,
73 					size_t buf_len)
74 {
75 	struct iovec iov = { nl_headers_buf, buf_len };
76 	struct sockaddr_nl sa;
77 	struct msghdr msg = {
78 		.msg_name = &sa,
79 		.msg_namelen = sizeof(sa),
80 		.msg_iov = &iov,
81 		.msg_iovlen = 1
82 	};
83 
84 	return safe_recvmsg(file, lineno, 0, fd, &msg, 0);
85 }
86 
87 /**
88  * Receives a netlink message using safe_recvmsg().
89  *
90  * @param fd netlink socket file descriptor.
91  * @param nl_header_buf buffer to contain the received netlink header structure.
92  * @param buf_len The length of the header buffer. Must be greater than the page
93  *                size.
94  *
95  * @return The number of bytes received.
96  */
97 #define SAFE_NETLINK_RECV(fd, nl_header_buf, buf_len)			\
98 	safe_netlink_recv(__FILE__, __LINE__, fd, nl_header_buf, buf_len)
99 
100 #endif /* TST_NETLINK_H */
101