udp_conn.c 28 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905
  1. /****************************************************************************
  2. * net/udp/udp_conn.c
  3. *
  4. * Copyright (C) 2007-2009, 2011-2012, 2016, 2018 Gregory Nutt. All rights
  5. * reserved.
  6. * Author: Gregory Nutt <gnutt@nuttx.org>
  7. *
  8. * Large parts of this file were leveraged from uIP logic:
  9. *
  10. * Copyright (c) 2001-2003, Adam Dunkels.
  11. * All rights reserved.
  12. *
  13. * Redistribution and use in source and binary forms, with or without
  14. * modification, are permitted provided that the following conditions
  15. * are met:
  16. *
  17. * 1. Redistributions of source code must retain the above copyright
  18. * notice, this list of conditions and the following disclaimer.
  19. * 2. Redistributions in binary form must reproduce the above copyright
  20. * notice, this list of conditions and the following disclaimer in the
  21. * documentation and/or other materials provided with the distribution.
  22. * 3. The name of the author may not be used to endorse or promote
  23. * products derived from this software without specific prior
  24. * written permission.
  25. *
  26. * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS
  27. * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
  28. * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
  29. * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
  30. * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
  31. * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
  32. * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
  33. * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
  34. * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
  35. * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
  36. * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  37. *
  38. ****************************************************************************/
  39. /****************************************************************************
  40. * Included Files
  41. ****************************************************************************/
  42. #include <nuttx/config.h>
  43. #if defined(CONFIG_NET) && defined(CONFIG_NET_UDP)
  44. #include <stdint.h>
  45. #include <string.h>
  46. #include <assert.h>
  47. #include <errno.h>
  48. #include <debug.h>
  49. #include <netinet/in.h>
  50. #include <arch/irq.h>
  51. #include <nuttx/semaphore.h>
  52. #include <nuttx/net/netconfig.h>
  53. #include <nuttx/net/net.h>
  54. #include <nuttx/net/netdev.h>
  55. #include <nuttx/net/ip.h>
  56. #include <nuttx/net/udp.h>
  57. #include "devif/devif.h"
  58. #include "netdev/netdev.h"
  59. #include "inet/inet.h"
  60. #include "udp/udp.h"
  61. /****************************************************************************
  62. * Pre-processor Definitions
  63. ****************************************************************************/
  64. #define IPv4BUF ((struct ipv4_hdr_s *)&dev->d_buf[NET_LL_HDRLEN(dev)])
  65. #define IPv6BUF ((struct ipv6_hdr_s *)&dev->d_buf[NET_LL_HDRLEN(dev)])
  66. /****************************************************************************
  67. * Private Data
  68. ****************************************************************************/
  69. /* The array containing all UDP connections. */
  70. struct udp_conn_s g_udp_connections[CONFIG_NET_UDP_CONNS];
  71. /* A list of all free UDP connections */
  72. static dq_queue_t g_free_udp_connections;
  73. static sem_t g_free_sem;
  74. /* A list of all allocated UDP connections */
  75. static dq_queue_t g_active_udp_connections;
  76. /* Last port used by a UDP connection connection. */
  77. static uint16_t g_last_udp_port;
  78. /****************************************************************************
  79. * Private Functions
  80. ****************************************************************************/
  81. /****************************************************************************
  82. * Name: _udp_semtake() and _udp_semgive()
  83. *
  84. * Description:
  85. * Take/give semaphore
  86. *
  87. ****************************************************************************/
  88. static inline void _udp_semtake(FAR sem_t *sem)
  89. {
  90. int ret;
  91. /* Take the semaphore (perhaps waiting) */
  92. while ((ret = net_lockedwait(sem)) < 0)
  93. {
  94. /* The only case that an error should occur here is if
  95. * the wait was awakened by a signal.
  96. */
  97. DEBUGASSERT(ret == -EINTR || ret == -ECANCELED);
  98. }
  99. UNUSED(ret);
  100. }
  101. #define _udp_semgive(sem) nxsem_post(sem)
  102. /****************************************************************************
  103. * Name: udp_find_conn()
  104. *
  105. * Description:
  106. * Find the UDP connection that uses this local port number.
  107. *
  108. * Assumptions:
  109. * This function must be called with the network locked.
  110. *
  111. ****************************************************************************/
  112. static FAR struct udp_conn_s *udp_find_conn(uint8_t domain,
  113. FAR union ip_binding_u *ipaddr,
  114. uint16_t portno)
  115. {
  116. FAR struct udp_conn_s *conn;
  117. int i;
  118. /* Now search each connection structure. */
  119. for (i = 0; i < CONFIG_NET_UDP_CONNS; i++)
  120. {
  121. conn = &g_udp_connections[i];
  122. /* If the port local port number assigned to the connections matches
  123. * AND the IP address of the connection matches, then return a
  124. * reference to the connection structure. INADDR_ANY is a special
  125. * case: There can only be instance of a port number with INADDR_ANY.
  126. */
  127. #ifdef CONFIG_NET_IPv4
  128. #ifdef CONFIG_NET_IPv6
  129. if (domain == PF_INET)
  130. #endif
  131. {
  132. if (conn->lport == portno &&
  133. (net_ipv4addr_cmp(conn->u.ipv4.laddr, ipaddr->ipv4.laddr) ||
  134. net_ipv4addr_cmp(conn->u.ipv4.laddr, INADDR_ANY)))
  135. {
  136. return conn;
  137. }
  138. }
  139. #endif /* CONFIG_NET_IPv4 */
  140. #ifdef CONFIG_NET_IPv6
  141. #ifdef CONFIG_NET_IPv4
  142. else
  143. #endif
  144. {
  145. if (conn->lport == portno &&
  146. (net_ipv6addr_cmp(conn->u.ipv6.laddr, ipaddr->ipv6.laddr) ||
  147. net_ipv6addr_cmp(conn->u.ipv6.laddr, g_ipv6_unspecaddr)))
  148. {
  149. return conn;
  150. }
  151. }
  152. #endif /* CONFIG_NET_IPv6 */
  153. }
  154. return NULL;
  155. }
  156. /****************************************************************************
  157. * Name: udp_select_port
  158. *
  159. * Description:
  160. * Select an unused port number.
  161. *
  162. * NOTE that in principle this function could fail if there is no available
  163. * port number. There is no check for that case and it would actually
  164. * in an infinite loop if that were the case. In this simple, small UDP
  165. * implementation, it is reasonable to assume that that error cannot happen
  166. * and that a port number will always be available.
  167. *
  168. * Input Parameters:
  169. * None
  170. *
  171. * Returned Value:
  172. * Next available port number
  173. *
  174. ****************************************************************************/
  175. static uint16_t udp_select_port(uint8_t domain, FAR union ip_binding_u *u)
  176. {
  177. uint16_t portno;
  178. /* Find an unused local port number. Loop until we find a valid
  179. * listen port number that is not being used by any other connection.
  180. */
  181. net_lock();
  182. do
  183. {
  184. /* Guess that the next available port number will be the one after
  185. * the last port number assigned.
  186. */
  187. ++g_last_udp_port;
  188. /* Make sure that the port number is within range */
  189. if (g_last_udp_port >= 32000)
  190. {
  191. g_last_udp_port = 4096;
  192. }
  193. }
  194. while (udp_find_conn(domain, u, htons(g_last_udp_port)) != NULL);
  195. /* Initialize and return the connection structure, bind it to the
  196. * port number
  197. */
  198. portno = g_last_udp_port;
  199. net_unlock();
  200. return portno;
  201. }
  202. /****************************************************************************
  203. * Name: udp_ipv4_active
  204. *
  205. * Description:
  206. * Find a connection structure that is the appropriate connection to be
  207. * used within the provided UDP header
  208. *
  209. * Assumptions:
  210. * This function must be called with the network locked.
  211. *
  212. ****************************************************************************/
  213. #ifdef CONFIG_NET_IPv4
  214. static inline FAR struct udp_conn_s *
  215. udp_ipv4_active(FAR struct net_driver_s *dev, FAR struct udp_hdr_s *udp)
  216. {
  217. #ifdef CONFIG_NET_BROADCAST
  218. static const in_addr_t bcast = INADDR_BROADCAST;
  219. #endif
  220. FAR struct ipv4_hdr_s *ip = IPv4BUF;
  221. FAR struct udp_conn_s *conn;
  222. conn = (FAR struct udp_conn_s *)g_active_udp_connections.head;
  223. while (conn)
  224. {
  225. /* If the local UDP port is non-zero, the connection is considered
  226. * to be used. If so, then the following checks are performed:
  227. *
  228. * 1. The destination address is verified against the bound address
  229. * of the connection.
  230. *
  231. * - The local port number is checked against the destination port
  232. * number in the received packet.
  233. * - If multiple network interfaces are supported, then the local
  234. * IP address is available and we will insist that the
  235. * destination IP matches the bound address (or the destination
  236. * IP address is a broadcast address). If a socket is bound to
  237. * INADDRY_ANY (laddr), then it should receive all packets
  238. * directed to the port.
  239. *
  240. * 2. If this is a connection mode UDP socket, then the source address
  241. * is verified against the connected remote address.
  242. *
  243. * - The remote port number is checked if the connection is bound
  244. * to a remote port.
  245. * - Finally, if the connection is bound to a remote IP address,
  246. * the source IP address of the packet is checked. Broadcast
  247. * addresses are also accepted.
  248. *
  249. * If all of the above are true then the newly received UDP packet
  250. * is destined for this UDP connection.
  251. *
  252. * To send and receive multicast packets, the application should:
  253. *
  254. * - Bind socket to INADDR6_ANY (for the all-nodes multicast address)
  255. * or to a specific <multicast-address>
  256. * - setsockopt to SO_BROADCAST (for all-nodes address)
  257. *
  258. * For connection-less UDP sockets:
  259. *
  260. * - call sendto with sendaddr.sin_addr.s_addr = <multicast-address>
  261. * - call recvfrom.
  262. *
  263. * For connection-mode UDP sockets:
  264. *
  265. * - call connect() to connect the UDP socket to a specific remote
  266. * address, then
  267. * - Call send() with no address address information
  268. * - call recv() (from address information should not be needed)
  269. *
  270. * REVIST: SO_BROADCAST flag is currently ignored.
  271. */
  272. /* Check that there is a local port number and this is matches
  273. * the port number in the destination address.
  274. */
  275. if (conn->lport != 0 && udp->destport == conn->lport &&
  276. /* Local port accepts any address on this port or there
  277. * is an exact match in destipaddr and the bound local
  278. * address. This catches the receipt of a broadcast when
  279. * the socket is bound to INADDR_ANY.
  280. */
  281. (net_ipv4addr_cmp(conn->u.ipv4.laddr, INADDR_ANY) ||
  282. net_ipv4addr_hdrcmp(ip->destipaddr, &conn->u.ipv4.laddr)))
  283. {
  284. /* Check if the socket is connection mode. In this case, only
  285. * packets with source addresses from the connected remote peer
  286. * will be accepted.
  287. */
  288. if (_UDP_ISCONNECTMODE(conn->flags))
  289. {
  290. /* Check if the UDP connection is either (1) accepting packets
  291. * from any port or (2) the packet srcport matches the local
  292. * bound port number.
  293. */
  294. if ((conn->rport == 0 || udp->srcport == conn->rport) &&
  295. /* If (1) not connected to a remote address, or (2) a
  296. * broadcast destipaddr was received, or (3) there is an
  297. * exact match between the srcipaddr and the bound remote IP
  298. * address, then accept the packet.
  299. */
  300. (net_ipv4addr_cmp(conn->u.ipv4.raddr, INADDR_ANY) ||
  301. #ifdef CONFIG_NET_BROADCAST
  302. net_ipv4addr_hdrcmp(ip->destipaddr, &bcast) ||
  303. #endif
  304. net_ipv4addr_hdrcmp(ip->srcipaddr, &conn->u.ipv4.raddr)))
  305. {
  306. /* Matching connection found.. Break out of the loop and
  307. * return this reference to it.
  308. */
  309. break;
  310. }
  311. }
  312. else
  313. {
  314. /* This UDP socket is not connected. We need to match only
  315. * the destination address with the bound socket address.
  316. * Break out out of the loop and return this reference to
  317. * the matching connection structure.
  318. */
  319. break;
  320. }
  321. }
  322. /* Look at the next active connection */
  323. conn = (FAR struct udp_conn_s *)conn->node.flink;
  324. }
  325. return conn;
  326. }
  327. #endif /* CONFIG_NET_IPv4 */
  328. /****************************************************************************
  329. * Name: udp_ipv6_active
  330. *
  331. * Description:
  332. * Find a connection structure that is the appropriate connection to be
  333. * used within the provided UDP header
  334. *
  335. * Assumptions:
  336. * This function must be called with the network locked.
  337. *
  338. ****************************************************************************/
  339. #ifdef CONFIG_NET_IPv6
  340. static inline FAR struct udp_conn_s *
  341. udp_ipv6_active(FAR struct net_driver_s *dev, FAR struct udp_hdr_s *udp)
  342. {
  343. FAR struct ipv6_hdr_s *ip = IPv6BUF;
  344. FAR struct udp_conn_s *conn;
  345. conn = (FAR struct udp_conn_s *)g_active_udp_connections.head;
  346. while (conn != NULL)
  347. {
  348. /* If the local UDP port is non-zero, the connection is considered
  349. * to be used. If so, then the following checks are performed:
  350. *
  351. * 1. The destination address is verified against the bound address
  352. * of the connection.
  353. *
  354. * - The local port number is checked against the destination port
  355. * number in the received packet.
  356. * - If multiple network interfaces are supported, then the local
  357. * IP address is available and we will insist that the
  358. * destination IP matches the bound address. If a socket is bound
  359. * to INADDR6_ANY (laddr), then it should receive all packets
  360. * directed to the port. REVISIT: Should also depend on
  361. * SO_BROADCAST.
  362. *
  363. * 2. If this is a connection mode UDP socket, then the source address
  364. * is verified against the connected remote address.
  365. *
  366. * - The remote port number is checked if the connection is bound
  367. * to a remote port.
  368. * - Finally, if the connection is bound to a remote IP address,
  369. * the source IP address of the packet is checked.
  370. *
  371. * If all of the above are true then the newly received UDP packet
  372. * is destined for this UDP connection.
  373. *
  374. * To send and receive multicast packets, the application should:
  375. *
  376. * - Bind socket to INADDR6_ANY (for the all-nodes multicast address)
  377. * or to a specific <multicast-address>
  378. * - setsockopt to SO_BROADCAST (for all-nodes address)
  379. *
  380. * For connection-less UDP sockets:
  381. *
  382. * - call sendto with sendaddr.sin_addr.s_addr = <multicast-address>
  383. * - call recvfrom.
  384. *
  385. * For connection-mode UDP sockets:
  386. *
  387. * - call connect() to connect the UDP socket to a specific remote
  388. * address, then
  389. * - Call send() with no address address information
  390. * - call recv() (from address information should not be needed)
  391. *
  392. * REVIST: SO_BROADCAST flag is currently ignored.
  393. */
  394. /* Check that there is a local port number and this is matches
  395. * the port number in the destination address.
  396. */
  397. if ((conn->lport != 0 && udp->destport == conn->lport &&
  398. /* Check if the local port accepts any address on this port or
  399. * that there is an exact match between the destipaddr and the
  400. * bound local address. This catches the case of the all nodes
  401. * multicast when the socket is bound to the IPv6 unspecified
  402. * address.
  403. */
  404. (net_ipv6addr_cmp(conn->u.ipv6.laddr, g_ipv6_unspecaddr) ||
  405. net_ipv6addr_hdrcmp(ip->destipaddr, conn->u.ipv6.laddr))))
  406. {
  407. /* Check if the socket is connection mode. In this case, only
  408. * packets with source addresses from the connected remote peer
  409. * will be accepted.
  410. */
  411. if (_UDP_ISCONNECTMODE(conn->flags))
  412. {
  413. /* Check if the UDP connection is either (1) accepting packets
  414. * from any port or (2) the packet srcport matches the local
  415. * bound port number.
  416. */
  417. if ((conn->rport == 0 || udp->srcport == conn->rport) &&
  418. /* If (1) not connected to a remote address, or (2) a all-
  419. * nodes multicast destipaddr was received, or (3) there is an
  420. * exact match between the srcipaddr and the bound remote IP
  421. * address, then accept the packet.
  422. */
  423. (net_ipv6addr_cmp(conn->u.ipv6.raddr, g_ipv6_unspecaddr) ||
  424. #ifdef CONFIG_NET_BROADCAST
  425. net_ipv6addr_hdrcmp(ip->destipaddr, g_ipv6_allnodes) ||
  426. #endif
  427. net_ipv6addr_hdrcmp(ip->srcipaddr, conn->u.ipv6.raddr)))
  428. {
  429. /* Matching connection found.. Break out of the loop and
  430. * return this reference to it.
  431. */
  432. break;
  433. }
  434. }
  435. else
  436. {
  437. /* This UDP socket is not connected. We need to match only
  438. * the destination address with the bound socket address.
  439. * Break out out of the loop and return this reference to
  440. * the matching connection structure.
  441. */
  442. break;
  443. }
  444. }
  445. /* Look at the next active connection */
  446. conn = (FAR struct udp_conn_s *)conn->node.flink;
  447. }
  448. return conn;
  449. }
  450. #endif /* CONFIG_NET_IPv6 */
  451. /****************************************************************************
  452. * Public Functions
  453. ****************************************************************************/
  454. /****************************************************************************
  455. * Name: udp_initialize
  456. *
  457. * Description:
  458. * Initialize the UDP connection structures. Called once and only from
  459. * the UIP layer.
  460. *
  461. ****************************************************************************/
  462. void udp_initialize(void)
  463. {
  464. int i;
  465. /* Initialize the queues */
  466. dq_init(&g_free_udp_connections);
  467. dq_init(&g_active_udp_connections);
  468. nxsem_init(&g_free_sem, 0, 1);
  469. for (i = 0; i < CONFIG_NET_UDP_CONNS; i++)
  470. {
  471. /* Mark the connection closed and move it to the free list */
  472. g_udp_connections[i].lport = 0;
  473. dq_addlast(&g_udp_connections[i].node, &g_free_udp_connections);
  474. }
  475. g_last_udp_port = 1024;
  476. }
  477. /****************************************************************************
  478. * Name: udp_alloc
  479. *
  480. * Description:
  481. * Allocate a new, uninitialized UDP connection structure. This is
  482. * normally something done by the implementation of the socket() API
  483. *
  484. ****************************************************************************/
  485. FAR struct udp_conn_s *udp_alloc(uint8_t domain)
  486. {
  487. FAR struct udp_conn_s *conn;
  488. /* The free list is protected by a semaphore (that behaves like a mutex). */
  489. _udp_semtake(&g_free_sem);
  490. conn = (FAR struct udp_conn_s *)dq_remfirst(&g_free_udp_connections);
  491. if (conn)
  492. {
  493. /* Make sure that the connection is marked as uninitialized */
  494. conn->flags = 0;
  495. #if defined(CONFIG_NET_IPv4) && defined(CONFIG_NET_IPv6)
  496. conn->domain = domain;
  497. #endif
  498. #ifdef CONFIG_NET_UDP_BINDTODEVICE
  499. conn->boundto = 0; /* Not bound to any interface */
  500. #endif
  501. conn->lport = 0;
  502. conn->ttl = IP_TTL;
  503. #ifdef CONFIG_NET_UDP_WRITE_BUFFERS
  504. /* Initialize the write buffer lists */
  505. sq_init(&conn->write_q);
  506. #endif
  507. /* Enqueue the connection into the active list */
  508. dq_addlast(&conn->node, &g_active_udp_connections);
  509. }
  510. _udp_semgive(&g_free_sem);
  511. return conn;
  512. }
  513. /****************************************************************************
  514. * Name: udp_free
  515. *
  516. * Description:
  517. * Free a UDP connection structure that is no longer in use. This should be
  518. * done by the implementation of close().
  519. *
  520. ****************************************************************************/
  521. void udp_free(FAR struct udp_conn_s *conn)
  522. {
  523. #ifdef CONFIG_NET_UDP_WRITE_BUFFERS
  524. FAR struct udp_wrbuffer_s *wrbuffer;
  525. #endif
  526. /* The free list is protected by a semaphore (that behaves like a mutex). */
  527. DEBUGASSERT(conn->crefs == 0);
  528. _udp_semtake(&g_free_sem);
  529. conn->lport = 0;
  530. /* Remove the connection from the active list */
  531. dq_rem(&conn->node, &g_active_udp_connections);
  532. #ifdef CONFIG_NET_UDP_READAHEAD
  533. /* Release any read-ahead buffers attached to the connection */
  534. iob_free_queue(&conn->readahead);
  535. #endif
  536. #ifdef CONFIG_NET_UDP_WRITE_BUFFERS
  537. /* Release any write buffers attached to the connection */
  538. while ((wrbuffer = (struct udp_wrbuffer_s *)
  539. sq_remfirst(&conn->write_q)) != NULL)
  540. {
  541. udp_wrbuffer_release(wrbuffer);
  542. }
  543. #endif
  544. /* Free the connection */
  545. dq_addlast(&conn->node, &g_free_udp_connections);
  546. _udp_semgive(&g_free_sem);
  547. }
  548. /****************************************************************************
  549. * Name: udp_active
  550. *
  551. * Description:
  552. * Find a connection structure that is the appropriate
  553. * connection to be used within the provided UDP header
  554. *
  555. * Assumptions:
  556. * This function must be called with the network locked.
  557. *
  558. ****************************************************************************/
  559. FAR struct udp_conn_s *udp_active(FAR struct net_driver_s *dev,
  560. FAR struct udp_hdr_s *udp)
  561. {
  562. #ifdef CONFIG_NET_IPv6
  563. #ifdef CONFIG_NET_IPv4
  564. if (IFF_IS_IPv6(dev->d_flags))
  565. #endif
  566. {
  567. return udp_ipv6_active(dev, udp);
  568. }
  569. #endif /* CONFIG_NET_IPv6 */
  570. #ifdef CONFIG_NET_IPv4
  571. #ifdef CONFIG_NET_IPv6
  572. else
  573. #endif
  574. {
  575. return udp_ipv4_active(dev, udp);
  576. }
  577. #endif /* CONFIG_NET_IPv4 */
  578. }
  579. /****************************************************************************
  580. * Name: udp_nextconn
  581. *
  582. * Description:
  583. * Traverse the list of allocated UDP connections
  584. *
  585. * Assumptions:
  586. * This function must be called with the network locked.
  587. *
  588. ****************************************************************************/
  589. FAR struct udp_conn_s *udp_nextconn(FAR struct udp_conn_s *conn)
  590. {
  591. if (!conn)
  592. {
  593. return (FAR struct udp_conn_s *)g_active_udp_connections.head;
  594. }
  595. else
  596. {
  597. return (FAR struct udp_conn_s *)conn->node.flink;
  598. }
  599. }
  600. /****************************************************************************
  601. * Name: udp_bind
  602. *
  603. * Description:
  604. * This function implements the low level parts of the standard UDP
  605. * bind() operation.
  606. *
  607. * Assumptions:
  608. * This function is called from normal user level code.
  609. *
  610. ****************************************************************************/
  611. int udp_bind(FAR struct udp_conn_s *conn, FAR const struct sockaddr *addr)
  612. {
  613. uint16_t portno;
  614. int ret;
  615. #ifdef CONFIG_NET_IPv4
  616. #ifdef CONFIG_NET_IPv6
  617. if (conn->domain == PF_INET)
  618. #endif
  619. {
  620. FAR const struct sockaddr_in *inaddr =
  621. (FAR const struct sockaddr_in *)addr;
  622. /* Get the port number that we are binding to */
  623. portno = inaddr->sin_port;
  624. /* Bind the local IP address to the connection. NOTE this address may
  625. * be INADDR_ANY meaning, essentially, that we are binding to all
  626. * interfaces for receiving (Sending will use the default port).
  627. */
  628. net_ipv4addr_copy(conn->u.ipv4.laddr, inaddr->sin_addr.s_addr);
  629. }
  630. #endif /* CONFIG_NET_IPv4 */
  631. #ifdef CONFIG_NET_IPv6
  632. #ifdef CONFIG_NET_IPv4
  633. else
  634. #endif
  635. {
  636. FAR const struct sockaddr_in6 *inaddr =
  637. (FAR const struct sockaddr_in6 *)addr;
  638. /* Get the port number that we are binding to */
  639. portno = inaddr->sin6_port;
  640. /* Bind the local IP address to the connection. NOTE this address may
  641. * be INADDR_ANY meaning, essentially, that we are binding to all
  642. * interfaces for receiving (Sending will use the default port).
  643. */
  644. net_ipv6addr_copy(conn->u.ipv6.laddr,
  645. inaddr->sin6_addr.in6_u.u6_addr16);
  646. }
  647. #endif /* CONFIG_NET_IPv6 */
  648. /* Is the user requesting to bind to any port? */
  649. if (portno == 0)
  650. {
  651. /* Yes.. Select any unused local port number */
  652. conn->lport = htons(udp_select_port(conn->domain, &conn->u));
  653. ret = OK;
  654. }
  655. else
  656. {
  657. /* Interrupts must be disabled while access the UDP connection list */
  658. net_lock();
  659. /* Is any other UDP connection already bound to this address and port? */
  660. if (udp_find_conn(conn->domain, &conn->u, portno) == NULL)
  661. {
  662. /* No.. then bind the socket to the port */
  663. conn->lport = portno;
  664. ret = OK;
  665. }
  666. else
  667. {
  668. ret = -EADDRINUSE;
  669. }
  670. net_unlock();
  671. }
  672. return ret;
  673. }
  674. /****************************************************************************
  675. * Name: udp_connect
  676. *
  677. * Description:
  678. * This function simply assigns a remote address to UDP "connection"
  679. * structure. This function is called as part of the implementation of:
  680. *
  681. * - connect(). If connect() is called for a SOCK_DGRAM socket, then
  682. * this logic performs the moral equivalent of connect() operation
  683. * for the UDP socket.
  684. * - recvfrom() and sendto(). This function is called to set the
  685. * remote address of the peer.
  686. *
  687. * The function will automatically allocate an unused local port for the
  688. * new connection if the socket is not yet bound to a local address.
  689. * However, another port can be chosen by using the udp_bind() call,
  690. * after the udp_connect() function has been called.
  691. *
  692. * Input Parameters:
  693. * conn - A reference to UDP connection structure. A value of NULL will
  694. * disconnect from any previously connected address.
  695. * addr - The address of the remote host.
  696. *
  697. * Assumptions:
  698. * This function is called (indirectly) from user code. Interrupts may
  699. * be enabled.
  700. *
  701. ****************************************************************************/
  702. int udp_connect(FAR struct udp_conn_s *conn, FAR const struct sockaddr *addr)
  703. {
  704. /* Has this address already been bound to a local port (lport)? */
  705. if (!conn->lport)
  706. {
  707. /* No.. Find an unused local port number and bind it to the
  708. * connection structure.
  709. */
  710. conn->lport = htons(udp_select_port(conn->domain, &conn->u));
  711. }
  712. /* Is there a remote port (rport)? */
  713. if (addr != NULL)
  714. {
  715. #ifdef CONFIG_NET_IPv4
  716. #ifdef CONFIG_NET_IPv6
  717. if (conn->domain == PF_INET)
  718. #endif
  719. {
  720. FAR const struct sockaddr_in *inaddr =
  721. (FAR const struct sockaddr_in *)addr;
  722. conn->rport = inaddr->sin_port;
  723. net_ipv4addr_copy(conn->u.ipv4.raddr, inaddr->sin_addr.s_addr);
  724. }
  725. #endif /* CONFIG_NET_IPv4 */
  726. #ifdef CONFIG_NET_IPv6
  727. #ifdef CONFIG_NET_IPv4
  728. else
  729. #endif
  730. {
  731. FAR const struct sockaddr_in6 *inaddr =
  732. (FAR const struct sockaddr_in6 *)addr;
  733. conn->rport = inaddr->sin6_port;
  734. net_ipv6addr_copy(conn->u.ipv6.raddr, inaddr->sin6_addr.s6_addr16);
  735. }
  736. #endif /* CONFIG_NET_IPv6 */
  737. }
  738. else
  739. {
  740. conn->rport = 0;
  741. #ifdef CONFIG_NET_IPv4
  742. #ifdef CONFIG_NET_IPv6
  743. if (conn->domain == PF_INET)
  744. #endif
  745. {
  746. net_ipv4addr_copy(conn->u.ipv4.raddr, INADDR_ANY);
  747. }
  748. #endif /* CONFIG_NET_IPv4 */
  749. #ifdef CONFIG_NET_IPv6
  750. #ifdef CONFIG_NET_IPv4
  751. else
  752. #endif
  753. {
  754. net_ipv6addr_copy(conn->u.ipv6.raddr, g_ipv6_unspecaddr);
  755. }
  756. #endif /* CONFIG_NET_IPv6 */
  757. }
  758. return OK;
  759. }
  760. #endif /* CONFIG_NET && CONFIG_NET_UDP */