]> git.saurik.com Git - apple/ipsec.git/blob - ipsec-tools/racoon/plog.c
ipsec-332.tar.gz
[apple/ipsec.git] / ipsec-tools / racoon / plog.c
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>
38 #include <fcntl.h>
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>
59 #include <pthread.h>
60 #include <unistd.h>
61 #include <asl.h>
62 #include <syslog.h>
63 #include <asl_private.h>
64
65 #include "var.h"
66 #include "misc.h"
67 #include "plog.h"
68 #include "debug.h"
69 #include "gcmalloc.h"
70 #include "preferences.h"
71
72 #ifndef VA_COPY
73 # define VA_COPY(dst,src) memcpy(&(dst), (src), sizeof(va_list))
74 #endif
75
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
81 extern int print_pid;
82
83 char *pname = NULL;
84 u_int32_t loglevel = ASL_LEVEL_NOTICE;
85 //u_int32_t loglevel = ASL_LEVEL_DEBUG;
86 int f_foreground = 0;
87
88 int print_location = 0;
89
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;
97
98 void
99 plogdump_asl (aslmsg msg, int pri, const char *fmt, ...)
100 {
101 caddr_t buf;
102 size_t buflen = 512;
103 va_list args;
104 char *level;
105
106 switch (pri) {
107 case ASL_LEVEL_INFO:
108 level = ASL_STRING_INFO;
109 break;
110
111 case ASL_LEVEL_NOTICE:
112 level = ASL_STRING_NOTICE;
113 break;
114
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:
128 return;
129 }
130
131 asl_set(msg, ASL_KEY_LEVEL, level);
132
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);
141 }
142 }
143
144 void
145 plogdump_func(int pri, void *data, size_t len, const char *fmt, ...)
146 {
147 caddr_t buf;
148 size_t buflen;
149 int i, j;
150 va_list args;
151 char fmt_buf[512];
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 }
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);
184
185 racoon_free(buf);
186 }
187
188 void
189 clog_func (clog_err_t *cerr, clog_err_op_t cerr_op, int pri, const char *function, const char *line, const char *fmt, ...)
190 {
191 clog_err_t *new, *p;
192 va_list args;
193
194 if (!cerr) {
195 return;
196 }
197
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 }
244 }
245
246 void
247 plogsetfile(file)
248 char *file;
249 {
250 syslog(LOG_NOTICE, "%s: about to add racoon log file: %s\n", __FUNCTION__, file? file:"bad file path");
251 if (logfile != NULL) {
252 racoon_free(logfile);
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 }
259 logfile = racoon_strdup(file);
260 STRDUP_FATAL(logfile);
261 if ((logfile_fd = open(logfile, O_CREAT | O_WRONLY | O_APPEND | O_NOFOLLOW, S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH)) >= 0) {
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 }
266 }
267
268 void
269 plogresetfile(file)
270 char *file;
271 {
272 /* if log paths equal - do nothing */
273 if (logfile == NULL && file == NULL) {
274 return;
275 }
276 if (logfile != NULL && file != NULL) {
277 if (!strcmp(logfile, file)) {
278 return;
279 }
280 if (logfile_fd != -1) {
281 asl_remove_log_file(logRef, logfile_fd);
282 close(logfile_fd);
283 logfile_fd = -1;
284 }
285 }
286
287 if (logfile) {
288 racoon_free(logfile);
289 logfile = NULL;
290 }
291
292 if (file)
293 plogsetfile(file);
294 }
295
296 int
297 ploggetlevel(void)
298 {
299 return loglevel;
300 }
301
302 void
303 plogsetlevel(int level)
304 {
305 int mask;
306
307 if (level && level >= ASL_LEVEL_EMERG && level <= ASL_LEVEL_DEBUG) {
308 loglevel = level;
309 }
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);
318 }
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