a0a774bfe5299c334df31e0e3d724623eae94b8a
[debian/uanytun.git] / src / log_targets.h
1 /*
2  *  uAnytun
3  *
4  *  uAnytun is a tiny implementation of SATP. Unlike Anytun which is a full
5  *  featured implementation uAnytun has no support for multiple connections
6  *  or synchronisation. It is a small single threaded implementation intended
7  *  to act as a client on small platforms.
8  *  The secure anycast tunneling protocol (satp) defines a protocol used
9  *  for communication between any combination of unicast and anycast
10  *  tunnel endpoints.  It has less protocol overhead than IPSec in Tunnel
11  *  mode and allows tunneling of every ETHER TYPE protocol (e.g.
12  *  ethernet, ip, arp ...). satp directly includes cryptography and
13  *  message authentication based on the methods used by SRTP.  It is
14  *  intended to deliver a generic, scaleable and secure solution for
15  *  tunneling and relaying of packets of any protocol.
16  *
17  *
18  *  Copyright (C) 2007-2014 Christian Pointner <equinox@anytun.org>
19  *
20  *  This file is part of uAnytun.
21  *
22  *  uAnytun is free software: you can redistribute it and/or modify
23  *  it under the terms of the GNU General Public License as published by
24  *  the Free Software Foundation, either version 3 of the License, or
25  *  any later version.
26  *
27  *  uAnytun is distributed in the hope that it will be useful,
28  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
29  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
30  *  GNU General Public License for more details.
31  *
32  *  You should have received a copy of the GNU General Public License
33  *  along with uAnytun. If not, see <http://www.gnu.org/licenses/>.
34  *
35  *  In addition, as a special exception, the copyright holders give
36  *  permission to link the code of portions of this program with the
37  *  OpenSSL library under certain conditions as described in each
38  *  individual source file, and distribute linked combinations
39  *  including the two.
40  *  You must obey the GNU General Public License in all respects
41  *  for all of the code used other than OpenSSL.  If you modify
42  *  file(s) with this exception, you may extend this exception to your
43  *  version of the file(s), but you are not obligated to do so.  If you
44  *  do not wish to do so, delete this exception statement from your
45  *  version.  If you delete this exception statement from all source
46  *  files in the program, then also delete it here.
47  */
48
49 #ifndef UANYTUN_log_targets_h_INCLUDED
50 #define UANYTUN_log_targets_h_INCLUDED
51
52 #include <time.h>
53
54 static char* get_time_formatted()
55 {
56   char* time_string;
57   time_t t = time(NULL);
58   if(t < 0)
59     time_string = "<time read error>";
60   else {
61     time_string = ctime(&t);
62     if(!time_string)
63       time_string = "<time format error>";
64     else {
65       char* newline = strchr(time_string, '\n');
66       if(newline)
67         newline[0] = 0;
68     }
69   }
70   return time_string;
71 }
72
73 enum syslog_facility_enum { USER = LOG_USER, MAIL = LOG_MAIL,
74                             DAEMON = LOG_DAEMON, AUTH = LOG_AUTH,
75                             SYSLOG = LOG_SYSLOG, LPR = LOG_LPR,
76                             NEWS = LOG_NEWS, UUCP = LOG_UUCP,
77                             CRON = LOG_CRON, AUTHPRIV = LOG_AUTHPRIV,
78                             FTP = LOG_FTP, LOCAL0 = LOG_LOCAL0,
79                             LOCAL1 = LOG_LOCAL1, LOCAL2 = LOG_LOCAL2,
80                             LOCAL3 = LOG_LOCAL3, LOCAL4 = LOG_LOCAL4,
81                             LOCAL5 = LOG_LOCAL5, LOCAL6 = LOG_LOCAL6,
82                             LOCAL7 = LOG_LOCAL7 };
83 typedef enum syslog_facility_enum syslog_facility_t;
84
85 struct log_target_syslog_param_struct {
86   char* logname_;
87   syslog_facility_t facility_;
88 };
89 typedef struct log_target_syslog_param_struct log_target_syslog_param_t;
90
91 int log_target_syslog_init(log_target_t* self, const char* conf)
92 {
93   if(!self || (conf && conf[0] == 0))
94     return -1;
95
96   self->param_ = malloc(sizeof(log_target_syslog_param_t));
97   if(!self->param_)
98     return -2;
99
100   char* logname;
101   const char* end = NULL;
102   if(!conf)
103     logname = strdup("uanytun");
104   else {
105     end = strchr(conf, ',');
106     if(end) {
107       size_t len = (size_t)(end - conf);
108       if(!len) {
109         free(self->param_);
110         return -1;
111       }
112       logname = malloc(len+1);
113       if(logname) {
114         strncpy(logname, conf, len);
115         logname[len] = 0;
116       }
117     }
118     else
119       logname = strdup(conf);
120   }
121
122   if(!logname) {
123     free(self->param_);
124     return -2;
125   }
126   ((log_target_syslog_param_t*)(self->param_))->logname_ = logname;
127
128   if(!end) {
129     ((log_target_syslog_param_t*)(self->param_))->facility_ = DAEMON;
130     return 0;
131   }
132
133   if(end[1] == 0 || end[1] == ',') {
134     free(logname);
135     free(self->param_);
136     return -1;
137   }
138
139   const char* start = end + 1;
140   end = strchr(start, ',');
141   int i;
142   for(i=0;;++i) {
143     if(facilitynames[i].c_name == NULL) {
144       free(logname);
145       free(self->param_);
146       return -1;
147     }
148
149     if(( end && !strncmp(start, facilitynames[i].c_name, (size_t)(end - start)) && facilitynames[i].c_name[(size_t)(end-start)] == 0) ||
150        (!end && !strcmp(start, facilitynames[i].c_name))) {
151         ((log_target_syslog_param_t*)(self->param_))->facility_ = facilitynames[i].c_val;
152         break;
153     }
154   }
155
156   return 0;
157 }
158
159 void log_target_syslog_open(log_target_t* self)
160 {
161   if(!self || !self->param_)
162     return;
163
164   openlog(((log_target_syslog_param_t*)(self->param_))->logname_, LOG_PID, ((log_target_syslog_param_t*)(self->param_))->facility_);
165   self->opened_ = 1;
166 }
167
168 void log_target_syslog_log(log_target_t* self, log_prio_t prio, const char* msg)
169 {
170   if(!self || !self->param_ || !self->opened_)
171     return;
172
173   syslog((prio + 2) | ((log_target_syslog_param_t*)(self->param_))->facility_, "%s", msg);
174 }
175
176 void log_target_syslog_close(log_target_t* self)
177 {
178   closelog();
179   self->opened_ = 0;
180 }
181
182 void log_target_syslog_clear(log_target_t* self)
183 {
184   if(!self || !self->param_)
185     return;
186
187   if(((log_target_syslog_param_t*)(self->param_))->logname_)
188     free(((log_target_syslog_param_t*)(self->param_))->logname_);
189
190   free(self->param_);
191 }
192
193 log_target_t* log_target_syslog_new()
194 {
195   log_target_t* tmp = malloc(sizeof(log_target_t));
196   if(!tmp)
197     return NULL;
198
199   tmp->type_ = TARGET_SYSLOG;
200   tmp->init = &log_target_syslog_init;
201   tmp->open = &log_target_syslog_open;
202   tmp->log = &log_target_syslog_log;
203   tmp->close = &log_target_syslog_close;
204   tmp->clear = &log_target_syslog_clear;
205   tmp->opened_ = 0;
206   tmp->enabled_ = 0;
207   tmp->max_prio_ = NOTICE;
208   tmp->param_ = NULL;
209   tmp->next_ = NULL;
210
211   return tmp;
212 }
213
214
215 struct log_target_file_param_struct {
216   char* logfilename_;
217   FILE* file_;
218 };
219 typedef struct log_target_file_param_struct log_target_file_param_t;
220
221 int log_target_file_init(log_target_t* self, const char* conf)
222 {
223   if(!self || (conf && conf[0] == 0))
224     return -1;
225
226   self->param_ = malloc(sizeof(log_target_file_param_t));
227   if(!self->param_)
228     return -2;
229
230   char* logfilename;
231   if(!conf)
232     logfilename = strdup("uanytun.log");
233   else {
234     const char* end = strchr(conf, ',');
235     if(end) {
236       size_t len = (size_t)(end - conf);
237       if(!len) {
238         free(self->param_);
239         return -1;
240       }
241       logfilename = malloc(len+1);
242       if(logfilename) {
243         strncpy(logfilename, conf, len);
244         logfilename[len] = 0;
245       }
246     }
247     else
248       logfilename = strdup(conf);
249   }
250
251   if(!logfilename) {
252     free(self->param_);
253     return -2;
254   }
255   ((log_target_file_param_t*)(self->param_))->logfilename_ = logfilename;
256   ((log_target_file_param_t*)(self->param_))->file_ = NULL;
257
258   return 0;
259 }
260
261 void log_target_file_open(log_target_t* self)
262 {
263   if(!self || !self->param_)
264     return;
265
266   ((log_target_file_param_t*)(self->param_))->file_ = fopen(((log_target_file_param_t*)(self->param_))->logfilename_, "w");
267   if(((log_target_file_param_t*)(self->param_))->file_)
268     self->opened_ = 1;
269 }
270
271 void log_target_file_log(log_target_t* self, log_prio_t prio, const char* msg)
272 {
273   if(!self || !self->param_ || !self->opened_)
274     return;
275
276   fprintf(((log_target_file_param_t*)(self->param_))->file_, "%s %s: %s\n", get_time_formatted(), log_prio_to_string(prio), msg);
277   fflush(((log_target_file_param_t*)(self->param_))->file_);
278 }
279
280 void log_target_file_close(log_target_t* self)
281 {
282   if(!self || !self->param_)
283     return;
284
285   fclose(((log_target_file_param_t*)(self->param_))->file_);
286   self->opened_ = 0;
287 }
288
289 void log_target_file_clear(log_target_t* self)
290 {
291   if(!self || !self->param_)
292     return;
293
294   if(((log_target_file_param_t*)(self->param_))->logfilename_)
295     free(((log_target_file_param_t*)(self->param_))->logfilename_);
296
297   free(self->param_);
298 }
299
300
301 log_target_t* log_target_file_new()
302 {
303   log_target_t* tmp = malloc(sizeof(log_target_t));
304   if(!tmp)
305     return NULL;
306
307   tmp->type_ = TARGET_FILE;
308   tmp->init = &log_target_file_init;
309   tmp->open = &log_target_file_open;
310   tmp->log = &log_target_file_log;
311   tmp->close = &log_target_file_close;
312   tmp->clear = &log_target_file_clear;
313   tmp->opened_ = 0;
314   tmp->enabled_ = 0;
315   tmp->max_prio_ = NOTICE;
316   tmp->param_ = NULL;
317   tmp->next_ = NULL;
318
319   return tmp;
320 }
321
322
323 void log_target_stdout_log(log_target_t* self, log_prio_t prio, const char* msg)
324 {
325   printf("%s %s: %s\n", get_time_formatted(), log_prio_to_string(prio), msg);
326 }
327
328 log_target_t* log_target_stdout_new()
329 {
330   log_target_t* tmp = malloc(sizeof(log_target_t));
331   if(!tmp)
332     return NULL;
333
334   tmp->type_ = TARGET_STDOUT;
335   tmp->init = NULL;
336   tmp->open = NULL;
337   tmp->log = &log_target_stdout_log;
338   tmp->close = NULL;
339   tmp->clear = NULL;
340   tmp->opened_ = 0;
341   tmp->enabled_ = 0;
342   tmp->max_prio_ = NOTICE;
343   tmp->param_ = NULL;
344   tmp->next_ = NULL;
345
346   return tmp;
347 }
348
349
350 void log_target_stderr_log(log_target_t* self, log_prio_t prio, const char* msg)
351 {
352   fprintf(stderr, "%s %s: %s\n", get_time_formatted(), log_prio_to_string(prio), msg);
353 }
354
355 log_target_t* log_target_stderr_new()
356 {
357   log_target_t* tmp = malloc(sizeof(log_target_t));
358   if(!tmp)
359     return NULL;
360
361   tmp->type_ = TARGET_STDERR;
362   tmp->init = NULL;
363   tmp->open = NULL;
364   tmp->log = &log_target_stderr_log;
365   tmp->close = NULL;
366   tmp->clear = NULL;
367   tmp->opened_ = 0;
368   tmp->enabled_ = 0;
369   tmp->max_prio_ = NOTICE;
370   tmp->param_ = NULL;
371   tmp->next_ = NULL;
372
373   return tmp;
374 }
375
376 #endif