summaryrefslogtreecommitdiffstats
path: root/include/libmnl/libmnl.h
blob: 01ae4845d2f38ae3916bcaf2ee981499d71e80f8 (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
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
#ifndef _LIBMNL_H_
#define _LIBMNL_H_

#ifdef __cplusplus
#	include <cstdio>
#	include <cstdint>
#else
#	include <stdbool.h> /* not in C++ */
#	include <stdio.h>
#	include <stdint.h>
#endif
#include <sys/socket.h> /* for sa_family_t */
#include <linux/netlink.h>

#ifdef __cplusplus
extern "C" {
#endif

#if defined(HAVE_VISIBILITY) && defined(BUILDING_MNL)
#define MNL_API extern  __attribute__ ((visibility("default")))
#else
#define MNL_API extern
#endif

/*
 * Netlink socket API
 */

#define MNL_SOCKET_AUTOPID	0
#define MNL_SOCKET_BUFFER_SIZE	8192UL	/* see linux/netlink.h */

struct mnl_socket;

MNL_API struct mnl_socket *mnl_socket_open(int type);
MNL_API int mnl_socket_bind(struct mnl_socket *nl, unsigned int groups, pid_t pid);
MNL_API int mnl_socket_close(struct mnl_socket *nl);
MNL_API int mnl_socket_get_fd(const struct mnl_socket *nl);
MNL_API unsigned int mnl_socket_get_portid(const struct mnl_socket *nl);
MNL_API ssize_t mnl_socket_sendto(const struct mnl_socket *nl, const void *req, size_t siz);
MNL_API ssize_t mnl_socket_recvfrom(const struct mnl_socket *nl, void *buf, size_t siz);
MNL_API int mnl_socket_setsockopt(const struct mnl_socket *nl, int type, void *buf, socklen_t len);
MNL_API int mnl_socket_getsockopt(const struct mnl_socket *nl, int type, void *buf, socklen_t *len);

/*
 * Netlink message API
 */

#define MNL_ALIGNTO		4
#define MNL_ALIGN(len)		(((len)+MNL_ALIGNTO-1) & ~(MNL_ALIGNTO-1))
#define MNL_NLMSG_HDRLEN	MNL_ALIGN(sizeof(struct nlmsghdr))

MNL_API size_t mnl_nlmsg_size(size_t len);
MNL_API size_t mnl_nlmsg_total_size(size_t len);
MNL_API size_t mnl_nlmsg_get_payload_len(const struct nlmsghdr *nlh);

/* Netlink message header builder */
MNL_API struct nlmsghdr *mnl_nlmsg_put_header(void *buf);
MNL_API void *mnl_nlmsg_put_extra_header(struct nlmsghdr *nlh, size_t size);

/* Netlink message iterators */
MNL_API bool mnl_nlmsg_ok(const struct nlmsghdr *nlh, int len);
MNL_API struct nlmsghdr *mnl_nlmsg_next(const struct nlmsghdr *nlh, int *len);

/* Netlink sequence tracking */
MNL_API bool mnl_nlmsg_seq_ok(const struct nlmsghdr *nlh, unsigned int seq);

/* Netlink portID checking */
MNL_API bool mnl_nlmsg_portid_ok(const struct nlmsghdr *nlh, unsigned int portid);

/* Netlink message getters */
MNL_API void *mnl_nlmsg_get_payload(const struct nlmsghdr *nlh);
MNL_API void *mnl_nlmsg_get_payload_offset(const struct nlmsghdr *nlh, size_t offset);
MNL_API void *mnl_nlmsg_get_payload_tail(const struct nlmsghdr *nlh);

/* Netlink message printer */
MNL_API void mnl_nlmsg_fprintf(FILE *fd, const void *data, size_t datalen, size_t extra_header_size);

/*
 * Netlink attributes API
 */
#define MNL_ATTR_HDRLEN	MNL_ALIGN(sizeof(struct nlattr))

/* TLV attribute getters */
MNL_API uint16_t mnl_attr_get_type(const struct nlattr *attr);
MNL_API uint16_t mnl_attr_get_len(const struct nlattr *attr);
MNL_API uint16_t mnl_attr_get_payload_len(const struct nlattr *attr);
MNL_API void *mnl_attr_get_payload(const struct nlattr *attr);
MNL_API uint8_t mnl_attr_get_u8(const struct nlattr *attr);
MNL_API uint16_t mnl_attr_get_u16(const struct nlattr *attr);
MNL_API uint32_t mnl_attr_get_u32(const struct nlattr *attr);
MNL_API uint64_t mnl_attr_get_u64(const struct nlattr *attr);
MNL_API const char *mnl_attr_get_str(const struct nlattr *attr);

/* TLV attribute putters */
MNL_API void mnl_attr_put(struct nlmsghdr *nlh, uint16_t type, size_t len, const void *data);
MNL_API void mnl_attr_put_u8(struct nlmsghdr *nlh, uint16_t type, uint8_t data);
MNL_API void mnl_attr_put_u16(struct nlmsghdr *nlh, uint16_t type, uint16_t data);
MNL_API void mnl_attr_put_u32(struct nlmsghdr *nlh, uint16_t type, uint32_t data);
MNL_API void mnl_attr_put_u64(struct nlmsghdr *nlh, uint16_t type, uint64_t data);
MNL_API void mnl_attr_put_str(struct nlmsghdr *nlh, uint16_t type, const char *data);
MNL_API void mnl_attr_put_strz(struct nlmsghdr *nlh, uint16_t type, const char *data);

/* TLV attribute nesting */
MNL_API struct nlattr *mnl_attr_nest_start(struct nlmsghdr *nlh, uint16_t type);
MNL_API void mnl_attr_nest_end(struct nlmsghdr *nlh, struct nlattr *start);

/* TLV validation */
MNL_API int mnl_attr_type_valid(const struct nlattr *attr, uint16_t maxtype);

enum mnl_attr_data_type {
	MNL_TYPE_UNSPEC,
	MNL_TYPE_U8,
	MNL_TYPE_U16,
	MNL_TYPE_U32,
	MNL_TYPE_U64,
	MNL_TYPE_STRING,
	MNL_TYPE_FLAG,
	MNL_TYPE_MSECS,
	MNL_TYPE_NESTED,
	MNL_TYPE_NESTED_COMPAT,
	MNL_TYPE_NUL_STRING,
	MNL_TYPE_BINARY,
	MNL_TYPE_MAX,
};

MNL_API int mnl_attr_validate(const struct nlattr *attr, enum mnl_attr_data_type type);
MNL_API int mnl_attr_validate2(const struct nlattr *attr, enum mnl_attr_data_type type, size_t len);

/* TLV iterators */
MNL_API bool mnl_attr_ok(const struct nlattr *attr, int len);
MNL_API struct nlattr *mnl_attr_next(const struct nlattr *attr);

#define mnl_attr_for_each(attr, nlh, offset) \
	for ((attr) = mnl_nlmsg_get_payload_offset((nlh), (offset)); \
	     mnl_attr_ok((attr), mnl_nlmsg_get_payload_tail(nlh) - (void *)(attr)); \
	     (attr) = mnl_attr_next(attr))

#define mnl_attr_for_each_nested(attr, nest) \
	for ((attr) = mnl_attr_get_payload(nest); \
	     mnl_attr_ok((attr), mnl_attr_get_payload(nest) + mnl_attr_get_payload_len(nest) - (void *)(attr)); \
	     (attr) = mnl_attr_next(attr))

/* TLV callback-based attribute parsers */
typedef int (*mnl_attr_cb_t)(const struct nlattr *attr, void *data);

MNL_API int mnl_attr_parse(const struct nlmsghdr *nlh, unsigned int offset, mnl_attr_cb_t cb, void *data);
MNL_API int mnl_attr_parse_nested(const struct nlattr *attr, mnl_attr_cb_t cb, void *data);

/*
 * callback API
 */
#define MNL_CB_ERROR		-1
#define MNL_CB_STOP		 0
#define MNL_CB_OK		 1

typedef int (*mnl_cb_t)(const struct nlmsghdr *nlh, void *data);

MNL_API int mnl_cb_run(const void *buf, size_t numbytes, unsigned int seq,
		      unsigned int portid, mnl_cb_t cb_data, void *data);

MNL_API int mnl_cb_run2(const void *buf, size_t numbytes, unsigned int seq,
		       unsigned int portid, mnl_cb_t cb_data, void *data,
		       mnl_cb_t *cb_ctl_array, unsigned int cb_ctl_array_len);

/*
 * other declarations
 */

#ifndef SOL_NETLINK
#define SOL_NETLINK	270
#endif

#ifdef __cplusplus
} /* extern "C" */
#endif

#endif