mirror of
https://github.com/3proxy/3proxy.git
synced 2026-10-28 22:05:48 +08:00
Logs: an ODBC log named by its data source, user and password its parameters
The string up to the first comma names an ODBC log; the user and the password are kept apart as its parameters, never shown, and do not tell logs apart. Another log or -l naming the same data source with other parameters gives them to the logger, which reconnects with them. The password is whatever follows the comma after the user. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
parent
e87ffcd7e1
commit
477a2d3822
@ -326,7 +326,11 @@ sets logfile for all gateways <br>
|
||||
@ (for Unix) use syslog, filename is used as ident name <br>
|
||||
& use ODBC, filename consists of comma-delimited
|
||||
datasource,username,password (username and password are
|
||||
optional) <br>
|
||||
optional; the password is everything after the second comma).
|
||||
The datasource alone names the log: the username and password
|
||||
are its parameters, never shown in messages, and a later log
|
||||
or -l with the same datasource and other parameters reconnects
|
||||
the log with them <br>
|
||||
radius - use RADIUS for logging <br>
|
||||
LOGTYPE is one of: <b><br>
|
||||
c</b> Minutely <b><br>
|
||||
|
||||
@ -325,7 +325,10 @@ proxy on a client with FTP proxy support. Username format is one of
|
||||
.br
|
||||
@ (for Unix) use syslog, filename is used as ident name
|
||||
.br
|
||||
& use ODBC, filename consists of comma-delimited datasource,username,password (username and password are optional)
|
||||
& use ODBC, filename consists of comma-delimited datasource,username,password (username and password are optional;
|
||||
the password is everything after the second comma). The datasource alone names the log: the username and password
|
||||
are its parameters, never shown in messages, and a later log or -l with the same datasource and other parameters
|
||||
reconnects the log with them
|
||||
.br
|
||||
radius - use RADIUS for logging
|
||||
.br
|
||||
|
||||
63
src/log.c
63
src/log.c
@ -675,27 +675,67 @@ void loginit(void){
|
||||
#endif
|
||||
}
|
||||
|
||||
/* The length of the name in a log string: for a type with parameters up to
|
||||
the comma they follow. */
|
||||
static size_t lognamelen(const struct logtype *type, const unsigned char *selector){
|
||||
return type->params? strcspn((char *)selector, ",") : strlen((char *)selector);
|
||||
}
|
||||
|
||||
/* Parameters which differ from those a logger has: given to it, and the
|
||||
logger opened again with them. Called holding a reference. */
|
||||
static void logsetparams(struct logger *lg, const unsigned char *params){
|
||||
unsigned char *p = NULL;
|
||||
|
||||
if(params && !(p = (unsigned char *)strdup((char *)params))) return;
|
||||
_3proxy_mutex_lock(&lg->mutex);
|
||||
if(lg->params) free(lg->params);
|
||||
lg->params = p;
|
||||
if(lg->type->close) lg->type->close(lg);
|
||||
lg->errors = 0;
|
||||
lg->failed = 0;
|
||||
if(lg->type->init && lg->type->init(lg)){
|
||||
lg->failed = 1;
|
||||
lg->failtime = time(NULL);
|
||||
}
|
||||
_3proxy_mutex_unlock(&lg->mutex);
|
||||
}
|
||||
|
||||
/* The logger named so, opened if none is: held until logput(). NULL, with
|
||||
errno set, if it cannot be opened. */
|
||||
errno set, if it cannot be opened. A logger found with other parameters
|
||||
takes the new ones. */
|
||||
struct logger *logget(const unsigned char *selector, ROTATION rotation){
|
||||
struct logger *lg;
|
||||
int err = 0;
|
||||
const struct logtype *type;
|
||||
const unsigned char *params;
|
||||
size_t len;
|
||||
int err = 0, changed;
|
||||
|
||||
_3proxy_mutex_lock(&log_mutex);
|
||||
type = logmatch(selector);
|
||||
len = lognamelen(type, selector);
|
||||
params = selector[len]? selector + len + 1 : NULL;
|
||||
for(lg = loggers; lg; lg = lg->next){
|
||||
if(!strcmp((char *)lg->selector, (char *)selector)){
|
||||
if(lg->type == type && !strncmp((char *)lg->selector, (char *)selector, len) && !lg->selector[len]){
|
||||
lg->refs++;
|
||||
changed = (params && lg->params)? strcmp((char *)params, (char *)lg->params) : (params != NULL || lg->params != NULL);
|
||||
_3proxy_mutex_unlock(&log_mutex);
|
||||
if(changed) logsetparams(lg, params);
|
||||
return lg;
|
||||
}
|
||||
}
|
||||
if(!(lg = calloc(1, sizeof(*lg))) || !(lg->selector = (unsigned char *)strdup((char *)selector))){
|
||||
if(lg) free(lg);
|
||||
if(!(lg = calloc(1, sizeof(*lg))) || !(lg->selector = malloc(len + 1)) ||
|
||||
(params && !(lg->params = (unsigned char *)strdup((char *)params)))){
|
||||
if(lg){
|
||||
if(lg->selector) free(lg->selector);
|
||||
free(lg);
|
||||
}
|
||||
_3proxy_mutex_unlock(&log_mutex);
|
||||
errno = ENOMEM;
|
||||
return NULL;
|
||||
}
|
||||
lg->type = logmatch(selector);
|
||||
memcpy(lg->selector, selector, len);
|
||||
lg->selector[len] = 0;
|
||||
lg->type = type;
|
||||
lg->rotation = rotation;
|
||||
lg->rotated = time(NULL);
|
||||
_3proxy_mutex_init(&lg->mutex);
|
||||
@ -708,6 +748,7 @@ struct logger *logget(const unsigned char *selector, ROTATION rotation){
|
||||
err = errno;
|
||||
_3proxy_mutex_unlock(&log_mutex);
|
||||
_3proxy_mutex_destroy(&lg->mutex);
|
||||
if(lg->params) free(lg->params);
|
||||
free(lg->selector);
|
||||
free(lg);
|
||||
errno = err;
|
||||
@ -758,6 +799,7 @@ void logput(struct logger *lg){
|
||||
if(lg->type->close) lg->type->close(lg);
|
||||
_3proxy_mutex_destroy(&lg->mutex);
|
||||
logfreearchiver(lg);
|
||||
if(lg->params) free(lg->params);
|
||||
free(lg->selector);
|
||||
free(lg);
|
||||
}
|
||||
@ -808,10 +850,10 @@ static void logfallback(struct logger *lg, struct clientparam *param, const unsi
|
||||
logput(to);
|
||||
}
|
||||
|
||||
/* The part of a log string fit to be shown: up to a comma, an ODBC string
|
||||
going on with the user and the password, and at most 200 bytes. */
|
||||
/* The part of a log string fit to be shown: its name, without parameters
|
||||
(an ODBC user and password), and at most 200 bytes. */
|
||||
size_t logselen(const unsigned char *selector){
|
||||
size_t len = strcspn((char *)selector, ",");
|
||||
size_t len = lognamelen(logmatch(selector), selector);
|
||||
|
||||
return len > 200? 200 : len;
|
||||
}
|
||||
@ -846,8 +888,7 @@ static void logwrite(struct logger *lg, struct clientparam *param, const unsigne
|
||||
if(report){
|
||||
unsigned char msg[300];
|
||||
|
||||
/* up to a comma: an ODBC string goes on with user and password */
|
||||
sprintf((char *)msg, "Log %.*s failed, its lines go to the error log", (int)logselen(lg->selector), lg->selector);
|
||||
sprintf((char *)msg, "Log %.200s failed, its lines go to the error log", lg->selector);
|
||||
logerror(msg);
|
||||
}
|
||||
}
|
||||
|
||||
33
src/sql.c
33
src/sql.c
@ -26,14 +26,17 @@ static void odbcdisconnect(struct logodbc *d){
|
||||
}
|
||||
}
|
||||
|
||||
/* &DATASOURCE,USERNAME,PASSWORD */
|
||||
/* The log string is &DATASOURCE,USERNAME,PASSWORD. The data source
|
||||
alone names the log; user and password are its parameters, the
|
||||
password being whatever follows the comma after the user. */
|
||||
static int odbcconnect(struct logger *lg){
|
||||
struct logodbc *d = (struct logodbc *)lg->data;
|
||||
SQLRETURN retcode;
|
||||
char * datasource;
|
||||
char * username;
|
||||
char * password;
|
||||
char * string;
|
||||
char * username = NULL;
|
||||
char * password = NULL;
|
||||
char * string = NULL;
|
||||
size_t slen = 0;
|
||||
|
||||
if(d->hstmt || d->hdbc || d->henv) odbcdisconnect(d);
|
||||
if(!d->henv){
|
||||
@ -58,20 +61,24 @@ static int odbcconnect(struct logger *lg){
|
||||
}
|
||||
SQLSetConnectAttr(d->hdbc, SQL_LOGIN_TIMEOUT, (void*)15, 0);
|
||||
}
|
||||
string = strdup((char *)lg->selector + 1);
|
||||
if(!string) return 0;
|
||||
datasource = strtok(string, ",");
|
||||
username = strtok(NULL, ",");
|
||||
password = strtok(NULL, ",");
|
||||
if(!datasource) datasource = "";
|
||||
|
||||
datasource = (char *)lg->selector + 1;
|
||||
if(lg->params){
|
||||
if(!(string = strdup((char *)lg->params))) return 0;
|
||||
slen = strlen(string);
|
||||
username = string;
|
||||
if((password = strchr(string, ','))) *password++ = 0;
|
||||
}
|
||||
|
||||
/* Connect to data source */
|
||||
retcode = SQLConnect(d->hdbc, (SQLCHAR*) datasource, (SQLSMALLINT)strlen(datasource),
|
||||
(SQLCHAR*) username, (SQLSMALLINT)((username)?strlen(username):0),
|
||||
(SQLCHAR*) password, (SQLSMALLINT)((password)?strlen(password):0));
|
||||
|
||||
free(string);
|
||||
if(string) {
|
||||
/* no copy of the password left behind */
|
||||
memset(string, 0, slen);
|
||||
free(string);
|
||||
}
|
||||
if (retcode != SQL_SUCCESS && retcode != SQL_SUCCESS_WITH_INFO){
|
||||
SQLFreeHandle(SQL_HANDLE_DBC, d->hdbc);
|
||||
d->hdbc = NULL;
|
||||
@ -125,7 +132,7 @@ static void odbcclose(struct logger *lg){
|
||||
}
|
||||
|
||||
const struct logtype logtype_odbc = {
|
||||
"odbc", odbcmatch, odbcinit, odbcformat, odbcwrite, odbcclose, NULL, LOGSTACKSIZE, 0, 0
|
||||
"odbc", odbcmatch, odbcinit, odbcformat, odbcwrite, odbcclose, NULL, LOGSTACKSIZE, 0, 0, 1
|
||||
};
|
||||
|
||||
#endif
|
||||
|
||||
@ -627,7 +627,9 @@ struct hashtable {
|
||||
|
||||
/* A log, named by the string the log command or -l gives it: "" standard
|
||||
output, "/dev/null" none, "@IDENT" syslog, "&DSN" ODBC, "radius" RADIUS
|
||||
accounting, anything else a file. One logger serves every service and
|
||||
accounting, anything else a file. For a type with parameters, ODBC, the
|
||||
string up to its first comma names the log and the rest, user and
|
||||
password, are its parameters, neither shown nor telling logs apart. One logger serves every service and
|
||||
configuration naming it the same way, and is closed once none uses it,
|
||||
the standard ones (none, standard output and error, syslog) excepted. */
|
||||
struct logtype {
|
||||
@ -647,12 +649,14 @@ struct logtype {
|
||||
int stacksize; /* the client thread stack its writing needs */
|
||||
int standard; /* kept open for the life of the process */
|
||||
int text; /* writes a line of text: errors can go there */
|
||||
int params; /* the string after a comma is parameters */
|
||||
};
|
||||
|
||||
struct logger {
|
||||
struct logger *next;
|
||||
const struct logtype *type;
|
||||
unsigned char *selector;
|
||||
unsigned char *selector; /* the name, without parameters */
|
||||
unsigned char *params; /* what follows the name's comma, or NULL */
|
||||
void *data; /* the type's own */
|
||||
int refs;
|
||||
int errors; /* writes failed in a row */
|
||||
|
||||
Loading…
Reference in New Issue
Block a user