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
40 #define SYSLOG_DGRAM_SIZE 1024
42 static BOOL syslog_opened
= FALSE
;
44 static int syslog_mask
= 0xFF;
45 static char syslog_ident
[ 128 ] = "";
46 static int syslog_facility
= LOG_USER
;
47 static char syslog_procid_str
[ 20 ];
49 static SOCKADDR_IN syslog_hostaddr
;
50 static SOCKET syslog_socket
= INVALID_SOCKET
;
51 static char local_hostname
[ MAX_COMPUTERNAME_LENGTH
+ 1 ];
53 static char syslog_hostname
[ MAX_COMPUTERNAME_LENGTH
+ 1 ] = "localhost";
54 static unsigned short syslog_port
= SYSLOG_PORT
;
56 static int datagramm_size
;
58 volatile BOOL initialized
= FALSE
;
59 BOOL wsa_initialized
= FALSE
;
60 CRITICAL_SECTION cs_syslog
;
62 ROKEN_LIB_FUNCTION
void ROKEN_LIB_CALL
63 init_syslog(const char * hostname
)
71 if( WSAStartup( MAKEWORD( 2, 2 ), &wsd
) ) {
72 fprintf(stderr
, "Can't initialize WinSock\n");
73 /* we let the rest of the initialization code go through,
74 although none of the syslog calls would succeed. */
76 wsa_initialized
= TRUE
;
80 strcpy_s(syslog_hostname
, sizeof(syslog_hostname
), hostname
);
82 strcpy_s(syslog_hostname
, sizeof(syslog_hostname
), "");
84 service
= strchr(syslog_hostname
, ':');
91 if ((tp
= atoi(service
)) <= 0) {
94 se
= getservbyname(service
, "udp");
96 syslog_port
= (se
== NULL
)? SYSLOG_PORT
: se
->s_port
;
98 syslog_port
= (unsigned short) tp
;
101 syslog_port
= SYSLOG_PORT
;
104 InitializeCriticalSection(&cs_syslog
);
110 ROKEN_LIB_FUNCTION
void ROKEN_LIB_CALL
118 if ( wsa_initialized
)
121 DeleteCriticalSection(&cs_syslog
);
125 static void init_logger_addr()
127 struct hostent
* phe
= NULL
;
129 memset( &syslog_hostaddr
, 0, sizeof(SOCKADDR_IN
) );
130 syslog_hostaddr
.sin_family
= AF_INET
;
132 if (syslog_hostname
[0] == '\0')
135 phe
= gethostbyname( syslog_hostname
);
139 memcpy( &syslog_hostaddr
.sin_addr
.s_addr
, phe
->h_addr
, phe
->h_length
);
141 syslog_hostaddr
.sin_port
= htons( syslog_port
);
145 syslog_hostaddr
.sin_addr
.S_un
.S_addr
= htonl( 0x7F000001 );
146 syslog_hostaddr
.sin_port
= htons( SYSLOG_PORT
);
149 /******************************************************************************
152 * Close desriptor used to write to system logger.
154 ROKEN_LIB_FUNCTION
void ROKEN_LIB_CALL
160 EnterCriticalSection(&cs_syslog
);
161 if( syslog_opened
) {
162 closesocket( syslog_socket
);
163 syslog_socket
= INVALID_SOCKET
;
164 syslog_opened
= FALSE
;
166 LeaveCriticalSection(&cs_syslog
);
169 /******************************************************************************
172 * Open connection to system logger.
174 ROKEN_LIB_FUNCTION
void ROKEN_LIB_CALL
175 openlog( char* ident
, int option
, int facility
)
178 SOCKADDR_IN sa_local
;
185 EnterCriticalSection(&cs_syslog
);
192 syslog_facility
= facility
? facility
: LOG_USER
;
194 if( option
& LOG_PID
)
195 sprintf_s( syslog_procid_str
, sizeof(syslog_procid_str
), "[%lu]", GetCurrentProcessId() );
197 syslog_procid_str
[0] = '\0';
199 /* FIXME: handle other options */
201 n
= sizeof(local_hostname
);
202 if( !GetComputerName( local_hostname
, &n
) )
205 syslog_socket
= INVALID_SOCKET
;
211 syslog_socket
= socket( AF_INET
, SOCK_DGRAM
, 0 );
212 if( INVALID_SOCKET
== syslog_socket
)
215 memset( &sa_local
, 0, sizeof(SOCKADDR_IN
) );
216 sa_local
.sin_family
= AF_INET
;
217 if( bind( syslog_socket
, (SOCKADDR
*) &sa_local
, sizeof(SOCKADDR_IN
) ) == 0 )
219 rk_closesocket( syslog_socket
);
220 syslog_socket
= INVALID_SOCKET
;
226 /* get size of datagramm */
227 size
= sizeof(datagramm_size
);
228 if( getsockopt( syslog_socket
, SOL_SOCKET
, SO_MAX_MSG_SIZE
, (char*) &datagramm_size
, &size
) )
230 if( datagramm_size
- strlen(local_hostname
) - (ident
? strlen(ident
) : 0) < 64 )
232 if( datagramm_size
> SYSLOG_DGRAM_SIZE
)
233 datagramm_size
= SYSLOG_DGRAM_SIZE
;
236 strcpy_s(syslog_ident
, sizeof(syslog_ident
), ident
);
238 syslog_facility
= (facility
? facility
: LOG_USER
);
243 if( syslog_socket
!= INVALID_SOCKET
)
244 rk_closesocket( syslog_socket
);
246 syslog_opened
= !failed
;
248 LeaveCriticalSection(&cs_syslog
);
251 /******************************************************************************
254 * Set the log mask level.
256 ROKEN_LIB_FUNCTION
int ROKEN_LIB_CALL
257 setlogmask( int mask
)
264 EnterCriticalSection(&cs_syslog
);
270 LeaveCriticalSection(&cs_syslog
);
275 /******************************************************************************
278 * Generate a log message using FMT string and option arguments.
280 ROKEN_LIB_FUNCTION
void
281 syslog( int pri
, char* fmt
, ... )
286 vsyslog( pri
, fmt
, ap
);
290 /******************************************************************************
293 * Generate a log message using FMT and using arguments pointed to by AP.
295 ROKEN_LIB_FUNCTION
void ROKEN_LIB_CALL
296 vsyslog( int pri
, char* fmt
, va_list ap
)
298 static char *month
[] = {"Jan", "Feb", "Mar", "Apr", "May", "Jun",
299 "Jul", "Aug", "Sep", "Oct", "Nov", "Dec" };
300 char datagramm
[ SYSLOG_DGRAM_SIZE
];
308 EnterCriticalSection(&cs_syslog
);
310 if( !(LOG_MASK( LOG_PRI( pri
)) & syslog_mask
) )
313 openlog( NULL
, 0, pri
& LOG_FACMASK
);
317 if( !(pri
& LOG_FACMASK
) )
318 pri
|= syslog_facility
;
320 GetLocalTime( &stm
);
321 len
= sprintf_s( datagramm
, sizeof(datagramm
),
322 "<%d>%s %2d %02d:%02d:%02d %s %s%s: ",
324 month
[ stm
.wMonth
- 1 ], stm
.wDay
, stm
.wHour
, stm
.wMinute
, stm
.wSecond
,
325 local_hostname
, syslog_ident
, syslog_procid_str
);
326 vsprintf_s( datagramm
+ len
, datagramm_size
- len
, fmt
, ap
);
327 p
= strchr( datagramm
, '\n' );
330 p
= strchr( datagramm
, '\r' );
334 sendto( syslog_socket
, datagramm
, strlen(datagramm
), 0, (SOCKADDR
*) &syslog_hostaddr
, sizeof(SOCKADDR_IN
) );
337 LeaveCriticalSection(&cs_syslog
);