1 /***********************************************************************
2 * Copyright (c) 2009, Secure Endpoints Inc.
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
9 * - Redistributions of source code must retain the above copyright
10 * notice, this list of conditions and the following disclaimer.
12 * - Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in
14 * the documentation and/or other materials provided with the
17 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
18 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
19 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
20 * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
21 * COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
22 * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
23 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
24 * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
25 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
26 * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
27 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
28 * OF THE POSSIBILITY OF SUCH DAMAGE.
30 **********************************************************************/
33 * Based on code by Alexander Yaworsky
42 #define SYSLOG_DGRAM_SIZE 1024
44 static BOOL syslog_opened
= FALSE
;
46 static int syslog_mask
= 0xFF;
47 static char syslog_ident
[ 128 ] = "";
48 static int syslog_facility
= LOG_USER
;
49 static char syslog_procid_str
[ 20 ];
51 static SOCKADDR_IN syslog_hostaddr
;
52 static SOCKET syslog_socket
= INVALID_SOCKET
;
53 static char local_hostname
[ MAX_COMPUTERNAME_LENGTH
+ 1 ];
55 static char syslog_hostname
[ MAX_COMPUTERNAME_LENGTH
+ 1 ] = "localhost";
56 static unsigned short syslog_port
= SYSLOG_PORT
;
58 static int datagramm_size
;
60 volatile BOOL initialized
= FALSE
;
61 BOOL wsa_initialized
= FALSE
;
62 CRITICAL_SECTION cs_syslog
;
64 ROKEN_LIB_FUNCTION
void ROKEN_LIB_CALL
65 init_syslog(const char * hostname
)
73 if( WSAStartup( MAKEWORD( 2, 2 ), &wsd
) ) {
74 fprintf(stderr
, "Can't initialize WinSock\n");
75 /* we let the rest of the initialization code go through,
76 although none of the syslog calls would succeed. */
78 wsa_initialized
= TRUE
;
82 strcpy_s(syslog_hostname
, sizeof(syslog_hostname
), hostname
);
84 strcpy_s(syslog_hostname
, sizeof(syslog_hostname
), "");
86 service
= strchr(syslog_hostname
, ':');
93 if ((tp
= atoi(service
)) <= 0) {
96 se
= getservbyname(service
, "udp");
98 syslog_port
= (se
== NULL
)? SYSLOG_PORT
: se
->s_port
;
100 syslog_port
= (unsigned short) tp
;
103 syslog_port
= SYSLOG_PORT
;
106 InitializeCriticalSection(&cs_syslog
);
112 ROKEN_LIB_FUNCTION
void ROKEN_LIB_CALL
120 if ( wsa_initialized
)
123 DeleteCriticalSection(&cs_syslog
);
127 static void init_logger_addr()
129 struct hostent
* phe
= NULL
;
131 memset( &syslog_hostaddr
, 0, sizeof(SOCKADDR_IN
) );
132 syslog_hostaddr
.sin_family
= AF_INET
;
134 if (syslog_hostname
[0] == '\0')
137 phe
= gethostbyname( syslog_hostname
);
141 memcpy( &syslog_hostaddr
.sin_addr
.s_addr
, phe
->h_addr
, phe
->h_length
);
143 syslog_hostaddr
.sin_port
= htons( syslog_port
);
147 syslog_hostaddr
.sin_addr
.S_un
.S_addr
= htonl( 0x7F000001 );
148 syslog_hostaddr
.sin_port
= htons( SYSLOG_PORT
);
151 /******************************************************************************
154 * Close desriptor used to write to system logger.
156 ROKEN_LIB_FUNCTION
void ROKEN_LIB_CALL
162 EnterCriticalSection(&cs_syslog
);
163 if( syslog_opened
) {
164 closesocket( syslog_socket
);
165 syslog_socket
= INVALID_SOCKET
;
166 syslog_opened
= FALSE
;
168 LeaveCriticalSection(&cs_syslog
);
171 /******************************************************************************
174 * Open connection to system logger.
176 ROKEN_LIB_FUNCTION
void ROKEN_LIB_CALL
177 openlog( char* ident
, int option
, int facility
)
180 SOCKADDR_IN sa_local
;
187 EnterCriticalSection(&cs_syslog
);
194 syslog_facility
= facility
? facility
: LOG_USER
;
196 if( option
& LOG_PID
)
197 sprintf_s( syslog_procid_str
, sizeof(syslog_procid_str
), "[%lu]", GetCurrentProcessId() );
199 syslog_procid_str
[0] = '\0';
201 /* FIXME: handle other options */
203 n
= sizeof(local_hostname
);
204 if( !GetComputerName( local_hostname
, &n
) )
207 syslog_socket
= INVALID_SOCKET
;
213 syslog_socket
= socket( AF_INET
, SOCK_DGRAM
, 0 );
214 if( INVALID_SOCKET
== syslog_socket
)
217 memset( &sa_local
, 0, sizeof(SOCKADDR_IN
) );
218 sa_local
.sin_family
= AF_INET
;
219 if( bind( syslog_socket
, (SOCKADDR
*) &sa_local
, sizeof(SOCKADDR_IN
) ) == 0 )
221 rk_closesocket( syslog_socket
);
222 syslog_socket
= INVALID_SOCKET
;
228 /* get size of datagramm */
229 size
= sizeof(datagramm_size
);
230 if( getsockopt( syslog_socket
, SOL_SOCKET
, SO_MAX_MSG_SIZE
, (char*) &datagramm_size
, &size
) )
232 if( datagramm_size
- strlen(local_hostname
) - (ident
? strlen(ident
) : 0) < 64 )
234 if( datagramm_size
> SYSLOG_DGRAM_SIZE
)
235 datagramm_size
= SYSLOG_DGRAM_SIZE
;
238 strcpy_s(syslog_ident
, sizeof(syslog_ident
), ident
);
240 syslog_facility
= (facility
? facility
: LOG_USER
);
245 if( syslog_socket
!= INVALID_SOCKET
)
246 rk_closesocket( syslog_socket
);
248 syslog_opened
= !failed
;
250 LeaveCriticalSection(&cs_syslog
);
253 /******************************************************************************
256 * Set the log mask level.
258 ROKEN_LIB_FUNCTION
int ROKEN_LIB_CALL
259 setlogmask( int mask
)
266 EnterCriticalSection(&cs_syslog
);
272 LeaveCriticalSection(&cs_syslog
);
277 /******************************************************************************
280 * Generate a log message using FMT string and option arguments.
282 ROKEN_LIB_FUNCTION
void
283 syslog( int pri
, char* fmt
, ... )
288 vsyslog( pri
, fmt
, ap
);
292 /******************************************************************************
295 * Generate a log message using FMT and using arguments pointed to by AP.
297 ROKEN_LIB_FUNCTION
void ROKEN_LIB_CALL
298 vsyslog( int pri
, char* fmt
, va_list ap
)
300 static char *month
[] = {"Jan", "Feb", "Mar", "Apr", "May", "Jun",
301 "Jul", "Aug", "Sep", "Oct", "Nov", "Dec" };
302 char datagramm
[ SYSLOG_DGRAM_SIZE
];
310 EnterCriticalSection(&cs_syslog
);
312 if( !(LOG_MASK( LOG_PRI( pri
)) & syslog_mask
) )
315 openlog( NULL
, 0, pri
& LOG_FACMASK
);
319 if( !(pri
& LOG_FACMASK
) )
320 pri
|= syslog_facility
;
322 GetLocalTime( &stm
);
323 len
= sprintf_s( datagramm
, sizeof(datagramm
),
324 "<%d>%s %2d %02d:%02d:%02d %s %s%s: ",
326 month
[ stm
.wMonth
- 1 ], stm
.wDay
, stm
.wHour
, stm
.wMinute
, stm
.wSecond
,
327 local_hostname
, syslog_ident
, syslog_procid_str
);
328 vsprintf_s( datagramm
+ len
, datagramm_size
- len
, fmt
, ap
);
329 p
= strchr( datagramm
, '\n' );
332 p
= strchr( datagramm
, '\r' );
336 sendto( syslog_socket
, datagramm
, strlen(datagramm
), 0, (SOCKADDR
*) &syslog_hostaddr
, sizeof(SOCKADDR_IN
) );
339 LeaveCriticalSection(&cs_syslog
);