|
64 | 64 | #include <nuttx/net/udp.h>
|
65 | 65 |
|
66 | 66 | #include "devif/devif.h"
|
| 67 | +#include "inet/inet.h" |
67 | 68 | #include "nat/nat.h"
|
68 | 69 | #include "netdev/netdev.h"
|
69 |
| -#include "inet/inet.h" |
| 70 | +#include "socket/socket.h" |
70 | 71 | #include "udp/udp.h"
|
71 | 72 |
|
72 | 73 | /****************************************************************************
|
@@ -98,21 +99,42 @@ static dq_queue_t g_active_udp_connections;
|
98 | 99 | * Description:
|
99 | 100 | * Find the UDP connection that uses this local port number.
|
100 | 101 | *
|
| 102 | + * Input Parameters: |
| 103 | + * domain - IP domain (PF_INET or PF_INET6) |
| 104 | + * ipaddr - The IP address to use in the lookup |
| 105 | + * portno - The port to use in the lookup |
| 106 | + * opt - The option from another conn to match the conflict conn |
| 107 | + * SO_REUSEADDR: If both sockets have this, they never confilct. |
| 108 | + * |
101 | 109 | * Assumptions:
|
102 | 110 | * This function must be called with the network locked.
|
103 | 111 | *
|
104 | 112 | ****************************************************************************/
|
105 | 113 |
|
106 | 114 | static FAR struct udp_conn_s *udp_find_conn(uint8_t domain,
|
107 | 115 | FAR union ip_binding_u *ipaddr,
|
108 |
| - uint16_t portno) |
| 116 | + uint16_t portno, sockopt_t opt) |
109 | 117 | {
|
110 | 118 | FAR struct udp_conn_s *conn = NULL;
|
| 119 | +#ifdef CONFIG_NET_SOCKOPTS |
| 120 | + bool skip_reusable = _SO_GETOPT(opt, SO_REUSEADDR); |
| 121 | +#endif |
111 | 122 |
|
112 | 123 | /* Now search each connection structure. */
|
113 | 124 |
|
114 | 125 | while ((conn = udp_nextconn(conn)) != NULL)
|
115 | 126 | {
|
| 127 | + /* With SO_REUSEADDR set for both sockets, we do not need to check its |
| 128 | + * address and port. |
| 129 | + */ |
| 130 | + |
| 131 | +#ifdef CONFIG_NET_SOCKOPTS |
| 132 | + if (skip_reusable && _SO_GETOPT(conn->sconn.s_options, SO_REUSEADDR)) |
| 133 | + { |
| 134 | + continue; |
| 135 | + } |
| 136 | +#endif |
| 137 | + |
116 | 138 | /* If the port local port number assigned to the connections matches
|
117 | 139 | * AND the IP address of the connection matches, then return a
|
118 | 140 | * reference to the connection structure. INADDR_ANY is a special
|
@@ -534,7 +556,7 @@ uint16_t udp_select_port(uint8_t domain, FAR union ip_binding_u *u)
|
534 | 556 | g_last_udp_port = 4096;
|
535 | 557 | }
|
536 | 558 | }
|
537 |
| - while (udp_find_conn(domain, u, HTONS(g_last_udp_port)) != NULL |
| 559 | + while (udp_find_conn(domain, u, HTONS(g_last_udp_port), 0) != NULL |
538 | 560 | #if defined(CONFIG_NET_NAT) && defined(CONFIG_NET_IPv4)
|
539 | 561 | || (domain == PF_INET &&
|
540 | 562 | ipv4_nat_port_inuse(IP_PROTO_UDP, u->ipv4.laddr,
|
@@ -823,7 +845,13 @@ int udp_bind(FAR struct udp_conn_s *conn, FAR const struct sockaddr *addr)
|
823 | 845 | * and port ?
|
824 | 846 | */
|
825 | 847 |
|
826 |
| - if (udp_find_conn(conn->domain, &conn->u, portno) == NULL |
| 848 | + if (udp_find_conn(conn->domain, &conn->u, portno, |
| 849 | +#ifdef CONFIG_NET_SOCKOPTS |
| 850 | + conn->sconn.s_options |
| 851 | +#else |
| 852 | + 0 |
| 853 | +#endif |
| 854 | + ) == NULL |
827 | 855 | #if defined(CONFIG_NET_NAT) && defined(CONFIG_NET_IPv4)
|
828 | 856 | && !(conn->domain == PF_INET &&
|
829 | 857 | ipv4_nat_port_inuse(IP_PROTO_UDP, conn->u.ipv4.laddr,
|
|
0 commit comments