mirror of
https://github.com/Ed94/Odin.git
synced 2026-07-31 20:00:09 +00:00
manually start merging core_net
This commit is contained in:
@@ -179,6 +179,93 @@ RTLD_NODELETE :: 0x80
|
||||
RTLD_NOLOAD :: 0x10
|
||||
RTLD_FIRST :: 0x100
|
||||
|
||||
SOL_SOCKET :: 0xFFFF
|
||||
|
||||
SOCK_STREAM :: 1
|
||||
SOCK_DGRAM :: 2
|
||||
SOCK_RAW :: 3
|
||||
SOCK_RDM :: 4
|
||||
SOCK_SEQPACKET :: 5
|
||||
|
||||
SO_DEBUG :: 0x0001
|
||||
SO_ACCEPTCONN :: 0x0002
|
||||
SO_REUSEADDR :: 0x0004
|
||||
SO_KEEPALIVE :: 0x0008
|
||||
SO_DONTROUTE :: 0x0010
|
||||
SO_BROADCAST :: 0x0020
|
||||
SO_USELOOPBACK :: 0x0040
|
||||
SO_LINGER :: 0x0080
|
||||
SO_OOBINLINE :: 0x0100
|
||||
SO_REUSEPORT :: 0x0200
|
||||
SO_TIMESTAMP :: 0x0400
|
||||
|
||||
SO_DONTTRUNC :: 0x2000
|
||||
SO_WANTMORE :: 0x4000
|
||||
SO_WANTOOBFLAG :: 0x8000
|
||||
SO_SNDBUF :: 0x1001
|
||||
SO_RCVBUF :: 0x1002
|
||||
SO_SNDLOWAT :: 0x1003
|
||||
SO_RCVLOWAT :: 0x1004
|
||||
SO_SNDTIMEO :: 0x1005
|
||||
SO_RCVTIMEO :: 0x1006
|
||||
SO_ERROR :: 0x1007
|
||||
SO_TYPE :: 0x1008
|
||||
SO_PRIVSTATE :: 0x1009
|
||||
SO_NREAD :: 0x1020
|
||||
SO_NKE :: 0x1021
|
||||
|
||||
AF_UNSPEC :: 0
|
||||
AF_LOCAL :: 1
|
||||
AF_UNIX :: AF_LOCAL
|
||||
AF_INET :: 2
|
||||
AF_IMPLINK :: 3
|
||||
AF_PUP :: 4
|
||||
AF_CHAOS :: 5
|
||||
AF_NS :: 6
|
||||
AF_ISO :: 7
|
||||
AF_OSI :: AF_ISO
|
||||
AF_ECMA :: 8
|
||||
AF_DATAKIT :: 9
|
||||
AF_CCITT :: 10
|
||||
AF_SNA :: 11
|
||||
AF_DECnet :: 12
|
||||
AF_DLI :: 13
|
||||
AF_LAT :: 14
|
||||
AF_HYLINK :: 15
|
||||
AF_APPLETALK :: 16
|
||||
AF_ROUTE :: 17
|
||||
AF_LINK :: 18
|
||||
pseudo_AF_XTP :: 19
|
||||
AF_COIP :: 20
|
||||
AF_CNT :: 21
|
||||
pseudo_AF_RTIP :: 22
|
||||
AF_IPX :: 23
|
||||
AF_SIP :: 24
|
||||
pseudo_AF_PIP :: 25
|
||||
pseudo_AF_BLUE :: 26
|
||||
AF_NDRV :: 27
|
||||
AF_ISDN :: 28
|
||||
AF_E164 :: AF_ISDN
|
||||
pseudo_AF_KEY :: 29
|
||||
AF_INET6 :: 30
|
||||
AF_NATM :: 31
|
||||
AF_SYSTEM :: 32
|
||||
AF_NETBIOS :: 33
|
||||
AF_PPP :: 34
|
||||
|
||||
TCP_NODELAY :: 0x01
|
||||
TCP_MAXSEG :: 0x02
|
||||
TCP_NOPUSH :: 0x04
|
||||
TCP_NOOPT :: 0x08
|
||||
|
||||
IPPROTO_ICMP :: 1
|
||||
IPPROTO_TCP :: 6
|
||||
IPPROTO_UDP :: 17
|
||||
|
||||
SHUT_RD :: 0
|
||||
SHUT_WR :: 1
|
||||
SHUT_RDWR :: 2
|
||||
|
||||
|
||||
// "Argv" arguments converted to Odin strings
|
||||
args := _alloc_command_line_arguments()
|
||||
@@ -224,6 +311,58 @@ Dirent :: struct {
|
||||
|
||||
Dir :: distinct rawptr // DIR*
|
||||
|
||||
SOCKADDR :: struct #packed {
|
||||
len: c.char,
|
||||
family: c.char,
|
||||
sa_data: [14]c.char,
|
||||
}
|
||||
|
||||
SOCKADDR_STORAGE_LH :: struct #packed {
|
||||
len: c.char,
|
||||
family: c.char,
|
||||
__ss_pad1: [6]c.char,
|
||||
__ss_align: i64,
|
||||
__ss_pad2: [112]c.char,
|
||||
}
|
||||
|
||||
sockaddr_in :: struct #packed {
|
||||
sin_len: c.char,
|
||||
sin_family: c.char,
|
||||
sin_port: u16be,
|
||||
sin_addr: in_addr,
|
||||
sin_zero: [8]c.char,
|
||||
}
|
||||
|
||||
sockaddr_in6 :: struct #packed {
|
||||
sin6_len: c.char,
|
||||
sin6_family: c.char,
|
||||
sin6_port: u16be,
|
||||
sin6_flowinfo: c.uint,
|
||||
sin6_addr: in6_addr,
|
||||
sin6_scope_id: c.uint,
|
||||
}
|
||||
|
||||
in_addr :: struct #packed {
|
||||
s_addr: u32,
|
||||
}
|
||||
|
||||
in6_addr :: struct #packed {
|
||||
s6_addr: [16]u8,
|
||||
}
|
||||
|
||||
Timeval :: struct {
|
||||
seconds: i64,
|
||||
nanoseconds: int,
|
||||
}
|
||||
|
||||
Linger :: struct {
|
||||
onoff: int,
|
||||
linger: int,
|
||||
}
|
||||
|
||||
Socket :: distinct int
|
||||
socklen_t :: c.int
|
||||
|
||||
// File type
|
||||
S_IFMT :: 0o170000 // Type of file mask
|
||||
S_IFIFO :: 0o010000 // Named pipe (fifo)
|
||||
@@ -318,6 +457,18 @@ foreign libc {
|
||||
@(link_name="strerror") _darwin_string_error :: proc(num : c.int) -> cstring ---
|
||||
@(link_name="sysctlbyname") _sysctlbyname :: proc(path: cstring, oldp: rawptr, oldlenp: rawptr, newp: rawptr, newlen: int) -> c.int ---
|
||||
|
||||
@(link_name="socket") _unix_socket :: proc(domain: int, type: int, protocol: int) -> int ---
|
||||
@(link_name="listen") _unix_listen :: proc(socket: int, backlog: int) -> int ---
|
||||
@(link_name="accept") _unix_accept :: proc(socket: int, addr: rawptr, addr_len: rawptr) -> int ---
|
||||
@(link_name="connect") _unix_connect :: proc(socket: int, addr: rawptr, addr_len: socklen_t) -> int ---
|
||||
@(link_name="bind") _unix_bind :: proc(socket: int, addr: rawptr, addr_len: socklen_t) -> int ---
|
||||
@(link_name="setsockopt") _unix_setsockopt :: proc(socket: int, level: int, opt_name: int, opt_val: rawptr, opt_len: socklen_t) -> int ---
|
||||
@(link_name="recvfrom") _unix_recvfrom :: proc(socket: int, buffer: rawptr, buffer_len: c.size_t, flags: int, addr: rawptr, addr_len: ^socklen_t) -> c.ssize_t ---
|
||||
@(link_name="recv") _unix_recv :: proc(socket: int, buffer: rawptr, buffer_len: c.size_t, flags: int) -> c.ssize_t ---
|
||||
@(link_name="sendto") _unix_sendto :: proc(socket: int, buffer: rawptr, buffer_len: c.size_t, flags: int, addr: rawptr, addr_len: socklen_t) -> c.ssize_t ---
|
||||
@(link_name="send") _unix_send :: proc(socket: int, buffer: rawptr, buffer_len: c.size_t, flags: int) -> c.ssize_t ---
|
||||
@(link_name="shutdown") _unix_shutdown :: proc(socket: int, how: int) -> int ---
|
||||
|
||||
@(link_name="exit") _unix_exit :: proc(status: c.int) -> ! ---
|
||||
}
|
||||
|
||||
@@ -815,3 +966,91 @@ _alloc_command_line_arguments :: proc() -> []string {
|
||||
}
|
||||
return res
|
||||
}
|
||||
|
||||
socket :: proc(domain: int, type: int, protocol: int) -> (Socket, Errno) {
|
||||
result := _unix_socket(domain, type, protocol)
|
||||
if result < 0 {
|
||||
return 0, Errno(get_last_error())
|
||||
}
|
||||
return Socket(result), ERROR_NONE
|
||||
}
|
||||
|
||||
connect :: proc(sd: Socket, addr: ^SOCKADDR, len: socklen_t) -> (Errno) {
|
||||
result := _unix_connect(int(sd), addr, len)
|
||||
if result < 0 {
|
||||
return Errno(get_last_error())
|
||||
}
|
||||
return ERROR_NONE
|
||||
}
|
||||
|
||||
bind :: proc(sd: Socket, addr: ^SOCKADDR, len: socklen_t) -> (Errno) {
|
||||
result := _unix_bind(int(sd), addr, len)
|
||||
if result < 0 {
|
||||
return Errno(get_last_error())
|
||||
}
|
||||
return ERROR_NONE
|
||||
}
|
||||
|
||||
accept :: proc(sd: Socket, addr: ^SOCKADDR, len: rawptr) -> (Socket, Errno) {
|
||||
result := _unix_accept(int(sd), rawptr(addr), len)
|
||||
if result < 0 {
|
||||
return 0, Errno(get_last_error())
|
||||
}
|
||||
return Socket(result), ERROR_NONE
|
||||
}
|
||||
|
||||
listen :: proc(sd: Socket, backlog: int) -> (Errno) {
|
||||
result := _unix_listen(int(sd), backlog)
|
||||
if result < 0 {
|
||||
return Errno(get_last_error())
|
||||
}
|
||||
return ERROR_NONE
|
||||
}
|
||||
|
||||
setsockopt :: proc(sd: Socket, level: int, optname: int, optval: rawptr, optlen: socklen_t) -> (Errno) {
|
||||
result := _unix_setsockopt(int(sd), level, optname, optval, optlen)
|
||||
if result < 0 {
|
||||
return Errno(get_last_error())
|
||||
}
|
||||
return ERROR_NONE
|
||||
}
|
||||
|
||||
recvfrom :: proc(sd: Socket, data: []byte, flags: int, addr: ^SOCKADDR, addr_size: ^socklen_t) -> (u32, Errno) {
|
||||
result := _unix_recvfrom(int(sd), raw_data(data), len(data), flags, addr, addr_size)
|
||||
if result < 0 {
|
||||
return 0, Errno(get_last_error())
|
||||
}
|
||||
return u32(result), ERROR_NONE
|
||||
}
|
||||
|
||||
recv :: proc(sd: Socket, data: []byte, flags: int) -> (u32, Errno) {
|
||||
result := _unix_recv(int(sd), raw_data(data), len(data), flags)
|
||||
if result < 0 {
|
||||
return 0, Errno(get_last_error())
|
||||
}
|
||||
return u32(result), ERROR_NONE
|
||||
}
|
||||
|
||||
sendto :: proc(sd: Socket, data: []u8, flags: int, addr: ^SOCKADDR, addrlen: socklen_t) -> (u32, Errno) {
|
||||
result := _unix_sendto(int(sd), raw_data(data), len(data), flags, addr, addrlen)
|
||||
if result < 0 {
|
||||
return 0, Errno(get_last_error())
|
||||
}
|
||||
return u32(result), ERROR_NONE
|
||||
}
|
||||
|
||||
send :: proc(sd: Socket, data: []byte, flags: int) -> (u32, Errno) {
|
||||
result := _unix_send(int(sd), raw_data(data), len(data), 0)
|
||||
if result < 0 {
|
||||
return 0, Errno(get_last_error())
|
||||
}
|
||||
return u32(result), ERROR_NONE
|
||||
}
|
||||
|
||||
shutdown :: proc(sd: Socket, how: int) -> (Errno) {
|
||||
result := _unix_shutdown(int(sd), how)
|
||||
if result < 0 {
|
||||
return Errno(get_last_error())
|
||||
}
|
||||
return ERROR_NONE
|
||||
}
|
||||
|
||||
@@ -171,6 +171,59 @@ SEEK_DATA :: 3
|
||||
SEEK_HOLE :: 4
|
||||
SEEK_MAX :: SEEK_HOLE
|
||||
|
||||
|
||||
AF_UNSPEC: int : 0
|
||||
AF_UNIX: int : 1
|
||||
AF_LOCAL: int : AF_UNIX
|
||||
AF_INET: int : 2
|
||||
AF_INET6: int : 10
|
||||
AF_PACKET: int : 17
|
||||
AF_BLUETOOTH: int : 31
|
||||
|
||||
SOCK_STREAM: int : 1
|
||||
SOCK_DGRAM: int : 2
|
||||
SOCK_RAW: int : 3
|
||||
SOCK_RDM: int : 4
|
||||
SOCK_SEQPACKET: int : 5
|
||||
SOCK_PACKET: int : 10
|
||||
|
||||
INADDR_ANY: c.ulong : 0
|
||||
INADDR_BROADCAST: c.ulong : 0xffffffff
|
||||
INADDR_NONE: c.ulong : 0xffffffff
|
||||
INADDR_DUMMY: c.ulong : 0xc0000008
|
||||
|
||||
IPPROTO_IP: int : 0
|
||||
IPPROTO_ICMP: int : 1
|
||||
IPPROTO_TCP: int : 6
|
||||
IPPROTO_UDP: int : 17
|
||||
IPPROTO_IPV6: int : 41
|
||||
IPPROTO_ETHERNET: int : 143
|
||||
IPPROTO_RAW: int : 255
|
||||
|
||||
SHUT_RD: int : 0
|
||||
SHUT_WR: int : 1
|
||||
SHUT_RDWR: int : 2
|
||||
|
||||
|
||||
SOL_SOCKET: int : 1
|
||||
SO_DEBUG: int : 1
|
||||
SO_REUSEADDR: int : 2
|
||||
SO_DONTROUTE: int : 5
|
||||
SO_BROADCAST: int : 6
|
||||
SO_SNDBUF: int : 7
|
||||
SO_RCVBUF: int : 8
|
||||
SO_KEEPALIVE: int : 9
|
||||
SO_OOBINLINE: int : 10
|
||||
SO_LINGER: int : 13
|
||||
SO_REUSEPORT: int : 15
|
||||
SO_RCVTIMEO_NEW: int : 66
|
||||
SO_SNDTIMEO_NEW: int : 67
|
||||
|
||||
TCP_NODELAY: int : 1
|
||||
TCP_CORK: int : 3
|
||||
|
||||
MSG_TRUNC : int : 0x20
|
||||
|
||||
// NOTE(zangent): These are OS specific!
|
||||
// Do not mix these up!
|
||||
RTLD_LAZY :: 0x001
|
||||
@@ -217,6 +270,102 @@ Dirent :: struct {
|
||||
name: [256]byte,
|
||||
}
|
||||
|
||||
ADDRESS_FAMILY :: u16
|
||||
SOCKADDR :: struct #packed {
|
||||
sa_family: ADDRESS_FAMILY,
|
||||
sa_data: [14]c.char,
|
||||
}
|
||||
|
||||
SOCKADDR_STORAGE_LH :: struct #packed {
|
||||
ss_family: ADDRESS_FAMILY,
|
||||
__ss_pad1: [6]c.char,
|
||||
__ss_align: i64,
|
||||
__ss_pad2: [112]c.char,
|
||||
}
|
||||
|
||||
sockaddr_in :: struct #packed {
|
||||
sin_family: ADDRESS_FAMILY,
|
||||
sin_port: u16be,
|
||||
sin_addr: in_addr,
|
||||
sin_zero: [8]c.char,
|
||||
}
|
||||
|
||||
sockaddr_in6 :: struct #packed {
|
||||
sin6_family: ADDRESS_FAMILY,
|
||||
sin6_port: u16be,
|
||||
sin6_flowinfo: c.ulong,
|
||||
sin6_addr: in6_addr,
|
||||
sin6_scope_id: c.ulong,
|
||||
}
|
||||
|
||||
in_addr :: struct #packed {
|
||||
s_addr: u32,
|
||||
}
|
||||
|
||||
in6_addr :: struct #packed {
|
||||
s6_addr: [16]u8,
|
||||
}
|
||||
|
||||
rtnl_link_stats :: struct #packed {
|
||||
rx_packets: u32,
|
||||
tx_packets: u32,
|
||||
rx_bytes: u32,
|
||||
tx_bytes: u32,
|
||||
rx_errors: u32,
|
||||
tx_errors: u32,
|
||||
rx_dropped: u32,
|
||||
tx_dropped: u32,
|
||||
multicast: u32,
|
||||
collisions: u32,
|
||||
rx_length_errors: u32,
|
||||
rx_over_errors: u32,
|
||||
rx_crc_errors: u32,
|
||||
rx_frame_errors: u32,
|
||||
rx_fifo_errors: u32,
|
||||
rx_missed_errors: u32,
|
||||
tx_aborted_errors: u32,
|
||||
tx_carrier_errors: u32,
|
||||
tx_fifo_errors: u32,
|
||||
tx_heartbeat_errors: u32,
|
||||
tx_window_errors: u32,
|
||||
rx_compressed: u32,
|
||||
tx_compressed: u32,
|
||||
rx_nohandler: u32,
|
||||
}
|
||||
|
||||
SIOCGIFFLAG :: enum c.int {
|
||||
UP = 0, /* Interface is up. */
|
||||
BROADCAST = 1, /* Broadcast address valid. */
|
||||
DEBUG = 2, /* Turn on debugging. */
|
||||
LOOPBACK = 3, /* Is a loopback net. */
|
||||
POINT_TO_POINT = 4, /* Interface is point-to-point link. */
|
||||
NO_TRAILERS = 5, /* Avoid use of trailers. */
|
||||
RUNNING = 6, /* Resources allocated. */
|
||||
NOARP = 7, /* No address resolution protocol. */
|
||||
PROMISC = 8, /* Receive all packets. */
|
||||
ALL_MULTI = 9, /* Receive all multicast packets. Unimplemented. */
|
||||
MASTER = 10, /* Master of a load balancer. */
|
||||
SLAVE = 11, /* Slave of a load balancer. */
|
||||
MULTICAST = 12, /* Supports multicast. */
|
||||
PORTSEL = 13, /* Can set media type. */
|
||||
AUTOMEDIA = 14, /* Auto media select active. */
|
||||
DYNAMIC = 15, /* Dialup device with changing addresses. */
|
||||
LOWER_UP = 16,
|
||||
DORMANT = 17,
|
||||
ECHO = 18,
|
||||
}
|
||||
SIOCGIFFLAGS :: bit_set[SIOCGIFFLAG; c.int]
|
||||
|
||||
ifaddrs :: struct {
|
||||
next: ^ifaddrs,
|
||||
name: cstring,
|
||||
flags: SIOCGIFFLAGS,
|
||||
address: ^SOCKADDR,
|
||||
netmask: ^SOCKADDR,
|
||||
broadcast_or_dest: ^SOCKADDR, // Broadcast or Point-to-Point address
|
||||
data: rawptr, // Address-specific data.
|
||||
}
|
||||
|
||||
Dir :: distinct rawptr // DIR*
|
||||
|
||||
// File type
|
||||
@@ -297,6 +446,9 @@ foreign dl {
|
||||
@(link_name="dlsym") _unix_dlsym :: proc(handle: rawptr, symbol: cstring) -> rawptr ---
|
||||
@(link_name="dlclose") _unix_dlclose :: proc(handle: rawptr) -> c.int ---
|
||||
@(link_name="dlerror") _unix_dlerror :: proc() -> cstring ---
|
||||
|
||||
@(link_name="getifaddrs") _getifaddrs :: proc(ifap: ^^ifaddrs) -> (c.int) ---
|
||||
@(link_name="freeifaddrs") _freeifaddrs :: proc(ifa: ^ifaddrs) ---
|
||||
}
|
||||
|
||||
is_path_separator :: proc(r: rune) -> bool {
|
||||
@@ -823,3 +975,94 @@ _alloc_command_line_arguments :: proc() -> []string {
|
||||
}
|
||||
return res
|
||||
}
|
||||
|
||||
socket :: proc(domain: int, type: int, protocol: int) -> (Socket, Errno) {
|
||||
result := unix.sys_socket(domain, type, protocol)
|
||||
if result < 0 {
|
||||
return 0, _get_errno(result)
|
||||
}
|
||||
return Socket(result), ERROR_NONE
|
||||
}
|
||||
|
||||
bind :: proc(sd: Socket, addr: ^SOCKADDR, len: socklen_t) -> (Errno) {
|
||||
result := unix.sys_bind(int(sd), addr, len)
|
||||
if result < 0 {
|
||||
return _get_errno(result)
|
||||
}
|
||||
return ERROR_NONE
|
||||
}
|
||||
|
||||
|
||||
connect :: proc(sd: Socket, addr: ^SOCKADDR, len: socklen_t) -> (Errno) {
|
||||
result := unix.sys_connect(int(sd), addr, len)
|
||||
if result < 0 {
|
||||
return _get_errno(result)
|
||||
}
|
||||
return ERROR_NONE
|
||||
}
|
||||
|
||||
accept :: proc(sd: Socket, addr: ^SOCKADDR, len: rawptr) -> (Socket, Errno) {
|
||||
result := unix.sys_accept(int(sd), rawptr(addr), len)
|
||||
if result < 0 {
|
||||
return 0, _get_errno(result)
|
||||
}
|
||||
return Socket(result), ERROR_NONE
|
||||
}
|
||||
|
||||
listen :: proc(sd: Socket, backlog: int) -> (Errno) {
|
||||
result := unix.sys_listen(int(sd), backlog)
|
||||
if result < 0 {
|
||||
return _get_errno(result)
|
||||
}
|
||||
return ERROR_NONE
|
||||
}
|
||||
|
||||
setsockopt :: proc(sd: Socket, level: int, optname: int, optval: rawptr, optlen: socklen_t) -> (Errno) {
|
||||
result := unix.sys_setsockopt(int(sd), level, optname, optval, optlen)
|
||||
if result < 0 {
|
||||
return _get_errno(result)
|
||||
}
|
||||
return ERROR_NONE
|
||||
}
|
||||
|
||||
|
||||
recvfrom :: proc(sd: Socket, data: []byte, flags: int, addr: ^SOCKADDR, addr_size: ^socklen_t) -> (u32, Errno) {
|
||||
result := unix.sys_recvfrom(int(sd), raw_data(data), len(data), flags, addr, uintptr(addr_size))
|
||||
if result < 0 {
|
||||
return 0, _get_errno(int(result))
|
||||
}
|
||||
return u32(result), ERROR_NONE
|
||||
}
|
||||
|
||||
recv :: proc(sd: Socket, data: []byte, flags: int) -> (u32, Errno) {
|
||||
result := unix.sys_recvfrom(int(sd), raw_data(data), len(data), flags, nil, 0)
|
||||
if result < 0 {
|
||||
return 0, _get_errno(int(result))
|
||||
}
|
||||
return u32(result), ERROR_NONE
|
||||
}
|
||||
|
||||
|
||||
sendto :: proc(sd: Socket, data: []u8, flags: int, addr: ^SOCKADDR, addrlen: socklen_t) -> (u32, Errno) {
|
||||
result := unix.sys_sendto(int(sd), raw_data(data), len(data), flags, addr, addrlen)
|
||||
if result < 0 {
|
||||
return 0, _get_errno(int(result))
|
||||
}
|
||||
return u32(result), ERROR_NONE
|
||||
}
|
||||
|
||||
send :: proc(sd: Socket, data: []byte, flags: int) -> (u32, Errno) {
|
||||
result := unix.sys_sendto(int(sd), raw_data(data), len(data), 0, nil, 0)
|
||||
if result < 0 {
|
||||
return 0, _get_errno(int(result))
|
||||
}
|
||||
return u32(result), ERROR_NONE
|
||||
}
|
||||
|
||||
shutdown :: proc(sd: Socket, how: int) -> (Errno) {
|
||||
result := unix.sys_shutdown(int(sd), how)
|
||||
if result < 0 {
|
||||
return _get_errno(result)
|
||||
}
|
||||
return ERROR_NONE
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user