Compare commits

...
Author SHA1 Message Date
Doczom b6e583d41c Krn/network: added getsockname and getpeername
Check kernel codestyle / Check kernel codestyle (pull_request) Successful in 21s
Test PR / Build (en_US) (pull_request) Successful in 2m2s
Test PR / Build (ru_RU) (pull_request) Successful in 2m9s
Test PR / Build (es_ES) (pull_request) Successful in 2m13s
2026-07-30 13:29:22 +05:00
LeencyandClaude Opus 5 f7dd4033ba kernel/net: honour the window scale factor advertised by the peer (#619)
Build system / Build (es_ES) (push) Successful in 2m21s
Build system / Build (en_US) (push) Successful in 2m24s
Build system / Build (ru_RU) (push) Successful in 2m28s
Build system / Publish Images (push) Successful in 3m24s
Summary: the received window scale option was stored into SND_SCALE, which
the connection setup code then immediately overwrote with zero, so every
peer window was interpreted unscaled.

Details:
RFC 1323 negotiation is completed in two places -- the SYN_RECEIVED branch
and the active-open branch of tcp_input. Both do

        mov     ax, word[ebx + TCP_SOCKET.requested_s_scale]
        mov     word[ebx + TCP_SOCKET.SND_SCALE], ax

relying on the declared order of the four adjacent bytes SND_SCALE,
RCV_SCALE, requested_s_scale, request_r_scale to move both factors at once.
requested_s_scale, however, was never filled in: the option parser wrote the
peer's shift count into SND_SCALE directly, and that value was then clobbered
by the word move with the zero left in requested_s_scale by socket_alloc.

The result was that SND_SCALE ended up 0 on every connection while
TF_RCVD_SCALE was set, so a peer advertising, say, 64 KiB with a shift of 7
was read as advertising 512 bytes. Sending to any modern host was throttled
to a fraction of the real window.

The parser now stores into requested_s_scale, where the setup code expects
it, and clamps the value to TCP_max_winshift (14) as required by RFC 1323 --
a peer sending a larger shift must not be allowed to make our SND_WND
computation shift out of range.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Reviewed-on: #619
Reviewed-by: hidnplayr <hidnplayr@gmail.com>
Reviewed-by: Mikhail Frolov <mixa.frolov2003@gmail.com>
Co-authored-by: leency <lipatov.kiril@gmail.com>
2026-07-30 02:26:39 +00:00
3 changed files with 147 additions and 4 deletions

No files matched your search

+137 -2
View File
@@ -279,8 +279,10 @@ sys_socket:
dd socket_get_opt ; 9
dd socket_pair ; 10
;dd socket_sendto ; 11
;dd socket_recvfrom ; 12
dd socket_getpeername ; 11
dd socket_getsockname ; 12
;dd socket_sendto ; 13
;dd socket_recvfrom ; 14
.number = ($ - .table) / 4 - 1
.error:
@@ -1396,6 +1398,139 @@ socket_pair:
;-----------------------------------------------------------------;
; ;
; socket_getpeername: Get name of connected peer socket. ;
; ;
; IN: ecx = socket number ;
; edx = pointer to sockaddr struct ;
; esi = length of sockaddr struct ;
; ;
; OUT: eax = length of sockaddr struct ;
; eax = -1 on error ;
; ebx = errorcode on error ;
; ;
;-----------------------------------------------------------------;
align 4
socket_getpeername:
DEBUGF DEBUG_NETWORK_VERBOSE, "SOCKET_getpeername: socknum=%u sockaddr=%x length=%u\n", ecx, edx, esi
call socket_num_to_ptr
test eax, eax
jz .notsock
stdcall is_region_userspace, edx, esi
jnz .efault
cmp [eax + SOCKET.Domain], AF_INET4
jne .invalid
cmp esi, 8 ; domain + port + ipv4_addr
jb .errlen
mov word[edx], AF_INET4
mov esi, edx
xor edx, edx
cmp [eax + SOCKET.Type], SOCK_RAW
je .raw_protocol
mov dx, [eax + TCP_SOCKET.RemotePort]
.raw_protocol:
cmp [eax + SOCKET.state], SS_ISCONNECTED
jne .notconn
mov [esi + sockaddr.port], dx
mov edx, [eax + IP_SOCKET.RemoteIP]
mov [esi + sockaddr.ip], edx
mov dword[esp + SYSCALL_STACK.eax], 8
ret
.efault:
mov dword[esp + SYSCALL_STACK.eax], -1
mov dword[esp + SYSCALL_STACK.ebx], EFAULT
ret
.notconn:
mov dword[esp + SYSCALL_STACK.ebx], ENOTCONN
mov dword[esp + SYSCALL_STACK.eax], -1
ret
.no_inet4:
.errlen:
.invalid:
mov dword[esp + SYSCALL_STACK.ebx], EINVAL
mov dword[esp + SYSCALL_STACK.eax], -1
ret
.notsock:
mov dword[esp + SYSCALL_STACK.ebx], ENOTSOCK
mov dword[esp + SYSCALL_STACK.eax], -1
ret
;-----------------------------------------------------------------;
; ;
; socket_getsockname: Get socket name. ;
; ;
; IN: ecx = socket number ;
; edx = pointer to sockaddr struct ;
; esi = length of sockaddr struct ;
; ;
; OUT: eax = length of sockaddr struct ;
; eax = -1 on error ;
; ebx = errorcode on error ;
; ;
;-----------------------------------------------------------------;
align 4
socket_getsockname:
DEBUGF DEBUG_NETWORK_VERBOSE, "SOCKET_getsockname: socknum=%u sockaddr=%x length=%u\n", ecx, edx, esi
call socket_num_to_ptr
test eax, eax
jz .notsock
stdcall is_region_userspace, edx, esi
jnz .efault
cmp [eax + SOCKET.Domain], AF_INET4
jne .invalid
cmp esi, 8 ; domain + port + ipv4_addr
jb .errlen
mov word[edx], AF_INET4
mov esi, edx
xor edx, edx
cmp [eax + SOCKET.Type], SOCK_RAW
je .raw_protocol
mov dx, [eax + TCP_SOCKET.RemotePort]
.raw_protocol:
mov [esi + sockaddr.port], dx
mov edx, [eax + IP_SOCKET.RemoteIP]
mov [esi + sockaddr.ip], edx
mov dword[esp + SYSCALL_STACK.eax], 8
ret
.efault:
mov dword[esp + SYSCALL_STACK.eax], -1
mov dword[esp + SYSCALL_STACK.ebx], EFAULT
ret
.errlen:
.invalid:
mov dword[esp + SYSCALL_STACK.ebx], EINVAL
mov dword[esp + SYSCALL_STACK.eax], -1
ret
.notsock:
mov dword[esp + SYSCALL_STACK.ebx], ENOTSOCK
mov dword[esp + SYSCALL_STACK.eax], -1
ret
;-----------------------------------------------------------------;
; ;
; socket_debug: Copy socket variables to application buffer. ;
+3
View File
@@ -139,6 +139,9 @@ EISCONN = 56
ETIMEDOUT = 60
ECONNREFUSED = 61
EFAULT = 14 ; copy, defined in posix/posix.inc ; Bad address
ENOTSOCK = 38 ; FreeBSD error code, Socket operation on non-socket
; Api protocol numbers
API_ETH = 0
API_IPv4 = 1
+7 -2
View File
@@ -355,9 +355,14 @@ endl
DEBUGF DEBUG_NETWORK_VERBOSE, "TCP_input: Got window scale option\n"
or [ebx + TCP_SOCKET.t_flags], TF_RCVD_SCALE
; remember the peer's scale factor; it is applied to SND_SCALE when the
; connection is established (together with our RCV_SCALE)
lodsb
mov [ebx + TCP_SOCKET.SND_SCALE], al
;;;;; TODO
cmp al, TCP_max_winshift
jbe .wscale_capped
mov al, TCP_max_winshift
.wscale_capped:
mov [ebx + TCP_SOCKET.requested_s_scale], al
@@:
jmp .opt_loop