29 |
#include <errno.h> |
#include <errno.h> |
30 |
#include <syslog.h> |
#include <syslog.h> |
31 |
#include <radiusd.h> |
#include <radiusd.h> |
32 |
|
#include <rewrite.h> |
33 |
|
|
34 |
static int logging_category = L_CAT(L_MAIN); |
static int logging_category = L_CAT(L_MAIN); |
35 |
static RAD_LIST /* of Channel*/ *chanlist; /* List of defined channels */ |
static RAD_LIST /* of Channel*/ *chanlist; /* List of defined channels */ |
36 |
|
|
|
static void log_to_channel(Channel *chan, int cat, int pri, |
|
|
char *buf1, char *buf2, char *buf3); |
|
|
static FILE *channel_open_file(Channel *chan); |
|
|
static void channel_close_file(Channel *chan, FILE *fp); |
|
|
|
|
37 |
#define SP(p) ((p)?(p):"") |
#define SP(p) ((p)?(p):"") |
38 |
|
|
39 |
static int |
static int |
60 |
log_set_category(L_MAIN); |
log_set_category(L_MAIN); |
61 |
} |
} |
62 |
|
|
|
void |
|
|
vlog(int level, |
|
|
const char *file, size_t line, |
|
|
const char *func_name, int en, |
|
|
const char *fmt, va_list ap) |
|
|
{ |
|
|
Channel *chan; |
|
|
int cat, pri; |
|
|
char *buf1 = NULL; |
|
|
char *buf2 = NULL; |
|
|
char *buf3 = NULL; |
|
|
ITERATOR *itr = iterator_create(chanlist); |
|
|
|
|
|
cat = L_CAT(level); |
|
|
if (cat == 0) |
|
|
cat = log_get_category(); |
|
|
pri = L_PRI(level); |
|
|
|
|
|
if (file) { |
|
|
if (func_name) |
|
|
asprintf(&buf1, |
|
|
"%s:%d:%s: ", file, line, func_name); |
|
|
else |
|
|
asprintf(&buf1, |
|
|
"%s:%d: ", file, line); |
|
|
} |
|
|
|
|
|
if (en) |
|
|
asprintf(&buf3, ": %s", strerror(en)); |
|
|
|
|
|
vasprintf(&buf2, fmt, ap); |
|
|
|
|
|
for (chan = iterator_first(itr); chan; chan = iterator_next(itr)) { |
|
|
/* Skip channels whith incorrect priority */ |
|
|
if (chan->pmask[cat] & L_MASK(pri)) |
|
|
log_to_channel(chan, cat, pri, buf1, buf2, buf3); |
|
|
} |
|
|
iterator_destroy(&itr); |
|
|
|
|
|
if (buf1) |
|
|
free(buf1); |
|
|
if (buf2) |
|
|
free(buf2); |
|
|
if (buf3) |
|
|
free(buf3); |
|
|
} |
|
|
|
|
63 |
static char *catname[] = { /* category names */ |
static char *catname[] = { /* category names */ |
64 |
N_("none"), |
N_("none"), |
65 |
N_("Main"), |
N_("Main"), |
80 |
N_("debug") |
N_("debug") |
81 |
}; |
}; |
82 |
|
|
83 |
|
static char * |
84 |
|
run_log_hook(const RADIUS_REQ *req, const char *hook_name) |
85 |
|
{ |
86 |
|
char *result; |
87 |
|
char nasbuf[MAX_LONGNAME]; |
88 |
|
|
89 |
|
if (rewrite_invoke(String, |
90 |
|
&result, |
91 |
|
hook_name, |
92 |
|
req, |
93 |
|
"ssi", |
94 |
|
auth_code_abbr(req->code), |
95 |
|
nas_request_to_name(req, nasbuf, sizeof nasbuf), |
96 |
|
req->id)) |
97 |
|
return NULL; |
98 |
|
return result; |
99 |
|
} |
100 |
|
|
101 |
|
static void |
102 |
|
channel_format_prefix(char **bufp, Channel *chan, const RADIUS_REQ *req) |
103 |
|
{ |
104 |
|
char *hook_res = NULL; |
105 |
|
|
106 |
|
if (chan->prefix_hook) { |
107 |
|
hook_res = run_log_hook(req, chan->prefix_hook); |
108 |
|
if (!hook_res) |
109 |
|
chan->prefix_hook = NULL; |
110 |
|
} |
111 |
|
|
112 |
|
if (hook_res) |
113 |
|
asprintf(bufp, "%s", hook_res); |
114 |
|
} |
115 |
|
|
116 |
|
static void |
117 |
|
channel_format_suffix(char **bufp, Channel *chan, const RADIUS_REQ *req) |
118 |
|
{ |
119 |
|
char *hook_res = NULL; |
120 |
|
|
121 |
|
if (chan->suffix_hook) { |
122 |
|
hook_res = run_log_hook(req, chan->suffix_hook); |
123 |
|
if (!hook_res) |
124 |
|
chan->suffix_hook = NULL; |
125 |
|
} |
126 |
|
|
127 |
|
if (hook_res) |
128 |
|
asprintf(bufp, "%s", hook_res); |
129 |
|
} |
130 |
|
|
131 |
|
static FILE * |
132 |
|
channel_open_file(Channel *chan) |
133 |
|
{ |
134 |
|
FILE *fp = NULL; |
135 |
|
|
136 |
|
if (strcmp(chan->id.file, "stdout")) |
137 |
|
fp = fopen(chan->id.file, "a"); |
138 |
|
return fp ? fp : stderr; |
139 |
|
} |
140 |
|
|
141 |
|
/*ARGSUSED*/ |
142 |
|
static void |
143 |
|
channel_close_file(Channel *chan, FILE *fp) |
144 |
|
{ |
145 |
|
if (fp != stderr) |
146 |
|
fclose(fp); |
147 |
|
} |
148 |
|
|
149 |
void |
void |
150 |
log_to_channel(Channel *chan, int cat, int pri, |
log_to_channel(Channel *chan, int cat, int pri, |
151 |
|
const RADIUS_REQ *req, |
152 |
char *buf1, char *buf2, char *buf3) |
char *buf1, char *buf2, char *buf3) |
153 |
{ |
{ |
154 |
char *cat_pref = NULL; |
char *cat_pref = NULL; |
155 |
char *prefix = NULL; |
char *prefix = NULL; |
156 |
|
char *req_prefix_buf = NULL, *req_suffix_buf = NULL; |
157 |
time_t timeval; |
time_t timeval; |
158 |
char buffer[256]; |
char buffer[256]; |
159 |
struct tm *tm, tms; |
struct tm *tm, tms; |
177 |
if (cat_pref) |
if (cat_pref) |
178 |
free(cat_pref); |
free(cat_pref); |
179 |
|
|
180 |
|
if (req) { |
181 |
|
channel_format_prefix(&req_prefix_buf, chan, req); |
182 |
|
channel_format_suffix(&req_suffix_buf, chan, req); |
183 |
|
} |
184 |
|
|
185 |
switch (chan->mode) { |
switch (chan->mode) { |
186 |
case LM_FILE: |
case LM_FILE: |
187 |
if (chan->options & LO_MSEC) { |
if (chan->options & LO_MSEC) { |
209 |
fprintf(fp, "%s: ", prefix); |
fprintf(fp, "%s: ", prefix); |
210 |
if (buf1) |
if (buf1) |
211 |
fprintf(fp, "%s", buf1); |
fprintf(fp, "%s", buf1); |
212 |
|
if (req_prefix_buf) |
213 |
|
fprintf(fp, "%s", req_prefix_buf); |
214 |
if (buf2) |
if (buf2) |
215 |
fprintf(fp, "%s", buf2); |
fprintf(fp, "%s", buf2); |
216 |
if (buf3) |
if (buf3) |
217 |
fprintf(fp, "%s", buf3); |
fprintf(fp, "%s", buf3); |
218 |
|
if (req_suffix_buf) |
219 |
|
fprintf(fp, "%s", req_suffix_buf); |
220 |
fprintf(fp, "\n"); |
fprintf(fp, "\n"); |
221 |
channel_close_file(chan, fp); |
channel_close_file(chan, fp); |
222 |
break; |
break; |
226 |
if (chan->options & LO_PID) |
if (chan->options & LO_PID) |
227 |
spri |= LOG_PID; |
spri |= LOG_PID; |
228 |
if (prefix) |
if (prefix) |
229 |
syslog(spri, "%s: %s%s%s", |
syslog(spri, "%s: %s%s%s%s%s", |
230 |
prefix, SP(buf1), SP(buf2), SP(buf3)); |
prefix, |
231 |
|
SP(buf1), |
232 |
|
SP(req_prefix_buf), |
233 |
|
SP(buf2), SP(buf3), |
234 |
|
SP(req_suffix_buf)); |
235 |
else |
else |
236 |
syslog(spri, "%s%s%s", |
syslog(spri, "%s%s%s%s%s", |
237 |
SP(buf1), SP(buf2), SP(buf3)); |
SP(buf1), |
238 |
|
SP(req_prefix_buf), |
239 |
|
SP(buf2), SP(buf3), |
240 |
|
SP(req_suffix_buf)); |
241 |
break; |
break; |
242 |
} |
} |
243 |
|
|
244 |
if (prefix) |
if (prefix) |
245 |
free(prefix); |
free(prefix); |
246 |
|
if (req_prefix_buf) |
247 |
|
free(req_prefix_buf); |
248 |
|
if (req_suffix_buf) |
249 |
|
free(req_suffix_buf); |
250 |
} |
} |
251 |
|
|
252 |
FILE * |
void |
253 |
channel_open_file(Channel *chan) |
vlog(int level, |
254 |
|
const RADIUS_REQ *req, |
255 |
|
const LOCUS *loc, |
256 |
|
const char *func_name, |
257 |
|
int en, |
258 |
|
const char *fmt, va_list ap) |
259 |
{ |
{ |
260 |
FILE *fp = NULL; |
Channel *chan; |
261 |
|
int cat, pri; |
262 |
|
char *buf1 = NULL; |
263 |
|
char *buf2 = NULL; |
264 |
|
char *buf3 = NULL; |
265 |
|
ITERATOR *itr = iterator_create(chanlist); |
266 |
|
|
267 |
if (strcmp(chan->id.file, "stdout")) |
cat = L_CAT(level); |
268 |
fp = fopen(chan->id.file, "a"); |
if (cat == 0) |
269 |
return fp ? fp : stderr; |
cat = log_get_category(); |
270 |
} |
pri = L_PRI(level); |
271 |
|
|
272 |
|
if (loc) { |
273 |
|
if (func_name) |
274 |
|
asprintf(&buf1, |
275 |
|
"%s:%d:%s: ", loc->file, loc->line, |
276 |
|
func_name); |
277 |
|
else |
278 |
|
asprintf(&buf1, |
279 |
|
"%s:%d: ", loc->file, loc->line); |
280 |
|
} |
281 |
|
|
282 |
|
if (en) |
283 |
|
asprintf(&buf3, ": %s", strerror(en)); |
284 |
|
|
285 |
/*ARGSUSED*/ |
vasprintf(&buf2, fmt, ap); |
286 |
void |
|
287 |
channel_close_file(Channel *chan, FILE *fp) |
for (chan = iterator_first(itr); chan; chan = iterator_next(itr)) { |
288 |
{ |
/* Skip channels whith incorrect priority */ |
289 |
if (fp != stderr) |
if (chan->pmask[cat] & L_MASK(pri)) |
290 |
fclose(fp); |
log_to_channel(chan, cat, pri, req, buf1, buf2, buf3); |
291 |
|
} |
292 |
|
iterator_destroy(&itr); |
293 |
|
|
294 |
|
if (buf1) |
295 |
|
free(buf1); |
296 |
|
if (buf2) |
297 |
|
free(buf2); |
298 |
|
if (buf3) |
299 |
|
free(buf3); |
300 |
} |
} |
301 |
|
|
302 |
/* Interface */ |
/* Interface */ |
335 |
efree(chan->name); |
efree(chan->name); |
336 |
if (chan->mode == LM_FILE) |
if (chan->mode == LM_FILE) |
337 |
efree(chan->id.file); |
efree(chan->id.file); |
338 |
|
efree(chan->prefix_hook); |
339 |
|
efree(chan->suffix_hook); |
340 |
efree(chan); |
efree(chan); |
341 |
} |
} |
342 |
|
|
433 |
else if (chan->mode == LM_SYSLOG) |
else if (chan->mode == LM_SYSLOG) |
434 |
channel->id.prio = chan->id.prio; |
channel->id.prio = chan->id.prio; |
435 |
channel->options = chan->options; |
channel->options = chan->options; |
436 |
|
channel->prefix_hook = chan->prefix_hook; |
437 |
|
channel->suffix_hook = chan->suffix_hook; |
438 |
|
|
439 |
if (!chanlist) |
if (!chanlist) |
440 |
chanlist = list_create(); |
chanlist = list_create(); |
441 |
list_prepend(chanlist, channel); |
list_prepend(chanlist, channel); |
503 |
chan.name = name; |
chan.name = name; |
504 |
chan.id.file = "radius.log"; |
chan.id.file = "radius.log"; |
505 |
chan.options = LO_CAT|LO_PRI; |
chan.options = LO_CAT|LO_PRI; |
506 |
|
chan.prefix_hook = chan.suffix_hook = NULL; |
507 |
|
|
508 |
if (!channel_lookup(name)) |
if (!channel_lookup(name)) |
509 |
register_channel(&chan); |
register_channel(&chan); |
510 |
register_category0(cat, pri, channel_lookup(name)); |
register_category0(cat, pri, channel_lookup(name)); |
526 |
snprintf(buffer, buflen, _("terminated")); |
snprintf(buffer, buflen, _("terminated")); |
527 |
} |
} |
528 |
|
|
529 |
|
|
530 |
/* ************************************************************************* */ |
/* ************************************************************************* */ |
531 |
/* Configuration issues */ |
/* Configuration issues */ |
532 |
|
|
537 |
int pri; |
int pri; |
538 |
RAD_LIST /* of Channel */ *clist; |
RAD_LIST /* of Channel */ *clist; |
539 |
int level; |
int level; |
|
char *hook; |
|
540 |
} cat_def; |
} cat_def; |
541 |
|
|
542 |
static struct keyword syslog_facility[] = { |
static struct keyword syslog_facility[] = { |
791 |
switch (cat_def.cat) { |
switch (cat_def.cat) { |
792 |
case L_AUTH: |
case L_AUTH: |
793 |
log_mode = cat_def.level; |
log_mode = cat_def.level; |
|
auth_log_hook = cat_def.hook; |
|
794 |
break; |
break; |
795 |
default: |
default: |
796 |
if (cat_def.level) |
if (cat_def.level) |
995 |
NULL, NULL }, |
NULL, NULL }, |
996 |
{ "print-milliseconds", CS_STMT, NULL, channel_set_flag, |
{ "print-milliseconds", CS_STMT, NULL, channel_set_flag, |
997 |
(void*)LO_MSEC, NULL, NULL }, |
(void*)LO_MSEC, NULL, NULL }, |
998 |
|
{ "prefix-hook", CS_STMT, NULL, cfg_get_string, &channel.prefix_hook, |
999 |
|
NULL, NULL }, |
1000 |
|
{ "suffix-hook", CS_STMT, NULL, cfg_get_string, &channel.suffix_hook, |
1001 |
|
NULL, NULL }, |
1002 |
{ NULL } |
{ NULL } |
1003 |
}; |
}; |
1004 |
|
|
1012 |
category_set_flag, (void*)RLOG_AUTH_PASS, NULL, NULL }, |
category_set_flag, (void*)RLOG_AUTH_PASS, NULL, NULL }, |
1013 |
{ "level", CS_STMT, NULL, |
{ "level", CS_STMT, NULL, |
1014 |
category_set_level, NULL, NULL, NULL }, |
category_set_level, NULL, NULL, NULL }, |
|
{ "hook", CS_STMT, NULL, cfg_get_string, &cat_def.hook, |
|
|
NULL, NULL }, |
|
1015 |
{ NULL } |
{ NULL } |
1016 |
}; |
}; |
1017 |
|
|