fixes init script for non ipv6 enabled systems #472755
[packages/xinetd.git] / xinetd / log.c
1 /*
2  * (c) Copyright 1992 by Panagiotis Tsirigotis
3  * (c) Sections Copyright 1998-2001 by Rob Braun
4  * All rights reserved.  The file named COPYRIGHT specifies the terms 
5  * and conditions for redistribution.
6  */
7
8 #include "config.h"
9 #include <stdlib.h>
10 #include <sys/types.h>
11 #include <sys/socket.h>
12 #include <sys/wait.h>
13 #include <syslog.h>
14 #include <time.h>
15 #include <stdio.h>
16 #include <stdarg.h>
17 #ifdef HAVE_NETDB_H
18 #include <netdb.h>
19 #endif
20
21 #include "str.h"
22 #include "log.h"
23 #include "sconf.h"
24 #include "sconst.h"
25 #include "msg.h"
26
27
28 #define LOGBUF_SIZE                  1024
29
30 static char ipv6_ret[NI_MAXHOST];
31
32 const char *xaddrname(const union xsockaddr *inaddr)
33 {
34    unsigned int len = 0;
35    if( inaddr->sa.sa_family == AF_INET )  len = sizeof(struct sockaddr_in);
36    if( inaddr->sa.sa_family == AF_INET6 ) len = sizeof(struct sockaddr_in6);
37    memset(ipv6_ret, 0, sizeof(ipv6_ret));
38    if( getnameinfo(&inaddr->sa, len, ipv6_ret, sizeof(ipv6_ret), NULL, 
39          0, NI_NUMERICHOST) )
40       strncpy(ipv6_ret, "<unknown>", NI_MAXHOST);
41    return ipv6_ret;
42 }
43
44 uint16_t xaddrport(const union xsockaddr *inaddr)
45 {
46    if( inaddr->sa.sa_family == AF_INET )  return inaddr->sa_in.sin_port;
47    if( inaddr->sa.sa_family == AF_INET6 ) return inaddr->sa_in6.sin6_port;
48    return 0;
49 }
50
51 static int log_common(mask_t *, char *, int, const connection_s *) ;
52
53 /*
54  * This function writes log records of the form:
55  *
56  *      START: service [pid] [from_address]
57  */
58 void svc_log_success( struct service *sp, const connection_s *cp, pid_t pid )
59 {
60    char                    buf[ LOGBUF_SIZE ] ;
61    int                     bufsize ;
62    struct service_config   *scp = SVC_CONF( sp ) ;
63    int                     len ;
64    int                     cc ;
65
66    if ( ! SVC_LOGS_ON_SUCCESS( sp ) )
67       return ;
68    
69    bufsize = sizeof( buf ) ;
70    len = 0 ;
71    
72    cc = strx_nprint( buf, bufsize, "%s: %s", START_ENTRY, SC_ID( scp ) ) ;
73    len += cc ;
74    bufsize -= cc ;
75
76    if ( SC_LOGS_PID( scp ) )
77    {
78       cc = strx_nprint( &buf[ len ], bufsize, " pid=%d", pid ) ;
79       len += cc ;
80       bufsize -= cc ;
81    }
82
83    cc = log_common( &SC_LOG_ON_SUCCESS( scp ), &buf[len], bufsize, cp ) ;
84    len += cc ;
85    bufsize -= cc ;
86
87    xlog_write( SVC_LOG(sp), buf, len, XLOG_NO_ERRNO ) ;
88 }
89
90
91 /*
92  * This function writes log records of the form:
93  *
94  *      FAIL: service failure-type [from_address]
95  *
96  */
97 void svc_log_failure( struct service *sp, 
98                       const connection_s *cp, 
99                       access_e access_failure )
100 {
101    char                    buf[ LOGBUF_SIZE ] ;
102    int                     bufsize ;
103    struct service_config   *scp = SVC_CONF( sp ) ;
104    int                     len = 0 ;
105    int                     cc ;
106    
107    if ( ! SVC_LOGS_ON_FAILURE( sp ) )
108       return ;
109    
110    bufsize = sizeof( buf ) ;
111    cc = strx_nprint( buf, bufsize, "%s: %s", FAIL_ENTRY, SC_ID( scp ) ) ;
112    len += cc ;
113    bufsize -= cc ;
114
115    cc = strx_nprint( &buf[ len ], bufsize,
116                         " %s", ACCESS_EXPLAIN( access_failure ) ) ;
117    len += cc ;
118    bufsize -= cc ;
119
120    cc = log_common( &SC_LOG_ON_FAILURE( scp ), &buf[ len ], bufsize, cp ) ;
121    len += cc ;
122    bufsize -= cc ;
123
124    xlog_write( SVC_LOG(sp), buf, len, XLOG_NO_ERRNO ) ;
125 }
126
127
128
129 static int log_common( mask_t *logmask, 
130                         char *buf, 
131                         int bufsize, 
132                         const connection_s *cp )
133 {
134    int len = 0 ;
135
136    if ( M_IS_SET( *logmask, LO_HOST ) )
137       len = strx_nprint( buf, bufsize, " from=%s", conn_addrstr( cp ) ) ;
138    return( len ) ;
139 }
140
141
142 void svc_log_exit( struct service *sp, const struct server *serp )
143 {
144    char                    buf[ LOGBUF_SIZE ] ;
145    int                     bufsize ;
146    int                     cc ;
147    int                     len ;
148    int                     exit_status = SERVER_EXITSTATUS( serp ) ;
149    struct service_config   *scp = SVC_CONF( sp ) ;
150    const char                    *func = "log_exit" ;
151
152    if ( ! SVC_LOGS_ON_EXIT( sp ) )
153       return ;
154
155    bufsize = sizeof( buf ) ;
156    len = 0 ;
157
158    cc = strx_nprint( buf, bufsize, "%s: %s", EXIT_ENTRY, SC_ID( scp ) ) ;
159    bufsize -= cc ;
160    len += cc ;
161
162    /*
163     * If the EXIT flag was used, log the exit status or the signal that
164     * killed the process. We assume that these are the only reasons
165     * for process termination.
166     */
167    if ( SC_LOGS_EXITS( scp ) )
168    {
169       int num  = 0;
170       const char *s ;
171
172       if ( PROC_EXITED( exit_status ) )
173       {
174          s = "status" ;
175          num = PROC_EXITSTATUS( exit_status ) ;
176       }
177       else if ( PROC_SIGNALED( exit_status ) )
178       {
179          s = "signal" ;
180          num = PROC_TERMSIG( exit_status ) ;
181       }
182       else
183       {
184          msg( LOG_ERR, func, "Bad exit status" ) ;
185          s = NULL ;
186       }
187
188       if ( s )
189       {
190          cc = strx_nprint( &buf[ len ], bufsize, " %s=%d", s, num ) ;
191          len += cc ;
192          bufsize -= cc ;
193       }
194    }
195
196    if ( SC_LOGS_PID( scp ) )
197    {
198       cc = strx_nprint( &buf[ len ], bufsize, " pid=%d", SERVER_PID( serp ) ) ;
199       len += cc ;
200       bufsize -= cc ;
201    }
202
203    if ( SC_LOGS_DURATION( scp ) )
204    {
205       time_t current_time ;
206
207       (void) time( &current_time ) ;
208       cc = strx_nprint( &buf[ len ], bufsize, " duration=%ld(sec)",
209          (long)(current_time - SERVER_STARTTIME( serp )) ) ;
210       len += cc ;
211       bufsize -= cc ;
212    }
213    xlog_write( SVC_LOG(sp), buf, len, XLOG_NO_ERRNO ) ;
214 }
215
216
217
218 /*
219  * Used by other parts of xinetd that want to log something without
220  * going through the proper channels (i.e. log_{success,failure} and log_exit)
221  */
222 /* VARARGS3 */
223 void svc_logprint( struct service *sp, const char *line_id, 
224                    const char *fmt, ...)
225 {
226    char     buf[ LOGBUF_SIZE ] ;
227    int      bufsize = sizeof( buf ) ;
228    int      len ;
229    int      cc ;
230    va_list  ap ;
231
232    if ( ! SVC_IS_LOGGING( sp ) )
233       return ;
234
235    len = strx_nprint( buf, bufsize, "%s: %s ", line_id, SVC_ID( sp ) ) ;
236    va_start( ap, fmt ) ;
237    cc = strx_nprintv( &buf[ len ], bufsize-len, fmt, ap ) ;
238    va_end( ap ) ;
239    xlog_write( SVC_LOG(sp), buf, len+cc, XLOG_NO_ERRNO | XLOG_NO_SIZECHECK ) ;
240 }
241