// Read(u32 socket) -> (i32 ret, u32 bsd_errno, buffer<i8, 0x22, 0> message) public long Read(ServiceCtx Context) { int SocketFd = Context.RequestData.ReadInt32(); (long ReceivePosition, long ReceiveLength) = Context.Request.GetBufferType0x22(); LinuxError Errno = LinuxError.EBADF; BsdSocket Socket = RetrieveSocket(SocketFd); int Result = -1; if (Socket != null) { byte[] ReceivedBuffer = new byte[ReceiveLength]; try { Result = Socket.Handle.Receive(ReceivedBuffer); Errno = SetResultErrno(Socket.Handle, Result); } catch (SocketException Exception) { Errno = ConvertError((WSAError)Exception.ErrorCode); } } return(WriteBsdResult(Context, Result, Errno)); }
// Shutdown(u32 socket, u32 how) -> (i32 ret, u32 bsd_errno) public ResultCode Shutdown(ServiceCtx context) { int socketFd = context.RequestData.ReadInt32(); int how = context.RequestData.ReadInt32(); LinuxError errno = LinuxError.EBADF; BsdSocket socket = RetrieveSocket(socketFd); if (socket != null) { errno = LinuxError.EINVAL; if (how >= 0 && how <= 2) { errno = LinuxError.SUCCESS; try { socket.Handle.Shutdown((SocketShutdown)how); } catch (SocketException exception) { errno = ConvertError((WsaError)exception.ErrorCode); } } } return(WriteBsdResult(context, 0, errno)); }
// Shutdown(u32 socket, u32 how) -> (i32 ret, u32 bsd_errno) public long Shutdown(ServiceCtx Context) { int SocketFd = Context.RequestData.ReadInt32(); int How = Context.RequestData.ReadInt32(); LinuxError Errno = LinuxError.EBADF; BsdSocket Socket = RetrieveSocket(SocketFd); if (Socket != null) { Errno = LinuxError.EINVAL; if (How >= 0 && How <= 2) { Errno = LinuxError.SUCCESS; try { Socket.Handle.Shutdown((SocketShutdown)How); } catch (SocketException Exception) { Errno = ConvertError((WSAError)Exception.ErrorCode); } } } return(WriteBsdResult(Context, 0, Errno)); }
private long SocketInternal(ServiceCtx Context, bool Exempt) { AddressFamily Domain = (AddressFamily)Context.RequestData.ReadInt32(); SocketType Type = (SocketType)Context.RequestData.ReadInt32(); ProtocolType Protocol = (ProtocolType)Context.RequestData.ReadInt32(); if (Domain == AddressFamily.Unknown) { return(WriteBsdResult(Context, -1, LinuxError.EPROTONOSUPPORT)); } else if ((Type == SocketType.Seqpacket || Type == SocketType.Raw) && !IsPrivileged) { if (Domain != AddressFamily.InterNetwork || Type != SocketType.Raw || Protocol != ProtocolType.Icmp) { return(WriteBsdResult(Context, -1, LinuxError.ENOENT)); } } BsdSocket NewBsdSocket = new BsdSocket { Family = (int)Domain, Type = (int)Type, Protocol = (int)Protocol, Handle = new Socket(Domain, Type, Protocol) }; Sockets.Add(NewBsdSocket); if (Exempt) { NewBsdSocket.Handle.Disconnect(true); } return(WriteBsdResult(Context, Sockets.Count - 1)); }
// Read(u32 socket) -> (i32 ret, u32 bsd_errno, buffer<i8, 0x22, 0> message) public ResultCode Read(ServiceCtx context) { int socketFd = context.RequestData.ReadInt32(); (long receivePosition, long receiveLength) = context.Request.GetBufferType0x22(); LinuxError errno = LinuxError.EBADF; BsdSocket socket = RetrieveSocket(socketFd); int result = -1; if (socket != null) { byte[] receivedBuffer = new byte[receiveLength]; try { result = socket.Handle.Receive(receivedBuffer); errno = SetResultErrno(socket.Handle, result); } catch (SocketException exception) { errno = ConvertError((WsaError)exception.ErrorCode); } } return(WriteBsdResult(context, result, errno)); }
// Connect(u32 socket, buffer<nn::socket::sockaddr_in, 0x21, 0x10>) -> (i32 ret, u32 bsd_errno) public ResultCode Connect(ServiceCtx context) { int socketFd = context.RequestData.ReadInt32(); (long bufferPos, long bufferSize) = context.Request.GetBufferType0x21(); LinuxError errno = LinuxError.EBADF; BsdSocket socket = RetrieveSocket(socketFd); if (socket != null) { errno = LinuxError.SUCCESS; try { IPEndPoint endPoint = ParseSockAddr(context, bufferPos, bufferSize); socket.Handle.Connect(endPoint); } catch (SocketException exception) { errno = ConvertError((WsaError)exception.ErrorCode); } } return(WriteBsdResult(context, 0, errno)); }
// Write(u32 socket, buffer<i8, 0x21, 0> message) -> (i32 ret, u32 bsd_errno) public long Write(ServiceCtx Context) { int SocketFd = Context.RequestData.ReadInt32(); (long SendPosition, long SendSize) = Context.Request.GetBufferType0x21(); LinuxError Errno = LinuxError.EBADF; BsdSocket Socket = RetrieveSocket(SocketFd); int Result = -1; if (Socket != null) { byte[] SendBuffer = Context.Memory.ReadBytes(SendPosition, SendSize); try { Result = Socket.Handle.Send(SendBuffer); Errno = SetResultErrno(Socket.Handle, Result); } catch (SocketException Exception) { Errno = ConvertError((WSAError)Exception.ErrorCode); } } return(WriteBsdResult(Context, Result, Errno)); }
// SetSockOpt(u32 socket, u32 level, u32 option_name, buffer<unknown, 0x21, 0> option_value) -> (i32 ret, u32 bsd_errno) public long SetSockOpt(ServiceCtx Context) { int SocketFd = Context.RequestData.ReadInt32(); int Level = Context.RequestData.ReadInt32(); int OptionName = Context.RequestData.ReadInt32(); (long BufferPos, long BufferSize) = Context.Request.GetBufferType0x21(); LinuxError Errno = LinuxError.EBADF; BsdSocket Socket = RetrieveSocket(SocketFd); if (Socket != null) { Errno = LinuxError.ENOPROTOOPT; if (Level == 0xFFFF) { Errno = HandleSetSocketOption(Context, Socket, (SocketOptionName)OptionName, BufferPos, BufferSize); } else { Logger.PrintWarning(LogClass.ServiceBsd, $"Unsupported SetSockOpt Level: {(SocketOptionLevel)Level}"); } } return(WriteBsdResult(Context, 0, Errno)); }
// Ioctl(u32 fd, u32 request, u32 bufcount, buffer<unknown, 0x21, 0>, buffer<unknown, 0x21, 0>, buffer<unknown, 0x21, 0>, buffer<unknown, 0x21, 0>) -> (i32 ret, u32 bsd_errno, buffer<unknown, 0x22, 0>, buffer<unknown, 0x22, 0>, buffer<unknown, 0x22, 0>, buffer<unknown, 0x22, 0>) public long Ioctl(ServiceCtx Context) { int SocketFd = Context.RequestData.ReadInt32(); BsdIoctl Cmd = (BsdIoctl)Context.RequestData.ReadInt32(); int BufferCount = Context.RequestData.ReadInt32(); LinuxError Errno = LinuxError.EBADF; BsdSocket Socket = RetrieveSocket(SocketFd); if (Socket != null) { switch (Cmd) { case BsdIoctl.AtMark: Errno = LinuxError.SUCCESS; (long BufferPosition, long BufferSize) = Context.Request.GetBufferType0x22(); // FIXME: OOB not implemented. Context.Memory.WriteInt32(BufferPosition, 0); break; default: Errno = LinuxError.EOPNOTSUPP; Logger.PrintWarning(LogClass.ServiceBsd, $"Unsupported Ioctl Cmd: {Cmd}"); break; } } return(WriteBsdResult(Context, 0, Errno)); }
// Fcntl(u32 socket, u32 cmd, u32 arg) -> (i32 ret, u32 bsd_errno) public long Fcntl(ServiceCtx Context) { int SocketFd = Context.RequestData.ReadInt32(); int Cmd = Context.RequestData.ReadInt32(); int Arg = Context.RequestData.ReadInt32(); int Result = 0; LinuxError Errno = LinuxError.EBADF; BsdSocket Socket = RetrieveSocket(SocketFd); if (Socket != null) { Errno = LinuxError.SUCCESS; if (Cmd == 0x3) { Result = !Socket.Handle.Blocking ? 0x800 : 0; } else if (Cmd == 0x4 && Arg == 0x800) { Socket.Handle.Blocking = false; Result = 0; } else { Errno = LinuxError.EOPNOTSUPP; } } return(WriteBsdResult(Context, Result, Errno)); }
// Connect(u32 socket, buffer<nn::socket::sockaddr_in, 0x21, 0x10>) -> (i32 ret, u32 bsd_errno) public long Connect(ServiceCtx Context) { int SocketFd = Context.RequestData.ReadInt32(); (long BufferPos, long BufferSize) = Context.Request.GetBufferType0x21(); LinuxError Errno = LinuxError.EBADF; BsdSocket Socket = RetrieveSocket(SocketFd); if (Socket != null) { Errno = LinuxError.SUCCESS; try { IPEndPoint EndPoint = ParseSockAddr(Context, BufferPos, BufferSize); Socket.Handle.Connect(EndPoint); } catch (SocketException Exception) { Errno = ConvertError((WSAError)Exception.ErrorCode); } } return(WriteBsdResult(Context, 0, Errno)); }
// Ioctl(u32 fd, u32 request, u32 bufcount, buffer<unknown, 0x21, 0>, buffer<unknown, 0x21, 0>, buffer<unknown, 0x21, 0>, buffer<unknown, 0x21, 0>) -> (i32 ret, u32 bsd_errno, buffer<unknown, 0x22, 0>, buffer<unknown, 0x22, 0>, buffer<unknown, 0x22, 0>, buffer<unknown, 0x22, 0>) public ResultCode Ioctl(ServiceCtx context) { int socketFd = context.RequestData.ReadInt32(); BsdIoctl cmd = (BsdIoctl)context.RequestData.ReadInt32(); int bufferCount = context.RequestData.ReadInt32(); LinuxError errno = LinuxError.EBADF; BsdSocket socket = RetrieveSocket(socketFd); if (socket != null) { switch (cmd) { case BsdIoctl.AtMark: errno = LinuxError.SUCCESS; (long bufferPosition, long bufferSize) = context.Request.GetBufferType0x22(); // FIXME: OOB not implemented. context.Memory.WriteInt32(bufferPosition, 0); break; default: errno = LinuxError.EOPNOTSUPP; Logger.PrintWarning(LogClass.ServiceBsd, $"Unsupported Ioctl Cmd: {cmd}"); break; } } return(WriteBsdResult(context, 0, errno)); }
// Fcntl(u32 socket, u32 cmd, u32 arg) -> (i32 ret, u32 bsd_errno) public ResultCode Fcntl(ServiceCtx context) { int socketFd = context.RequestData.ReadInt32(); int cmd = context.RequestData.ReadInt32(); int arg = context.RequestData.ReadInt32(); int result = 0; LinuxError errno = LinuxError.EBADF; BsdSocket socket = RetrieveSocket(socketFd); if (socket != null) { errno = LinuxError.SUCCESS; if (cmd == 0x3) { result = !socket.Handle.Blocking ? 0x800 : 0; } else if (cmd == 0x4 && arg == 0x800) { socket.Handle.Blocking = false; result = 0; } else { errno = LinuxError.EOPNOTSUPP; } } return(WriteBsdResult(context, result, errno)); }
// SetSockOpt(u32 socket, u32 level, u32 option_name, buffer<unknown, 0x21, 0> option_value) -> (i32 ret, u32 bsd_errno) public ResultCode SetSockOpt(ServiceCtx context) { int socketFd = context.RequestData.ReadInt32(); int level = context.RequestData.ReadInt32(); int optionName = context.RequestData.ReadInt32(); (long bufferPos, long bufferSize) = context.Request.GetBufferType0x21(); LinuxError errno = LinuxError.EBADF; BsdSocket socket = RetrieveSocket(socketFd); if (socket != null) { errno = LinuxError.ENOPROTOOPT; if (level == 0xFFFF) { errno = HandleSetSocketOption(context, socket, (SocketOptionName)optionName, bufferPos, bufferSize); } else { Logger.PrintWarning(LogClass.ServiceBsd, $"Unsupported SetSockOpt Level: {(SocketOptionLevel)level}"); } } return(WriteBsdResult(context, 0, errno)); }
private ResultCode SocketInternal(ServiceCtx context, bool exempt) { AddressFamily domain = (AddressFamily)context.RequestData.ReadInt32(); SocketType type = (SocketType)context.RequestData.ReadInt32(); ProtocolType protocol = (ProtocolType)context.RequestData.ReadInt32(); if (domain == AddressFamily.Unknown) { return(WriteBsdResult(context, -1, LinuxError.EPROTONOSUPPORT)); } else if ((type == SocketType.Seqpacket || type == SocketType.Raw) && !_isPrivileged) { if (domain != AddressFamily.InterNetwork || type != SocketType.Raw || protocol != ProtocolType.Icmp) { return(WriteBsdResult(context, -1, LinuxError.ENOENT)); } } BsdSocket newBsdSocket = new BsdSocket { Family = (int)domain, Type = (int)type, Protocol = (int)protocol, Handle = new Socket(domain, type, protocol) }; _sockets.Add(newBsdSocket); if (exempt) { newBsdSocket.Handle.Disconnect(true); } return(WriteBsdResult(context, _sockets.Count - 1)); }
// Write(u32 socket, buffer<i8, 0x21, 0> message) -> (i32 ret, u32 bsd_errno) public ResultCode Write(ServiceCtx context) { int socketFd = context.RequestData.ReadInt32(); (long sendPosition, long sendSize) = context.Request.GetBufferType0x21(); LinuxError errno = LinuxError.EBADF; BsdSocket socket = RetrieveSocket(socketFd); int result = -1; if (socket != null) { byte[] sendBuffer = context.Memory.ReadBytes(sendPosition, sendSize); try { result = socket.Handle.Send(sendBuffer); errno = SetResultErrno(socket.Handle, result); } catch (SocketException exception) { errno = ConvertError((WsaError)exception.ErrorCode); } } return(WriteBsdResult(context, result, errno)); }
// Accept(u32 socket) -> (i32 ret, u32 bsd_errno, u32 addrlen, buffer<nn::socket::sockaddr_in, 0x22, 0x10> addr) public ResultCode Accept(ServiceCtx context) { int socketFd = context.RequestData.ReadInt32(); (long bufferPos, long bufferSize) = context.Request.GetBufferType0x22(); LinuxError errno = LinuxError.EBADF; BsdSocket socket = RetrieveSocket(socketFd); if (socket != null) { errno = LinuxError.SUCCESS; Socket newSocket = null; try { newSocket = socket.Handle.Accept(); } catch (SocketException exception) { errno = ConvertError((WsaError)exception.ErrorCode); } if (newSocket == null && errno == LinuxError.SUCCESS) { errno = LinuxError.EWOULDBLOCK; } else if (errno == LinuxError.SUCCESS) { BsdSocket newBsdSocket = new BsdSocket { Family = (int)newSocket.AddressFamily, Type = (int)newSocket.SocketType, Protocol = (int)newSocket.ProtocolType, Handle = newSocket }; _sockets.Add(newBsdSocket); WriteSockAddr(context, bufferPos, newBsdSocket, true); WriteBsdResult(context, _sockets.Count - 1, errno); context.ResponseData.Write(0x10); return(ResultCode.Success); } } return(WriteBsdResult(context, -1, errno)); }
// Accept(u32 socket) -> (i32 ret, u32 bsd_errno, u32 addrlen, buffer<nn::socket::sockaddr_in, 0x22, 0x10> addr) public long Accept(ServiceCtx Context) { int SocketFd = Context.RequestData.ReadInt32(); (long BufferPos, long BufferSize) = Context.Request.GetBufferType0x22(); LinuxError Errno = LinuxError.EBADF; BsdSocket Socket = RetrieveSocket(SocketFd); if (Socket != null) { Errno = LinuxError.SUCCESS; Socket NewSocket = null; try { NewSocket = Socket.Handle.Accept(); } catch (SocketException Exception) { Errno = ConvertError((WSAError)Exception.ErrorCode); } if (NewSocket == null && Errno == LinuxError.SUCCESS) { Errno = LinuxError.EWOULDBLOCK; } else if (Errno == LinuxError.SUCCESS) { BsdSocket NewBsdSocket = new BsdSocket { Family = (int)NewSocket.AddressFamily, Type = (int)NewSocket.SocketType, Protocol = (int)NewSocket.ProtocolType, Handle = NewSocket, }; Sockets.Add(NewBsdSocket); WriteSockAddr(Context, BufferPos, NewBsdSocket, true); WriteBsdResult(Context, Sockets.Count - 1, Errno); Context.ResponseData.Write(0x10); return(0); } } return(WriteBsdResult(Context, -1, Errno)); }
// Close(u32 socket) -> (i32 ret, u32 bsd_errno) public ResultCode Close(ServiceCtx context) { int socketFd = context.RequestData.ReadInt32(); LinuxError errno = LinuxError.EBADF; BsdSocket socket = RetrieveSocket(socketFd); if (socket != null) { socket.Handle.Close(); _sockets[socketFd] = null; errno = LinuxError.SUCCESS; } return(WriteBsdResult(context, 0, errno)); }
// Close(u32 socket) -> (i32 ret, u32 bsd_errno) public long Close(ServiceCtx Context) { int SocketFd = Context.RequestData.ReadInt32(); LinuxError Errno = LinuxError.EBADF; BsdSocket Socket = RetrieveSocket(SocketFd); if (Socket != null) { Socket.Handle.Close(); Sockets[SocketFd] = null; Errno = LinuxError.SUCCESS; } return(WriteBsdResult(Context, 0, Errno)); }
private LinuxError HandleSetSocketOption(ServiceCtx context, BsdSocket socket, SocketOptionName optionName, long optionValuePosition, long optionValueSize) { try { switch (optionName) { case SocketOptionName.Broadcast: case SocketOptionName.DontLinger: case SocketOptionName.Debug: case SocketOptionName.Error: case SocketOptionName.KeepAlive: case SocketOptionName.OutOfBandInline: case SocketOptionName.ReceiveBuffer: case SocketOptionName.ReceiveTimeout: case SocketOptionName.SendBuffer: case SocketOptionName.SendTimeout: case SocketOptionName.Type: case SocketOptionName.ReuseAddress: socket.Handle.SetSocketOption(SocketOptionLevel.Socket, optionName, context.Memory.ReadInt32(optionValuePosition)); return(LinuxError.SUCCESS); case (SocketOptionName)0x200: socket.Handle.SetSocketOption(SocketOptionLevel.Socket, SocketOptionName.ReuseAddress, context.Memory.ReadInt32(optionValuePosition)); return(LinuxError.SUCCESS); case SocketOptionName.Linger: socket.Handle.SetSocketOption(SocketOptionLevel.Socket, SocketOptionName.Linger, new LingerOption(context.Memory.ReadInt32(optionValuePosition) != 0, context.Memory.ReadInt32(optionValuePosition + 4))); return(LinuxError.SUCCESS); default: Logger.PrintWarning(LogClass.ServiceBsd, $"Unsupported SetSockOpt OptionName: {optionName}"); return(LinuxError.EOPNOTSUPP); } } catch (SocketException exception) { return(ConvertError((WsaError)exception.ErrorCode)); } }
// RecvFrom(u32 sock, u32 flags) -> (i32 ret, u32 bsd_errno, u32 addrlen, buffer<i8, 0x22, 0> message, buffer<nn::socket::sockaddr_in, 0x22, 0x10>) public long RecvFrom(ServiceCtx Context) { int SocketFd = Context.RequestData.ReadInt32(); SocketFlags SocketFlags = (SocketFlags)Context.RequestData.ReadInt32(); (long ReceivePosition, long ReceiveLength) = Context.Request.GetBufferType0x22(); (long SockAddrInPosition, long SockAddrInSize) = Context.Request.GetBufferType0x21(); (long SockAddrOutPosition, long SockAddrOutSize) = Context.Request.GetBufferType0x22(1); LinuxError Errno = LinuxError.EBADF; BsdSocket Socket = RetrieveSocket(SocketFd); int Result = -1; if (Socket != null) { if (SocketFlags != SocketFlags.None && (SocketFlags & SocketFlags.OutOfBand) == 0 && (SocketFlags & SocketFlags.Peek) == 0) { Logger.PrintWarning(LogClass.ServiceBsd, $"Unsupported Recv flags: {SocketFlags}"); return(WriteBsdResult(Context, -1, LinuxError.EOPNOTSUPP)); } byte[] ReceivedBuffer = new byte[ReceiveLength]; EndPoint EndPoint = ParseSockAddr(Context, SockAddrInPosition, SockAddrInSize); try { Result = Socket.Handle.ReceiveFrom(ReceivedBuffer, ReceivedBuffer.Length, SocketFlags, ref EndPoint); Errno = SetResultErrno(Socket.Handle, Result); Context.Memory.WriteBytes(ReceivePosition, ReceivedBuffer); WriteSockAddr(Context, SockAddrOutPosition, (IPEndPoint)EndPoint); } catch (SocketException Exception) { Errno = ConvertError((WSAError)Exception.ErrorCode); } } return(WriteBsdResult(Context, Result, Errno)); }
private LinuxError HandleGetSocketOption(ServiceCtx Context, BsdSocket Socket, SocketOptionName OptionName, long OptionValuePosition, long OptionValueSize) { try { byte[] OptionValue = new byte[OptionValueSize]; switch (OptionName) { case SocketOptionName.Broadcast: case SocketOptionName.DontLinger: case SocketOptionName.Debug: case SocketOptionName.Error: case SocketOptionName.KeepAlive: case SocketOptionName.OutOfBandInline: case SocketOptionName.ReceiveBuffer: case SocketOptionName.ReceiveTimeout: case SocketOptionName.SendBuffer: case SocketOptionName.SendTimeout: case SocketOptionName.Type: case SocketOptionName.Linger: Socket.Handle.GetSocketOption(SocketOptionLevel.Socket, OptionName, OptionValue); Context.Memory.WriteBytes(OptionValuePosition, OptionValue); return(LinuxError.SUCCESS); case (SocketOptionName)0x200: Socket.Handle.GetSocketOption(SocketOptionLevel.Socket, SocketOptionName.ReuseAddress, OptionValue); Context.Memory.WriteBytes(OptionValuePosition, OptionValue); return(LinuxError.SUCCESS); default: Logger.PrintWarning(LogClass.ServiceBsd, $"Unsupported SetSockOpt OptionName: {OptionName}"); return(LinuxError.EOPNOTSUPP); } } catch (SocketException Exception) { return(ConvertError((WSAError)Exception.ErrorCode)); } }
// RecvFrom(u32 sock, u32 flags) -> (i32 ret, u32 bsd_errno, u32 addrlen, buffer<i8, 0x22, 0> message, buffer<nn::socket::sockaddr_in, 0x22, 0x10>) public long RecvFrom(ServiceCtx context) { int socketFd = context.RequestData.ReadInt32(); SocketFlags socketFlags = (SocketFlags)context.RequestData.ReadInt32(); (long receivePosition, long receiveLength) = context.Request.GetBufferType0x22(); (long sockAddrInPosition, long sockAddrInSize) = context.Request.GetBufferType0x21(); (long sockAddrOutPosition, long sockAddrOutSize) = context.Request.GetBufferType0x22(1); LinuxError errno = LinuxError.EBADF; BsdSocket socket = RetrieveSocket(socketFd); int result = -1; if (socket != null) { if (socketFlags != SocketFlags.None && (socketFlags & SocketFlags.OutOfBand) == 0 && (socketFlags & SocketFlags.Peek) == 0) { Logger.PrintWarning(LogClass.ServiceBsd, $"Unsupported Recv flags: {socketFlags}"); return(WriteBsdResult(context, -1, LinuxError.EOPNOTSUPP)); } byte[] receivedBuffer = new byte[receiveLength]; EndPoint endPoint = ParseSockAddr(context, sockAddrInPosition, sockAddrInSize); try { result = socket.Handle.ReceiveFrom(receivedBuffer, receivedBuffer.Length, socketFlags, ref endPoint); errno = SetResultErrno(socket.Handle, result); context.Memory.WriteBytes(receivePosition, receivedBuffer); WriteSockAddr(context, sockAddrOutPosition, (IPEndPoint)endPoint); } catch (SocketException exception) { errno = ConvertError((WsaError)exception.ErrorCode); } } return(WriteBsdResult(context, result, errno)); }
//(u32 domain, u32 type, u32 protocol) -> (i32 ret, u32 bsd_errno) public long Socket(ServiceCtx Context) { BsdSocket NewBsdSocket = new BsdSocket { Family = Context.RequestData.ReadInt32(), Type = Context.RequestData.ReadInt32(), Protocol = Context.RequestData.ReadInt32() }; Sockets.Add(NewBsdSocket); NewBsdSocket.Handle = new Socket((AddressFamily)NewBsdSocket.Family, (SocketType)NewBsdSocket.Type, (ProtocolType)NewBsdSocket.Protocol); Context.ResponseData.Write(Sockets.Count - 1); Context.ResponseData.Write(0); return(0); }
// GetSockName(u32 socket) -> (i32 ret, u32 bsd_errno, u32 addrlen, buffer<nn::socket::sockaddr_in, 0x22, 0x10> addr) public long GetSockName(ServiceCtx Context) { int SocketFd = Context.RequestData.ReadInt32(); (long BufferPos, long BufferSize) = Context.Request.GetBufferType0x22(); LinuxError Errno = LinuxError.EBADF; BsdSocket Socket = RetrieveSocket(SocketFd); if (Socket != null) { Errno = LinuxError.SUCCESS; WriteSockAddr(Context, BufferPos, Socket, false); WriteBsdResult(Context, 0, Errno); Context.ResponseData.Write(0x10); } return(WriteBsdResult(Context, 0, Errno)); }
// GetSockName(u32 socket) -> (i32 ret, u32 bsd_errno, u32 addrlen, buffer<nn::socket::sockaddr_in, 0x22, 0x10> addr) public ResultCode GetSockName(ServiceCtx context) { int socketFd = context.RequestData.ReadInt32(); (long bufferPos, long bufferSize) = context.Request.GetBufferType0x22(); LinuxError errno = LinuxError.EBADF; BsdSocket socket = RetrieveSocket(socketFd); if (socket != null) { errno = LinuxError.SUCCESS; WriteSockAddr(context, bufferPos, socket, false); WriteBsdResult(context, 0, errno); context.ResponseData.Write(0x10); } return(WriteBsdResult(context, 0, errno)); }
// SendTo(u32 socket, u32 flags, buffer<i8, 0x21, 0>, buffer<nn::socket::sockaddr_in, 0x21, 0x10>) -> (i32 ret, u32 bsd_errno) public long SendTo(ServiceCtx Context) { int SocketFd = Context.RequestData.ReadInt32(); SocketFlags SocketFlags = (SocketFlags)Context.RequestData.ReadInt32(); (long SendPosition, long SendSize) = Context.Request.GetBufferType0x21(); (long BufferPosition, long BufferSize) = Context.Request.GetBufferType0x21(1); LinuxError Errno = LinuxError.EBADF; BsdSocket Socket = RetrieveSocket(SocketFd); int Result = -1; if (Socket != null) { if (SocketFlags != SocketFlags.None && SocketFlags != SocketFlags.OutOfBand && SocketFlags != SocketFlags.Peek && SocketFlags != SocketFlags.DontRoute) { Logger.PrintWarning(LogClass.ServiceBsd, $"Unsupported Send flags: {SocketFlags}"); return(WriteBsdResult(Context, -1, LinuxError.EOPNOTSUPP)); } byte[] SendBuffer = Context.Memory.ReadBytes(SendPosition, SendSize); EndPoint EndPoint = ParseSockAddr(Context, BufferPosition, BufferSize); try { Result = Socket.Handle.SendTo(SendBuffer, SendBuffer.Length, SocketFlags, EndPoint); Errno = SetResultErrno(Socket.Handle, Result); } catch (SocketException Exception) { Errno = ConvertError((WSAError)Exception.ErrorCode); } } return(WriteBsdResult(Context, Result, Errno)); }
// SendTo(u32 socket, u32 flags, buffer<i8, 0x21, 0>, buffer<nn::socket::sockaddr_in, 0x21, 0x10>) -> (i32 ret, u32 bsd_errno) public ResultCode SendTo(ServiceCtx context) { int socketFd = context.RequestData.ReadInt32(); SocketFlags socketFlags = (SocketFlags)context.RequestData.ReadInt32(); (long sendPosition, long sendSize) = context.Request.GetBufferType0x21(); (long bufferPosition, long bufferSize) = context.Request.GetBufferType0x21(1); LinuxError errno = LinuxError.EBADF; BsdSocket socket = RetrieveSocket(socketFd); int result = -1; if (socket != null) { if (socketFlags != SocketFlags.None && socketFlags != SocketFlags.OutOfBand && socketFlags != SocketFlags.Peek && socketFlags != SocketFlags.DontRoute) { Logger.PrintWarning(LogClass.ServiceBsd, $"Unsupported Send flags: {socketFlags}"); return(WriteBsdResult(context, -1, LinuxError.EOPNOTSUPP)); } byte[] sendBuffer = context.Memory.ReadBytes(sendPosition, sendSize); EndPoint endPoint = ParseSockAddr(context, bufferPosition, bufferSize); try { result = socket.Handle.SendTo(sendBuffer, sendBuffer.Length, socketFlags, endPoint); errno = SetResultErrno(socket.Handle, result); } catch (SocketException exception) { errno = ConvertError((WsaError)exception.ErrorCode); } } return(WriteBsdResult(context, result, errno)); }
// DuplicateSocket(u32 socket, u64 reserved) -> (i32 ret, u32 bsd_errno) public ResultCode DuplicateSocket(ServiceCtx context) { int socketFd = context.RequestData.ReadInt32(); ulong reserved = context.RequestData.ReadUInt64(); LinuxError errno = LinuxError.ENOENT; int newSockFd = -1; if (_isPrivileged) { errno = LinuxError.EBADF; BsdSocket oldSocket = RetrieveSocket(socketFd); if (oldSocket != null) { _sockets.Add(oldSocket); newSockFd = _sockets.Count - 1; } } return(WriteBsdResult(context, newSockFd, errno)); }