You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

351 lines
10 KiB

2 years ago
  1. /*
  2. * (C) 2008-2010 by Pablo Neira Ayuso <pablo@netfilter.org>
  3. *
  4. * This program is free software; you can redistribute it and/or modify
  5. * it under the terms of the GNU Lesser General Public License as published
  6. * by the Free Software Foundation; either version 2.1 of the License, or
  7. * (at your option) any later version.
  8. */
  9. #include <sys/types.h>
  10. #include <sys/socket.h>
  11. #include <stdlib.h>
  12. #include <unistd.h>
  13. #include <time.h>
  14. #include <errno.h>
  15. #include "libmnl.h"
  16. /**
  17. * \mainpage
  18. *
  19. * libmnl is a minimalistic user-space library oriented to Netlink developers.
  20. * There are a lot of common tasks in parsing, validating, constructing of
  21. * both the Netlink header and TLVs that are repetitive and easy to get wrong.
  22. * This library aims to provide simple helpers that allows you to avoid
  23. * re-inventing the wheel in common Netlink tasks.
  24. *
  25. * \verbatim
  26. "Simplify, simplify" -- Henry David Thoureau. Walden (1854)
  27. \endverbatim
  28. *
  29. * The acronym libmnl stands for LIBrary Minimalistic NetLink.
  30. *
  31. * libmnl homepage is:
  32. * http://www.netfilter.org/projects/libmnl/
  33. *
  34. * \section features Main Features
  35. * - Small: the shared library requires around 30KB for an x86-based computer.
  36. * - Simple: this library avoids complex abstractions that tend to hide Netlink
  37. * details. It avoids elaborated object-oriented infrastructure and complex
  38. * callback-based workflow.
  39. * - Easy to use: the library simplifies the work for Netlink-wise developers.
  40. * It provides functions to make socket handling, message building,
  41. * validating, parsing and sequence tracking, easier.
  42. * - Easy to re-use: you can use this library to build your own abstraction
  43. * layer upon this library, if you want to provide another library that
  44. * hides Netlink details to your users.
  45. * - Decoupling: the interdependency of the main bricks that compose this
  46. * library is reduced, i.e. the library provides many helpers, but the
  47. * programmer is not forced to use them.
  48. *
  49. * \section licensing Licensing terms
  50. * This library is released under the LGPLv2.1 or any later (at your option).
  51. *
  52. * \section Dependencies
  53. * You have to install the Linux kernel headers that you want to use to develop
  54. * your application. Moreover, this library requires that you have some basics
  55. * on Netlink.
  56. *
  57. * \section scm Git Tree
  58. * The current development version of libmnl can be accessed at:
  59. * http://git.netfilter.org/cgi-bin/gitweb.cgi?p=libmnl.git;a=summary
  60. *
  61. * \section using Using libmnl
  62. * You can access several example files under examples/ in the libmnl source
  63. * code tree.
  64. */
  65. struct mnl_socket {
  66. int fd;
  67. struct sockaddr_nl addr;
  68. };
  69. /**
  70. * \defgroup socket Netlink socket helpers
  71. * @{
  72. */
  73. /**
  74. * mnl_socket_get_fd - obtain file descriptor from netlink socket
  75. * \param nl netlink socket obtained via mnl_socket_open()
  76. *
  77. * This function returns the file descriptor of a given netlink socket.
  78. */
  79. int mnl_socket_get_fd(const struct mnl_socket *nl)
  80. {
  81. return nl->fd;
  82. }
  83. /**
  84. * mnl_socket_get_portid - obtain Netlink PortID from netlink socket
  85. * \param nl netlink socket obtained via mnl_socket_open()
  86. *
  87. * This function returns the Netlink PortID of a given netlink socket.
  88. * It's a common mistake to assume that this PortID equals the process ID
  89. * which is not always true. This is the case if you open more than one
  90. * socket that is binded to the same Netlink subsystem from the same process.
  91. */
  92. unsigned int mnl_socket_get_portid(const struct mnl_socket *nl)
  93. {
  94. return nl->addr.nl_pid;
  95. }
  96. static struct mnl_socket *__mnl_socket_open(int bus, int flags)
  97. {
  98. struct mnl_socket *nl;
  99. nl = calloc(1, sizeof(struct mnl_socket));
  100. if (nl == NULL)
  101. return NULL;
  102. nl->fd = socket(AF_NETLINK, SOCK_RAW | flags, bus);
  103. if (nl->fd == -1) {
  104. free(nl);
  105. return NULL;
  106. }
  107. return nl;
  108. }
  109. /**
  110. * mnl_socket_open - open a netlink socket
  111. * \param bus the netlink socket bus ID (see NETLINK_* constants)
  112. *
  113. * On error, it returns NULL and errno is appropriately set. Otherwise, it
  114. * returns a valid pointer to the mnl_socket structure.
  115. */
  116. struct mnl_socket *mnl_socket_open(int bus)
  117. {
  118. return __mnl_socket_open(bus, 0);
  119. }
  120. /**
  121. * mnl_socket_open2 - open a netlink socket with appropriate flags
  122. * \param bus the netlink socket bus ID (see NETLINK_* constants)
  123. * \param flags the netlink socket flags (see SOCK_* constants in socket(2))
  124. *
  125. * This is similar to mnl_socket_open(), but allows to set flags like
  126. * SOCK_CLOEXEC at socket creation time (useful for multi-threaded programs
  127. * performing exec calls).
  128. *
  129. * On error, it returns NULL and errno is appropriately set. Otherwise, it
  130. * returns a valid pointer to the mnl_socket structure.
  131. */
  132. struct mnl_socket *mnl_socket_open2(int bus, int flags)
  133. {
  134. return __mnl_socket_open(bus, flags);
  135. }
  136. /**
  137. * mnl_socket_fdopen - associates a mnl_socket object with pre-existing socket.
  138. * \param fd pre-existing socket descriptor.
  139. *
  140. * On error, it returns NULL and errno is appropriately set. Otherwise, it
  141. * returns a valid pointer to the mnl_socket structure. It also sets the portID
  142. * if the socket fd is already bound and it is AF_NETLINK.
  143. *
  144. * Note that mnl_socket_get_portid() returns 0 if this function is used with
  145. * non-netlink socket.
  146. */
  147. struct mnl_socket *mnl_socket_fdopen(int fd)
  148. {
  149. int ret;
  150. struct mnl_socket *nl;
  151. struct sockaddr_nl addr;
  152. socklen_t addr_len = sizeof(struct sockaddr_nl);
  153. ret = getsockname(fd, (struct sockaddr *) &addr, &addr_len);
  154. if (ret == -1)
  155. return NULL;
  156. nl = calloc(1, sizeof(struct mnl_socket));
  157. if (nl == NULL)
  158. return NULL;
  159. nl->fd = fd;
  160. if (addr.nl_family == AF_NETLINK)
  161. nl->addr = addr;
  162. return nl;
  163. }
  164. /**
  165. * mnl_socket_bind - bind netlink socket
  166. * \param nl netlink socket obtained via mnl_socket_open()
  167. * \param groups the group of message you're interested in
  168. * \param pid the port ID you want to use (use zero for automatic selection)
  169. *
  170. * On error, this function returns -1 and errno is appropriately set. On
  171. * success, 0 is returned. You can use MNL_SOCKET_AUTOPID which is 0 for
  172. * automatic port ID selection.
  173. */
  174. int mnl_socket_bind(struct mnl_socket *nl, unsigned int groups,
  175. pid_t pid)
  176. {
  177. int ret;
  178. socklen_t addr_len;
  179. nl->addr.nl_family = AF_NETLINK;
  180. nl->addr.nl_groups = groups;
  181. nl->addr.nl_pid = pid;
  182. ret = bind(nl->fd, (struct sockaddr *) &nl->addr, sizeof (nl->addr));
  183. if (ret < 0)
  184. return ret;
  185. addr_len = sizeof(nl->addr);
  186. ret = getsockname(nl->fd, (struct sockaddr *) &nl->addr, &addr_len);
  187. if (ret < 0)
  188. return ret;
  189. if (addr_len != sizeof(nl->addr)) {
  190. errno = EINVAL;
  191. return -1;
  192. }
  193. if (nl->addr.nl_family != AF_NETLINK) {
  194. errno = EINVAL;
  195. return -1;
  196. }
  197. return 0;
  198. }
  199. /**
  200. * mnl_socket_sendto - send a netlink message of a certain size
  201. * \param nl netlink socket obtained via mnl_socket_open()
  202. * \param buf buffer containing the netlink message to be sent
  203. * \param len number of bytes in the buffer that you want to send
  204. *
  205. * On error, it returns -1 and errno is appropriately set. Otherwise, it
  206. * returns the number of bytes sent.
  207. */
  208. ssize_t mnl_socket_sendto(const struct mnl_socket *nl,
  209. const void *buf, size_t len)
  210. {
  211. static const struct sockaddr_nl snl = {
  212. .nl_family = AF_NETLINK
  213. };
  214. return sendto(nl->fd, buf, len, 0,
  215. (struct sockaddr *) &snl, sizeof(snl));
  216. }
  217. /**
  218. * mnl_socket_recvfrom - receive a netlink message
  219. * \param nl netlink socket obtained via mnl_socket_open()
  220. * \param buf buffer that you want to use to store the netlink message
  221. * \param bufsiz size of the buffer passed to store the netlink message
  222. *
  223. * On error, it returns -1 and errno is appropriately set. If errno is set
  224. * to ENOSPC, it means that the buffer that you have passed to store the
  225. * netlink message is too small, so you have received a truncated message.
  226. * To avoid this, you have to allocate a buffer of MNL_SOCKET_BUFFER_SIZE
  227. * (which is 8KB, see linux/netlink.h for more information). Using this
  228. * buffer size ensures that your buffer is big enough to store the netlink
  229. * message without truncating it.
  230. */
  231. ssize_t mnl_socket_recvfrom(const struct mnl_socket *nl,
  232. void *buf, size_t bufsiz)
  233. {
  234. ssize_t ret;
  235. struct sockaddr_nl addr;
  236. struct iovec iov = {
  237. .iov_base = buf,
  238. .iov_len = bufsiz,
  239. };
  240. struct msghdr msg = {
  241. .msg_name = &addr,
  242. .msg_namelen = sizeof(struct sockaddr_nl),
  243. .msg_iov = &iov,
  244. .msg_iovlen = 1,
  245. .msg_control = NULL,
  246. .msg_controllen = 0,
  247. .msg_flags = 0,
  248. };
  249. ret = recvmsg(nl->fd, &msg, 0);
  250. if (ret == -1)
  251. return ret;
  252. if (msg.msg_flags & MSG_TRUNC) {
  253. errno = ENOSPC;
  254. return -1;
  255. }
  256. if (msg.msg_namelen != sizeof(struct sockaddr_nl)) {
  257. errno = EINVAL;
  258. return -1;
  259. }
  260. return ret;
  261. }
  262. /**
  263. * mnl_socket_close - close a given netlink socket
  264. * \param nl netlink socket obtained via mnl_socket_open()
  265. *
  266. * On error, this function returns -1 and errno is appropriately set.
  267. * On success, it returns 0.
  268. */
  269. int mnl_socket_close(struct mnl_socket *nl)
  270. {
  271. int ret = close(nl->fd);
  272. free(nl);
  273. return ret;
  274. }
  275. /**
  276. * mnl_socket_setsockopt - set Netlink socket option
  277. * \param nl netlink socket obtained via mnl_socket_open()
  278. * \param type type of Netlink socket options
  279. * \param buf the buffer that contains the data about this option
  280. * \param len the size of the buffer passed
  281. *
  282. * This function allows you to set some Netlink socket option. As of writing
  283. * this (see linux/netlink.h), the existing options are:
  284. *
  285. * - \#define NETLINK_ADD_MEMBERSHIP 1
  286. * - \#define NETLINK_DROP_MEMBERSHIP 2
  287. * - \#define NETLINK_PKTINFO 3
  288. * - \#define NETLINK_BROADCAST_ERROR 4
  289. * - \#define NETLINK_NO_ENOBUFS 5
  290. *
  291. * In the early days, Netlink only supported 32 groups expressed in a
  292. * 32-bits mask. However, since 2.6.14, Netlink may have up to 2^32 multicast
  293. * groups but you have to use setsockopt() with NETLINK_ADD_MEMBERSHIP to
  294. * join a given multicast group. This function internally calls setsockopt()
  295. * to join a given netlink multicast group. You can still use mnl_bind()
  296. * and the 32-bit mask to join a set of Netlink multicast groups.
  297. *
  298. * On error, this function returns -1 and errno is appropriately set.
  299. */
  300. int mnl_socket_setsockopt(const struct mnl_socket *nl, int type,
  301. void *buf, socklen_t len)
  302. {
  303. return setsockopt(nl->fd, SOL_NETLINK, type, buf, len);
  304. }
  305. /**
  306. * mnl_socket_getsockopt - get a Netlink socket option
  307. * \param nl netlink socket obtained via mnl_socket_open()
  308. * \param type type of Netlink socket options
  309. * \param buf pointer to the buffer to store the value of this option
  310. * \param len size of the information written in the buffer
  311. *
  312. * On error, this function returns -1 and errno is appropriately set.
  313. */
  314. int mnl_socket_getsockopt(const struct mnl_socket *nl, int type,
  315. void *buf, socklen_t *len)
  316. {
  317. return getsockopt(nl->fd, SOL_NETLINK, type, buf, len);
  318. }
  319. /**
  320. * @}
  321. */