icmpv6_sockif.c 18 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499
  1. /****************************************************************************
  2. * net/icmpv6/icmpv6_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 <assert.h>
  29. #include <errno.h>
  30. #include <debug.h>
  31. #include <nuttx/mm/iob.h>
  32. #include <nuttx/net/net.h>
  33. #include <socket/socket.h>
  34. #include "icmpv6/icmpv6.h"
  35. #ifdef CONFIG_NET_ICMPv6_SOCKET
  36. /****************************************************************************
  37. * Private Function Prototypes
  38. ****************************************************************************/
  39. static int icmpv6_setup(FAR struct socket *psock, int protocol);
  40. static sockcaps_t icmpv6_sockcaps(FAR struct socket *psock);
  41. static void icmpv6_addref(FAR struct socket *psock);
  42. static int icmpv6_bind(FAR struct socket *psock,
  43. FAR const struct sockaddr *addr, socklen_t addrlen);
  44. static int icmpv6_getsockname(FAR struct socket *psock,
  45. FAR struct sockaddr *addr, FAR socklen_t *addrlen);
  46. static int icmpv6_getpeername(FAR struct socket *psock,
  47. FAR struct sockaddr *addr, FAR socklen_t *addrlen);
  48. static int icmpv6_listen(FAR struct socket *psock, int backlog);
  49. static int icmpv6_connect(FAR struct socket *psock,
  50. FAR const struct sockaddr *addr, socklen_t addrlen);
  51. static int icmpv6_accept(FAR struct socket *psock,
  52. FAR struct sockaddr *addr, FAR socklen_t *addrlen,
  53. FAR struct socket *newsock);
  54. static int icmpv6_netpoll(FAR struct socket *psock,
  55. FAR struct pollfd *fds, bool setup);
  56. static int icmpv6_close(FAR struct socket *psock);
  57. /****************************************************************************
  58. * Public Data
  59. ****************************************************************************/
  60. const struct sock_intf_s g_icmpv6_sockif =
  61. {
  62. icmpv6_setup, /* si_setup */
  63. icmpv6_sockcaps, /* si_sockcaps */
  64. icmpv6_addref, /* si_addref */
  65. icmpv6_bind, /* si_bind */
  66. icmpv6_getsockname, /* si_getsockname */
  67. icmpv6_getpeername, /* si_getpeername */
  68. icmpv6_listen, /* si_listen */
  69. icmpv6_connect, /* si_connect */
  70. icmpv6_accept, /* si_accept */
  71. icmpv6_netpoll, /* si_poll */
  72. icmpv6_sendmsg, /* si_sendmsg */
  73. icmpv6_recvmsg, /* si_recvmsg */
  74. icmpv6_close /* si_close */
  75. };
  76. /****************************************************************************
  77. * Private Functions
  78. ****************************************************************************/
  79. /****************************************************************************
  80. * Name: icmpv6_setup
  81. *
  82. * Description:
  83. * Called for socket() to verify that the provided socket type and
  84. * protocol are usable by this address family. Perform any family-
  85. * specific socket fields.
  86. *
  87. * Input Parameters:
  88. * psock A pointer to a user allocated socket structure to be
  89. * initialized.
  90. * protocol (see sys/socket.h)
  91. *
  92. * Returned Value:
  93. * Zero (OK) is returned on success. Otherwise, a negated errno value is
  94. * returned.
  95. *
  96. ****************************************************************************/
  97. static int icmpv6_setup(FAR struct socket *psock, int protocol)
  98. {
  99. /* Only SOCK_DGRAM and IPPROTO_ICMP6 are supported */
  100. if (psock->s_type == SOCK_DGRAM && protocol == IPPROTO_ICMP6)
  101. {
  102. /* Allocate the IPPROTO_ICMP6 socket connection structure and save in
  103. * the new socket instance.
  104. */
  105. FAR struct icmpv6_conn_s *conn = icmpv6_alloc();
  106. if (conn == NULL)
  107. {
  108. /* Failed to reserve a connection structure */
  109. return -ENOMEM;
  110. }
  111. /* Set the reference count on the connection structure.
  112. * This reference count will be incremented only if the socket is
  113. * dup'ed
  114. */
  115. DEBUGASSERT(conn->crefs == 0);
  116. conn->crefs = 1;
  117. /* Save the pre-allocated connection in the socket structure */
  118. psock->s_conn = conn;
  119. return OK;
  120. }
  121. else
  122. {
  123. return -EPROTONOSUPPORT;
  124. }
  125. }
  126. /****************************************************************************
  127. * Name: icmpv6_sockcaps
  128. *
  129. * Description:
  130. * Return the bit encoded capabilities of this socket.
  131. *
  132. * Input Parameters:
  133. * psock - Socket structure of the socket whose capabilities are being
  134. * queried.
  135. *
  136. * Returned Value:
  137. * The set of socket cababilities is returned.
  138. *
  139. ****************************************************************************/
  140. static sockcaps_t icmpv6_sockcaps(FAR struct socket *psock)
  141. {
  142. return SOCKCAP_NONBLOCKING;
  143. }
  144. /****************************************************************************
  145. * Name: icmpv6_addref
  146. *
  147. * Description:
  148. * Increment the reference count on the underlying connection structure.
  149. *
  150. * Input Parameters:
  151. * psock - Socket structure of the socket whose reference count will be
  152. * incremented.
  153. *
  154. * Returned Value:
  155. * None
  156. *
  157. ****************************************************************************/
  158. static void icmpv6_addref(FAR struct socket *psock)
  159. {
  160. FAR struct icmpv6_conn_s *conn;
  161. DEBUGASSERT(psock != NULL && psock->s_conn != NULL);
  162. conn = psock->s_conn;
  163. DEBUGASSERT(conn->crefs > 0 && conn->crefs < 255);
  164. conn->crefs++;
  165. }
  166. /****************************************************************************
  167. * Name: icmpv6_connect
  168. *
  169. * Description:
  170. * icmpv6_connect() connects the local socket referred to by the structure
  171. * 'psock' to the address specified by 'addr'. The addrlen argument
  172. * specifies the size of 'addr'. The format of the address in 'addr' is
  173. * determined by the address space of the socket 'psock'.
  174. *
  175. * If the socket 'psock' is of type SOCK_DGRAM then 'addr' is the address
  176. * to which datagrams are sent by default, and the only address from which
  177. * datagrams are received. If the socket is of type SOCK_STREAM or
  178. * SOCK_SEQPACKET, this call attempts to make a connection to the socket
  179. * that is bound to the address specified by 'addr'.
  180. *
  181. * Generally, connection-based protocol sockets may successfully
  182. * icmpv6_connect() only once; connectionless protocol sockets may use
  183. * icmpv6_connect() multiple times to change their association.
  184. * Connectionless sockets may dissolve the association by connecting to
  185. * an address with the sa_family member of sockaddr set to AF_UNSPEC.
  186. *
  187. * Input Parameters:
  188. * psock Pointer to a socket structure initialized by psock_socket()
  189. * addr Server address (form depends on type of socket)
  190. * addrlen Length of actual 'addr'
  191. *
  192. * Returned Value:
  193. * 0 on success; a negated errno value on failure. See connect() for the
  194. * list of appropriate errno values to be returned.
  195. *
  196. ****************************************************************************/
  197. static int icmpv6_connect(FAR struct socket *psock,
  198. FAR const struct sockaddr *addr, socklen_t addrlen)
  199. {
  200. return -EAFNOSUPPORT;
  201. }
  202. /****************************************************************************
  203. * Name: icmpv6_accept
  204. *
  205. * Description:
  206. * The icmpv6_accept function is used with connection-based socket types
  207. * (SOCK_STREAM, SOCK_SEQPACKET and SOCK_RDM). It extracts the first
  208. * connection request on the queue of pending connections, creates a new
  209. * connected socket with mostly the same properties as 'sockfd', and
  210. * allocates a new socket descriptor for the socket, which is returned. The
  211. * newly created socket is no longer in the listening state. The original
  212. * socket 'sockfd' is unaffected by this call. Per file descriptor flags
  213. * are not inherited across an icmpv6_accept.
  214. *
  215. * The 'sockfd' argument is a socket descriptor that has been created with
  216. * socket(), bound to a local address with bind(), and is listening for
  217. * connections after a call to listen().
  218. *
  219. * On return, the 'addr' structure is filled in with the address of the
  220. * connecting entity. The 'addrlen' argument initially contains the size
  221. * of the structure pointed to by 'addr'; on return it will contain the
  222. * actual length of the address returned.
  223. *
  224. * If no pending connections are present on the queue, and the socket is
  225. * not marked as non-blocking, icmpv6_accept blocks the caller until a
  226. * connection is present. If the socket is marked non-blocking and no
  227. * pending connections are present on the queue, icmpv6_accept returns
  228. * EAGAIN.
  229. *
  230. * Input Parameters:
  231. * psock Reference to the listening socket structure
  232. * addr Receives the address of the connecting client
  233. * addrlen Input: allocated size of 'addr',
  234. * Return: returned size of 'addr'
  235. * newsock Location to return the accepted socket information.
  236. *
  237. * Returned Value:
  238. * Returns 0 (OK) on success. On failure, it returns a negated errno
  239. * value. See accept() for a description of the appropriate error value.
  240. *
  241. * Assumptions:
  242. * The network is locked.
  243. *
  244. ****************************************************************************/
  245. static int icmpv6_accept(FAR struct socket *psock, FAR struct sockaddr *addr,
  246. FAR socklen_t *addrlen, FAR struct socket *newsock)
  247. {
  248. return -EAFNOSUPPORT;
  249. }
  250. /****************************************************************************
  251. * Name: icmpv6_bind
  252. *
  253. * Description:
  254. * icmpv6_bind() gives the socket 'psock' the local address 'addr'. 'addr'
  255. * is 'addrlen' bytes long. Traditionally, this is called "assigning a
  256. * name to a socket." When a socket is created with socket(), it exists
  257. * in a name space (address family) but has no name assigned.
  258. *
  259. * Input Parameters:
  260. * psock Socket structure of the socket to bind
  261. * addr Socket local address
  262. * addrlen Length of 'addr'
  263. *
  264. * Returned Value:
  265. * 0 on success; A negated errno value is returned on failure. See
  266. * bind() for a list a appropriate error values.
  267. *
  268. ****************************************************************************/
  269. static int icmpv6_bind(FAR struct socket *psock,
  270. FAR const struct sockaddr *addr,
  271. socklen_t addrlen)
  272. {
  273. /* An ICMPv6 socket cannot be bound to a local address */
  274. return -EBADF;
  275. }
  276. /****************************************************************************
  277. * Name: icmpv6_getsockname
  278. *
  279. * Description:
  280. * The icmpv6_getsockname() function retrieves the locally-bound name of
  281. * the specified packet socket, stores this address in the sockaddr
  282. * structure pointed to by the 'addr' argument, and stores the length of
  283. * this address in the object pointed to by the 'addrlen' argument.
  284. *
  285. * If the actual length of the address is greater than the length of the
  286. * supplied sockaddr structure, the stored address will be truncated.
  287. *
  288. * If the socket has not been bound to a local name, the value stored in
  289. * the object pointed to by address is unspecified.
  290. *
  291. * Input Parameters:
  292. * psock Socket structure of the socket to be queried
  293. * addr sockaddr structure to receive data [out]
  294. * addrlen Length of sockaddr structure [in/out]
  295. *
  296. * Returned Value:
  297. * On success, 0 is returned, the 'addr' argument points to the address
  298. * of the socket, and the 'addrlen' argument points to the length of the
  299. * address. Otherwise, a negated errno value is returned. See
  300. * getsockname() for the list of appropriate error numbers.
  301. *
  302. ****************************************************************************/
  303. static int icmpv6_getsockname(FAR struct socket *psock,
  304. FAR struct sockaddr *addr, FAR socklen_t *addrlen)
  305. {
  306. return -EAFNOSUPPORT;
  307. }
  308. /****************************************************************************
  309. * Name: icmpv6_getpeername
  310. *
  311. * Description:
  312. * The icmpv6_getpeername() function retrieves the remote-connected name of
  313. * the specified packet socket, stores this address in the sockaddr
  314. * structure pointed to by the 'addr' argument, and stores the length of
  315. * this address in the object pointed to by the 'addrlen' argument.
  316. *
  317. * If the actual length of the address is greater than the length of the
  318. * supplied sockaddr structure, the stored address will be truncated.
  319. *
  320. * If the socket has not been bound to a local name, the value stored in
  321. * the object pointed to by address is unspecified.
  322. *
  323. * Parameters:
  324. * psock Socket structure of the socket to be queried
  325. * addr sockaddr structure to receive data [out]
  326. * addrlen Length of sockaddr structure [in/out]
  327. *
  328. * Returned Value:
  329. * On success, 0 is returned, the 'addr' argument points to the address
  330. * of the socket, and the 'addrlen' argument points to the length of the
  331. * address. Otherwise, a negated errno value is returned. See
  332. * getpeername() for the list of appropriate error numbers.
  333. *
  334. ****************************************************************************/
  335. static int icmpv6_getpeername(FAR struct socket *psock,
  336. FAR struct sockaddr *addr, FAR socklen_t *addrlen)
  337. {
  338. return -EAFNOSUPPORT;
  339. }
  340. /****************************************************************************
  341. * Name: icmpv6_listen
  342. *
  343. * Description:
  344. * To accept connections, a socket is first created with psock_socket(), a
  345. * willingness to accept incoming connections and a queue limit for
  346. * incoming connections are specified with psock_listen(), and then the
  347. * connections are accepted with psock_accept(). For the case of raw
  348. * packet sockets, psock_listen() calls this function. The psock_listen()
  349. * call applies only to sockets of type SOCK_STREAM or SOCK_SEQPACKET.
  350. *
  351. * Input Parameters:
  352. * psock Reference to an internal, boound socket structure.
  353. * backlog The maximum length the queue of pending connections may grow.
  354. * If a connection request arrives with the queue full, the client
  355. * may receive an error with an indication of ECONNREFUSED or,
  356. * if the underlying protocol supports retransmission, the request
  357. * may be ignored so that retries succeed.
  358. *
  359. * Returned Value:
  360. * On success, zero is returned. On error, a negated errno value is
  361. * returned. See listen() for the set of appropriate error values.
  362. *
  363. ****************************************************************************/
  364. int icmpv6_listen(FAR struct socket *psock, int backlog)
  365. {
  366. return -EOPNOTSUPP;
  367. }
  368. /****************************************************************************
  369. * Name: icmpv6_netpoll
  370. *
  371. * Description:
  372. * The standard poll() operation redirects operations on socket descriptors
  373. * to net_poll which, indiectly, calls to function.
  374. *
  375. * Input Parameters:
  376. * psock - An instance of the internal socket structure.
  377. * fds - The structure describing the events to be monitored, OR NULL if
  378. * this is a request to stop monitoring events.
  379. * setup - true: Setup up the poll; false: Teardown the poll
  380. *
  381. * Returned Value:
  382. * 0: Success; Negated errno on failure
  383. *
  384. ****************************************************************************/
  385. static int icmpv6_netpoll(FAR struct socket *psock, FAR struct pollfd *fds,
  386. bool setup)
  387. {
  388. /* Check if we are setting up or tearing down the poll */
  389. if (setup)
  390. {
  391. /* Perform the ICMPv6 poll() setup */
  392. return icmpv6_pollsetup(psock, fds);
  393. }
  394. else
  395. {
  396. /* Perform the ICMPv6 poll() teardown */
  397. return icmpv6_pollteardown(psock, fds);
  398. }
  399. }
  400. /****************************************************************************
  401. * Name: icmpv6_close
  402. *
  403. * Description:
  404. * Performs the close operation on a raw packet socket instance
  405. *
  406. * Input Parameters:
  407. * psock Socket instance
  408. *
  409. * Returned Value:
  410. * 0 on success; a negated errno value is returned on any failure.
  411. *
  412. * Assumptions:
  413. *
  414. ****************************************************************************/
  415. static int icmpv6_close(FAR struct socket *psock)
  416. {
  417. FAR struct icmpv6_conn_s *conn;
  418. DEBUGASSERT(psock != NULL && psock->s_conn != NULL);
  419. conn = psock->s_conn;
  420. /* Is this the last reference to the connection structure (there could be\
  421. * more if the socket was dup'ed).
  422. */
  423. DEBUGASSERT(conn->crefs > 0);
  424. if (conn->crefs <= 1)
  425. {
  426. /* Yes... free any read-ahead data */
  427. iob_free_queue(&conn->readahead, IOBUSER_NET_SOCK_ICMPv6);
  428. /* Then free the connection structure */
  429. conn->crefs = 0; /* No more references on the connection */
  430. icmpv6_free(psock->s_conn); /* Free network resources */
  431. }
  432. else
  433. {
  434. /* No.. Just decrement the reference count */
  435. conn->crefs--;
  436. }
  437. return OK;
  438. }
  439. /****************************************************************************
  440. * Public Functions
  441. ****************************************************************************/
  442. #endif /* CONFIG_NET_ICMPv6_SOCKET */