|
|
|
@ -2453,10 +2453,11 @@ void oc_diff_percent(OPTIONCONTROL *oc, __maybe_unused const char *from)
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
/* An event limit setting looks like:
|
|
|
|
|
* OC_LIMITS + events_limits.name + '_' + Item |
|
|
|
|
* OC_LIMITS + event_limits.name + '_' + Item |
|
|
|
|
* Item is one of the field names in event_limits |
|
|
|
|
* e.g. user_low_time, user_low_time_limit etc |
|
|
|
|
* as below in the if tests */ |
|
|
|
|
* as below in the if tests |
|
|
|
|
* lifetime values can't = -EVENT_OK */ |
|
|
|
|
void oc_event_limits(OPTIONCONTROL *oc, const char *from) |
|
|
|
|
{ |
|
|
|
|
bool processed = false; |
|
|
|
@ -2490,7 +2491,14 @@ void oc_event_limits(OPTIONCONTROL *oc, const char *from)
|
|
|
|
|
} else if (strcmp(ptr2, "ip_hi_time_limit") == 0) { |
|
|
|
|
e_limits[i].ip_hi_time_limit = val; |
|
|
|
|
} else if (strcmp(ptr2, "lifetime") == 0) { |
|
|
|
|
if (val != -(EVENT_OK)) |
|
|
|
|
e_limits[i].lifetime = val; |
|
|
|
|
else { |
|
|
|
|
LOGERR("%s(%s): ERR: lifetime can't be" |
|
|
|
|
" %d in '%s'", |
|
|
|
|
from, __func__, -(EVENT_OK), |
|
|
|
|
oc->optionname); |
|
|
|
|
} |
|
|
|
|
} else { |
|
|
|
|
LOGERR("%s(%s): ERR: Unknown %s item '%s' " |
|
|
|
|
"in '%s'", |
|
|
|
@ -2503,7 +2511,14 @@ void oc_event_limits(OPTIONCONTROL *oc, const char *from)
|
|
|
|
|
} |
|
|
|
|
if (!processed) { |
|
|
|
|
if (strcmp(ptr, "hash_lifetime") == 0) { |
|
|
|
|
if (val != -(EVENT_OK)) |
|
|
|
|
event_limits_hash_lifetime = val; |
|
|
|
|
else { |
|
|
|
|
LOGERR("%s(%s): ERR: lifetime can't be" |
|
|
|
|
" %d in '%s'", |
|
|
|
|
from, __func__, -(EVENT_OK), |
|
|
|
|
oc->optionname); |
|
|
|
|
} |
|
|
|
|
processed = true; |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
@ -2514,6 +2529,85 @@ void oc_event_limits(OPTIONCONTROL *oc, const char *from)
|
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
/* An ovent limit setting looks like:
|
|
|
|
|
* OC_OLIMITS + event_limits.name + '_' + Item |
|
|
|
|
* Item is one of the field names in event_limits |
|
|
|
|
* e.g. user_low_time, user_low_time_limit etc |
|
|
|
|
* as below in the if tests |
|
|
|
|
* lifetime values can't = OVENT_OK */ |
|
|
|
|
void oc_ovent_limits(OPTIONCONTROL *oc, const char *from) |
|
|
|
|
{ |
|
|
|
|
bool processed = false, lifetime_changed = false; |
|
|
|
|
size_t len; |
|
|
|
|
char *ptr, *ptr2; |
|
|
|
|
int val, i; |
|
|
|
|
|
|
|
|
|
K_WLOCK(event_limits_free); |
|
|
|
|
val = atoi(oc->optionvalue); |
|
|
|
|
ptr = oc->optionname + strlen(OC_OLIMITS); |
|
|
|
|
i = -1; |
|
|
|
|
while (o_limits[++i].name) { |
|
|
|
|
len = strlen(o_limits[i].name); |
|
|
|
|
if (strncmp(ptr, o_limits[i].name, len) == 0 && |
|
|
|
|
ptr[len] == '_') { |
|
|
|
|
ptr2 = ptr + len + 1; |
|
|
|
|
if (strcmp(ptr2, "user_low_time") == 0) { |
|
|
|
|
o_limits[i].user_low_time = val; |
|
|
|
|
} else if (strcmp(ptr2, "user_low_time_limit") == 0) { |
|
|
|
|
o_limits[i].user_low_time_limit = val; |
|
|
|
|
} else if (strcmp(ptr2, "user_hi_time") == 0) { |
|
|
|
|
o_limits[i].user_hi_time = val; |
|
|
|
|
} else if (strcmp(ptr2, "user_hi_time_limit") == 0) { |
|
|
|
|
o_limits[i].user_hi_time_limit = val; |
|
|
|
|
} else if (strcmp(ptr2, "ip_low_time") == 0) { |
|
|
|
|
o_limits[i].ip_low_time = val; |
|
|
|
|
} else if (strcmp(ptr2, "ip_low_time_limit") == 0) { |
|
|
|
|
o_limits[i].ip_low_time_limit = val; |
|
|
|
|
} else if (strcmp(ptr2, "ip_hi_time") == 0) { |
|
|
|
|
o_limits[i].ip_hi_time = val; |
|
|
|
|
} else if (strcmp(ptr2, "ip_hi_time_limit") == 0) { |
|
|
|
|
o_limits[i].ip_hi_time_limit = val; |
|
|
|
|
} else if (strcmp(ptr2, "lifetime") == 0) { |
|
|
|
|
if (val != OVENT_OK) { |
|
|
|
|
o_limits[i].lifetime = val; |
|
|
|
|
lifetime_changed = true; |
|
|
|
|
} else { |
|
|
|
|
LOGERR("%s(%s): ERR: lifetime can't be" |
|
|
|
|
" %d in '%s'", |
|
|
|
|
from, __func__, OVENT_OK, |
|
|
|
|
oc->optionname); |
|
|
|
|
} |
|
|
|
|
} else { |
|
|
|
|
LOGERR("%s(%s): ERR: Unknown %s item '%s' " |
|
|
|
|
"in '%s'", |
|
|
|
|
from, __func__, OC_OLIMITS, ptr2, |
|
|
|
|
oc->optionname); |
|
|
|
|
} |
|
|
|
|
processed = true; |
|
|
|
|
break; |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
if (!processed) { |
|
|
|
|
if (strcmp(ptr, "ipc_factor") == 0) { |
|
|
|
|
ovent_limits_ipc_factor = atof(oc->optionvalue); |
|
|
|
|
processed = true; |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
if (lifetime_changed) { |
|
|
|
|
o_limits_max_lifetime = -1; |
|
|
|
|
i = -1; |
|
|
|
|
while (o_limits[++i].name) { |
|
|
|
|
if (o_limits_max_lifetime < o_limits[i].lifetime) |
|
|
|
|
o_limits_max_lifetime = o_limits[i].lifetime; |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
K_WUNLOCK(event_limits_free); |
|
|
|
|
if (!processed) { |
|
|
|
|
LOGERR("%s(%s): ERR: Unknown %s name '%s'", |
|
|
|
|
from, __func__, OC_OLIMITS, oc->optionname); |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
/* IPS for IPS_GROUP_OK/BAN look like:
|
|
|
|
|
* optionname: (OC_IPS_OK or OC_IPS_BAN) + description |
|
|
|
|
* optionvalue: is the IP address |
|
|
|
@ -2538,6 +2632,7 @@ OC_TRIGGER oc_trigger[] = {
|
|
|
|
|
{ SWITCH_STATE_NAME, true, oc_switch_state }, |
|
|
|
|
{ DIFF_PERCENT_NAME, true, oc_diff_percent }, |
|
|
|
|
{ OC_LIMITS, false, oc_event_limits }, |
|
|
|
|
{ OC_OLIMITS, false, oc_ovent_limits }, |
|
|
|
|
{ OC_IPS, false, oc_ips }, |
|
|
|
|
{ NULL, 0, NULL } |
|
|
|
|
}; |
|
|
|
@ -2769,8 +2864,10 @@ bool optioncontrol_fill(PGconn *conn)
|
|
|
|
|
PGresult *res; |
|
|
|
|
K_ITEM *item; |
|
|
|
|
OPTIONCONTROL *row; |
|
|
|
|
K_TREE_CTX ctx[1]; |
|
|
|
|
IPS *ips; |
|
|
|
|
char *params[1]; |
|
|
|
|
int n, i, par = 0; |
|
|
|
|
int n, i, par = 0, ban_count, ok_count; |
|
|
|
|
char *field; |
|
|
|
|
char *sel; |
|
|
|
|
int fields = 4; |
|
|
|
@ -2859,6 +2956,25 @@ bool optioncontrol_fill(PGconn *conn)
|
|
|
|
|
LOGWARNING("%s(): loaded %d optioncontrol records", __func__, n); |
|
|
|
|
LOGWARNING("%s() switch_state initially %d", |
|
|
|
|
__func__, switch_state); |
|
|
|
|
|
|
|
|
|
ok_count = ban_count = 0; |
|
|
|
|
K_RLOCK(ips_free); |
|
|
|
|
item = first_in_ktree(ips_root, ctx); |
|
|
|
|
while (item) { |
|
|
|
|
DATA_IPS(ips, item); |
|
|
|
|
if (CURRENT(&(ips->expirydate))) { |
|
|
|
|
if (strcmp(ips->group, IPS_GROUP_OK) == 0) |
|
|
|
|
ok_count++; |
|
|
|
|
else if (strcmp(ips->group, IPS_GROUP_BAN) == 0) |
|
|
|
|
ban_count++; |
|
|
|
|
} |
|
|
|
|
item = next_in_ktree(ctx); |
|
|
|
|
} |
|
|
|
|
K_RUNLOCK(ips_free); |
|
|
|
|
|
|
|
|
|
LOGWARNING("%s() IPS: %s:%d %s:%d", |
|
|
|
|
__func__, IPS_GROUP_OK, ok_count, |
|
|
|
|
IPS_GROUP_BAN, ban_count); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
return ok; |
|
|
|
@ -6274,63 +6390,6 @@ bool payouts_fill(PGconn *conn)
|
|
|
|
|
return ok; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
void ips_add(char *group, char *ip, char *des, bool log, bool cclass, int life, |
|
|
|
|
bool locked) |
|
|
|
|
{ |
|
|
|
|
K_ITEM *i_item, *i2_item; |
|
|
|
|
IPS *ips, *ips2; |
|
|
|
|
char *dot; |
|
|
|
|
tv_t now; |
|
|
|
|
bool ok; |
|
|
|
|
|
|
|
|
|
setnow(&now); |
|
|
|
|
if (!locked) |
|
|
|
|
K_WLOCK(ips_free); |
|
|
|
|
i_item = k_unlink_head(ips_free); |
|
|
|
|
DATA_IPS(ips, i_item); |
|
|
|
|
STRNCPY(ips->group, group); |
|
|
|
|
STRNCPY(ips->ip, ip); |
|
|
|
|
ips->lifetime = life; |
|
|
|
|
if (des) { |
|
|
|
|
ips->description = strdup(des); |
|
|
|
|
if (!ips->description) |
|
|
|
|
quithere(1, "strdup OOM"); |
|
|
|
|
LIST_MEM_ADD(ips_free, ips->description); |
|
|
|
|
} |
|
|
|
|
ips->log = log; |
|
|
|
|
HISTORYDATEDEFAULT(ips, &now); |
|
|
|
|
add_to_ktree(ips_root, i_item); |
|
|
|
|
k_add_head(ips_store, i_item); |
|
|
|
|
if (cclass) { |
|
|
|
|
i2_item = k_unlink_head(ips_free); |
|
|
|
|
DATA_IPS(ips2, i2_item); |
|
|
|
|
memcpy(ips2, ips, sizeof(*ips2)); |
|
|
|
|
ok = false; |
|
|
|
|
dot = strchr(ips->ip, '.'); |
|
|
|
|
if (dot) { |
|
|
|
|
dot = strchr(dot+1, '.'); |
|
|
|
|
if (dot) { |
|
|
|
|
dot = strchr(dot+1, '.'); |
|
|
|
|
if (dot) { |
|
|
|
|
*dot = '\0'; |
|
|
|
|
ok = true; |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
if (ok) { |
|
|
|
|
if (des) { |
|
|
|
|
ips2->description = strdup(des); |
|
|
|
|
LIST_MEM_ADD(ips_free, ips2->description); |
|
|
|
|
} |
|
|
|
|
add_to_ktree(ips_root, i2_item); |
|
|
|
|
k_add_head(ips_store, i2_item); |
|
|
|
|
} else |
|
|
|
|
k_add_head(ips_free, i2_item); |
|
|
|
|
} |
|
|
|
|
if (!locked) |
|
|
|
|
K_WUNLOCK(ips_free); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
// trf_root overrides by,inet,cd fields
|
|
|
|
|
int _events_add(int id, char *by, char *inet, tv_t *cd, K_TREE *trf_root) |
|
|
|
|
{ |
|
|
|
@ -6392,7 +6451,7 @@ int _events_add(int id, char *by, char *inet, tv_t *cd, K_TREE *trf_root)
|
|
|
|
|
if (dot) { |
|
|
|
|
dot = strchr(dot+1, '.'); |
|
|
|
|
if (dot) |
|
|
|
|
*dot = '\0'; |
|
|
|
|
*(dot+1) = '\0'; |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
@ -6444,6 +6503,202 @@ int _events_add(int id, char *by, char *inet, tv_t *cd, K_TREE *trf_root)
|
|
|
|
|
return check_events(&events); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
// trf_root overrides by,inet,cd fields
|
|
|
|
|
int _ovents_add(int id, char *by, char *inet, tv_t *cd, K_TREE *trf_root) |
|
|
|
|
{ |
|
|
|
|
K_ITEM *o_item, *i_webtime, *i_username; |
|
|
|
|
OVENTS ovents, *d_ovents; |
|
|
|
|
char reply[1024] = ""; |
|
|
|
|
size_t siz = sizeof(reply); |
|
|
|
|
char u_key[TXT_SML+1], i_key[TXT_SML+1], c_key[TXT_SML+1]; |
|
|
|
|
int hour, min; |
|
|
|
|
bool gotc; |
|
|
|
|
|
|
|
|
|
LOGDEBUG("%s(): add", __func__); |
|
|
|
|
|
|
|
|
|
bzero(&ovents, sizeof(ovents)); |
|
|
|
|
|
|
|
|
|
// Default to now if not specified
|
|
|
|
|
setnow(&(ovents.createdate)); |
|
|
|
|
|
|
|
|
|
if (by) |
|
|
|
|
STRNCPY(ovents.createby, by); |
|
|
|
|
|
|
|
|
|
if (inet) |
|
|
|
|
STRNCPY(ovents.createinet, inet); |
|
|
|
|
|
|
|
|
|
if (cd) |
|
|
|
|
copy_tv(&(ovents.createdate), cd); |
|
|
|
|
|
|
|
|
|
// trf_root values overrides parameters
|
|
|
|
|
HISTORYDATETRANSFER(trf_root, &ovents); |
|
|
|
|
|
|
|
|
|
// username overrides createby
|
|
|
|
|
i_username = optional_name(trf_root, "username", 1, NULL, |
|
|
|
|
reply, siz); |
|
|
|
|
if (i_username) |
|
|
|
|
STRNCPY(ovents.createby, transfer_data(i_username)); |
|
|
|
|
|
|
|
|
|
// webtime overrides
|
|
|
|
|
i_webtime = optional_name(trf_root, "webtime", 1, NULL, |
|
|
|
|
reply, siz); |
|
|
|
|
if (i_webtime) { |
|
|
|
|
TXT_TO_CTV("webtime", transfer_data(i_webtime), |
|
|
|
|
ovents.createdate); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
STRNCPY(u_key, ovents.createby); |
|
|
|
|
STRNCPY(i_key, ovents.createinet); |
|
|
|
|
gotc = false; |
|
|
|
|
if (i_key[0]) { |
|
|
|
|
char *dot; |
|
|
|
|
STRNCPY(c_key, i_key); |
|
|
|
|
dot = strchr(c_key, '.'); |
|
|
|
|
if (dot) { |
|
|
|
|
dot = strchr(dot+1, '.'); |
|
|
|
|
if (dot) { |
|
|
|
|
dot = strchr(dot+1, '.'); |
|
|
|
|
if (dot) { |
|
|
|
|
*(dot+1) = '\0'; |
|
|
|
|
gotc = true; |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
if (!gotc) |
|
|
|
|
c_key[0] = '\0'; |
|
|
|
|
|
|
|
|
|
if (!u_key[0] && !i_key[0] && !c_key[0]) |
|
|
|
|
return OVENT_OK; |
|
|
|
|
|
|
|
|
|
hour = TV_TO_HOUR(&(ovents.createdate)); |
|
|
|
|
min = TV_TO_MIN(&(ovents.createdate)); |
|
|
|
|
|
|
|
|
|
K_WLOCK(ovents_free); |
|
|
|
|
if (u_key[0]) { |
|
|
|
|
o_item = find_ovents(u_key, hour, NULL); |
|
|
|
|
if (o_item) { |
|
|
|
|
DATA_OVENTS(d_ovents, o_item); |
|
|
|
|
d_ovents->count[IDMIN(id, min)]++; |
|
|
|
|
} else { |
|
|
|
|
o_item = k_unlink_head(ovents_free); |
|
|
|
|
DATA_OVENTS(d_ovents, o_item); |
|
|
|
|
bzero(d_ovents, sizeof(*d_ovents)); |
|
|
|
|
STRNCPY(d_ovents->key, u_key); |
|
|
|
|
d_ovents->hour = hour; |
|
|
|
|
d_ovents->count[IDMIN(id, min)]++; |
|
|
|
|
copy_tv(&(d_ovents->createdate), &(ovents.createdate)); |
|
|
|
|
STRNCPY(d_ovents->createby, ovents.createby); |
|
|
|
|
STRNCPY(d_ovents->createinet, ovents.createinet); |
|
|
|
|
copy_tv(&(d_ovents->expirydate), &default_expiry); |
|
|
|
|
k_add_head(ovents_store, o_item); |
|
|
|
|
add_to_ktree(ovents_root, o_item); |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
if (i_key[0]) { |
|
|
|
|
o_item = find_ovents(i_key, hour, NULL); |
|
|
|
|
if (o_item) { |
|
|
|
|
DATA_OVENTS(d_ovents, o_item); |
|
|
|
|
d_ovents->count[IDMIN(id, min)]++; |
|
|
|
|
} else { |
|
|
|
|
o_item = k_unlink_head(ovents_free); |
|
|
|
|
DATA_OVENTS(d_ovents, o_item); |
|
|
|
|
bzero(d_ovents, sizeof(*d_ovents)); |
|
|
|
|
STRNCPY(d_ovents->key, i_key); |
|
|
|
|
d_ovents->hour = hour; |
|
|
|
|
d_ovents->count[IDMIN(id, min)]++; |
|
|
|
|
copy_tv(&(d_ovents->createdate), &(ovents.createdate)); |
|
|
|
|
STRNCPY(d_ovents->createby, ovents.createby); |
|
|
|
|
STRNCPY(d_ovents->createinet, ovents.createinet); |
|
|
|
|
copy_tv(&(d_ovents->expirydate), &default_expiry); |
|
|
|
|
k_add_head(ovents_store, o_item); |
|
|
|
|
add_to_ktree(ovents_root, o_item); |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
if (c_key[0]) { |
|
|
|
|
o_item = find_ovents(c_key, hour, NULL); |
|
|
|
|
if (o_item) { |
|
|
|
|
DATA_OVENTS(d_ovents, o_item); |
|
|
|
|
d_ovents->count[IDMIN(id, min)]++; |
|
|
|
|
} else { |
|
|
|
|
o_item = k_unlink_head(ovents_free); |
|
|
|
|
DATA_OVENTS(d_ovents, o_item); |
|
|
|
|
bzero(d_ovents, sizeof(*d_ovents)); |
|
|
|
|
STRNCPY(d_ovents->key, c_key); |
|
|
|
|
d_ovents->hour = hour; |
|
|
|
|
d_ovents->count[IDMIN(id, min)]++; |
|
|
|
|
copy_tv(&(d_ovents->createdate), &(ovents.createdate)); |
|
|
|
|
STRNCPY(d_ovents->createby, ovents.createby); |
|
|
|
|
STRNCPY(d_ovents->createinet, ovents.createinet); |
|
|
|
|
copy_tv(&(d_ovents->expirydate), &default_expiry); |
|
|
|
|
k_add_head(ovents_store, o_item); |
|
|
|
|
add_to_ktree(ovents_root, o_item); |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
K_WUNLOCK(ovents_free); |
|
|
|
|
|
|
|
|
|
return check_ovents(id, u_key, i_key, c_key, &(ovents.createdate)); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
void ips_add(char *group, char *ip, char *des, bool log, bool cclass, int life, |
|
|
|
|
bool locked) |
|
|
|
|
{ |
|
|
|
|
K_ITEM *i_item, *i2_item; |
|
|
|
|
IPS *ips, *ips2; |
|
|
|
|
char *dot; |
|
|
|
|
tv_t now; |
|
|
|
|
bool ok; |
|
|
|
|
|
|
|
|
|
setnow(&now); |
|
|
|
|
if (!locked) |
|
|
|
|
K_WLOCK(ips_free); |
|
|
|
|
i_item = k_unlink_head(ips_free); |
|
|
|
|
DATA_IPS(ips, i_item); |
|
|
|
|
STRNCPY(ips->group, group); |
|
|
|
|
STRNCPY(ips->ip, ip); |
|
|
|
|
ips->lifetime = life; |
|
|
|
|
if (des) { |
|
|
|
|
ips->description = strdup(des); |
|
|
|
|
if (!ips->description) |
|
|
|
|
quithere(1, "strdup OOM"); |
|
|
|
|
LIST_MEM_ADD(ips_free, ips->description); |
|
|
|
|
} |
|
|
|
|
ips->log = log; |
|
|
|
|
HISTORYDATEDEFAULT(ips, &now); |
|
|
|
|
add_to_ktree(ips_root, i_item); |
|
|
|
|
k_add_head(ips_store, i_item); |
|
|
|
|
if (cclass) { |
|
|
|
|
i2_item = k_unlink_head(ips_free); |
|
|
|
|
DATA_IPS(ips2, i2_item); |
|
|
|
|
memcpy(ips2, ips, sizeof(*ips2)); |
|
|
|
|
ok = false; |
|
|
|
|
dot = strchr(ips->ip, '.'); |
|
|
|
|
if (dot) { |
|
|
|
|
dot = strchr(dot+1, '.'); |
|
|
|
|
if (dot) { |
|
|
|
|
dot = strchr(dot+1, '.'); |
|
|
|
|
if (dot) { |
|
|
|
|
*(dot+1) = '\0'; |
|
|
|
|
ok = true; |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
if (ok) { |
|
|
|
|
if (des) { |
|
|
|
|
ips2->description = strdup(des); |
|
|
|
|
LIST_MEM_ADD(ips_free, ips2->description); |
|
|
|
|
} |
|
|
|
|
add_to_ktree(ips_root, i2_item); |
|
|
|
|
k_add_head(ips_store, i2_item); |
|
|
|
|
} else |
|
|
|
|
k_add_head(ips_free, i2_item); |
|
|
|
|
} |
|
|
|
|
if (!locked) |
|
|
|
|
K_WUNLOCK(ips_free); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
// TODO: discard them from RAM
|
|
|
|
|
bool auths_add(PGconn *conn, char *poolinstance, char *username, |
|
|
|
|
char *workername, char *clientid, char *enonce1, |
|
|
|
|