PageRenderTime 54ms CodeModel.GetById 28ms RepoModel.GetById 0ms app.codeStats 0ms

/lib/socket.c

https://github.com/tklauser/libnl
C | 784 lines | 360 code | 134 blank | 290 comment | 66 complexity | 90d5da8030c27d3b802002dfc6158628 MD5 | raw file
Possible License(s): LGPL-2.1, GPL-3.0
  1. /*
  2. * lib/socket.c Netlink Socket
  3. *
  4. * This library is free software; you can redistribute it and/or
  5. * modify it under the terms of the GNU Lesser General Public
  6. * License as published by the Free Software Foundation version 2.1
  7. * of the License.
  8. *
  9. * Copyright (c) 2003-2012 Thomas Graf <tgraf@suug.ch>
  10. */
  11. /**
  12. * @ingroup core_types
  13. * @defgroup socket Socket
  14. *
  15. * Representation of a netlink socket
  16. *
  17. * Related sections in the development guide:
  18. * - @core_doc{core_sockets, Netlink Sockets}
  19. *
  20. * @{
  21. *
  22. * Header
  23. * ------
  24. * ~~~~{.c}
  25. * #include <netlink/socket.h>
  26. * ~~~~
  27. */
  28. #include "defs.h"
  29. #include <netlink-private/netlink.h>
  30. #include <netlink-private/socket.h>
  31. #include <netlink/netlink.h>
  32. #include <netlink/utils.h>
  33. #include <netlink/handlers.h>
  34. #include <netlink/msg.h>
  35. #include <netlink/attr.h>
  36. static int default_cb = NL_CB_DEFAULT;
  37. static void __init init_default_cb(void)
  38. {
  39. char *nlcb;
  40. if ((nlcb = getenv("NLCB"))) {
  41. if (!strcasecmp(nlcb, "default"))
  42. default_cb = NL_CB_DEFAULT;
  43. else if (!strcasecmp(nlcb, "verbose"))
  44. default_cb = NL_CB_VERBOSE;
  45. else if (!strcasecmp(nlcb, "debug"))
  46. default_cb = NL_CB_DEBUG;
  47. else {
  48. fprintf(stderr, "Unknown value for NLCB, valid values: "
  49. "{default | verbose | debug}\n");
  50. }
  51. }
  52. }
  53. static uint32_t used_ports_map[32];
  54. static NL_RW_LOCK(port_map_lock);
  55. static uint32_t generate_local_port(void)
  56. {
  57. int i, j, n, m;
  58. static uint16_t idx_state = 0;
  59. uint32_t pid = getpid() & 0x3FFFFF;
  60. nl_write_lock(&port_map_lock);
  61. if (idx_state == 0) {
  62. uint32_t t = time(NULL);
  63. /* from time to time (on average each 2^15 calls), the idx_state will
  64. * be zero again. No problem, just "seed" anew with time(). */
  65. idx_state = t ^ (t >> 16) ^ 0x3047;
  66. } else
  67. idx_state = idx_state + 20011; /* add prime number */
  68. i = idx_state >> 5;
  69. n = idx_state;
  70. for (j = 0; j < 32; j++) {
  71. /* walk the index somewhat randomized, with always leaving the block
  72. * #0 as last. The reason is that libnl-1 will start at block #0,
  73. * so just leave the first 32 ports preferably for libnl-1 owned sockets
  74. * (this is relevant only if the applications ends up using both versions
  75. * of the library and doesn't hurt otherwise). */
  76. if (j == 31)
  77. i = 0;
  78. else
  79. i = (((i-1) + 7) % 31) + 1;
  80. if (used_ports_map[i] == 0xFFFFFFFF)
  81. continue;
  82. for (m = 0; m < 32; m++) {
  83. n = (n + 13) % 32;
  84. if (1UL & (used_ports_map[i] >> n))
  85. continue;
  86. used_ports_map[i] |= (1UL << n);
  87. n += (i * 32);
  88. /* PID_MAX_LIMIT is currently at 2^22, leaving 10 bit
  89. * to, i.e. 1024 unique ports per application. */
  90. nl_write_unlock(&port_map_lock);
  91. return pid + (((uint32_t)n) << 22);
  92. }
  93. }
  94. nl_write_unlock(&port_map_lock);
  95. /* Out of sockets in our own PID namespace, what to do? FIXME */
  96. NL_DBG(1, "Warning: Ran out of unique local port namespace\n");
  97. return UINT32_MAX;
  98. }
  99. static void release_local_port(uint32_t port)
  100. {
  101. int nr;
  102. uint32_t mask;
  103. if (port == UINT32_MAX)
  104. return;
  105. BUG_ON(port == 0);
  106. nr = port >> 22;
  107. mask = 1UL << (nr % 32);
  108. nr /= 32;
  109. nl_write_lock(&port_map_lock);
  110. BUG_ON((used_ports_map[nr] & mask) != mask);
  111. used_ports_map[nr] &= ~mask;
  112. nl_write_unlock(&port_map_lock);
  113. }
  114. /** \cond skip */
  115. void _nl_socket_used_ports_release_all(const uint32_t *used_ports)
  116. {
  117. int i;
  118. for (i = 0; i < 32; i++) {
  119. if (used_ports[i] != 0) {
  120. nl_write_lock(&port_map_lock);
  121. for (; i < 32; i++) {
  122. BUG_ON((used_ports_map[i] & used_ports[i]) != used_ports[i]);
  123. used_ports_map[i] &= ~(used_ports[i]);
  124. }
  125. nl_write_unlock(&port_map_lock);
  126. return;
  127. }
  128. }
  129. }
  130. void _nl_socket_used_ports_set(uint32_t *used_ports, uint32_t port)
  131. {
  132. int nr;
  133. int32_t mask;
  134. nr = port >> 22;
  135. mask = 1UL << (nr % 32);
  136. nr /= 32;
  137. /*
  138. BUG_ON(port == UINT32_MAX || port == 0 || (getpid() & 0x3FFFFF) != (port & 0x3FFFFF));
  139. BUG_ON(used_ports[nr] & mask);
  140. */
  141. used_ports[nr] |= mask;
  142. }
  143. /** \endcond */
  144. /**
  145. * @name Allocation
  146. * @{
  147. */
  148. static struct nl_sock *__alloc_socket(struct nl_cb *cb)
  149. {
  150. struct nl_sock *sk;
  151. sk = calloc(1, sizeof(*sk));
  152. if (!sk)
  153. return NULL;
  154. sk->s_fd = -1;
  155. sk->s_cb = nl_cb_get(cb);
  156. sk->s_local.nl_family = AF_NETLINK;
  157. sk->s_peer.nl_family = AF_NETLINK;
  158. sk->s_seq_expect = sk->s_seq_next = time(NULL);
  159. /* the port is 0 (unspecified), meaning NL_OWN_PORT */
  160. sk->s_flags = NL_OWN_PORT;
  161. return sk;
  162. }
  163. /**
  164. * Allocate new netlink socket
  165. *
  166. * @return Newly allocated netlink socket or NULL.
  167. */
  168. struct nl_sock *nl_socket_alloc(void)
  169. {
  170. struct nl_cb *cb;
  171. struct nl_sock *sk;
  172. cb = nl_cb_alloc(default_cb);
  173. if (!cb)
  174. return NULL;
  175. /* will increment cb reference count on success */
  176. sk = __alloc_socket(cb);
  177. nl_cb_put(cb);
  178. return sk;
  179. }
  180. /**
  181. * Allocate new socket with custom callbacks
  182. * @arg cb Callback handler
  183. *
  184. * The reference to the callback handler is taken into account
  185. * automatically, it is released again upon calling nl_socket_free().
  186. *
  187. *@return Newly allocted socket handle or NULL.
  188. */
  189. struct nl_sock *nl_socket_alloc_cb(struct nl_cb *cb)
  190. {
  191. if (cb == NULL)
  192. BUG();
  193. return __alloc_socket(cb);
  194. }
  195. /**
  196. * Free a netlink socket.
  197. * @arg sk Netlink socket.
  198. */
  199. void nl_socket_free(struct nl_sock *sk)
  200. {
  201. if (!sk)
  202. return;
  203. if (sk->s_fd >= 0)
  204. close(sk->s_fd);
  205. if (!(sk->s_flags & NL_OWN_PORT))
  206. release_local_port(sk->s_local.nl_pid);
  207. nl_cb_put(sk->s_cb);
  208. free(sk);
  209. }
  210. /** @} */
  211. /**
  212. * @name Sequence Numbers
  213. * @{
  214. */
  215. static int noop_seq_check(struct nl_msg *msg, void *arg)
  216. {
  217. return NL_OK;
  218. }
  219. /**
  220. * Disable sequence number checking.
  221. * @arg sk Netlink socket.
  222. *
  223. * Disables checking of sequence numbers on the netlink socket This is
  224. * required to allow messages to be processed which were not requested by
  225. * a preceding request message, e.g. netlink events.
  226. *
  227. * @note This function modifies the NL_CB_SEQ_CHECK configuration in
  228. * the callback handle associated with the socket.
  229. */
  230. void nl_socket_disable_seq_check(struct nl_sock *sk)
  231. {
  232. nl_cb_set(sk->s_cb, NL_CB_SEQ_CHECK,
  233. NL_CB_CUSTOM, noop_seq_check, NULL);
  234. }
  235. /**
  236. * Use next sequence number
  237. * @arg sk Netlink socket.
  238. *
  239. * Uses the next available sequence number and increases the counter
  240. * by one for subsequent calls.
  241. *
  242. * @return Unique serial sequence number
  243. */
  244. unsigned int nl_socket_use_seq(struct nl_sock *sk)
  245. {
  246. return sk->s_seq_next++;
  247. }
  248. /**
  249. * Disable automatic request for ACK
  250. * @arg sk Netlink socket.
  251. *
  252. * The default behaviour of a socket is to request an ACK for
  253. * each message sent to allow for the caller to synchronize to
  254. * the completion of the netlink operation. This function
  255. * disables this behaviour and will result in requests being
  256. * sent which will not have the NLM_F_ACK flag set automatically.
  257. * However, it is still possible for the caller to set the
  258. * NLM_F_ACK flag explicitely.
  259. */
  260. void nl_socket_disable_auto_ack(struct nl_sock *sk)
  261. {
  262. sk->s_flags |= NL_NO_AUTO_ACK;
  263. }
  264. /**
  265. * Enable automatic request for ACK (default)
  266. * @arg sk Netlink socket.
  267. * @see nl_socket_disable_auto_ack
  268. */
  269. void nl_socket_enable_auto_ack(struct nl_sock *sk)
  270. {
  271. sk->s_flags &= ~NL_NO_AUTO_ACK;
  272. }
  273. /** @} */
  274. /** \cond skip */
  275. int _nl_socket_is_local_port_unspecified(struct nl_sock *sk)
  276. {
  277. return (sk->s_local.nl_pid == 0);
  278. }
  279. uint32_t _nl_socket_generate_local_port_no_release(struct nl_sock *sk)
  280. {
  281. uint32_t port;
  282. /* reset the port to generate_local_port(), but do not release
  283. * the previously generated port. */
  284. port = generate_local_port();
  285. sk->s_flags &= ~NL_OWN_PORT;
  286. sk->s_local.nl_pid = port;
  287. return port;
  288. }
  289. /** \endcond */
  290. /**
  291. * @name Source Idenficiation
  292. * @{
  293. */
  294. uint32_t nl_socket_get_local_port(const struct nl_sock *sk)
  295. {
  296. if (sk->s_local.nl_pid == 0) {
  297. /* modify the const argument sk. This is justified, because
  298. * nobody ever saw the local_port from externally. So, we
  299. * initilize it on first use.
  300. *
  301. * Note that this also means that you cannot call this function
  302. * from multiple threads without synchronization. But nl_sock
  303. * is not automatically threadsafe anyway, so the user is not
  304. * allowed to do that.
  305. */
  306. return _nl_socket_generate_local_port_no_release((struct nl_sock *) sk);
  307. }
  308. return sk->s_local.nl_pid;
  309. }
  310. /**
  311. * Set local port of socket
  312. * @arg sk Netlink socket.
  313. * @arg port Local port identifier
  314. *
  315. * Assigns a local port identifier to the socket.
  316. *
  317. * If port is 0, the port is reset to 'unspecified' as it is after newly
  318. * calling nl_socket_alloc().
  319. * Unspecified means, that the port will be generated automatically later
  320. * on first use (either on nl_socket_get_local_port() or nl_connect()).
  321. */
  322. void nl_socket_set_local_port(struct nl_sock *sk, uint32_t port)
  323. {
  324. if (!(sk->s_flags & NL_OWN_PORT))
  325. release_local_port(sk->s_local.nl_pid);
  326. sk->s_flags |= NL_OWN_PORT;
  327. sk->s_local.nl_pid = port;
  328. }
  329. /** @} */
  330. /**
  331. * @name Group Subscriptions
  332. * @{
  333. */
  334. /**
  335. * Join groups
  336. * @arg sk Netlink socket
  337. * @arg group Group identifier
  338. *
  339. * Joins the specified groups using the modern socket option which
  340. * is available since kernel version 2.6.14. It allows joining an
  341. * almost arbitary number of groups without limitation. The list
  342. * of groups has to be terminated by 0 (%NFNLGRP_NONE).
  343. *
  344. * Make sure to use the correct group definitions as the older
  345. * bitmask definitions for nl_join_groups() are likely to still
  346. * be present for backward compatibility reasons.
  347. *
  348. * @return 0 on sucess or a negative error code.
  349. */
  350. int nl_socket_add_memberships(struct nl_sock *sk, int group, ...)
  351. {
  352. int err;
  353. va_list ap;
  354. if (sk->s_fd == -1)
  355. return -NLE_BAD_SOCK;
  356. va_start(ap, group);
  357. while (group != 0) {
  358. if (group < 0) {
  359. va_end(ap);
  360. return -NLE_INVAL;
  361. }
  362. err = setsockopt(sk->s_fd, SOL_NETLINK, NETLINK_ADD_MEMBERSHIP,
  363. &group, sizeof(group));
  364. if (err < 0) {
  365. va_end(ap);
  366. return -nl_syserr2nlerr(errno);
  367. }
  368. group = va_arg(ap, int);
  369. }
  370. va_end(ap);
  371. return 0;
  372. }
  373. int nl_socket_add_membership(struct nl_sock *sk, int group)
  374. {
  375. return nl_socket_add_memberships(sk, group, 0);
  376. }
  377. /**
  378. * Leave groups
  379. * @arg sk Netlink socket
  380. * @arg group Group identifier
  381. *
  382. * Leaves the specified groups using the modern socket option
  383. * which is available since kernel version 2.6.14. The list of groups
  384. * has to terminated by 0 (%NFNLGRP_NONE).
  385. *
  386. * @see nl_socket_add_membership
  387. * @return 0 on success or a negative error code.
  388. */
  389. int nl_socket_drop_memberships(struct nl_sock *sk, int group, ...)
  390. {
  391. int err;
  392. va_list ap;
  393. if (sk->s_fd == -1)
  394. return -NLE_BAD_SOCK;
  395. va_start(ap, group);
  396. while (group != 0) {
  397. if (group < 0) {
  398. va_end(ap);
  399. return -NLE_INVAL;
  400. }
  401. err = setsockopt(sk->s_fd, SOL_NETLINK, NETLINK_DROP_MEMBERSHIP,
  402. &group, sizeof(group));
  403. if (err < 0) {
  404. va_end(ap);
  405. return -nl_syserr2nlerr(errno);
  406. }
  407. group = va_arg(ap, int);
  408. }
  409. va_end(ap);
  410. return 0;
  411. }
  412. int nl_socket_drop_membership(struct nl_sock *sk, int group)
  413. {
  414. return nl_socket_drop_memberships(sk, group, 0);
  415. }
  416. /**
  417. * Join multicast groups (deprecated)
  418. * @arg sk Netlink socket.
  419. * @arg groups Bitmask of groups to join.
  420. *
  421. * This function defines the old way of joining multicast group which
  422. * has to be done prior to calling nl_connect(). It works on any kernel
  423. * version but is very limited as only 32 groups can be joined.
  424. */
  425. void nl_join_groups(struct nl_sock *sk, int groups)
  426. {
  427. sk->s_local.nl_groups |= groups;
  428. }
  429. /** @} */
  430. /**
  431. * @name Peer Identfication
  432. * @{
  433. */
  434. uint32_t nl_socket_get_peer_port(const struct nl_sock *sk)
  435. {
  436. return sk->s_peer.nl_pid;
  437. }
  438. void nl_socket_set_peer_port(struct nl_sock *sk, uint32_t port)
  439. {
  440. sk->s_peer.nl_pid = port;
  441. }
  442. uint32_t nl_socket_get_peer_groups(const struct nl_sock *sk)
  443. {
  444. return sk->s_peer.nl_groups;
  445. }
  446. void nl_socket_set_peer_groups(struct nl_sock *sk, uint32_t groups)
  447. {
  448. sk->s_peer.nl_groups = groups;
  449. }
  450. /** @} */
  451. /**
  452. * @name File Descriptor
  453. * @{
  454. */
  455. /**
  456. * Return the file descriptor of the backing socket
  457. * @arg sk Netlink socket
  458. *
  459. * Only valid after calling nl_connect() to create and bind the respective
  460. * socket.
  461. *
  462. * @return File descriptor or -1 if not available.
  463. */
  464. int nl_socket_get_fd(const struct nl_sock *sk)
  465. {
  466. return sk->s_fd;
  467. }
  468. /**
  469. * Set file descriptor of socket to non-blocking state
  470. * @arg sk Netlink socket.
  471. *
  472. * @return 0 on success or a negative error code.
  473. */
  474. int nl_socket_set_nonblocking(const struct nl_sock *sk)
  475. {
  476. if (sk->s_fd == -1)
  477. return -NLE_BAD_SOCK;
  478. if (fcntl(sk->s_fd, F_SETFL, O_NONBLOCK) < 0)
  479. return -nl_syserr2nlerr(errno);
  480. return 0;
  481. }
  482. /**
  483. * Enable use of MSG_PEEK when reading from socket
  484. * @arg sk Netlink socket.
  485. */
  486. void nl_socket_enable_msg_peek(struct nl_sock *sk)
  487. {
  488. sk->s_flags |= NL_MSG_PEEK;
  489. }
  490. /**
  491. * Disable use of MSG_PEEK when reading from socket
  492. * @arg sk Netlink socket.
  493. */
  494. void nl_socket_disable_msg_peek(struct nl_sock *sk)
  495. {
  496. sk->s_flags &= ~NL_MSG_PEEK;
  497. }
  498. /** @} */
  499. /**
  500. * @name Callback Handler
  501. * @{
  502. */
  503. struct nl_cb *nl_socket_get_cb(const struct nl_sock *sk)
  504. {
  505. return nl_cb_get(sk->s_cb);
  506. }
  507. void nl_socket_set_cb(struct nl_sock *sk, struct nl_cb *cb)
  508. {
  509. if (cb == NULL)
  510. BUG();
  511. nl_cb_put(sk->s_cb);
  512. sk->s_cb = nl_cb_get(cb);
  513. }
  514. /**
  515. * Modify the callback handler associated with the socket
  516. * @arg sk Netlink socket.
  517. * @arg type which type callback to set
  518. * @arg kind kind of callback
  519. * @arg func callback function
  520. * @arg arg argument to be passed to callback function
  521. *
  522. * @see nl_cb_set
  523. */
  524. int nl_socket_modify_cb(struct nl_sock *sk, enum nl_cb_type type,
  525. enum nl_cb_kind kind, nl_recvmsg_msg_cb_t func,
  526. void *arg)
  527. {
  528. return nl_cb_set(sk->s_cb, type, kind, func, arg);
  529. }
  530. /**
  531. * Modify the error callback handler associated with the socket
  532. * @arg sk Netlink socket.
  533. * @arg kind kind of callback
  534. * @arg func callback function
  535. * @arg arg argument to be passed to callback function
  536. *
  537. * @see nl_cb_err
  538. */
  539. int nl_socket_modify_err_cb(struct nl_sock *sk, enum nl_cb_kind kind,
  540. nl_recvmsg_err_cb_t func, void *arg)
  541. {
  542. return nl_cb_err(sk->s_cb, kind, func, arg);
  543. }
  544. /** @} */
  545. /**
  546. * @name Utilities
  547. * @{
  548. */
  549. /**
  550. * Set socket buffer size of netlink socket.
  551. * @arg sk Netlink socket.
  552. * @arg rxbuf New receive socket buffer size in bytes.
  553. * @arg txbuf New transmit socket buffer size in bytes.
  554. *
  555. * Sets the socket buffer size of a netlink socket to the specified
  556. * values \c rxbuf and \c txbuf. Providing a value of \c 0 assumes a
  557. * good default value.
  558. *
  559. * @note It is not required to call this function prior to nl_connect().
  560. * @return 0 on sucess or a negative error code.
  561. */
  562. int nl_socket_set_buffer_size(struct nl_sock *sk, int rxbuf, int txbuf)
  563. {
  564. int err;
  565. if (rxbuf <= 0)
  566. rxbuf = 32768;
  567. if (txbuf <= 0)
  568. txbuf = 32768;
  569. if (sk->s_fd == -1)
  570. return -NLE_BAD_SOCK;
  571. err = setsockopt(sk->s_fd, SOL_SOCKET, SO_SNDBUF,
  572. &txbuf, sizeof(txbuf));
  573. if (err < 0)
  574. return -nl_syserr2nlerr(errno);
  575. err = setsockopt(sk->s_fd, SOL_SOCKET, SO_RCVBUF,
  576. &rxbuf, sizeof(rxbuf));
  577. if (err < 0)
  578. return -nl_syserr2nlerr(errno);
  579. sk->s_flags |= NL_SOCK_BUFSIZE_SET;
  580. return 0;
  581. }
  582. /**
  583. * Set default message buffer size of netlink socket.
  584. * @arg sk Netlink socket.
  585. * @arg bufsize Default message buffer size in bytes.
  586. *
  587. * Sets the default message buffer size to the specified length in bytes.
  588. * The default message buffer size limits the maximum message size the
  589. * socket will be able to receive. It is generally recommneded to specify
  590. * a buffer size no less than the size of a memory page.
  591. *
  592. * @return 0 on success or a negative error code.
  593. */
  594. int nl_socket_set_msg_buf_size(struct nl_sock *sk, size_t bufsize)
  595. {
  596. sk->s_bufsize = bufsize;
  597. return 0;
  598. }
  599. /**
  600. * Get default message buffer size of netlink socket.
  601. * @arg sk Netlink socket.
  602. *
  603. * @return Size of default message buffer.
  604. */
  605. size_t nl_socket_get_msg_buf_size(struct nl_sock *sk)
  606. {
  607. return sk->s_bufsize;
  608. }
  609. /**
  610. * Enable/disable credential passing on netlink socket.
  611. * @arg sk Netlink socket.
  612. * @arg state New state (0 - disabled, 1 - enabled)
  613. *
  614. * @return 0 on success or a negative error code
  615. */
  616. int nl_socket_set_passcred(struct nl_sock *sk, int state)
  617. {
  618. int err;
  619. if (sk->s_fd == -1)
  620. return -NLE_BAD_SOCK;
  621. err = setsockopt(sk->s_fd, SOL_SOCKET, SO_PASSCRED,
  622. &state, sizeof(state));
  623. if (err < 0)
  624. return -nl_syserr2nlerr(errno);
  625. if (state)
  626. sk->s_flags |= NL_SOCK_PASSCRED;
  627. else
  628. sk->s_flags &= ~NL_SOCK_PASSCRED;
  629. return 0;
  630. }
  631. /**
  632. * Enable/disable receival of additional packet information
  633. * @arg sk Netlink socket.
  634. * @arg state New state (0 - disabled, 1 - enabled)
  635. *
  636. * @return 0 on success or a negative error code
  637. */
  638. int nl_socket_recv_pktinfo(struct nl_sock *sk, int state)
  639. {
  640. int err;
  641. if (sk->s_fd == -1)
  642. return -NLE_BAD_SOCK;
  643. err = setsockopt(sk->s_fd, SOL_NETLINK, NETLINK_PKTINFO,
  644. &state, sizeof(state));
  645. if (err < 0)
  646. return -nl_syserr2nlerr(errno);
  647. return 0;
  648. }
  649. /** @} */
  650. /** @} */