diff options
| author | Michael Brown | 2006-08-09 14:08:20 +0200 |
|---|---|---|
| committer | Michael Brown | 2006-08-09 14:08:20 +0200 |
| commit | 065a2a486dc3fc66d593c62e6d3e4c81287500a9 (patch) | |
| tree | fd310986e9b88dd1ace757f91db95178ba096eb5 /src/net | |
| parent | Remove some of the confusion surrounding the amount to strip off from (diff) | |
| download | ipxe-065a2a486dc3fc66d593c62e6d3e4c81287500a9.tar.gz ipxe-065a2a486dc3fc66d593c62e6d3e4c81287500a9.tar.xz ipxe-065a2a486dc3fc66d593c62e6d3e4c81287500a9.zip | |
Port the UDP port allocation code to TCP
Diffstat (limited to 'src/net')
| -rw-r--r-- | src/net/tcp.c | 66 |
1 files changed, 45 insertions, 21 deletions
diff --git a/src/net/tcp.c b/src/net/tcp.c index 8b8053b8b..f22c24eb6 100644 --- a/src/net/tcp.c +++ b/src/net/tcp.c @@ -529,35 +529,59 @@ int tcp_close ( struct tcp_connection *conn ) { return tcp_send ( conn, TCP_NOMSG, TCP_NOMSG_LEN ); } +/** + * Bind TCP connection to local port + * + * @v conn TCP connection + * @v local_port Local port, in network byte order + * @ret rc Return status code + */ +int tcp_bind ( struct tcp_connection *conn, uint16_t local_port ) { + struct tcp_connection *existing; + + list_for_each_entry ( existing, &tcp_conns, list ) { + if ( existing->local_port == local_port ) + return -EADDRINUSE; + } + conn->local_port = local_port; + return 0; +} + /** * Listen for a packet * - * @v conn TCP connection - * @v port Local port, in network byte order + * @v conn TCP connection + * @v local_port Local port, in network byte order * - * This function adds the connection to a list of registered tcp connections. If - * the local port is 0, the connection is assigned the lowest available port - * between MIN_TCP_PORT and 65535. + * This function adds the connection to a list of registered tcp + * connections. If the local port is 0, the connection is assigned an + * available port between MIN_TCP_PORT and 65535. */ -int tcp_listen ( struct tcp_connection *conn, uint16_t port ) { - struct tcp_connection *cconn; - if ( port != 0 ) { - list_for_each_entry ( cconn, &tcp_conns, list ) { - if ( cconn->local_port == port ) { - DBG ( "Error listening to %d\n", - ntohs ( port ) ); - return -EISCONN; - } +int tcp_listen ( struct tcp_connection *conn, uint16_t local_port ) { + static uint16_t try_port = 1024; + int rc; + + /* If no port specified, find the first available port */ + if ( ! local_port ) { + for ( ; try_port ; try_port++ ) { + if ( try_port < 1024 ) + continue; + if ( tcp_listen ( conn, htons ( try_port ) ) == 0 ) + return 0; } - /* Add the connection to the list of registered connections */ - conn->local_port = port; - list_add ( &conn->list, &tcp_conns ); - return 0; + return -EADDRINUSE; } - /* Assigning lowest port not supported */ - DBG ( "Assigning lowest port not implemented\n"); - return -ENOSYS; + + /* Attempt bind to local port */ + if ( ( rc = tcp_bind ( conn, local_port ) ) != 0 ) + return rc; + + /* Add to TCP connection list */ + list_add ( &conn->list, &tcp_conns ); + DBG ( "TCP opened %p on port %d\n", conn, ntohs ( local_port ) ); + + return 0; } /** |
