Add kernel sources from IP-Filter 5.1.2 to vendor-sys/ branch.
Approved by: glebius (mentor)
This commit is contained in:
parent
3d09eb5a27
commit
2472f6195d
Notes:
svn2git
2020-12-20 02:59:44 +00:00
svn path=/vendor-sys/ipfilter/dist/; revision=254562 svn path=/vendor-sys/ipfilter/5-1-2/; revision=254565; tag=vendor/ipfilter-sys/5-1-2
1351
netinet/ip_dstlist.c
Normal file
1351
netinet/ip_dstlist.c
Normal file
File diff suppressed because it is too large
Load Diff
68
netinet/ip_dstlist.h
Normal file
68
netinet/ip_dstlist.h
Normal file
@ -0,0 +1,68 @@
|
||||
/*
|
||||
* Copyright (C) 2012 by Darren Reed.
|
||||
*
|
||||
* See the IPFILTER.LICENCE file for details on licencing.
|
||||
*
|
||||
* $Id: ip_dstlist.h,v 1.5.2.6 2012/07/22 08:04:23 darren_r Exp $
|
||||
*/
|
||||
|
||||
#ifndef __IP_DSTLIST_H__
|
||||
#define __IP_DSTLIST_H__
|
||||
|
||||
typedef struct ipf_dstnode {
|
||||
struct ipf_dstnode *ipfd_next;
|
||||
struct ipf_dstnode **ipfd_pnext;
|
||||
ipfmutex_t ipfd_lock;
|
||||
frdest_t ipfd_dest;
|
||||
u_long ipfd_syncat;
|
||||
int ipfd_flags;
|
||||
int ipfd_size;
|
||||
int ipfd_states;
|
||||
int ipfd_ref;
|
||||
int ipfd_uid;
|
||||
char ipfd_names[1];
|
||||
} ipf_dstnode_t;
|
||||
|
||||
typedef enum ippool_policy_e {
|
||||
IPLDP_NONE = 0,
|
||||
IPLDP_ROUNDROBIN,
|
||||
IPLDP_CONNECTION,
|
||||
IPLDP_RANDOM,
|
||||
IPLDP_HASHED,
|
||||
IPLDP_SRCHASH,
|
||||
IPLDP_DSTHASH
|
||||
} ippool_policy_t;
|
||||
|
||||
typedef struct ippool_dst {
|
||||
struct ippool_dst *ipld_next;
|
||||
struct ippool_dst **ipld_pnext;
|
||||
ipfmutex_t ipld_lock;
|
||||
int ipld_seed;
|
||||
int ipld_unit;
|
||||
int ipld_ref;
|
||||
int ipld_flags;
|
||||
int ipld_nodes;
|
||||
int ipld_maxnodes;
|
||||
ippool_policy_t ipld_policy;
|
||||
ipf_dstnode_t **ipld_dests;
|
||||
ipf_dstnode_t *ipld_selected;
|
||||
char ipld_name[FR_GROUPLEN];
|
||||
} ippool_dst_t;
|
||||
|
||||
#define IPDST_DELETE 0x01
|
||||
|
||||
typedef struct dstlist_stat_s {
|
||||
void *ipls_list[LOOKUP_POOL_SZ];
|
||||
int ipls_numlists;
|
||||
u_long ipls_nomem;
|
||||
int ipls_numnodes;
|
||||
int ipls_numdereflists;
|
||||
int ipls_numderefnodes;
|
||||
} ipf_dstl_stat_t;
|
||||
|
||||
extern ipf_lookup_t ipf_dstlist_backend;
|
||||
|
||||
extern int ipf_dstlist_select_node __P((fr_info_t *, void *, u_32_t *,
|
||||
frdest_t *));
|
||||
|
||||
#endif /* __IP_DSTLIST_H__ */
|
364
netinet/ipf_rb.h
Normal file
364
netinet/ipf_rb.h
Normal file
@ -0,0 +1,364 @@
|
||||
/*
|
||||
* Copyright (C) 2012 by Darren Reed.
|
||||
*
|
||||
* See the IPFILTER.LICENCE file for details on licencing.
|
||||
*
|
||||
*/
|
||||
typedef enum rbcolour_e {
|
||||
C_BLACK = 0,
|
||||
C_RED = 1
|
||||
} rbcolour_t;
|
||||
|
||||
#define RBI_LINK(_n, _t) \
|
||||
struct _n##_rb_link { \
|
||||
struct _t *left; \
|
||||
struct _t *right; \
|
||||
struct _t *parent; \
|
||||
rbcolour_t colour; \
|
||||
}
|
||||
|
||||
#define RBI_HEAD(_n, _t) \
|
||||
struct _n##_rb_head { \
|
||||
struct _t top; \
|
||||
int count; \
|
||||
int (* compare)(struct _t *, struct _t *); \
|
||||
}
|
||||
|
||||
#define RBI_CODE(_n, _t, _f, _cmp) \
|
||||
\
|
||||
typedef void (*_n##_rb_walker_t)(_t *, void *); \
|
||||
\
|
||||
_t * _n##_rb_delete(struct _n##_rb_head *, _t *); \
|
||||
void _n##_rb_init(struct _n##_rb_head *); \
|
||||
void _n##_rb_insert(struct _n##_rb_head *, _t *); \
|
||||
_t * _n##_rb_search(struct _n##_rb_head *, void *); \
|
||||
void _n##_rb_walktree(struct _n##_rb_head *, _n##_rb_walker_t, void *);\
|
||||
\
|
||||
static void \
|
||||
rotate_left(struct _n##_rb_head *head, _t *node) \
|
||||
{ \
|
||||
_t *parent, *tmp1, *tmp2; \
|
||||
\
|
||||
parent = node->_f.parent; \
|
||||
tmp1 = node->_f.right; \
|
||||
tmp2 = tmp1->_f.left; \
|
||||
node->_f.right = tmp2; \
|
||||
if (tmp2 != & _n##_rb_zero) \
|
||||
tmp2->_f.parent = node; \
|
||||
if (parent == & _n##_rb_zero) \
|
||||
head->top._f.right = tmp1; \
|
||||
else if (parent->_f.right == node) \
|
||||
parent->_f.right = tmp1; \
|
||||
else \
|
||||
parent->_f.left = tmp1; \
|
||||
tmp1->_f.left = node; \
|
||||
tmp1->_f.parent = parent; \
|
||||
node->_f.parent = tmp1; \
|
||||
} \
|
||||
\
|
||||
static void \
|
||||
rotate_right(struct _n##_rb_head *head, _t *node) \
|
||||
{ \
|
||||
_t *parent, *tmp1, *tmp2; \
|
||||
\
|
||||
parent = node->_f.parent; \
|
||||
tmp1 = node->_f.left; \
|
||||
tmp2 = tmp1->_f.right; \
|
||||
node->_f.left = tmp2; \
|
||||
if (tmp2 != &_n##_rb_zero) \
|
||||
tmp2->_f.parent = node; \
|
||||
if (parent == &_n##_rb_zero) \
|
||||
head->top._f.right = tmp1; \
|
||||
else if (parent->_f.right == node) \
|
||||
parent->_f.right = tmp1; \
|
||||
else \
|
||||
parent->_f.left = tmp1; \
|
||||
tmp1->_f.right = node; \
|
||||
tmp1->_f.parent = parent; \
|
||||
node->_f.parent = tmp1; \
|
||||
} \
|
||||
\
|
||||
void \
|
||||
_n##_rb_insert(struct _n##_rb_head *head, _t *node) \
|
||||
{ \
|
||||
_t *n, *parent, **p, *tmp1, *gparent; \
|
||||
\
|
||||
parent = &head->top; \
|
||||
node->_f.left = &_n##_rb_zero; \
|
||||
node->_f.right = &_n##_rb_zero; \
|
||||
p = &head->top._f.right; \
|
||||
while ((n = *p) != &_n##_rb_zero) { \
|
||||
if (_cmp(node, n) < 0) \
|
||||
p = &n->_f.left; \
|
||||
else \
|
||||
p = &n->_f.right; \
|
||||
parent = n; \
|
||||
} \
|
||||
*p = node; \
|
||||
node->_f.colour = C_RED; \
|
||||
node->_f.parent = parent; \
|
||||
\
|
||||
while ((node != &_n##_rb_zero) && (parent->_f.colour == C_RED)){\
|
||||
gparent = parent->_f.parent; \
|
||||
if (parent == gparent->_f.left) { \
|
||||
tmp1 = gparent->_f.right; \
|
||||
if (tmp1->_f.colour == C_RED) { \
|
||||
parent->_f.colour = C_BLACK; \
|
||||
tmp1->_f.colour = C_BLACK; \
|
||||
gparent->_f.colour = C_RED; \
|
||||
node = gparent; \
|
||||
} else { \
|
||||
if (node == parent->_f.right) { \
|
||||
node = parent; \
|
||||
rotate_left(head, node); \
|
||||
parent = node->_f.parent; \
|
||||
} \
|
||||
parent->_f.colour = C_BLACK; \
|
||||
gparent->_f.colour = C_RED; \
|
||||
rotate_right(head, gparent); \
|
||||
} \
|
||||
} else { \
|
||||
tmp1 = gparent->_f.left; \
|
||||
if (tmp1->_f.colour == C_RED) { \
|
||||
parent->_f.colour = C_BLACK; \
|
||||
tmp1->_f.colour = C_BLACK; \
|
||||
gparent->_f.colour = C_RED; \
|
||||
node = gparent; \
|
||||
} else { \
|
||||
if (node == parent->_f.left) { \
|
||||
node = parent; \
|
||||
rotate_right(head, node); \
|
||||
parent = node->_f.parent; \
|
||||
} \
|
||||
parent->_f.colour = C_BLACK; \
|
||||
gparent->_f.colour = C_RED; \
|
||||
rotate_left(head, parent->_f.parent); \
|
||||
} \
|
||||
} \
|
||||
parent = node->_f.parent; \
|
||||
} \
|
||||
head->top._f.right->_f.colour = C_BLACK; \
|
||||
head->count++; \
|
||||
} \
|
||||
\
|
||||
static void \
|
||||
deleteblack(struct _n##_rb_head *head, _t *parent, _t *node) \
|
||||
{ \
|
||||
_t *tmp; \
|
||||
\
|
||||
while ((node == &_n##_rb_zero || node->_f.colour == C_BLACK) && \
|
||||
node != &head->top) { \
|
||||
if (parent->_f.left == node) { \
|
||||
tmp = parent->_f.right; \
|
||||
if (tmp->_f.colour == C_RED) { \
|
||||
tmp->_f.colour = C_BLACK; \
|
||||
parent->_f.colour = C_RED; \
|
||||
rotate_left(head, parent); \
|
||||
tmp = parent->_f.right; \
|
||||
} \
|
||||
if ((tmp->_f.left == &_n##_rb_zero || \
|
||||
tmp->_f.left->_f.colour == C_BLACK) && \
|
||||
(tmp->_f.right == &_n##_rb_zero || \
|
||||
tmp->_f.right->_f.colour == C_BLACK)) { \
|
||||
tmp->_f.colour = C_RED; \
|
||||
node = parent; \
|
||||
parent = node->_f.parent; \
|
||||
} else { \
|
||||
if (tmp->_f.right == &_n##_rb_zero || \
|
||||
tmp->_f.right->_f.colour == C_BLACK) {\
|
||||
_t *tmp2 = tmp->_f.left; \
|
||||
\
|
||||
if (tmp2 != &_n##_rb_zero) \
|
||||
tmp2->_f.colour = C_BLACK;\
|
||||
tmp->_f.colour = C_RED; \
|
||||
rotate_right(head, tmp); \
|
||||
tmp = parent->_f.right; \
|
||||
} \
|
||||
tmp->_f.colour = parent->_f.colour; \
|
||||
parent->_f.colour = C_BLACK; \
|
||||
if (tmp->_f.right != &_n##_rb_zero) \
|
||||
tmp->_f.right->_f.colour = C_BLACK;\
|
||||
rotate_left(head, parent); \
|
||||
node = head->top._f.right; \
|
||||
} \
|
||||
} else { \
|
||||
tmp = parent->_f.left; \
|
||||
if (tmp->_f.colour == C_RED) { \
|
||||
tmp->_f.colour = C_BLACK; \
|
||||
parent->_f.colour = C_RED; \
|
||||
rotate_right(head, parent); \
|
||||
tmp = parent->_f.left; \
|
||||
} \
|
||||
if ((tmp->_f.left == &_n##_rb_zero || \
|
||||
tmp->_f.left->_f.colour == C_BLACK) && \
|
||||
(tmp->_f.right == &_n##_rb_zero || \
|
||||
tmp->_f.right->_f.colour == C_BLACK)) { \
|
||||
tmp->_f.colour = C_RED; \
|
||||
node = parent; \
|
||||
parent = node->_f.parent; \
|
||||
} else { \
|
||||
if (tmp->_f.left == &_n##_rb_zero || \
|
||||
tmp->_f.left->_f.colour == C_BLACK) {\
|
||||
_t *tmp2 = tmp->_f.right; \
|
||||
\
|
||||
if (tmp2 != &_n##_rb_zero) \
|
||||
tmp2->_f.colour = C_BLACK;\
|
||||
tmp->_f.colour = C_RED; \
|
||||
rotate_left(head, tmp); \
|
||||
tmp = parent->_f.left; \
|
||||
} \
|
||||
tmp->_f.colour = parent->_f.colour; \
|
||||
parent->_f.colour = C_BLACK; \
|
||||
if (tmp->_f.left != &_n##_rb_zero) \
|
||||
tmp->_f.left->_f.colour = C_BLACK;\
|
||||
rotate_right(head, parent); \
|
||||
node = head->top._f.right; \
|
||||
break; \
|
||||
} \
|
||||
} \
|
||||
} \
|
||||
if (node != &_n##_rb_zero) \
|
||||
node->_f.colour = C_BLACK; \
|
||||
} \
|
||||
\
|
||||
_t * \
|
||||
_n##_rb_delete(struct _n##_rb_head *head, _t *node) \
|
||||
{ \
|
||||
_t *child, *parent, *old = node, *left; \
|
||||
rbcolour_t color; \
|
||||
\
|
||||
if (node->_f.left == &_n##_rb_zero) { \
|
||||
child = node->_f.right; \
|
||||
} else if (node->_f.right == &_n##_rb_zero) { \
|
||||
child = node->_f.left; \
|
||||
} else { \
|
||||
node = node->_f.right; \
|
||||
while ((left = node->_f.left) != &_n##_rb_zero) \
|
||||
node = left; \
|
||||
child = node->_f.right; \
|
||||
parent = node->_f.parent; \
|
||||
color = node->_f.colour; \
|
||||
if (child != &_n##_rb_zero) \
|
||||
child->_f.parent = parent; \
|
||||
if (parent != &_n##_rb_zero) { \
|
||||
if (parent->_f.left == node) \
|
||||
parent->_f.left = child; \
|
||||
else \
|
||||
parent->_f.right = child; \
|
||||
} else { \
|
||||
head->top._f.right = child; \
|
||||
} \
|
||||
if (node->_f.parent == old) \
|
||||
parent = node; \
|
||||
*node = *old; \
|
||||
if (old->_f.parent != &_n##_rb_zero) { \
|
||||
if (old->_f.parent->_f.left == old) \
|
||||
old->_f.parent->_f.left = node; \
|
||||
else \
|
||||
old->_f.parent->_f.right = node; \
|
||||
} else { \
|
||||
head->top._f.right = child; \
|
||||
} \
|
||||
old->_f.left->_f.parent = node; \
|
||||
if (old->_f.right != &_n##_rb_zero) \
|
||||
old->_f.right->_f.parent = node; \
|
||||
if (parent != &_n##_rb_zero) { \
|
||||
left = parent; \
|
||||
} \
|
||||
goto colour; \
|
||||
} \
|
||||
parent = node->_f.parent; \
|
||||
color= node->_f.colour; \
|
||||
if (child != &_n##_rb_zero) \
|
||||
child->_f.parent = parent; \
|
||||
if (parent != &_n##_rb_zero) { \
|
||||
if (parent->_f.left == node) \
|
||||
parent->_f.left = child; \
|
||||
else \
|
||||
parent->_f.right = child; \
|
||||
} else { \
|
||||
head->top._f.right = child; \
|
||||
} \
|
||||
colour: \
|
||||
if (color == C_BLACK) \
|
||||
deleteblack(head, parent, node); \
|
||||
head->count--; \
|
||||
return old; \
|
||||
} \
|
||||
\
|
||||
void \
|
||||
_n##_rb_init(struct _n##_rb_head *head) \
|
||||
{ \
|
||||
memset(head, 0, sizeof(*head)); \
|
||||
memset(&_n##_rb_zero, 0, sizeof(_n##_rb_zero)); \
|
||||
head->top._f.left = &_n##_rb_zero; \
|
||||
head->top._f.right = &_n##_rb_zero; \
|
||||
head->top._f.parent = &head->top; \
|
||||
_n##_rb_zero._f.left = &_n##_rb_zero; \
|
||||
_n##_rb_zero._f.right = &_n##_rb_zero; \
|
||||
_n##_rb_zero._f.parent = &_n##_rb_zero; \
|
||||
} \
|
||||
\
|
||||
void \
|
||||
_n##_rb_walktree(struct _n##_rb_head *head, _n##_rb_walker_t func, void *arg)\
|
||||
{ \
|
||||
_t *prev; \
|
||||
_t *next; \
|
||||
_t *node = head->top._f.right; \
|
||||
_t *base; \
|
||||
\
|
||||
while (node != &_n##_rb_zero) \
|
||||
node = node->_f.left; \
|
||||
\
|
||||
for (;;) { \
|
||||
base = node; \
|
||||
prev = node; \
|
||||
while ((node->_f.parent->_f.right == node) && \
|
||||
(node != &_n##_rb_zero)) { \
|
||||
prev = node; \
|
||||
node = node->_f.parent; \
|
||||
} \
|
||||
\
|
||||
node = prev; \
|
||||
for (node = node->_f.parent->_f.right; node != &_n##_rb_zero;\
|
||||
node = node->_f.left) \
|
||||
prev = node; \
|
||||
next = prev; \
|
||||
\
|
||||
if (node != &_n##_rb_zero) \
|
||||
func(node, arg); \
|
||||
\
|
||||
node = next; \
|
||||
if (node == &_n##_rb_zero) \
|
||||
break; \
|
||||
} \
|
||||
} \
|
||||
\
|
||||
_t * \
|
||||
_n##_rb_search(struct _n##_rb_head *head, void *key) \
|
||||
{ \
|
||||
int match; \
|
||||
_t *node; \
|
||||
node = head->top._f.right; \
|
||||
while (node != &_n##_rb_zero) { \
|
||||
match = _cmp(key, node); \
|
||||
if (match == 0) \
|
||||
break; \
|
||||
if (match< 0) \
|
||||
node = node->_f.left; \
|
||||
else \
|
||||
node = node->_f.right; \
|
||||
} \
|
||||
if (node == &_n##_rb_zero || match != 0) \
|
||||
return (NULL); \
|
||||
return (node); \
|
||||
}
|
||||
|
||||
#define RBI_DELETE(_n, _h, _v) _n##_rb_delete(_h, _v)
|
||||
#define RBI_FIELD(_n) struct _n##_rb_link
|
||||
#define RBI_INIT(_n, _h) _n##_rb_init(_h)
|
||||
#define RBI_INSERT(_n, _h, _v) _n##_rb_insert(_h, _v)
|
||||
#define RBI_ISEMPTY(_h) ((_h)->count == 0)
|
||||
#define RBI_SEARCH(_n, _h, _k) _n##_rb_search(_h, _k)
|
||||
#define RBI_WALK(_n, _h, _w, _a) _n##_rb_walktree(_h, _w, _a)
|
||||
#define RBI_ZERO(_n) _n##_rb_zero
|
1528
netinet/radix_ipf.c
Normal file
1528
netinet/radix_ipf.c
Normal file
File diff suppressed because it is too large
Load Diff
95
netinet/radix_ipf.h
Normal file
95
netinet/radix_ipf.h
Normal file
@ -0,0 +1,95 @@
|
||||
/*
|
||||
* Copyright (C) 2012 by Darren Reed.
|
||||
*
|
||||
* See the IPFILTER.LICENCE file for details on licencing.
|
||||
*/
|
||||
#ifndef __RADIX_IPF_H__
|
||||
#define __RADIX_IPF_H__
|
||||
|
||||
#ifndef U_32_T
|
||||
typedef unsigned int u_32_t;
|
||||
# define U_32_T 1
|
||||
#endif
|
||||
|
||||
typedef struct ipf_rdx_mask {
|
||||
struct ipf_rdx_mask *next;
|
||||
struct ipf_rdx_node *node;
|
||||
u_32_t *mask;
|
||||
int maskbitcount;
|
||||
} ipf_rdx_mask_t;
|
||||
|
||||
typedef struct ipf_rdx_node {
|
||||
struct ipf_rdx_node *left;
|
||||
struct ipf_rdx_node *right;
|
||||
struct ipf_rdx_node *parent;
|
||||
struct ipf_rdx_node *dupkey;
|
||||
struct ipf_rdx_mask *masks;
|
||||
struct ipf_rdx_mask *mymask;
|
||||
u_32_t *addrkey;
|
||||
u_32_t *maskkey;
|
||||
u_32_t *addroff;
|
||||
u_32_t *maskoff;
|
||||
u_32_t lastmask;
|
||||
u_32_t bitmask;
|
||||
int offset;
|
||||
int index;
|
||||
int maskbitcount;
|
||||
int root;
|
||||
#ifdef RDX_DEBUG
|
||||
char name[40];
|
||||
#endif
|
||||
} ipf_rdx_node_t;
|
||||
|
||||
struct ipf_rdx_head;
|
||||
|
||||
typedef void (* radix_walk_func_t)(ipf_rdx_node_t *, void *);
|
||||
typedef ipf_rdx_node_t *(* idx_hamn_func_t)(struct ipf_rdx_head *,
|
||||
addrfamily_t *, addrfamily_t *,
|
||||
ipf_rdx_node_t *);
|
||||
typedef ipf_rdx_node_t *(* idx_ham_func_t)(struct ipf_rdx_head *,
|
||||
addrfamily_t *, addrfamily_t *);
|
||||
typedef ipf_rdx_node_t *(* idx_ha_func_t)(struct ipf_rdx_head *,
|
||||
addrfamily_t *);
|
||||
typedef void (* idx_walk_func_t)(struct ipf_rdx_head *,
|
||||
radix_walk_func_t, void *);
|
||||
|
||||
typedef struct ipf_rdx_head {
|
||||
ipf_rdx_node_t *root;
|
||||
ipf_rdx_node_t nodes[3];
|
||||
ipfmutex_t lock;
|
||||
idx_hamn_func_t addaddr; /* add addr/mask to tree */
|
||||
idx_ham_func_t deladdr; /* delete addr/mask from tree */
|
||||
idx_ham_func_t lookup; /* look for specific addr/mask */
|
||||
idx_ha_func_t matchaddr; /* search tree for address match */
|
||||
idx_walk_func_t walktree; /* walk entire tree */
|
||||
} ipf_rdx_head_t;
|
||||
|
||||
typedef struct radix_softc {
|
||||
u_char *zeros;
|
||||
u_char *ones;
|
||||
} radix_softc_t;
|
||||
|
||||
#undef RADIX_NODE_HEAD_LOCK
|
||||
#undef RADIX_NODE_HEAD_UNLOCK
|
||||
#ifdef _KERNEL
|
||||
# define RADIX_NODE_HEAD_LOCK(x) MUTEX_ENTER(&(x)->lock)
|
||||
# define RADIX_NODE_HEAD_UNLOCK(x) MUTEX_UNLOCK(&(x)->lock)
|
||||
#else
|
||||
# define RADIX_NODE_HEAD_LOCK(x)
|
||||
# define RADIX_NODE_HEAD_UNLOCK(x)
|
||||
#endif
|
||||
|
||||
extern void *ipf_rx_create __P((void));
|
||||
extern int ipf_rx_init __P((void *));
|
||||
extern void ipf_rx_destroy __P((void *));
|
||||
extern int ipf_rx_inithead __P((radix_softc_t *, ipf_rdx_head_t **));
|
||||
extern void ipf_rx_freehead __P((ipf_rdx_head_t *));
|
||||
extern ipf_rdx_node_t *ipf_rx_addroute __P((ipf_rdx_head_t *,
|
||||
addrfamily_t *, addrfamily_t *,
|
||||
ipf_rdx_node_t *));
|
||||
extern ipf_rdx_node_t *ipf_rx_delete __P((ipf_rdx_head_t *, addrfamily_t *,
|
||||
addrfamily_t *));
|
||||
extern void ipf_rx_walktree __P((ipf_rdx_head_t *, radix_walk_func_t,
|
||||
void *));
|
||||
|
||||
#endif /* __RADIX_IPF_H__ */
|
Loading…
Reference in New Issue
Block a user