summaryrefslogtreecommitdiffstats
path: root/src/net/udp.c
diff options
context:
space:
mode:
authorMichael Brown2013-08-06 16:56:54 +0200
committerMichael Brown2013-08-06 16:56:54 +0200
commit252d28f098bfd12df59fe147d7e8354be61a6da8 (patch)
tree234bc573f3c7a27730d04016c809dc6ae5ba8c24 /src/net/udp.c
parent[ipv6] Rename sin_{family,port} to sin6_{family,port} in struct sockaddr_in6 (diff)
downloadipxe-252d28f098bfd12df59fe147d7e8354be61a6da8.tar.gz
ipxe-252d28f098bfd12df59fe147d7e8354be61a6da8.tar.xz
ipxe-252d28f098bfd12df59fe147d7e8354be61a6da8.zip
[tcpip] Allow binding to unspecified privileged ports (below 1024)
Originally-implemented-by: Marin Hannache <git@mareo.fr> Signed-off-by: Michael Brown <mcb30@ipxe.org>
Diffstat (limited to 'src/net/udp.c')
-rw-r--r--src/net/udp.c53
1 files changed, 18 insertions, 35 deletions
diff --git a/src/net/udp.c b/src/net/udp.c
index bae5f4a7..edc7488a 100644
--- a/src/net/udp.c
+++ b/src/net/udp.c
@@ -48,45 +48,19 @@ static struct interface_descriptor udp_xfer_desc;
struct tcpip_protocol udp_protocol __tcpip_protocol;
/**
- * Bind UDP connection to local port
+ * Check if local UDP port is available
*
- * @v udp UDP connection
- * @ret rc Return status code
- *
- * Opens the UDP connection and binds to the specified local port. If
- * no local port is specified, the first available port will be used.
+ * @v port Local port number
+ * @ret port Local port number, or negative error
*/
-static int udp_bind ( struct udp_connection *udp ) {
- struct udp_connection *existing;
- static uint16_t try_port = 1023;
-
- /* If no port specified, find the first available port */
- if ( ! udp->local.st_port ) {
- while ( try_port ) {
- try_port++;
- if ( try_port < 1024 )
- continue;
- udp->local.st_port = htons ( try_port );
- if ( udp_bind ( udp ) == 0 )
- return 0;
- }
- return -EADDRINUSE;
- }
+static int udp_port_available ( int port ) {
+ struct udp_connection *udp;
- /* Attempt bind to local port */
- list_for_each_entry ( existing, &udp_conns, list ) {
- if ( existing->local.st_port == udp->local.st_port ) {
- DBGC ( udp, "UDP %p could not bind: port %d in use\n",
- udp, ntohs ( udp->local.st_port ) );
+ list_for_each_entry ( udp, &udp_conns, list ) {
+ if ( udp->local.st_port == htons ( port ) )
return -EADDRINUSE;
- }
}
-
- /* Add to UDP connection list */
- DBGC ( udp, "UDP %p bound to port %d\n",
- udp, ntohs ( udp->local.st_port ) );
-
- return 0;
+ return port;
}
/**
@@ -104,6 +78,7 @@ static int udp_open_common ( struct interface *xfer,
struct sockaddr_tcpip *st_peer = ( struct sockaddr_tcpip * ) peer;
struct sockaddr_tcpip *st_local = ( struct sockaddr_tcpip * ) local;
struct udp_connection *udp;
+ int port;
int rc;
/* Allocate and initialise structure */
@@ -120,8 +95,16 @@ static int udp_open_common ( struct interface *xfer,
/* Bind to local port */
if ( ! promisc ) {
- if ( ( rc = udp_bind ( udp ) ) != 0 )
+ port = tcpip_bind ( st_local, udp_port_available );
+ if ( port < 0 ) {
+ rc = port;
+ DBGC ( udp, "UDP %p could not bind: %s\n",
+ udp, strerror ( rc ) );
goto err;
+ }
+ udp->local.st_port = htons ( port );
+ DBGC ( udp, "UDP %p bound to port %d\n",
+ udp, ntohs ( udp->local.st_port ) );
}
/* Attach parent interface, transfer reference to connection