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