diff options
author | Michael Brown | 2013-08-06 16:56:54 +0200 |
---|---|---|
committer | Michael Brown | 2013-08-06 16:56:54 +0200 |
commit | 252d28f098bfd12df59fe147d7e8354be61a6da8 (patch) | |
tree | 234bc573f3c7a27730d04016c809dc6ae5ba8c24 /src/net/udp.c | |
parent | [ipv6] Rename sin_{family,port} to sin6_{family,port} in struct sockaddr_in6 (diff) | |
download | ipxe-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.c | 53 |
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 |