Pull fix from branch_1_1, so proxied EAP replies work
[freeradius.git] / src / main / log.c
1 /*
2  * log.c        Logging module.
3  *
4  * Version:     $Id$
5  *
6  *   This program is free software; you can redistribute it and/or modify
7  *   it under the terms of the GNU General Public License as published by
8  *   the Free Software Foundation; either version 2 of the License, or
9  *   (at your option) any later version.
10  *
11  *   This program is distributed in the hope that it will be useful,
12  *   but WITHOUT ANY WARRANTY; without even the implied warranty of
13  *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14  *   GNU General Public License for more details.
15  *
16  *   You should have received a copy of the GNU General Public License
17  *   along with this program; if not, write to the Free Software
18  *   Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
19  *
20  * Copyright 2001,2006  The FreeRADIUS server project
21  * Copyright 2000  Miquel van Smoorenburg <miquels@cistron.nl>
22  * Copyright 2000  Alan DeKok <aland@ox.org>
23  * Copyright 2001  Chad Miller <cmiller@surfsouth.com>
24  */
25
26 #include <freeradius-devel/ident.h>
27 RCSID("$Id$")
28
29 #include <freeradius-devel/autoconf.h>
30
31 #include <stdlib.h>
32 #include <string.h>
33 #include <unistd.h>
34 #include <sys/types.h>
35 #include <errno.h>
36
37 #include <freeradius-devel/radiusd.h>
38
39 #ifdef HAVE_SYSLOG_H
40 #       include <syslog.h>
41 /* keep track of whether we've run openlog() */
42 static int openlog_run = 0;
43 #endif
44
45  /*
46  * Logging facility names
47  */
48 static const LRAD_NAME_NUMBER levels[] = {
49         { ": Debug: ",          L_DBG   },
50         { ": Auth: ",           L_AUTH  },
51         { ": Proxy: ",          L_PROXY },
52         { ": Info: ",           L_INFO  },
53         { ": Error: ",          L_ERR   },
54         { NULL, 0 }
55 };
56
57 /*
58  *      Log the message to the logfile. Include the severity and
59  *      a time stamp.
60  */
61 int vradlog(int lvl, const char *fmt, va_list ap)
62 {
63         int fd = mainconfig.radlog_fd;
64         FILE *fp = NULL;
65         unsigned char *p;
66         char buffer[8192];
67         int len, print_timestamp = 0;
68
69         /*
70          *      NOT debugging, and trying to log debug messages.
71          *
72          *      Throw the message away.
73          */
74         if (!debug_flag && (lvl == L_DBG)) {
75                 return 0;
76         }
77
78         /*
79          *      If we don't want any messages, then
80          *      throw them away.
81          */
82         if (mainconfig.radlog_dest == RADLOG_NULL) {
83                 return 0;
84         }
85         
86         /*
87          *      Don't print timestamps to syslog, it does that for us.
88          *      Don't print timestamps for low levels of debugging.
89          *
90          *      Print timestamps for non-debugging, and for high levels
91          *      of debugging.
92          */
93         if ((mainconfig.radlog_dest != RADLOG_SYSLOG) &&
94             (debug_flag != 1) && (debug_flag != 2)) {
95                 print_timestamp = 1;
96         }
97
98         *buffer = '\0';
99         len = 0;
100         if (fd != -1) {
101                 /*
102                  *      Use it, rather than anything else.
103                  */
104
105 #ifdef HAVE_SYSLOG_H
106         } else if (mainconfig.radlog_dest == RADLOG_SYSLOG) {
107                 /*
108                  *      Open run openlog() on the first log message
109                  */
110                 if(!openlog_run) {
111                         openlog(progname, LOG_PID, mainconfig.syslog_facility);
112                         openlog_run = 1;
113                 }
114 #endif
115
116         } else if (!mainconfig.log_file) {
117                 /*
118                  *      Errors go to stderr, in the hope that they will
119                  *      be printed somewhere.
120                  */
121                 if (lvl & L_ERR) {
122                         fd = STDERR_FILENO;
123                         print_timestamp = 0;
124                         snprintf(buffer, sizeof(buffer), "%s: ", progname);
125                         len = strlen(buffer);
126                 } else {
127                         /*
128                          *      No log file set.  Discard it.
129                          */
130                         return 0;
131                 }
132
133         } else if ((fp = fopen(mainconfig.log_file, "a")) == NULL) {
134                 fprintf(stderr, "%s: Couldn't open %s for logging: %s\n",
135                         progname, mainconfig.log_file, strerror(errno));
136                 
137                 fprintf(stderr, "  (");
138                 vfprintf(stderr, fmt, ap);  /* the message that caused the log */
139                 fprintf(stderr, ")\n");
140                 return -1;
141         }
142
143         if (print_timestamp) {
144                 const char *s;
145                 time_t timeval;
146
147                 timeval = time(NULL);
148                 CTIME_R(&timeval, buffer + len, sizeof(buffer) - len - 1);
149
150                 s = lrad_int2str(levels, (lvl & ~L_CONS), ": ");
151
152                 strcat(buffer, s);
153                 len = strlen(buffer);
154         }
155
156         vsnprintf(buffer + len, sizeof(buffer) - len - 1, fmt, ap);
157
158         /*
159          *      Filter out characters not in Latin-1.
160          */
161         for (p = (unsigned char *)buffer; *p != '\0'; p++) {
162                 if (*p == '\r' || *p == '\n')
163                         *p = ' ';
164                 else if (*p == '\t') continue;
165                 else if (*p < 32 || (*p >= 128 && *p <= 160))
166                         *p = '?';
167         }
168         strcat(buffer, "\n");
169
170 #ifdef HAVE_SYSLOG_H
171         if (mainconfig.radlog_dest == RADLOG_SYSLOG) {
172                 switch(lvl & ~L_CONS) {
173                         case L_DBG:
174                                 lvl = LOG_DEBUG;
175                                 break;
176                         case L_AUTH:
177                                 lvl = LOG_NOTICE;
178                                 break;
179                         case L_PROXY:
180                                 lvl = LOG_NOTICE;
181                                 break;
182                         case L_INFO:
183                                 lvl = LOG_INFO;
184                                 break;
185                         case L_ERR:
186                                 lvl = LOG_ERR;
187                                 break;
188                 }
189                 syslog(lvl, "%s", buffer);
190         } else
191 #endif
192         if (fp != NULL) {
193                 fputs(buffer, fp);
194                 fflush(fp);
195                 fclose(fp);
196         } else if (fd >= 0) {
197                 write(fd, buffer, strlen(buffer));
198         }
199
200         return 0;
201 }
202
203 int log_debug(const char *msg, ...)
204 {
205         va_list ap;
206         int r;
207
208         va_start(ap, msg);
209         r = vradlog(L_DBG, msg, ap);
210         va_end(ap);
211
212         return r;
213 }
214
215 int radlog(int lvl, const char *msg, ...)
216 {
217         va_list ap;
218         int r;
219
220         va_start(ap, msg);
221         r = vradlog(lvl, msg, ap);
222         va_end(ap);
223
224         return r;
225 }
226
227
228 /*
229  *      Dump a whole list of attributes to DEBUG2
230  */
231 void vp_listdebug(VALUE_PAIR *vp)
232 {
233         char tmpPair[70];
234         for (; vp; vp = vp->next) {
235                 vp_prints(tmpPair, sizeof(tmpPair), vp);
236                 DEBUG2("     %s", tmpPair);
237         }
238 }
239
240
241
242