From 59368f3b13b0b810ee8950d66118cc8160aeeea2 Mon Sep 17 00:00:00 2001 From: Pavel <68122101+red-prig@users.noreply.github.com> Date: Sun, 20 Oct 2024 23:19:59 +0300 Subject: [PATCH] + --- fpPS4.lpi | 9 + sys/init_sysent.pas | 8 +- sys/kern/kern_budget.pas | 8 +- sys/kern/uipc_syscalls.pas | 462 ++++++++++++++++++++++++++++++++++--- sys/sockopt.pas | 23 ++ sys/syscalls.pas | 32 +++ sys/vfs/vsocket.pas | 4 +- 7 files changed, 502 insertions(+), 44 deletions(-) create mode 100644 sys/sockopt.pas diff --git a/fpPS4.lpi b/fpPS4.lpi index 911d8441..ecd32eab 100644 --- a/fpPS4.lpi +++ b/fpPS4.lpi @@ -1462,6 +1462,15 @@ + + + + + + + + + diff --git a/sys/init_sysent.pas b/sys/init_sysent.pas index d405b861..4524c482 100644 --- a/sys/init_sysent.pas +++ b/sys/init_sysent.pas @@ -208,7 +208,7 @@ var ), (//[30] sy_narg:3; - sy_call:nil; + sy_call:@sys_accept; sy_name:'sys_accept' ), (//[31] @@ -578,17 +578,17 @@ var ), (//[104] sy_narg:3; - sy_call:nil; + sy_call:@sys_bind; sy_name:'sys_bind' ), (//[105] sy_narg:5; - sy_call:nil; + sy_call:@sys_setsockopt; sy_name:'sys_setsockopt' ), (//[106] sy_narg:2; - sy_call:nil; + sy_call:@sys_listen; sy_name:'sys_listen' ), (//[107] diff --git a/sys/kern/kern_budget.pas b/sys/kern/kern_budget.pas index 5c25853b..d5a5bd46 100644 --- a/sys/kern/kern_budget.pas +++ b/sys/kern/kern_budget.pas @@ -698,10 +698,10 @@ begin end; - Writeln('DMEM_LIMIT =0x',HexStr(DMEM_LIMIT,16)); - Writeln('FMEM_LIMIT =0x',HexStr(FMEM_LIMIT,16)); - Writeln('BigAppMem =0x',HexStr(BigAppMemory,16)); - Writeln('game_fmem_size =0x',HexStr(game_fmem_size,16)); + Writeln('DMEM_LIMIT =0x',HexStr(DMEM_LIMIT,16)); + Writeln('FMEM_LIMIT =0x',HexStr(FMEM_LIMIT,16)); + Writeln('BigAppMem =0x',HexStr(BigAppMemory,16)); + Writeln('game_fmem_size =0x',HexStr(game_fmem_size,16)); // Writeln('vm_budget_dmem_alloc=0x',HexStr(vm_budget_limit(PTYPE_BIG_APP,field_dmem_alloc),16)); Writeln('vm_budget_mlock =0x',HexStr(vm_budget_limit(PTYPE_BIG_APP,field_mlock ),16)); diff --git a/sys/kern/uipc_syscalls.pas b/sys/kern/uipc_syscalls.pas index 42f51b2c..aa0cd850 100644 --- a/sys/kern/uipc_syscalls.pas +++ b/sys/kern/uipc_syscalls.pas @@ -8,22 +8,65 @@ interface function sys_socket(domain,stype,protocol:Integer):Integer; function sys_socketex(name:pchar;domain,stype,protocol:Integer):Integer; function sys_socketclose(fd:Integer):Integer; +function sys_bind(s:Integer;name:Pointer;namelen:Integer):Integer; +function sys_listen(s,backlog:Integer):Integer; +function sys_accept(s:Integer;aname,anamelen:Pointer):Integer; function sys_connect(fd:Integer;name:Pointer;namelen:Integer):Integer; +function sys_setsockopt(s,level,name:Integer;val:Pointer;valsize:Integer):Integer; implementation uses errno, + mqueue, systm, kern_thr, kern_descrip, sys_conf, vsocket, + sockopt, + vsocketvar, + vuio, vfile, vfcntl, vcapability, subr_backtrace; +{ + Convert a user file descriptor to a kernel file entry and check that, if + it is a capability, the right rights are present. A reference on the file + entry is held upon returning. +} +function getsock_cap(fd :Integer; + rights:cap_rights_t; + fpp :pp_file; + fflagp:PDWORD):Integer; +var + fp:p_file; +begin + fp:=fget_unlocked(fd); + + if (fp=nil) then + begin + Exit(EBADF); + end; + + if (fp^.f_type<>DTYPE_SOCKET) and + (fp^.f_type<>DTYPE_IPCSOCKET) then + begin + fdrop(fp); + Exit(ENOTSOCK); + end; + + if (fflagp<>nil) then + begin + fflagp^:=fp^.f_flag; + end; + + fpp^:=fp; + Exit(0); +end; + function soo_ioctl(fp:p_file;com:QWORD;data:Pointer):Integer; begin Result:=0; @@ -124,41 +167,6 @@ begin Result:=kern_close(fd); end; -{ - Convert a user file descriptor to a kernel file entry and check that, if - it is a capability, the right rights are present. A reference on the file - entry is held upon returning. -} -function getsock_cap(fd :Integer; - rights:cap_rights_t; - fpp :pp_file; - fflagp:PDWORD):Integer; -var - fp:p_file; -begin - fp:=fget_unlocked(fd); - - if (fp=nil) then - begin - Exit(EBADF); - end; - - if (fp^.f_type<>DTYPE_SOCKET) and - (fp^.f_type<>DTYPE_IPCSOCKET) then - begin - fdrop(fp); - Exit(ENOTSOCK); - end; - - if (fflagp<>nil) then - begin - fflagp^:=fp^.f_flag; - end; - - fpp^:=fp; - Exit(0); -end; - function getsockaddr(namp:pp_sockaddr;uaddr:Pointer;len:size_t):Integer; var sa:p_sockaddr; @@ -189,6 +197,42 @@ begin end; end; +function kern_bind(fd:Integer;sa:p_sockaddr):Integer; +var + //so:p_socket; + fp:p_file; + error:Integer; +begin + error:=getsock_cap(fd, CAP_BIND, @fp, nil); + if (error<>0) then + begin + Exit(error); + end; + //so:=fp^.f_data; + //error:=sobind(so, sa, td); + fdrop(fp); + Exit(error); +end; + +function sys_bind(s:Integer;name:Pointer;namelen:Integer):Integer; +var + sa:p_sockaddr; + error:Integer; +begin + error:=getsockaddr(@sa, name, namelen); + + if (error<>0) then + begin + Exit(error); + end; + + error:=kern_bind(s, sa); + + FreeMem(sa); + + Exit(error); +end; + function kern_connect(fd:Integer;sa:p_sockaddr):Integer; var fp:p_file; @@ -202,6 +246,307 @@ begin fdrop(fp); end; +function sys_listen(s,backlog:Integer):Integer; +var + //so:p_socket; + fp:p_file; + error:Integer; +begin + error:=getsock_cap(s, CAP_LISTEN, @fp, nil); + if (error=0) then + begin + //so:=fp^.f_data; + //error:=solisten(so, uap^.backlog, td); + fdrop(fp); + end; + Exit(error); +end; + +function kern_accept(s:Integer;name:pp_sockaddr; + namelen:p_socklen_t;fp:pp_file):Integer; +label + done, + noconnection; +var + td:p_kthread; + headfp,nfp:p_file; + sa:p_sockaddr; + error:Integer; + //so,head:p_socket; + fd:Integer; + fflag:DWORD; + pgid:Integer; //pid_t + tmp:Integer; +begin + td:=curkthread; + headfp:=nil; + nfp :=nil; + sa :=nil; + + if (name<>nil) then + begin + name^:=nil; + if (namelen^ < 0) then + begin + Exit(EINVAL); + end; + end; + + error:=getsock_cap(s, CAP_ACCEPT, @headfp, @fflag); + + if (error<>0) then + begin + Exit(error); + end; + + { + head:=headfp^.f_data; + if ((head^.so_options and SO_ACCEPTCONN)=0) then + begin + error:=EINVAL; + goto done; + end; + } + + error:=falloc(@nfp, @fd, 0); + + if (error<>0) then + begin + goto done; + end; + + ////////////////// + error:=EWOULDBLOCK; + goto noconnection; + ////////////////// + + ACCEPT_LOCK(); + + { + if (((head^.so_state and SS_NBIO)<>0) and TAILQ_EMPTY(@head^.so_comp)) then + begin + ACCEPT_UNLOCK(); + error:=EWOULDBLOCK; + goto noconnection; + end; + } + + { + while ((TAILQ_EMPTY(@head^.so_comp)) and (head^.so_error=0)) do + begin + if (head^.so_rcv.sb_state & SBS_CANTRCVMORE) then + begin + head^.so_error:=ECONNABORTED; + break; + end; + error:=msleep(@head^.so_timeo, @accept_mtx, PSOCK or PCATCH, 'accept', 0); + if (error) then + begin + ACCEPT_UNLOCK(); + goto noconnection; + end; + end; + } + + { + if (head^.so_error<>0) then + begin + error:=head^.so_error; + head^.so_error:=0; + ACCEPT_UNLOCK(); + goto noconnection; + end; + } + + { + so:=TAILQ_FIRST(@head^.so_comp); + Assert(not (so^.so_qstate and SQ_INCOMP), 'accept1: so SQ_INCOMP'); + Assert(so^.so_qstate and SQ_COMP, 'accept1: so not SQ_COMP'); + } + + { + * Before changing the flags on the socket, we have to bump the + * reference count. Otherwise, if the protocol calls sofree(), + * the socket will be released due to a zero refcount. + } + + { + SOCK_LOCK(so); { soref() and so_state update } + soref(so); { file descriptor reference } + + TAILQ_REMOVE(@head^.so_comp, so, so_list); + Dec(head^.so_qlen); + so^.so_state :=so^.so_state or (head^.so_state and SS_NBIO); + so^.so_qstate:=so^.so_qstate and (not SQ_COMP); + so^.so_head :=nil; + + SOCK_UNLOCK(so); + } + + ACCEPT_UNLOCK(); + + + { An extra reference on `nfp' has been held for us by falloc(). } + td^.td_retval[0]:=fd; + + { + { connection has been removed from the listen queue } + KNOTE_UNLOCKED(@head^.so_rcv.sb_sel.si_note, 0); + + pgid:=fgetown(@head^.so_sigio); + if (pgid<>0) then + begin + fsetown(pgid, @so^.so_sigio); + end; + + finit(nfp, fflag, DTYPE_SOCKET, so, @socketops); + + { Sync socket nonblocking/async state with file flags } + tmp:=fflag and FNONBLOCK; + fo_ioctl(nfp, FIONBIO, @tmp, td^.td_ucred, td); + + tmp:=fflag and FASYNC; + fo_ioctl(nfp, FIOASYNC, @tmp, td^.td_ucred, td); + + sa:=0; + error:=soaccept(so, @sa); + } + + if (error<>0) then + begin + { + * Exit a namelen of zero for older code which might + * ignore the Exit value from accept. + } + if (name<>nil) then + begin + namelen^:=0; + end; + goto noconnection; + end; + + if (sa=nil) then + begin + if (name<>nil) then + begin + namelen^:=0; + end; + goto done; + end; + + if (name<>nil) then + begin + { check sa_len before it is destroyed } + if (namelen^ > sa^.sa_len) then + begin + namelen^:=sa^.sa_len; + end; + + name^:=sa; + sa:=nil; + end; + +noconnection: + if (sa<>nil) then + begin + FreeMem(sa); + end; + + { + * close the new descriptor, assuming someone hasn't ripped it + * out from under us. + } + if (error<>0) then + begin + fdclose(nfp, fd); + end; + + { + * Release explicitly held references before Exiting. We Exit + * a reference on nfp to the caller on success if they request it. + } +done: + if (fp<>nil) then + begin + if (error=0) then + begin + fp^:=nfp; + nfp:=nil; + end else + begin + fp^:=nil; + end; + end; + // + if (nfp<>nil) then + begin + fdrop(nfp); + end; + fdrop(headfp); + // + Exit(error); +end; + +function accept1(s:Integer;aname:p_sockaddr;anamelen:p_socklen_t):Integer; +var + td:p_kthread; + name:p_sockaddr; + namelen:socklen_t; + fp:p_file; + error:Integer; +begin + td:=curkthread; + + if (aname=nil) then + begin + Exit(kern_accept(s, nil, nil, nil)); + end; + + error:=copyin(anamelen, @namelen, sizeof(namelen)); + + if (error<>0) then + begin + Exit(error); + end; + + error:=kern_accept(s, @name, @namelen, @fp); + + { + * Exit a namelen of zero for older code which might + * ignore the Exit value from accept. + } + if (error<>0) then + begin + copyout(@namelen, anamelen, sizeof(anamelen^)); + Exit(error); + end; + + if (error=0) and (name<>nil) then + begin + error:=copyout(name, name, namelen); + end; + + if (error=0) then + begin + error:=copyout(@namelen,anamelen,sizeof(namelen)); + end; + + if (error<>0) then + begin + fdclose(fp, td^.td_retval[0]); + end; + + fdrop(fp); + FreeMem(name); + + Exit(error); +end; + +function sys_accept(s:Integer;aname,anamelen:Pointer):Integer; +begin + Exit(accept1(s,aname,anamelen)); +end; + function sys_connect(fd:Integer;name:Pointer;namelen:Integer):Integer; var sa:p_sockaddr; @@ -215,5 +560,52 @@ begin FreeMem(sa); end; +function kern_setsockopt(s,level,name:Integer;val:Pointer;valseg:uio_seg;valsize:Integer):Integer; +var + error:Integer; + //so:p_socket; + fp:p_file; + sopt:t_sockopt; +begin + if (val=nil) and (valsize<>0) then + begin + Exit(EFAULT); + end; + + if (valsize < 0) then + begin + Exit(EINVAL); + end; + + sopt.sopt_dir :=SOPT_SET; + sopt.sopt_level :=level; + sopt.sopt_name :=name; + sopt.sopt_val :=val; + sopt.sopt_valsize:=valsize; + + case (valseg) of + UIO_USERSPACE:sopt.sopt_td:=curkthread; + UIO_SYSSPACE :sopt.sopt_td:=nil; + else + Assert(false,'kern_setsockopt called with bad valseg'); + end; + + error:=getsock_cap(s, CAP_SETSOCKOPT, @fp, nil); + if (error=0) then + begin + //so:=fp->f_data; + //error:=sosetopt(so, @sopt); + fdrop(fp); + end; + + Exit(error); +end; + +function sys_setsockopt(s,level,name:Integer;val:Pointer;valsize:Integer):Integer; +begin + Result:=kern_setsockopt(s,level,name,val,UIO_USERSPACE,valsize); +end; + + end. diff --git a/sys/sockopt.pas b/sys/sockopt.pas new file mode 100644 index 00000000..8f7cc067 --- /dev/null +++ b/sys/sockopt.pas @@ -0,0 +1,23 @@ +unit sockopt; + +{$mode ObjFPC}{$H+} +{$CALLING SysV_ABI_CDecl} + +interface + +type + t_sopt_dir=(SOPT_GET,SOPT_SET); + + t_sockopt=record + sopt_dir :t_sopt_dir; + sopt_level :Integer; + sopt_name :Integer; + sopt_val :Pointer; + sopt_valsize:QWORD; + sopt_td :Pointer; //p_kthread; + end; + +implementation + +end. + diff --git a/sys/syscalls.pas b/sys/syscalls.pas index 2726f651..3bbf4c45 100644 --- a/sys/syscalls.pas +++ b/sys/syscalls.pas @@ -26,6 +26,7 @@ function unmount(path:PChar;flags:Integer):Integer; function setuid(uid:Integer):Integer; function getuid():Integer; function geteuid():Integer; +function _accept(s:Integer;aname,anamelen:Pointer):Integer; function access(path:PChar;flags:Integer):Integer; function chflags(path:PChar;flags:Integer):Integer; function fchflags(fd,flags:Integer):Integer; @@ -63,6 +64,9 @@ function socket(domain,stype,protocol:Integer):Integer; function _connect(fd:Integer;name:Pointer;namelen:Integer):Integer; function __sys_netcontrol(fd,op:Integer;buf:Pointer;nbuf:DWORD):Integer; function getpriority(which,who:Integer):Integer; +function _bind(s:Integer;name:Pointer;namelen:Integer):Integer; +function _setsockopt(s,level,name:Integer;val:Pointer;valsize:Integer):Integer; +function _listen(s,backlog:Integer):Integer; function __sys_socketex(name:pchar;domain,stype,protocol:Integer):Integer; function __sys_socketclose(fd:Integer):Integer; function gettimeofday(tp,tzp:Pointer):Integer; @@ -395,6 +399,13 @@ asm jmp cerror end; +function _accept(s:Integer;aname,anamelen:Pointer):Integer; assembler; nostackframe; +asm + movq $30,%rax + call fast_syscall + jmp cerror +end; + function access(path:PChar;flags:Integer):Integer; assembler; nostackframe; asm movq $33,%rax @@ -654,6 +665,27 @@ asm jmp cerror end; +function _bind(s:Integer;name:Pointer;namelen:Integer):Integer; assembler; nostackframe; +asm + movq $104,%rax + call fast_syscall + jmp cerror +end; + +function _setsockopt(s,level,name:Integer;val:Pointer;valsize:Integer):Integer; assembler; nostackframe; +asm + movq $105,%rax + call fast_syscall + jmp cerror +end; + +function _listen(s,backlog:Integer):Integer; assembler; nostackframe; +asm + movq $106,%rax + call fast_syscall + jmp cerror +end; + function __sys_socketex(name:pchar;domain,stype,protocol:Integer):Integer; assembler; nostackframe; asm movq $113,%rax diff --git a/sys/vfs/vsocket.pas b/sys/vfs/vsocket.pas index 8f35597e..5a74804d 100644 --- a/sys/vfs/vsocket.pas +++ b/sys/vfs/vsocket.pas @@ -17,7 +17,9 @@ uses } type sa_family_t=Byte; - socklen_t =DWORD; + + p_socklen_t=^socklen_t; + socklen_t =Integer; const //socket types