udp_conn.c 28 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902
  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 SO_BROADCAST.
  361. *
  362. * 2. If this is a connection mode UDP socket, then the source address
  363. * is verified against the connected remote address.
  364. *
  365. * - The remote port number is checked if the connection is bound
  366. * to a remote port.
  367. * - Finally, if the connection is bound to a remote IP address,
  368. * the source IP address of the packet is checked.
  369. *
  370. * If all of the above are true then the newly received UDP packet
  371. * is destined for this UDP connection.
  372. *
  373. * To send and receive multicast packets, the application should:
  374. *
  375. * - Bind socket to INADDR6_ANY (for the all-nodes multicast address)
  376. * or to a specific <multicast-address>
  377. * - setsockopt to SO_BROADCAST (for all-nodes address)
  378. *
  379. * For connection-less UDP sockets:
  380. *
  381. * - call sendto with sendaddr.sin_addr.s_addr = <multicast-address>
  382. * - call recvfrom.
  383. *
  384. * For connection-mode UDP sockets:
  385. *
  386. * - call connect() to connect the UDP socket to a specific remote
  387. * address, then
  388. * - Call send() with no address address information
  389. * - call recv() (from address information should not be needed)
  390. *
  391. * REVIST: SO_BROADCAST flag is currently ignored.
  392. */
  393. /* Check that there is a local port number and this is matches
  394. * the port number in the destination address.
  395. */
  396. if ((conn->lport != 0 && udp->destport == conn->lport &&
  397. /* Check if the local port accepts any address on this port or
  398. * that there is an exact match between the destipaddr and the
  399. * bound local address. This catches the case of the all nodes
  400. * multicast when the socket is bound to the IPv6 unspecified
  401. * address.
  402. */
  403. (net_ipv6addr_cmp(conn->u.ipv6.laddr, g_ipv6_unspecaddr) ||
  404. net_ipv6addr_hdrcmp(ip->destipaddr, conn->u.ipv6.laddr))))
  405. {
  406. /* Check if the socket is connection mode. In this case, only
  407. * packets with source addresses from the connected remote peer
  408. * will be accepted.
  409. */
  410. if (_UDP_ISCONNECTMODE(conn->flags))
  411. {
  412. /* Check if the UDP connection is either (1) accepting packets
  413. * from any port or (2) the packet srcport matches the local
  414. * bound port number.
  415. */
  416. if ((conn->rport == 0 || udp->srcport == conn->rport) &&
  417. /* If (1) not connected to a remote address, or (2) a all-
  418. * nodes multicast destipaddr was received, or (3) there is an
  419. * exact match between the srcipaddr and the bound remote IP
  420. * address, then accept the packet.
  421. */
  422. (net_ipv6addr_cmp(conn->u.ipv6.raddr, g_ipv6_unspecaddr) ||
  423. #ifdef CONFIG_NET_BROADCAST
  424. net_ipv6addr_hdrcmp(ip->destipaddr, g_ipv6_allnodes) ||
  425. #endif
  426. net_ipv6addr_hdrcmp(ip->srcipaddr, conn->u.ipv6.raddr)))
  427. {
  428. /* Matching connection found.. Break out of the loop and
  429. * return this reference to it.
  430. */
  431. break;
  432. }
  433. }
  434. else
  435. {
  436. /* This UDP socket is not connected. We need to match only
  437. * the destination address with the bound socket address.
  438. * Break out out of the loop and return this reference to
  439. * the matching connection structure.
  440. */
  441. break;
  442. }
  443. }
  444. /* Look at the next active connection */
  445. conn = (FAR struct udp_conn_s *)conn->node.flink;
  446. }
  447. return conn;
  448. }
  449. #endif /* CONFIG_NET_IPv6 */
  450. /****************************************************************************
  451. * Public Functions
  452. ****************************************************************************/
  453. /****************************************************************************
  454. * Name: udp_initialize
  455. *
  456. * Description:
  457. * Initialize the UDP connection structures. Called once and only from
  458. * the UIP layer.
  459. *
  460. ****************************************************************************/
  461. void udp_initialize(void)
  462. {
  463. int i;
  464. /* Initialize the queues */
  465. dq_init(&g_free_udp_connections);
  466. dq_init(&g_active_udp_connections);
  467. nxsem_init(&g_free_sem, 0, 1);
  468. for (i = 0; i < CONFIG_NET_UDP_CONNS; i++)
  469. {
  470. /* Mark the connection closed and move it to the free list */
  471. g_udp_connections[i].lport = 0;
  472. dq_addlast(&g_udp_connections[i].node, &g_free_udp_connections);
  473. }
  474. g_last_udp_port = 1024;
  475. }
  476. /****************************************************************************
  477. * Name: udp_alloc
  478. *
  479. * Description:
  480. * Allocate a new, uninitialized UDP connection structure. This is
  481. * normally something done by the implementation of the socket() API
  482. *
  483. ****************************************************************************/
  484. FAR struct udp_conn_s *udp_alloc(uint8_t domain)
  485. {
  486. FAR struct udp_conn_s *conn;
  487. /* The free list is protected by a semaphore (that behaves like a mutex). */
  488. _udp_semtake(&g_free_sem);
  489. conn = (FAR struct udp_conn_s *)dq_remfirst(&g_free_udp_connections);
  490. if (conn)
  491. {
  492. /* Make sure that the connection is marked as uninitialized */
  493. conn->flags = 0;
  494. #if defined(CONFIG_NET_IPv4) && defined(CONFIG_NET_IPv6)
  495. conn->domain = domain;
  496. #endif
  497. #ifdef CONFIG_NET_UDP_BINDTODEVICE
  498. conn->boundto = 0; /* Not bound to any interface */
  499. #endif
  500. conn->lport = 0;
  501. conn->ttl = IP_TTL;
  502. #ifdef CONFIG_NET_UDP_WRITE_BUFFERS
  503. /* Initialize the write buffer lists */
  504. sq_init(&conn->write_q);
  505. #endif
  506. /* Enqueue the connection into the active list */
  507. dq_addlast(&conn->node, &g_active_udp_connections);
  508. }
  509. _udp_semgive(&g_free_sem);
  510. return conn;
  511. }
  512. /****************************************************************************
  513. * Name: udp_free
  514. *
  515. * Description:
  516. * Free a UDP connection structure that is no longer in use. This should be
  517. * done by the implementation of close().
  518. *
  519. ****************************************************************************/
  520. void udp_free(FAR struct udp_conn_s *conn)
  521. {
  522. #ifdef CONFIG_NET_UDP_WRITE_BUFFERS
  523. FAR struct udp_wrbuffer_s *wrbuffer;
  524. #endif
  525. /* The free list is protected by a semaphore (that behaves like a mutex). */
  526. DEBUGASSERT(conn->crefs == 0);
  527. _udp_semtake(&g_free_sem);
  528. conn->lport = 0;
  529. /* Remove the connection from the active list */
  530. dq_rem(&conn->node, &g_active_udp_connections);
  531. #ifdef CONFIG_NET_UDP_READAHEAD
  532. /* Release any read-ahead buffers attached to the connection */
  533. iob_free_queue(&conn->readahead);
  534. #endif
  535. #ifdef CONFIG_NET_UDP_WRITE_BUFFERS
  536. /* Release any write buffers attached to the connection */
  537. while ((wrbuffer = (struct udp_wrbuffer_s *)sq_remfirst(&conn->write_q)) != NULL)
  538. {
  539. udp_wrbuffer_release(wrbuffer);
  540. }
  541. #endif
  542. /* Free the connection */
  543. dq_addlast(&conn->node, &g_free_udp_connections);
  544. _udp_semgive(&g_free_sem);
  545. }
  546. /****************************************************************************
  547. * Name: udp_active
  548. *
  549. * Description:
  550. * Find a connection structure that is the appropriate
  551. * connection to be used within the provided UDP header
  552. *
  553. * Assumptions:
  554. * This function must be called with the network locked.
  555. *
  556. ****************************************************************************/
  557. FAR struct udp_conn_s *udp_active(FAR struct net_driver_s *dev,
  558. FAR struct udp_hdr_s *udp)
  559. {
  560. #ifdef CONFIG_NET_IPv6
  561. #ifdef CONFIG_NET_IPv4
  562. if (IFF_IS_IPv6(dev->d_flags))
  563. #endif
  564. {
  565. return udp_ipv6_active(dev, udp);
  566. }
  567. #endif /* CONFIG_NET_IPv6 */
  568. #ifdef CONFIG_NET_IPv4
  569. #ifdef CONFIG_NET_IPv6
  570. else
  571. #endif
  572. {
  573. return udp_ipv4_active(dev, udp);
  574. }
  575. #endif /* CONFIG_NET_IPv4 */
  576. }
  577. /****************************************************************************
  578. * Name: udp_nextconn
  579. *
  580. * Description:
  581. * Traverse the list of allocated UDP connections
  582. *
  583. * Assumptions:
  584. * This function must be called with the network locked.
  585. *
  586. ****************************************************************************/
  587. FAR struct udp_conn_s *udp_nextconn(FAR struct udp_conn_s *conn)
  588. {
  589. if (!conn)
  590. {
  591. return (FAR struct udp_conn_s *)g_active_udp_connections.head;
  592. }
  593. else
  594. {
  595. return (FAR struct udp_conn_s *)conn->node.flink;
  596. }
  597. }
  598. /****************************************************************************
  599. * Name: udp_bind
  600. *
  601. * Description:
  602. * This function implements the low level parts of the standard UDP
  603. * bind() operation.
  604. *
  605. * Assumptions:
  606. * This function is called from normal user level code.
  607. *
  608. ****************************************************************************/
  609. int udp_bind(FAR struct udp_conn_s *conn, FAR const struct sockaddr *addr)
  610. {
  611. uint16_t portno;
  612. int ret;
  613. #ifdef CONFIG_NET_IPv4
  614. #ifdef CONFIG_NET_IPv6
  615. if (conn->domain == PF_INET)
  616. #endif
  617. {
  618. FAR const struct sockaddr_in *inaddr =
  619. (FAR const struct sockaddr_in *)addr;
  620. /* Get the port number that we are binding to */
  621. portno = inaddr->sin_port;
  622. /* Bind the local IP address to the connection. NOTE this address may
  623. * be INADDR_ANY meaning, essentially, that we are binding to all
  624. * interfaces for receiving (Sending will use the default port).
  625. */
  626. net_ipv4addr_copy(conn->u.ipv4.laddr, inaddr->sin_addr.s_addr);
  627. }
  628. #endif /* CONFIG_NET_IPv4 */
  629. #ifdef CONFIG_NET_IPv6
  630. #ifdef CONFIG_NET_IPv4
  631. else
  632. #endif
  633. {
  634. FAR const struct sockaddr_in6 *inaddr =
  635. (FAR const struct sockaddr_in6 *)addr;
  636. /* Get the port number that we are binding to */
  637. portno = inaddr->sin6_port;
  638. /* Bind the local IP address to the connection. NOTE this address may
  639. * be INADDR_ANY meaning, essentially, that we are binding to all
  640. * interfaces for receiving (Sending will use the default port).
  641. */
  642. net_ipv6addr_copy(conn->u.ipv6.laddr, inaddr->sin6_addr.in6_u.u6_addr16);
  643. }
  644. #endif /* CONFIG_NET_IPv6 */
  645. /* Is the user requesting to bind to any port? */
  646. if (portno == 0)
  647. {
  648. /* Yes.. Select any unused local port number */
  649. conn->lport = htons(udp_select_port(conn->domain, &conn->u));
  650. ret = OK;
  651. }
  652. else
  653. {
  654. /* Interrupts must be disabled while access the UDP connection list */
  655. net_lock();
  656. /* Is any other UDP connection already bound to this address and port? */
  657. if (udp_find_conn(conn->domain, &conn->u, portno) == NULL)
  658. {
  659. /* No.. then bind the socket to the port */
  660. conn->lport = portno;
  661. ret = OK;
  662. }
  663. else
  664. {
  665. ret = -EADDRINUSE;
  666. }
  667. net_unlock();
  668. }
  669. return ret;
  670. }
  671. /****************************************************************************
  672. * Name: udp_connect
  673. *
  674. * Description:
  675. * This function simply assigns a remote address to UDP "connection"
  676. * structure. This function is called as part of the implementation of:
  677. *
  678. * - connect(). If connect() is called for a SOCK_DGRAM socket, then
  679. * this logic performs the moral equivalent of connect() operation
  680. * for the UDP socket.
  681. * - recvfrom() and sendto(). This function is called to set the
  682. * remote address of the peer.
  683. *
  684. * The function will automatically allocate an unused local port for the
  685. * new connection if the socket is not yet bound to a local address.
  686. * However, another port can be chosen by using the udp_bind() call,
  687. * after the udp_connect() function has been called.
  688. *
  689. * Input Parameters:
  690. * conn - A reference to UDP connection structure. A value of NULL will
  691. * disconnect from any previously connected address.
  692. * addr - The address of the remote host.
  693. *
  694. * Assumptions:
  695. * This function is called (indirectly) from user code. Interrupts may
  696. * be enabled.
  697. *
  698. ****************************************************************************/
  699. int udp_connect(FAR struct udp_conn_s *conn, FAR const struct sockaddr *addr)
  700. {
  701. /* Has this address already been bound to a local port (lport)? */
  702. if (!conn->lport)
  703. {
  704. /* No.. Find an unused local port number and bind it to the
  705. * connection structure.
  706. */
  707. conn->lport = htons(udp_select_port(conn->domain, &conn->u));
  708. }
  709. /* Is there a remote port (rport)? */
  710. if (addr != NULL)
  711. {
  712. #ifdef CONFIG_NET_IPv4
  713. #ifdef CONFIG_NET_IPv6
  714. if (conn->domain == PF_INET)
  715. #endif
  716. {
  717. FAR const struct sockaddr_in *inaddr =
  718. (FAR const struct sockaddr_in *)addr;
  719. conn->rport = inaddr->sin_port;
  720. net_ipv4addr_copy(conn->u.ipv4.raddr, inaddr->sin_addr.s_addr);
  721. }
  722. #endif /* CONFIG_NET_IPv4 */
  723. #ifdef CONFIG_NET_IPv6
  724. #ifdef CONFIG_NET_IPv4
  725. else
  726. #endif
  727. {
  728. FAR const struct sockaddr_in6 *inaddr =
  729. (FAR const struct sockaddr_in6 *)addr;
  730. conn->rport = inaddr->sin6_port;
  731. net_ipv6addr_copy(conn->u.ipv6.raddr, inaddr->sin6_addr.s6_addr16);
  732. }
  733. #endif /* CONFIG_NET_IPv6 */
  734. }
  735. else
  736. {
  737. conn->rport = 0;
  738. #ifdef CONFIG_NET_IPv4
  739. #ifdef CONFIG_NET_IPv6
  740. if (conn->domain == PF_INET)
  741. #endif
  742. {
  743. net_ipv4addr_copy(conn->u.ipv4.raddr, INADDR_ANY);
  744. }
  745. #endif /* CONFIG_NET_IPv4 */
  746. #ifdef CONFIG_NET_IPv6
  747. #ifdef CONFIG_NET_IPv4
  748. else
  749. #endif
  750. {
  751. net_ipv6addr_copy(conn->u.ipv6.raddr, g_ipv6_unspecaddr);
  752. }
  753. #endif /* CONFIG_NET_IPv6 */
  754. }
  755. return OK;
  756. }
  757. #endif /* CONFIG_NET && CONFIG_NET_UDP */