1 /*
2 * tcpproxy
3 *
4 * tcpproxy is a simple tcp connection proxy which combines the
5 * features of rinetd and 6tunnel. tcpproxy supports IPv4 and
6 * IPv6 and also supports connections from IPv6 to IPv4
7 * endpoints and vice versa.
8 *
9 *
10 * Copyright (C) 2010-2015 Christian Pointner <equinox@spreadspace.org>
11 *
12 * This file is part of tcpproxy.
13 *
14 * tcpproxy is free software: you can redistribute it and/or modify
15 * it under the terms of the GNU General Public License as published by
16 * the Free Software Foundation, either version 3 of the License, or
17 * any later version.
18 *
19 * tcpproxy is distributed in the hope that it will be useful,
20 * but WITHOUT ANY WARRANTY; without even the implied warranty of
21 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
22 * GNU General Public License for more details.
23 *
24 * You should have received a copy of the GNU General Public License
25 * along with tcpproxy. If not, see <http://www.gnu.org/licenses/>.
26 */
27
28 #ifndef TCPPROXY_log_targets_h_INCLUDED
29 #define TCPPROXY_log_targets_h_INCLUDED
30
31 #include <time.h>
32
get_time_formatted()33 static char* get_time_formatted()
34 {
35 char* time_string;
36 time_t t = time(NULL);
37 if(t < 0)
38 time_string = "<time read error>";
39 else {
40 time_string = ctime(&t);
41 if(!time_string)
42 time_string = "<time format error>";
43 else {
44 char* newline = strchr(time_string, '\n');
45 if(newline)
46 newline[0] = 0;
47 }
48 }
49 return time_string;
50 }
51
52 #ifndef WINVER
53 enum syslog_facility_enum { USER = LOG_USER, MAIL = LOG_MAIL,
54 DAEMON = LOG_DAEMON, AUTH = LOG_AUTH,
55 SYSLOG = LOG_SYSLOG, LPR = LOG_LPR,
56 NEWS = LOG_NEWS, UUCP = LOG_UUCP,
57 CRON = LOG_CRON, AUTHPRIV = LOG_AUTHPRIV,
58 FTP = LOG_FTP, LOCAL0 = LOG_LOCAL0,
59 LOCAL1 = LOG_LOCAL1, LOCAL2 = LOG_LOCAL2,
60 LOCAL3 = LOG_LOCAL3, LOCAL4 = LOG_LOCAL4,
61 LOCAL5 = LOG_LOCAL5, LOCAL6 = LOG_LOCAL6,
62 LOCAL7 = LOG_LOCAL7 };
63 typedef enum syslog_facility_enum syslog_facility_t;
64
65 struct log_target_syslog_param_struct {
66 char* logname_;
67 syslog_facility_t facility_;
68 };
69 typedef struct log_target_syslog_param_struct log_target_syslog_param_t;
70
log_target_syslog_init(log_target_t * self,const char * conf)71 int log_target_syslog_init(log_target_t* self, const char* conf)
72 {
73 if(!self || (conf && conf[0] == 0))
74 return -1;
75
76 self->param_ = malloc(sizeof(log_target_syslog_param_t));
77 if(!self->param_)
78 return -2;
79
80 char* logname;
81 const char* end = NULL;
82 if(!conf)
83 logname = strdup("tcpproxy");
84 else {
85 end = strchr(conf, ',');
86 if(end) {
87 size_t len = (size_t)(end - conf);
88 if(!len) {
89 free(self->param_);
90 return -1;
91 }
92 logname = malloc(len+1);
93 if(logname) {
94 strncpy(logname, conf, len);
95 logname[len] = 0;
96 }
97 }
98 else
99 logname = strdup(conf);
100 }
101
102 if(!logname) {
103 free(self->param_);
104 return -2;
105 }
106 ((log_target_syslog_param_t*)(self->param_))->logname_ = logname;
107
108 if(!end) {
109 ((log_target_syslog_param_t*)(self->param_))->facility_ = DAEMON;
110 return 0;
111 }
112
113 if(end[1] == 0 || end[1] == ',') {
114 free(logname);
115 free(self->param_);
116 return -1;
117 }
118
119 const char* start = end + 1;
120 end = strchr(start, ',');
121 int i;
122 for(i=0;;++i) {
123 if(facilitynames[i].c_name == NULL) {
124 free(logname);
125 free(self->param_);
126 return -1;
127 }
128
129 if(( end && !strncmp(start, facilitynames[i].c_name, (size_t)(end - start)) && facilitynames[i].c_name[(size_t)(end-start)] == 0) ||
130 (!end && !strcmp(start, facilitynames[i].c_name))) {
131 ((log_target_syslog_param_t*)(self->param_))->facility_ = facilitynames[i].c_val;
132 break;
133 }
134 }
135
136 return 0;
137 }
138
log_target_syslog_open(log_target_t * self)139 void log_target_syslog_open(log_target_t* self)
140 {
141 if(!self || !self->param_)
142 return;
143
144 openlog(((log_target_syslog_param_t*)(self->param_))->logname_, LOG_PID, ((log_target_syslog_param_t*)(self->param_))->facility_);
145 self->opened_ = 1;
146 }
147
log_target_syslog_log(log_target_t * self,log_prio_t prio,const char * msg)148 void log_target_syslog_log(log_target_t* self, log_prio_t prio, const char* msg)
149 {
150 if(!self || !self->param_ || !self->opened_)
151 return;
152
153 syslog((prio + 2) | ((log_target_syslog_param_t*)(self->param_))->facility_, "%s", msg);
154 }
155
log_target_syslog_close(log_target_t * self)156 void log_target_syslog_close(log_target_t* self)
157 {
158 closelog();
159 self->opened_ = 0;
160 }
161
log_target_syslog_clear(log_target_t * self)162 void log_target_syslog_clear(log_target_t* self)
163 {
164 if(!self || !self->param_)
165 return;
166
167 if(((log_target_syslog_param_t*)(self->param_))->logname_)
168 free(((log_target_syslog_param_t*)(self->param_))->logname_);
169
170 free(self->param_);
171 }
172
log_target_syslog_new()173 log_target_t* log_target_syslog_new()
174 {
175 log_target_t* tmp = malloc(sizeof(log_target_t));
176 if(!tmp)
177 return NULL;
178
179 tmp->type_ = TARGET_SYSLOG;
180 tmp->init = &log_target_syslog_init;
181 tmp->open = &log_target_syslog_open;
182 tmp->log = &log_target_syslog_log;
183 tmp->close = &log_target_syslog_close;
184 tmp->clear = &log_target_syslog_clear;
185 tmp->opened_ = 0;
186 tmp->enabled_ = 0;
187 tmp->max_prio_ = NOTICE;
188 tmp->param_ = NULL;
189 tmp->next_ = NULL;
190
191 return tmp;
192 }
193 #endif
194
195 struct log_target_file_param_struct {
196 char* logfilename_;
197 FILE* file_;
198 };
199 typedef struct log_target_file_param_struct log_target_file_param_t;
200
log_target_file_init(log_target_t * self,const char * conf)201 int log_target_file_init(log_target_t* self, const char* conf)
202 {
203 if(!self || (conf && conf[0] == 0))
204 return -1;
205
206 self->param_ = malloc(sizeof(log_target_file_param_t));
207 if(!self->param_)
208 return -2;
209
210 char* logfilename;
211 if(!conf)
212 logfilename = strdup("tcpproxy.log");
213 else {
214 const char* end = strchr(conf, ',');
215 if(end) {
216 size_t len = (size_t)(end - conf);
217 if(!len) {
218 free(self->param_);
219 return -1;
220 }
221 logfilename = malloc(len+1);
222 if(logfilename) {
223 strncpy(logfilename, conf, len);
224 logfilename[len] = 0;
225 }
226 }
227 else
228 logfilename = strdup(conf);
229 }
230
231 if(!logfilename) {
232 free(self->param_);
233 return -2;
234 }
235 ((log_target_file_param_t*)(self->param_))->logfilename_ = logfilename;
236 ((log_target_file_param_t*)(self->param_))->file_ = NULL;
237
238 return 0;
239 }
240
log_target_file_open(log_target_t * self)241 void log_target_file_open(log_target_t* self)
242 {
243 if(!self || !self->param_)
244 return;
245
246 ((log_target_file_param_t*)(self->param_))->file_ = fopen(((log_target_file_param_t*)(self->param_))->logfilename_, "w");
247 if(((log_target_file_param_t*)(self->param_))->file_)
248 self->opened_ = 1;
249 }
250
log_target_file_log(log_target_t * self,log_prio_t prio,const char * msg)251 void log_target_file_log(log_target_t* self, log_prio_t prio, const char* msg)
252 {
253 if(!self || !self->param_ || !self->opened_)
254 return;
255
256 fprintf(((log_target_file_param_t*)(self->param_))->file_, "%s %s: %s\n", get_time_formatted(), log_prio_to_string(prio), msg);
257 fflush(((log_target_file_param_t*)(self->param_))->file_);
258 }
259
log_target_file_close(log_target_t * self)260 void log_target_file_close(log_target_t* self)
261 {
262 if(!self || !self->param_)
263 return;
264
265 fclose(((log_target_file_param_t*)(self->param_))->file_);
266 self->opened_ = 0;
267 }
268
log_target_file_clear(log_target_t * self)269 void log_target_file_clear(log_target_t* self)
270 {
271 if(!self || !self->param_)
272 return;
273
274 if(((log_target_file_param_t*)(self->param_))->logfilename_)
275 free(((log_target_file_param_t*)(self->param_))->logfilename_);
276
277 free(self->param_);
278 }
279
280
log_target_file_new()281 log_target_t* log_target_file_new()
282 {
283 log_target_t* tmp = malloc(sizeof(log_target_t));
284 if(!tmp)
285 return NULL;
286
287 tmp->type_ = TARGET_FILE;
288 tmp->init = &log_target_file_init;
289 tmp->open = &log_target_file_open;
290 tmp->log = &log_target_file_log;
291 tmp->close = &log_target_file_close;
292 tmp->clear = &log_target_file_clear;
293 tmp->opened_ = 0;
294 tmp->enabled_ = 0;
295 tmp->max_prio_ = NOTICE;
296 tmp->param_ = NULL;
297 tmp->next_ = NULL;
298
299 return tmp;
300 }
301
302
log_target_stdout_log(log_target_t * self,log_prio_t prio,const char * msg)303 void log_target_stdout_log(log_target_t* self, log_prio_t prio, const char* msg)
304 {
305 printf("%s %s: %s\n", get_time_formatted(), log_prio_to_string(prio), msg);
306 }
307
log_target_stdout_new()308 log_target_t* log_target_stdout_new()
309 {
310 log_target_t* tmp = malloc(sizeof(log_target_t));
311 if(!tmp)
312 return NULL;
313
314 tmp->type_ = TARGET_STDOUT;
315 tmp->init = NULL;
316 tmp->open = NULL;
317 tmp->log = &log_target_stdout_log;
318 tmp->close = NULL;
319 tmp->clear = NULL;
320 tmp->opened_ = 0;
321 tmp->enabled_ = 0;
322 tmp->max_prio_ = NOTICE;
323 tmp->param_ = NULL;
324 tmp->next_ = NULL;
325
326 return tmp;
327 }
328
329
log_target_stderr_log(log_target_t * self,log_prio_t prio,const char * msg)330 void log_target_stderr_log(log_target_t* self, log_prio_t prio, const char* msg)
331 {
332 fprintf(stderr, "%s %s: %s\n", get_time_formatted(), log_prio_to_string(prio), msg);
333 }
334
log_target_stderr_new()335 log_target_t* log_target_stderr_new()
336 {
337 log_target_t* tmp = malloc(sizeof(log_target_t));
338 if(!tmp)
339 return NULL;
340
341 tmp->type_ = TARGET_STDERR;
342 tmp->init = NULL;
343 tmp->open = NULL;
344 tmp->log = &log_target_stderr_log;
345 tmp->close = NULL;
346 tmp->clear = NULL;
347 tmp->opened_ = 0;
348 tmp->enabled_ = 0;
349 tmp->max_prio_ = NOTICE;
350 tmp->param_ = NULL;
351 tmp->next_ = NULL;
352
353 return tmp;
354 }
355
356 #endif
357