netlink_sockif.c 27 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863
  1. /****************************************************************************
  2. * net/netlink/netlink_sockif.c
  3. *
  4. * Licensed to the Apache Software Foundation (ASF) under one or more
  5. * contributor license agreements. See the NOTICE file distributed with
  6. * this work for additional information regarding copyright ownership. The
  7. * ASF licenses this file to you under the Apache License, Version 2.0 (the
  8. * "License"); you may not use this file except in compliance with the
  9. * License. You may obtain a copy of the License at
  10. *
  11. * http://www.apache.org/licenses/LICENSE-2.0
  12. *
  13. * Unless required by applicable law or agreed to in writing, software
  14. * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
  15. * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
  16. * License for the specific language governing permissions and limitations
  17. * under the License.
  18. *
  19. ****************************************************************************/
  20. /****************************************************************************
  21. * Included Files
  22. ****************************************************************************/
  23. #include <nuttx/config.h>
  24. #include <sys/types.h>
  25. #include <sys/socket.h>
  26. #include <stdbool.h>
  27. #include <string.h>
  28. #include <poll.h>
  29. #include <sched.h>
  30. #include <assert.h>
  31. #include <errno.h>
  32. #include <debug.h>
  33. #include <nuttx/kmalloc.h>
  34. #include <nuttx/semaphore.h>
  35. #include <nuttx/wqueue.h>
  36. #include <nuttx/net/net.h>
  37. #include "netlink/netlink.h"
  38. #ifdef CONFIG_NET_NETLINK
  39. /****************************************************************************
  40. * Private Function Prototypes
  41. ****************************************************************************/
  42. static int netlink_setup(FAR struct socket *psock, int protocol);
  43. static sockcaps_t netlink_sockcaps(FAR struct socket *psock);
  44. static void netlink_addref(FAR struct socket *psock);
  45. static int netlink_bind(FAR struct socket *psock,
  46. FAR const struct sockaddr *addr, socklen_t addrlen);
  47. static int netlink_getsockname(FAR struct socket *psock,
  48. FAR struct sockaddr *addr, FAR socklen_t *addrlen);
  49. static int netlink_getpeername(FAR struct socket *psock,
  50. FAR struct sockaddr *addr, FAR socklen_t *addrlen);
  51. static int netlink_listen(FAR struct socket *psock, int backlog);
  52. static int netlink_connect(FAR struct socket *psock,
  53. FAR const struct sockaddr *addr, socklen_t addrlen);
  54. static int netlink_accept(FAR struct socket *psock,
  55. FAR struct sockaddr *addr, FAR socklen_t *addrlen,
  56. FAR struct socket *newsock);
  57. static int netlink_poll(FAR struct socket *psock, FAR struct pollfd *fds,
  58. bool setup);
  59. static ssize_t netlink_sendmsg(FAR struct socket *psock,
  60. FAR struct msghdr *msg, int flags);
  61. static ssize_t netlink_recvmsg(FAR struct socket *psock,
  62. FAR struct msghdr *msg, int flags);
  63. static int netlink_close(FAR struct socket *psock);
  64. /****************************************************************************
  65. * Public Data
  66. ****************************************************************************/
  67. const struct sock_intf_s g_netlink_sockif =
  68. {
  69. netlink_setup, /* si_setup */
  70. netlink_sockcaps, /* si_sockcaps */
  71. netlink_addref, /* si_addref */
  72. netlink_bind, /* si_bind */
  73. netlink_getsockname, /* si_getsockname */
  74. netlink_getpeername, /* si_getpeername */
  75. netlink_listen, /* si_listen */
  76. netlink_connect, /* si_connect */
  77. netlink_accept, /* si_accept */
  78. netlink_poll, /* si_poll */
  79. netlink_sendmsg, /* si_sendmsg */
  80. netlink_recvmsg, /* si_recvmsg */
  81. netlink_close /* si_close */
  82. };
  83. /****************************************************************************
  84. * Private Functions
  85. ****************************************************************************/
  86. /****************************************************************************
  87. * Name: netlink_setup
  88. *
  89. * Description:
  90. * Called for socket() to verify that the provided socket type and
  91. * protocol are usable by this address family. Perform any family-
  92. * specific socket fields.
  93. *
  94. * Input Parameters:
  95. * psock - A pointer to a user allocated socket structure to be
  96. * initialized.
  97. * protocol - NetLink socket protocol (see sys/socket.h)
  98. *
  99. * Returned Value:
  100. * Zero (OK) is returned on success. Otherwise, a negated errno value is
  101. * returned.
  102. *
  103. ****************************************************************************/
  104. static int netlink_setup(FAR struct socket *psock, int protocol)
  105. {
  106. int domain = psock->s_domain;
  107. int type = psock->s_type;
  108. /* Verify that the protocol is supported */
  109. DEBUGASSERT((unsigned int)protocol <= UINT8_MAX);
  110. switch (protocol)
  111. {
  112. #ifdef CONFIG_NETLINK_ROUTE
  113. case NETLINK_ROUTE:
  114. break;
  115. #endif
  116. default:
  117. return -EPROTONOSUPPORT;
  118. }
  119. /* Verify the socket type (domain should always be PF_NETLINK here) */
  120. if (domain == PF_NETLINK && (type == SOCK_RAW || type == SOCK_DGRAM))
  121. {
  122. /* Allocate the NetLink socket connection structure and save it in the
  123. * new socket instance.
  124. */
  125. FAR struct netlink_conn_s *conn = netlink_alloc();
  126. if (conn == NULL)
  127. {
  128. /* Failed to reserve a connection structure */
  129. return -ENOMEM;
  130. }
  131. /* Initialize the connection instance */
  132. conn->protocol = (uint8_t)protocol;
  133. /* Set the reference count on the connection structure. This
  134. * reference count will be incremented only if the socket is
  135. * dup'ed
  136. */
  137. conn->crefs = 1;
  138. /* Attach the connection instance to the socket */
  139. psock->s_conn = conn;
  140. return OK;
  141. }
  142. return -EPROTONOSUPPORT;
  143. }
  144. /****************************************************************************
  145. * Name: netlink_sockcaps
  146. *
  147. * Description:
  148. * Return the bit encoded capabilities of this socket.
  149. *
  150. * Input Parameters:
  151. * psock - Socket structure of the socket whose capabilities are being
  152. * queried.
  153. *
  154. * Returned Value:
  155. * The non-negative set of socket capabilities is returned.
  156. *
  157. ****************************************************************************/
  158. static sockcaps_t netlink_sockcaps(FAR struct socket *psock)
  159. {
  160. /* Permit vfcntl to set socket to non-blocking */
  161. return SOCKCAP_NONBLOCKING;
  162. }
  163. /****************************************************************************
  164. * Name: netlink_addref
  165. *
  166. * Description:
  167. * Increment the reference count on the underlying connection structure.
  168. *
  169. * Input Parameters:
  170. * psock - Socket structure of the socket whose reference count will be
  171. * incremented.
  172. *
  173. * Returned Value:
  174. * None
  175. *
  176. ****************************************************************************/
  177. static void netlink_addref(FAR struct socket *psock)
  178. {
  179. FAR struct netlink_conn_s *conn;
  180. DEBUGASSERT(psock != NULL && psock->s_conn != NULL);
  181. conn = psock->s_conn;
  182. DEBUGASSERT(conn->crefs > 0 && conn->crefs < 255);
  183. conn->crefs++;
  184. }
  185. /****************************************************************************
  186. * Name: netlink_bind
  187. *
  188. * Description:
  189. * netlink_bind() gives the socket 'conn' the local address 'addr'. 'addr'
  190. * is 'addrlen' bytes long. Traditionally, this is called "assigning a name
  191. * to a socket." When a socket is created with socket, it exists in a name
  192. * space (address family) but has no name assigned.
  193. *
  194. * Input Parameters:
  195. * conn NetLink socket connection structure
  196. * addr Socket local address
  197. * addrlen Length of 'addr'
  198. *
  199. * Returned Value:
  200. * 0 on success; -1 on error with errno set appropriately
  201. *
  202. * EACCES
  203. * The address is protected, and the user is not the superuser.
  204. * EADDRINUSE
  205. * The given address is already in use.
  206. * EINVAL
  207. * The socket is already bound to an address.
  208. * ENOTSOCK
  209. * psock is a descriptor for a file, not a socket.
  210. *
  211. * Assumptions:
  212. *
  213. ****************************************************************************/
  214. static int netlink_bind(FAR struct socket *psock,
  215. FAR const struct sockaddr *addr, socklen_t addrlen)
  216. {
  217. FAR struct sockaddr_nl *nladdr;
  218. FAR struct netlink_conn_s *conn;
  219. DEBUGASSERT(psock != NULL && psock->s_conn != NULL && addr != NULL &&
  220. addrlen >= sizeof(struct sockaddr_nl));
  221. /* Save the address information in the connection structure */
  222. nladdr = (FAR struct sockaddr_nl *)addr;
  223. conn = (FAR struct netlink_conn_s *)psock->s_conn;
  224. conn->pid = nladdr->nl_pid ? nladdr->nl_pid : getpid();
  225. conn->groups = nladdr->nl_groups;
  226. return OK;
  227. }
  228. /****************************************************************************
  229. * Name: netlink_getsockname
  230. *
  231. * Description:
  232. * The getsockname() function retrieves the locally-bound name of the
  233. * specified socket, stores this address in the sockaddr structure pointed
  234. * to by the 'addr' argument, and stores the length of this address in the
  235. * object pointed to by the 'addrlen' argument.
  236. *
  237. * If the actual length of the address is greater than the length of the
  238. * supplied sockaddr structure, the stored address will be truncated.
  239. *
  240. * If the socket has not been bound to a local name, the value stored in
  241. * the object pointed to by address is unspecified.
  242. *
  243. * Input Parameters:
  244. * conn NetLink socket connection structure
  245. * addr sockaddr structure to receive data [out]
  246. * addrlen Length of sockaddr structure [in/out]
  247. *
  248. ****************************************************************************/
  249. static int netlink_getsockname(FAR struct socket *psock,
  250. FAR struct sockaddr *addr,
  251. FAR socklen_t *addrlen)
  252. {
  253. FAR struct sockaddr_nl *nladdr;
  254. FAR struct netlink_conn_s *conn;
  255. DEBUGASSERT(psock != NULL && psock->s_conn != NULL && addr != NULL &&
  256. addrlen != NULL && *addrlen >= sizeof(struct sockaddr_nl));
  257. conn = (FAR struct netlink_conn_s *)psock->s_conn;
  258. /* Return the address information in the address structure */
  259. nladdr = (FAR struct sockaddr_nl *)addr;
  260. memset(nladdr, 0, sizeof(struct sockaddr_nl));
  261. nladdr->nl_family = AF_NETLINK;
  262. nladdr->nl_pid = conn->pid;
  263. nladdr->nl_groups = conn->groups;
  264. *addrlen = sizeof(struct sockaddr_nl);
  265. return OK;
  266. }
  267. /****************************************************************************
  268. * Name: netlink_getpeername
  269. *
  270. * Description:
  271. * The netlink_getpeername() function retrieves the remote-connected name
  272. * of the specified packet socket, stores this address in the sockaddr
  273. * structure pointed to by the 'addr' argument, and stores the length of
  274. * this address in the object pointed to by the 'addrlen' argument.
  275. *
  276. * If the actual length of the address is greater than the length of the
  277. * supplied sockaddr structure, the stored address will be truncated.
  278. *
  279. * If the socket has not been bound to a local name, the value stored in
  280. * the object pointed to by address is unspecified.
  281. *
  282. * Parameters:
  283. * psock Socket structure of the socket to be queried
  284. * addr sockaddr structure to receive data [out]
  285. * addrlen Length of sockaddr structure [in/out]
  286. *
  287. * Returned Value:
  288. * On success, 0 is returned, the 'addr' argument points to the address
  289. * of the socket, and the 'addrlen' argument points to the length of the
  290. * address. Otherwise, a negated errno value is returned. See
  291. * getpeername() for the list of appropriate error numbers.
  292. *
  293. ****************************************************************************/
  294. static int netlink_getpeername(FAR struct socket *psock,
  295. FAR struct sockaddr *addr,
  296. FAR socklen_t *addrlen)
  297. {
  298. FAR struct sockaddr_nl *nladdr;
  299. FAR struct netlink_conn_s *conn;
  300. DEBUGASSERT(psock != NULL && psock->s_conn != NULL && addr != NULL &&
  301. addrlen != NULL && *addrlen >= sizeof(struct sockaddr_nl));
  302. conn = (FAR struct netlink_conn_s *)psock->s_conn;
  303. /* Return the address information in the address structure */
  304. nladdr = (FAR struct sockaddr_nl *)addr;
  305. memset(nladdr, 0, sizeof(struct sockaddr_nl));
  306. nladdr->nl_family = AF_NETLINK;
  307. nladdr->nl_pid = conn->dst_pid;
  308. nladdr->nl_groups = conn->dst_groups;
  309. *addrlen = sizeof(struct sockaddr_nl);
  310. return OK;
  311. }
  312. /****************************************************************************
  313. * Name: netlink_listen
  314. *
  315. * Description:
  316. * To accept connections, a socket is first created with psock_socket(), a
  317. * willingness to accept incoming connections and a queue limit for
  318. * incoming connections are specified with psock_listen(), and then the
  319. * connections are accepted with psock_accept(). For the case of AFINET
  320. * and AFINET6 sockets, psock_listen() calls this function. The
  321. * psock_listen() call applies only to sockets of type SOCK_STREAM or
  322. * SOCK_SEQPACKET.
  323. *
  324. * Input Parameters:
  325. * psock Reference to an internal, bound socket structure.
  326. * backlog The maximum length the queue of pending connections may grow.
  327. * If a connection request arrives with the queue full, the client
  328. * may receive an error with an indication of ECONNREFUSED or,
  329. * if the underlying protocol supports retransmission, the request
  330. * may be ignored so that retries succeed.
  331. *
  332. * Returned Value:
  333. * On success, zero is returned. On error, a negated errno value is
  334. * returned. See listen() for the set of appropriate error values.
  335. *
  336. ****************************************************************************/
  337. static int netlink_listen(FAR struct socket *psock, int backlog)
  338. {
  339. return -EOPNOTSUPP;
  340. }
  341. /****************************************************************************
  342. * Name: netlink_connect
  343. *
  344. * Description:
  345. * Perform a netlink connection
  346. *
  347. * Input Parameters:
  348. * psock A reference to the structure of the socket to be connected
  349. * addr The address of the remote server to connect to
  350. * addrlen Length of address buffer
  351. *
  352. * Returned Value:
  353. * None
  354. *
  355. * Assumptions:
  356. *
  357. ****************************************************************************/
  358. static int netlink_connect(FAR struct socket *psock,
  359. FAR const struct sockaddr *addr,
  360. socklen_t addrlen)
  361. {
  362. FAR struct sockaddr_nl *nladdr;
  363. FAR struct netlink_conn_s *conn;
  364. DEBUGASSERT(psock != NULL && psock->s_conn != NULL && addr != NULL &&
  365. addrlen >= sizeof(struct sockaddr_nl));
  366. /* Save the address information in the connection structure */
  367. nladdr = (FAR struct sockaddr_nl *)addr;
  368. conn = (FAR struct netlink_conn_s *)psock->s_conn;
  369. conn->dst_pid = nladdr->nl_pid;
  370. conn->dst_groups = nladdr->nl_groups;
  371. return OK;
  372. }
  373. /****************************************************************************
  374. * Name: netlink_accept
  375. *
  376. * Description:
  377. * The netlink_accept function is used with connection-based socket
  378. * types (SOCK_STREAM, SOCK_SEQPACKET and SOCK_RDM). It extracts the first
  379. * connection request on the queue of pending connections, creates a new
  380. * connected socket with mostly the same properties as 'sockfd', and
  381. * allocates a new socket descriptor for the socket, which is returned. The
  382. * newly created socket is no longer in the listening state. The original
  383. * socket 'sockfd' is unaffected by this call. Per file descriptor flags
  384. * are not inherited across an inet_accept.
  385. *
  386. * The 'sockfd' argument is a socket descriptor that has been created with
  387. * socket(), bound to a local address with bind(), and is listening for
  388. * connections after a call to listen().
  389. *
  390. * On return, the 'addr' structure is filled in with the address of the
  391. * connecting entity. The 'addrlen' argument initially contains the size
  392. * of the structure pointed to by 'addr'; on return it will contain the
  393. * actual length of the address returned.
  394. *
  395. * If no pending connections are present on the queue, and the socket is
  396. * not marked as non-blocking, accept blocks the caller until a
  397. * connection is present. If the socket is marked non-blocking and no
  398. * pending connections are present on the queue, inet_accept returns
  399. * EAGAIN.
  400. *
  401. * Input Parameters:
  402. * psock Reference to the listening socket structure
  403. * addr Receives the address of the connecting client
  404. * addrlen Input: Allocated size of 'addr'
  405. * Return: Actual size returned size of 'addr'
  406. * newsock Location to return the accepted socket information.
  407. *
  408. * Returned Value:
  409. * Returns 0 (OK) on success. On failure, it returns a negated errno
  410. * value. See accept() for a description of the appropriate error value.
  411. *
  412. * Assumptions:
  413. * The network is locked.
  414. *
  415. ****************************************************************************/
  416. static int netlink_accept(FAR struct socket *psock,
  417. FAR struct sockaddr *addr, FAR socklen_t *addrlen,
  418. FAR struct socket *newsock)
  419. {
  420. return -EOPNOTSUPP;
  421. }
  422. /****************************************************************************
  423. * Name: netlink_response_available
  424. *
  425. * Description:
  426. * Handle a Netlink response available notification.
  427. *
  428. * Input Parameters:
  429. * Standard work handler parameters
  430. *
  431. * Returned Value:
  432. * None
  433. *
  434. ****************************************************************************/
  435. static void netlink_response_available(FAR void *arg)
  436. {
  437. FAR struct netlink_conn_s *conn = arg;
  438. DEBUGASSERT(conn != NULL);
  439. /* The following should always be true ... but maybe not in some race
  440. * condition?
  441. */
  442. sched_lock();
  443. net_lock();
  444. if (conn->pollsem != NULL && conn->pollevent != NULL)
  445. {
  446. /* Wake up the poll() with POLLIN */
  447. *conn->pollevent |= POLLIN;
  448. nxsem_post(conn->pollsem);
  449. }
  450. else
  451. {
  452. nwarn("WARNING: Missing references in connection.\n");
  453. }
  454. /* Allow another poll() */
  455. conn->pollsem = NULL;
  456. conn->pollevent = NULL;
  457. net_unlock();
  458. sched_unlock();
  459. }
  460. /****************************************************************************
  461. * Name: netlink_poll
  462. *
  463. * Description:
  464. * The standard poll() operation redirects operations on socket descriptors
  465. * to this function.
  466. *
  467. * POLLUP: Will never be reported
  468. * POLLERR: Reported in the event of any failure.
  469. * POLLOUT: Always reported if requested.
  470. * POLLIN: Reported if requested but only when pending response data is
  471. * available
  472. *
  473. * Input Parameters:
  474. * psock - An instance of the internal socket structure.
  475. * fds - The structure describing the events to be monitored.
  476. * setup - true: Setup up the poll; false: Tear down the poll
  477. *
  478. * Returned Value:
  479. * 0: Success; Negated errno on failure
  480. *
  481. ****************************************************************************/
  482. static int netlink_poll(FAR struct socket *psock, FAR struct pollfd *fds,
  483. bool setup)
  484. {
  485. FAR struct netlink_conn_s *conn;
  486. int ret = OK;
  487. DEBUGASSERT(psock != NULL && psock->s_conn != NULL);
  488. conn = (FAR struct netlink_conn_s *)psock->s_conn;
  489. /* Check if we are setting up or tearing down the poll */
  490. if (setup)
  491. {
  492. /* If POLLOUT is selected, return immediately (maybe) */
  493. pollevent_t revents = POLLOUT;
  494. /* If POLLIN is selected and a response is available, return
  495. * immediately (maybe).
  496. */
  497. net_lock();
  498. if (netlink_check_response(conn))
  499. {
  500. revents |= POLLIN;
  501. }
  502. /* But return ONLY if POLLIN and/or POLLIN are included in the
  503. * requested event set.
  504. */
  505. revents &= fds->events;
  506. if (revents != 0)
  507. {
  508. fds->revents = revents;
  509. nxsem_post(fds->sem);
  510. net_unlock();
  511. return OK;
  512. }
  513. /* Set up to be notified when a response is available if POLLIN is
  514. * requested.
  515. */
  516. if ((fds->events & POLLIN) != 0)
  517. {
  518. /* Some limitations: There can be only a single outstanding POLLIN
  519. * on the Netlink connection.
  520. */
  521. if (conn->pollsem != NULL || conn->pollevent != NULL)
  522. {
  523. nerr("ERROR: Multiple polls() on socket not supported.\n");
  524. net_unlock();
  525. return -EBUSY;
  526. }
  527. /* Set up the notification */
  528. conn->pollsem = fds->sem;
  529. conn->pollevent = &fds->revents;
  530. ret = netlink_notifier_setup(netlink_response_available,
  531. conn, conn);
  532. if (ret < 0)
  533. {
  534. nerr("ERROR: netlink_notifier_setup() failed: %d\n", ret);
  535. conn->pollsem = NULL;
  536. conn->pollevent = NULL;
  537. }
  538. }
  539. net_unlock();
  540. }
  541. else
  542. {
  543. /* Cancel any response notifications */
  544. ret = netlink_notifier_teardown(conn);
  545. conn->pollsem = NULL;
  546. conn->pollevent = NULL;
  547. }
  548. return ret;
  549. }
  550. /****************************************************************************
  551. * Name: netlink_sendmsg
  552. *
  553. * Description:
  554. * If sendmsg() is used on a connection-mode (SOCK_STREAM, SOCK_SEQPACKET)
  555. * socket, the parameters 'msg_name' and 'msg_namelen' are ignored (and the
  556. * error EISCONN may be returned when they are not NULL and 0), and the
  557. * error ENOTCONN is returned when the socket was not actually connected.
  558. *
  559. * Input Parameters:
  560. * psock A reference to the structure of the socket to be connected
  561. * msg msg to send
  562. * flags Send flags (ignored)
  563. *
  564. * Returned Value:
  565. * On success, returns the number of characters sent. On error, a negated
  566. * errno value is returned (see sendmsg() for the list of appropriate error
  567. * values.
  568. *
  569. * Assumptions:
  570. *
  571. ****************************************************************************/
  572. static ssize_t netlink_sendmsg(FAR struct socket *psock,
  573. FAR struct msghdr *msg, int flags)
  574. {
  575. FAR const void *buf = msg->msg_iov->iov_base;
  576. size_t len = msg->msg_iov->iov_len;
  577. FAR const struct sockaddr *to = msg->msg_name;
  578. socklen_t tolen = msg->msg_namelen;
  579. FAR struct netlink_conn_s *conn;
  580. FAR struct nlmsghdr *nlmsg;
  581. struct sockaddr_nl nladdr;
  582. int ret;
  583. DEBUGASSERT(psock != NULL && psock->s_conn != NULL && buf != NULL);
  584. /* Validity check, only single iov supported */
  585. if (msg->msg_iovlen != 1)
  586. {
  587. return -ENOTSUP;
  588. }
  589. /* Get the underlying connection structure */
  590. conn = (FAR struct netlink_conn_s *)psock->s_conn;
  591. if (to == NULL)
  592. {
  593. /* netlink_send() */
  594. /* Format the address */
  595. nladdr.nl_family = AF_NETLINK;
  596. nladdr.nl_pad = 0;
  597. nladdr.nl_pid = conn->dst_pid;
  598. nladdr.nl_groups = conn->dst_groups;
  599. to = (FAR const struct sockaddr *)&nladdr;
  600. tolen = sizeof(struct sockaddr_nl);
  601. }
  602. DEBUGASSERT(tolen >= sizeof(struct sockaddr_nl));
  603. /* Get a reference to the netlink message */
  604. nlmsg = (FAR struct nlmsghdr *)buf;
  605. DEBUGASSERT(nlmsg->nlmsg_len >= sizeof(struct nlmsghdr));
  606. switch (conn->protocol)
  607. {
  608. #ifdef CONFIG_NETLINK_ROUTE
  609. case NETLINK_ROUTE:
  610. ret = netlink_route_sendto(conn, nlmsg, len, flags,
  611. (FAR const struct sockaddr_nl *)to,
  612. tolen);
  613. break;
  614. #endif
  615. default:
  616. ret = -EOPNOTSUPP;
  617. break;
  618. }
  619. return ret;
  620. }
  621. /****************************************************************************
  622. * Name: netlink_recvmsg
  623. *
  624. * Description:
  625. * recvmsg() receives messages from a socket, and may be used to receive
  626. * data on a socket whether or not it is connection-oriented.
  627. *
  628. * If msg_name is not NULL, and the underlying protocol provides the source
  629. * address, this source address is filled in. The argument 'msg_namelen' is
  630. * initialized to the size of the buffer associated with msg_name, and
  631. * modified on return to indicate the actual size of the address stored
  632. * there.
  633. *
  634. * Input Parameters:
  635. * psock A pointer to a NuttX-specific, internal socket structure
  636. * msg Buffer to receive the message
  637. * flags Receive flags (ignored)
  638. *
  639. ****************************************************************************/
  640. static ssize_t netlink_recvmsg(FAR struct socket *psock,
  641. FAR struct msghdr *msg, int flags)
  642. {
  643. FAR void *buf = msg->msg_iov->iov_base;
  644. size_t len = msg->msg_iov->iov_len;
  645. FAR struct sockaddr *from = msg->msg_name;
  646. FAR socklen_t *fromlen = &msg->msg_namelen;
  647. FAR struct netlink_response_s *entry;
  648. DEBUGASSERT(psock != NULL && psock->s_conn != NULL && buf != NULL);
  649. DEBUGASSERT(from == NULL ||
  650. (fromlen != NULL && *fromlen >= sizeof(struct sockaddr_nl)));
  651. /* Find the response to this message. The return value */
  652. entry = netlink_tryget_response(psock->s_conn);
  653. if (entry == NULL)
  654. {
  655. /* No response is variable, but presumably, one is expected. Check
  656. * if the socket has been configured for non-blocking operation.
  657. */
  658. if (_SS_ISNONBLOCK(psock->s_flags) || (flags & MSG_DONTWAIT) != 0)
  659. {
  660. return -EAGAIN;
  661. }
  662. /* Wait for the response. This should always succeed. */
  663. entry = netlink_get_response(psock->s_conn);
  664. DEBUGASSERT(entry != NULL);
  665. if (entry == NULL)
  666. {
  667. return -EPIPE;
  668. }
  669. }
  670. if (len > entry->msg.nlmsg_len)
  671. {
  672. len = entry->msg.nlmsg_len;
  673. }
  674. /* Copy the payload to the user buffer */
  675. memcpy(buf, &entry->msg, len);
  676. kmm_free(entry);
  677. if (from != NULL)
  678. {
  679. netlink_getpeername(psock, from, fromlen);
  680. }
  681. return len;
  682. }
  683. /****************************************************************************
  684. * Name: netlink_close
  685. *
  686. * Description:
  687. * Performs the close operation on a NetLink socket instance
  688. *
  689. * Input Parameters:
  690. * psock Socket instance
  691. *
  692. * Returned Value:
  693. * 0 on success; -1 on error with errno set appropriately.
  694. *
  695. * Assumptions:
  696. *
  697. ****************************************************************************/
  698. static int netlink_close(FAR struct socket *psock)
  699. {
  700. FAR struct netlink_conn_s *conn = psock->s_conn;
  701. int ret = OK;
  702. /* Perform some pre-close operations for the NETLINK socket type. */
  703. /* Is this the last reference to the connection structure (there
  704. * could be more if the socket was dup'ed).
  705. */
  706. if (conn->crefs <= 1)
  707. {
  708. /* Free the connection structure */
  709. conn->crefs = 0;
  710. netlink_free(psock->s_conn);
  711. if (ret < 0)
  712. {
  713. /* Return with error code, but free resources. */
  714. nerr("ERROR: netlink_close failed: %d\n", ret);
  715. return ret;
  716. }
  717. }
  718. else
  719. {
  720. /* No.. Just decrement the reference count */
  721. conn->crefs--;
  722. }
  723. return ret;
  724. }
  725. #endif /* CONFIG_NET_NETLINK */