]>
Commit | Line | Data |
---|---|---|
52b7d2ce A |
1 | /* $Id: plog.c,v 1.6.10.1 2005/12/07 10:19:51 vanhu Exp $ */ |
2 | ||
3 | /* | |
4 | * Copyright (C) 1995, 1996, 1997, and 1998 WIDE Project. | |
5 | * All rights reserved. | |
6 | * | |
7 | * Redistribution and use in source and binary forms, with or without | |
8 | * modification, are permitted provided that the following conditions | |
9 | * are met: | |
10 | * 1. Redistributions of source code must retain the above copyright | |
11 | * notice, this list of conditions and the following disclaimer. | |
12 | * 2. Redistributions in binary form must reproduce the above copyright | |
13 | * notice, this list of conditions and the following disclaimer in the | |
14 | * documentation and/or other materials provided with the distribution. | |
15 | * 3. Neither the name of the project nor the names of its contributors | |
16 | * may be used to endorse or promote products derived from this software | |
17 | * without specific prior written permission. | |
18 | * | |
19 | * THIS SOFTWARE IS PROVIDED BY THE PROJECT AND CONTRIBUTORS ``AS IS'' AND | |
20 | * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE | |
21 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE | |
22 | * ARE DISCLAIMED. IN NO EVENT SHALL THE PROJECT OR CONTRIBUTORS BE LIABLE | |
23 | * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL | |
24 | * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS | |
25 | * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) | |
26 | * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT | |
27 | * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY | |
28 | * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF | |
29 | * SUCH DAMAGE. | |
30 | */ | |
31 | ||
32 | #include "config.h" | |
33 | ||
34 | #include <sys/types.h> | |
35 | #include <sys/param.h> | |
36 | ||
37 | #include <stdlib.h> | |
65c25746 | 38 | #include <fcntl.h> |
52b7d2ce A |
39 | #include <stdio.h> |
40 | #include <string.h> | |
41 | #include <errno.h> | |
42 | #ifdef HAVE_STDARG_H | |
43 | #include <stdarg.h> | |
44 | #else | |
45 | #include <varargs.h> | |
46 | #endif | |
47 | #if TIME_WITH_SYS_TIME | |
48 | # include <sys/time.h> | |
49 | # include <time.h> | |
50 | #else | |
51 | # if HAVE_SYS_TIME_H | |
52 | # include <sys/time.h> | |
53 | # else | |
54 | # include <time.h> | |
55 | # endif | |
56 | #endif | |
57 | #include <ctype.h> | |
58 | #include <err.h> | |
e8d9021d A |
59 | #include <pthread.h> |
60 | #include <unistd.h> | |
65c25746 A |
61 | #include <asl.h> |
62 | #include <syslog.h> | |
63 | #include <asl_private.h> | |
52b7d2ce A |
64 | |
65 | #include "var.h" | |
66 | #include "misc.h" | |
67 | #include "plog.h" | |
52b7d2ce A |
68 | #include "debug.h" |
69 | #include "gcmalloc.h" | |
65c25746 | 70 | #include "preferences.h" |
52b7d2ce A |
71 | |
72 | #ifndef VA_COPY | |
d1e348cf | 73 | # define VA_COPY(dst,src) memcpy(&(dst), (src), sizeof(va_list)) |
52b7d2ce A |
74 | #endif |
75 | ||
65c25746 A |
76 | const char *plog_facility = "com.apple.racoon"; |
77 | const char *plog_session_id = "com.apple.racoon.sessionid"; | |
78 | const char *plog_session_type = "com.apple.racoon.sessiontype"; | |
79 | const char *plog_session_ver = "com.apple.racoon.sessionversion"; | |
80 | ||
52b7d2ce A |
81 | extern int print_pid; |
82 | ||
83 | char *pname = NULL; | |
65c25746 A |
84 | u_int32_t loglevel = ASL_LEVEL_NOTICE; |
85 | //u_int32_t loglevel = ASL_LEVEL_DEBUG; | |
52b7d2ce A |
86 | int f_foreground = 0; |
87 | ||
88 | int print_location = 0; | |
89 | ||
65c25746 A |
90 | char *logfile = NULL; |
91 | int logfile_fd = -1; | |
92 | char logFileStr[MAXPATHLEN+1]; | |
93 | char *gSessId = NULL; | |
94 | char *gSessType = NULL; | |
95 | char *gSessVer = NULL; | |
96 | aslclient logRef = NULL; | |
52b7d2ce A |
97 | |
98 | void | |
65c25746 | 99 | plogdump_asl (aslmsg msg, int pri, const char *fmt, ...) |
e8d9021d | 100 | { |
65c25746 A |
101 | caddr_t buf; |
102 | size_t buflen = 512; | |
103 | va_list args; | |
104 | char *level; | |
e8d9021d | 105 | |
65c25746 A |
106 | switch (pri) { |
107 | case ASL_LEVEL_INFO: | |
108 | level = ASL_STRING_INFO; | |
109 | break; | |
52b7d2ce | 110 | |
65c25746 A |
111 | case ASL_LEVEL_NOTICE: |
112 | level = ASL_STRING_NOTICE; | |
113 | break; | |
52b7d2ce | 114 | |
65c25746 A |
115 | case ASL_LEVEL_WARNING: |
116 | level = ASL_STRING_WARNING; | |
117 | break; | |
118 | ||
119 | case ASL_LEVEL_ERR: | |
120 | level = ASL_STRING_ERR; | |
121 | break; | |
122 | ||
123 | case ASL_LEVEL_DEBUG: | |
124 | level = ASL_STRING_DEBUG; | |
125 | break; | |
126 | ||
127 | default: | |
52b7d2ce | 128 | return; |
65c25746 | 129 | } |
52b7d2ce | 130 | |
65c25746 | 131 | asl_set(msg, ASL_KEY_LEVEL, level); |
52b7d2ce | 132 | |
65c25746 A |
133 | buf = racoon_malloc(buflen); |
134 | if (buf) { | |
135 | buf[0] = '\0'; | |
136 | va_start(args, fmt); | |
137 | vsnprintf(buf, buflen, fmt, args); | |
138 | // asl_set(msg, ASL_KEY_MESSAGE, buf); | |
139 | va_end(args); | |
140 | racoon_free(buf); | |
52b7d2ce A |
141 | } |
142 | } | |
143 | ||
144 | void | |
65c25746 | 145 | plogdump_func(int pri, void *data, size_t len, const char *fmt, ...) |
52b7d2ce A |
146 | { |
147 | caddr_t buf; | |
148 | size_t buflen; | |
149 | int i, j; | |
65c25746 A |
150 | va_list args; |
151 | char fmt_buf[512]; | |
52b7d2ce A |
152 | |
153 | /* | |
154 | * 2 words a bytes + 1 space 4 bytes + 1 newline 32 bytes | |
155 | * + 2 newline + '\0' | |
156 | */ | |
157 | buflen = (len * 2) + (len / 4) + (len / 32) + 3; | |
158 | buf = racoon_malloc(buflen); | |
159 | ||
160 | i = 0; | |
161 | j = 0; | |
162 | while (j < len) { | |
163 | if (j % 32 == 0) | |
164 | buf[i++] = '\n'; | |
165 | else | |
166 | if (j % 4 == 0) | |
167 | buf[i++] = ' '; | |
168 | snprintf(&buf[i], buflen - i, "%02x", | |
169 | ((unsigned char *)data)[j] & 0xff); | |
170 | i += 2; | |
171 | j++; | |
172 | } | |
173 | if (buflen - i >= 2) { | |
174 | buf[i++] = '\n'; | |
175 | buf[i] = '\0'; | |
176 | } | |
65c25746 A |
177 | |
178 | fmt_buf[0] = '\n'; | |
179 | va_start(args, fmt); | |
180 | vsnprintf(fmt_buf, sizeof(fmt_buf), fmt, args); | |
181 | va_end(args); | |
182 | ||
183 | plog(pri, "%s %s", fmt_buf, buf); | |
52b7d2ce A |
184 | |
185 | racoon_free(buf); | |
186 | } | |
187 | ||
188 | void | |
65c25746 | 189 | clog_func (clog_err_t *cerr, clog_err_op_t cerr_op, int pri, const char *function, const char *line, const char *fmt, ...) |
52b7d2ce | 190 | { |
65c25746 A |
191 | clog_err_t *new, *p; |
192 | va_list args; | |
e8d9021d | 193 | |
65c25746 | 194 | if (!cerr) { |
52b7d2ce A |
195 | return; |
196 | } | |
e8d9021d | 197 | |
65c25746 A |
198 | if (!(new = racoon_calloc(1, sizeof(*cerr)))) { |
199 | return; | |
200 | } | |
201 | // fill in new | |
202 | cerr->clog_err_level = pri; /* will be used for filtering */ | |
203 | /* TODO */ | |
204 | //cerr->clog_err_code; | |
205 | //cerr->client_id; | |
206 | //cerr->client_type; | |
207 | va_start(args, fmt); | |
208 | cerr->description_len = vasprintf(&cerr->description, fmt, args); | |
209 | va_end(args); | |
210 | cerr->function = function; | |
211 | cerr->line = line; | |
212 | ||
213 | // add new to the tail | |
214 | TAILQ_FOREACH(p, &cerr->chain_head, chain) { | |
215 | if (TAILQ_NEXT(p, chain) == NULL) { | |
216 | TAILQ_NEXT(p, chain) = new; | |
217 | new->chain.tqe_prev = &TAILQ_NEXT(p, chain); | |
218 | break; | |
219 | } | |
220 | } | |
221 | ||
222 | if (cerr_op == CLOG_ERR_DUMP) { | |
223 | char *prev = NULL, *backtrace = NULL; | |
224 | ||
225 | TAILQ_FOREACH(p, &cerr->chain_head, chain) { | |
226 | // collapse list into backtrace | |
227 | if (cerr->description) { | |
228 | if (backtrace) { | |
229 | prev = backtrace; | |
230 | backtrace = NULL; | |
231 | asprintf(&backtrace, "%s\n\t\t-> %s", prev, cerr->description); | |
232 | free(prev); | |
233 | } else { | |
234 | asprintf(&backtrace, "%s", cerr->description); | |
235 | } | |
236 | } | |
237 | } | |
238 | ||
239 | if (backtrace) { | |
240 | // use plog to dump event. | |
241 | plog(pri, "%s", backtrace); | |
242 | } | |
243 | } | |
52b7d2ce A |
244 | } |
245 | ||
246 | void | |
65c25746 | 247 | plogsetfile(file) |
52b7d2ce A |
248 | char *file; |
249 | { | |
65c25746 A |
250 | syslog(LOG_NOTICE, "%s: about to add racoon log file: %s\n", __FUNCTION__, file? file:"bad file path"); |
251 | if (logfile != NULL) { | |
52b7d2ce | 252 | racoon_free(logfile); |
65c25746 A |
253 | if (logfile_fd != -1) { |
254 | asl_remove_log_file(logRef, logfile_fd); | |
255 | asl_close_auxiliary_file(logfile_fd); | |
256 | logfile_fd = -1; | |
257 | } | |
258 | } | |
d1e348cf A |
259 | logfile = racoon_strdup(file); |
260 | STRDUP_FATAL(logfile); | |
d9c572c0 | 261 | if ((logfile_fd = open(logfile, O_CREAT | O_WRONLY | O_APPEND | O_NOFOLLOW, S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH)) >= 0) { |
65c25746 A |
262 | asl_add_log_file(logRef, logfile_fd); |
263 | } else { | |
264 | syslog(LOG_NOTICE, "%s: failed to add racoon log file: %s. error %d\n", __FUNCTION__, file? file:"bad file path", errno); | |
265 | } | |
52b7d2ce A |
266 | } |
267 | ||
268 | void | |
65c25746 | 269 | plogresetfile(file) |
52b7d2ce A |
270 | char *file; |
271 | { | |
52b7d2ce | 272 | /* if log paths equal - do nothing */ |
e8d9021d | 273 | if (logfile == NULL && file == NULL) { |
52b7d2ce | 274 | return; |
e8d9021d | 275 | } |
65c25746 | 276 | if (logfile != NULL && file != NULL) { |
e8d9021d | 277 | if (!strcmp(logfile, file)) { |
52b7d2ce | 278 | return; |
e8d9021d | 279 | } |
65c25746 A |
280 | if (logfile_fd != -1) { |
281 | asl_remove_log_file(logRef, logfile_fd); | |
282 | close(logfile_fd); | |
283 | logfile_fd = -1; | |
284 | } | |
52b7d2ce | 285 | } |
65c25746 A |
286 | |
287 | if (logfile) { | |
288 | racoon_free(logfile); | |
289 | logfile = NULL; | |
290 | } | |
291 | ||
52b7d2ce | 292 | if (file) |
65c25746 A |
293 | plogsetfile(file); |
294 | } | |
e8d9021d | 295 | |
65c25746 A |
296 | int |
297 | ploggetlevel(void) | |
298 | { | |
299 | return loglevel; | |
300 | } | |
d1e348cf | 301 | |
65c25746 A |
302 | void |
303 | plogsetlevel(int level) | |
d1e348cf | 304 | { |
65c25746 A |
305 | int mask; |
306 | ||
307 | if (level && level >= ASL_LEVEL_EMERG && level <= ASL_LEVEL_DEBUG) { | |
308 | loglevel = level; | |
d1e348cf | 309 | } |
65c25746 A |
310 | if (loglevel >= ASL_LEVEL_INFO) { |
311 | mask = ASL_FILTER_MASK_TUNNEL; | |
312 | } else { | |
313 | mask = 0; | |
314 | } | |
315 | mask |= ASL_FILTER_MASK_UPTO(loglevel); | |
316 | syslog(LOG_DEBUG, "%s: about to set racoon's log level %d, mask %x\n", __FUNCTION__, level, mask); | |
317 | asl_set_filter(NULL, mask); | |
d1e348cf | 318 | } |
65c25746 A |
319 | |
320 | void | |
321 | plogsetlevelstr(char *levelstr) | |
322 | { | |
323 | if (!levelstr) { | |
324 | return; | |
325 | } | |
326 | ||
327 | if (strncmp(levelstr, ASL_STRING_EMERG, sizeof(ASL_STRING_EMERG) - 1) == 0) { | |
328 | plogsetlevel(ASL_LEVEL_EMERG); | |
329 | } else if (strncmp(levelstr, ASL_STRING_ALERT, sizeof(ASL_STRING_ALERT) - 1) == 0) { | |
330 | plogsetlevel(ASL_LEVEL_ALERT); | |
331 | } else if (strncmp(levelstr, ASL_STRING_CRIT, sizeof(ASL_STRING_CRIT) - 1) == 0) { | |
332 | plogsetlevel(ASL_LEVEL_CRIT); | |
333 | } else if (strncmp(levelstr, ASL_STRING_ERR, sizeof(ASL_STRING_ERR) - 1) == 0) { | |
334 | plogsetlevel(ASL_LEVEL_ERR); | |
335 | } else if (strncmp(levelstr, ASL_STRING_WARNING, sizeof(ASL_STRING_NOTICE) - 1) == 0) { | |
336 | plogsetlevel(ASL_LEVEL_WARNING); | |
337 | } else if (strncmp(levelstr, ASL_STRING_NOTICE, sizeof(ASL_STRING_NOTICE) - 1) == 0) { | |
338 | plogsetlevel(ASL_LEVEL_NOTICE); | |
339 | } else if (strncmp(levelstr, ASL_STRING_INFO, sizeof(ASL_STRING_INFO) - 1) == 0) { | |
340 | plogsetlevel(ASL_LEVEL_INFO); | |
341 | } else if (strncmp(levelstr, ASL_STRING_DEBUG, sizeof(ASL_STRING_DEBUG) - 1) == 0) { | |
342 | plogsetlevel(ASL_LEVEL_DEBUG); | |
343 | } | |
344 | } | |
345 | ||
346 | void | |
347 | plogsetlevelquotedstr (char *levelquotedstr) | |
348 | { | |
349 | int len; | |
350 | ||
351 | if (!levelquotedstr) { | |
352 | plog(ASL_LEVEL_ERR, "Null log level (quoted string)"); | |
353 | return; | |
354 | } | |
355 | ||
356 | len = strlen(levelquotedstr); | |
357 | if (len < 3 || | |
358 | levelquotedstr[0] != '"' || | |
359 | levelquotedstr[len - 1] != '"') { | |
360 | plog(ASL_LEVEL_ERR, "Invalid log level (quoted string): %s", levelquotedstr); | |
361 | return; | |
362 | } | |
363 | // skip quotes | |
364 | levelquotedstr[len - 1] = '\0'; | |
365 | plogsetlevelstr(&levelquotedstr[1]); | |
366 | } | |
367 | ||
368 | void | |
369 | plogreadprefs (void) | |
370 | { | |
371 | CFPropertyListRef globals; | |
372 | CFStringRef logFileRef; | |
373 | CFNumberRef debugLevelRef; | |
374 | CFStringRef debugLevelStringRef; | |
375 | char logLevelStr[16]; | |
376 | int level = 0; | |
377 | ||
378 | logLevelStr[0] = 0; | |
379 | ||
380 | SCPreferencesSynchronize(gPrefs); | |
381 | ||
382 | globals = SCPreferencesGetValue(gPrefs, CFSTR("Global")); | |
383 | if (!globals || (CFGetTypeID(globals) != CFDictionaryGetTypeID())) { | |
384 | return; | |
385 | } | |
386 | debugLevelRef = CFDictionaryGetValue(globals, CFSTR("DebugLevel")); | |
387 | if (debugLevelRef && (CFGetTypeID(debugLevelRef) == CFNumberGetTypeID())) { | |
388 | CFNumberGetValue(debugLevelRef, kCFNumberSInt32Type, &level); | |
389 | plogsetlevel(level); | |
390 | } else { | |
391 | debugLevelStringRef = CFDictionaryGetValue(globals, CFSTR("DebugLevelString")); | |
392 | if (debugLevelStringRef && (CFGetTypeID(debugLevelStringRef) == CFStringGetTypeID())) { | |
393 | CFStringGetCString(debugLevelStringRef, logLevelStr, sizeof(logLevelStr), kCFStringEncodingMacRoman); | |
394 | plogsetlevelstr(logLevelStr); | |
395 | } | |
396 | } | |
397 | ||
398 | logFileRef = CFDictionaryGetValue(globals, CFSTR("DebugLogfile")); | |
399 | if (!logFileRef || (CFGetTypeID(logFileRef) != CFStringGetTypeID())) { | |
400 | return; | |
401 | } | |
402 | CFStringGetCString(logFileRef, logFileStr, MAXPATHLEN, kCFStringEncodingMacRoman); | |
403 | plogsetfile(logFileStr); | |
404 | } | |
405 | ||
406 | void | |
407 | ploginit(void) | |
408 | { | |
409 | logFileStr[0] = 0; | |
410 | logRef = NULL;//asl_open(NULL, plog_facility, 0); | |
411 | plogsetlevel(ASL_LEVEL_NOTICE); | |
412 | //plogsetlevel(ASL_LEVEL_DEBUG); | |
413 | plogreadprefs(); | |
414 | } | |
415 | ||
416 | void | |
417 | plogsetsessioninfo (const char *session_id, | |
418 | const char *session_type, | |
419 | const char *session_ver) | |
420 | { | |
421 | if (gSessId) { | |
422 | free(gSessId); | |
423 | } | |
424 | if (!session_id) { | |
425 | gSessId = NULL; | |
426 | } else { | |
427 | gSessId = strdup(session_id); | |
428 | } | |
429 | if (gSessId) { | |
430 | free(gSessId); | |
431 | } | |
432 | if (!session_type) { | |
433 | gSessType = NULL; | |
434 | } else { | |
435 | gSessType = strdup(session_id); | |
436 | } | |
437 | if (gSessVer) { | |
438 | free(gSessVer); | |
439 | } | |
440 | if (!session_ver) { | |
441 | gSessVer = NULL; | |
442 | } else { | |
443 | gSessVer = strdup(session_ver); | |
444 | } | |
445 | } | |
446 | ||
447 | char * | |
448 | createCStringFromCFString(CFAllocatorRef allocator, CFStringRef cfstr) | |
449 | { | |
450 | CFIndex cstr_len = CFStringGetMaximumSizeForEncoding(CFStringGetLength(cfstr), kCFStringEncodingUTF8) + 1; | |
451 | char *cstr = (char *)CFAllocatorAllocate(allocator, cstr_len, 0); | |
452 | CFStringGetCString(cfstr, cstr, cstr_len, kCFStringEncodingUTF8); | |
453 | return cstr; | |
454 | } | |
455 | ||
456 | void | |
457 | plogcf(int priority, CFStringRef fmt, ...) | |
458 | { | |
459 | va_list args; | |
460 | CFStringRef cfstr; | |
461 | char *cstr; | |
462 | ||
463 | va_start(args, fmt); | |
464 | cfstr = CFStringCreateWithFormatAndArguments(kCFAllocatorDefault, NULL, fmt, args); | |
465 | va_end(args); | |
466 | ||
467 | cstr = createCStringFromCFString(kCFAllocatorDefault, cfstr); | |
468 | plog(priority, "%s", cstr); | |
469 | ||
470 | CFAllocatorDeallocate(kCFAllocatorDefault, cstr); | |
471 | CFRelease(cfstr); | |
472 | } | |
473 | ||
474 |