1e18a033bSKonstantin Ananyev
2e18a033bSKonstantin Ananyev/*
3e18a033bSKonstantin Ananyev * Copyright (C) Nginx, Inc.
4e18a033bSKonstantin Ananyev */
5e18a033bSKonstantin Ananyev
6e18a033bSKonstantin Ananyev
7e18a033bSKonstantin Ananyev#include <ngx_config.h>
8e18a033bSKonstantin Ananyev#include <ngx_core.h>
9e18a033bSKonstantin Ananyev#include <ngx_event.h>
10e18a033bSKonstantin Ananyev
11e18a033bSKonstantin Ananyev
12e18a033bSKonstantin Ananyev#define NGX_SYSLOG_MAX_STR                                                    \
13e18a033bSKonstantin Ananyev    NGX_MAX_ERROR_STR + sizeof("<255>Jan 01 00:00:00 ") - 1                   \
14e18a033bSKonstantin Ananyev    + (NGX_MAXHOSTNAMELEN - 1) + 1 /* space */                                \
15e18a033bSKonstantin Ananyev    + 32 /* tag */ + 2 /* colon, space */
16e18a033bSKonstantin Ananyev
17e18a033bSKonstantin Ananyev
18e18a033bSKonstantin Ananyevstatic char *ngx_syslog_parse_args(ngx_conf_t *cf, ngx_syslog_peer_t *peer);
19e18a033bSKonstantin Ananyevstatic ngx_int_t ngx_syslog_init_peer(ngx_syslog_peer_t *peer);
20e18a033bSKonstantin Ananyevstatic void ngx_syslog_cleanup(void *data);
21e18a033bSKonstantin Ananyev
22e18a033bSKonstantin Ananyev
23e18a033bSKonstantin Ananyevstatic char  *facilities[] = {
24e18a033bSKonstantin Ananyev    "kern", "user", "mail", "daemon", "auth", "intern", "lpr", "news", "uucp",
25e18a033bSKonstantin Ananyev    "clock", "authpriv", "ftp", "ntp", "audit", "alert", "cron", "local0",
26e18a033bSKonstantin Ananyev    "local1", "local2", "local3", "local4", "local5", "local6", "local7",
27e18a033bSKonstantin Ananyev    NULL
28e18a033bSKonstantin Ananyev};
29e18a033bSKonstantin Ananyev
30e18a033bSKonstantin Ananyev/* note 'error/warn' like in nginx.conf, not 'err/warning' */
31e18a033bSKonstantin Ananyevstatic char  *severities[] = {
32e18a033bSKonstantin Ananyev    "emerg", "alert", "crit", "error", "warn", "notice", "info", "debug", NULL
33e18a033bSKonstantin Ananyev};
34e18a033bSKonstantin Ananyev
35e18a033bSKonstantin Ananyevstatic ngx_log_t    ngx_syslog_dummy_log;
36e18a033bSKonstantin Ananyevstatic ngx_event_t  ngx_syslog_dummy_event;
37e18a033bSKonstantin Ananyev
38e18a033bSKonstantin Ananyev
39e18a033bSKonstantin Ananyevchar *
40e18a033bSKonstantin Ananyevngx_syslog_process_conf(ngx_conf_t *cf, ngx_syslog_peer_t *peer)
41e18a033bSKonstantin Ananyev{
42e18a033bSKonstantin Ananyev    peer->pool = cf->pool;
43e18a033bSKonstantin Ananyev    peer->facility = NGX_CONF_UNSET_UINT;
44e18a033bSKonstantin Ananyev    peer->severity = NGX_CONF_UNSET_UINT;
45e18a033bSKonstantin Ananyev
46e18a033bSKonstantin Ananyev    if (ngx_syslog_parse_args(cf, peer) != NGX_CONF_OK) {
47e18a033bSKonstantin Ananyev        return NGX_CONF_ERROR;
48e18a033bSKonstantin Ananyev    }
49e18a033bSKonstantin Ananyev
50e18a033bSKonstantin Ananyev    if (peer->server.sockaddr == NULL) {
51e18a033bSKonstantin Ananyev        ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
52e18a033bSKonstantin Ananyev                           "no syslog server specified");
53e18a033bSKonstantin Ananyev        return NGX_CONF_ERROR;
54e18a033bSKonstantin Ananyev    }
55e18a033bSKonstantin Ananyev
56e18a033bSKonstantin Ananyev    if (peer->facility == NGX_CONF_UNSET_UINT) {
57e18a033bSKonstantin Ananyev        peer->facility = 23; /* local7 */
58e18a033bSKonstantin Ananyev    }
59e18a033bSKonstantin Ananyev
60e18a033bSKonstantin Ananyev    if (peer->severity == NGX_CONF_UNSET_UINT) {
61e18a033bSKonstantin Ananyev        peer->severity = 6; /* info */
62e18a033bSKonstantin Ananyev    }
63e18a033bSKonstantin Ananyev
64e18a033bSKonstantin Ananyev    if (peer->tag.data == NULL) {
65e18a033bSKonstantin Ananyev        ngx_str_set(&peer->tag, "nginx");
66e18a033bSKonstantin Ananyev    }
67e18a033bSKonstantin Ananyev
68e18a033bSKonstantin Ananyev    peer->conn.fd = (ngx_socket_t) -1;
69e18a033bSKonstantin Ananyev
70e18a033bSKonstantin Ananyev    return NGX_CONF_OK;
71e18a033bSKonstantin Ananyev}
72e18a033bSKonstantin Ananyev
73e18a033bSKonstantin Ananyev
74e18a033bSKonstantin Ananyevstatic char *
75e18a033bSKonstantin Ananyevngx_syslog_parse_args(ngx_conf_t *cf, ngx_syslog_peer_t *peer)
76e18a033bSKonstantin Ananyev{
77e18a033bSKonstantin Ananyev    u_char      *p, *comma, c;
78e18a033bSKonstantin Ananyev    size_t       len;
79e18a033bSKonstantin Ananyev    ngx_str_t   *value;
80e18a033bSKonstantin Ananyev    ngx_url_t    u;
81e18a033bSKonstantin Ananyev    ngx_uint_t   i;
82e18a033bSKonstantin Ananyev
83e18a033bSKonstantin Ananyev    value = cf->args->elts;
84e18a033bSKonstantin Ananyev
85e18a033bSKonstantin Ananyev    p = value[1].data + sizeof("syslog:") - 1;
86e18a033bSKonstantin Ananyev
87e18a033bSKonstantin Ananyev    for ( ;; ) {
88e18a033bSKonstantin Ananyev        comma = (u_char *) ngx_strchr(p, ',');
89e18a033bSKonstantin Ananyev
90e18a033bSKonstantin Ananyev        if (comma != NULL) {
91e18a033bSKonstantin Ananyev            len = comma - p;
92e18a033bSKonstantin Ananyev            *comma = '\0';
93e18a033bSKonstantin Ananyev
94e18a033bSKonstantin Ananyev        } else {
95e18a033bSKonstantin Ananyev            len = value[1].data + value[1].len - p;
96e18a033bSKonstantin Ananyev        }
97e18a033bSKonstantin Ananyev
98e18a033bSKonstantin Ananyev        if (ngx_strncmp(p, "server=", 7) == 0) {
99e18a033bSKonstantin Ananyev
100e18a033bSKonstantin Ananyev            if (peer->server.sockaddr != NULL) {
101e18a033bSKonstantin Ananyev                ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
102e18a033bSKonstantin Ananyev                                   "duplicate syslog \"server\"");
103e18a033bSKonstantin Ananyev                return NGX_CONF_ERROR;
104e18a033bSKonstantin Ananyev            }
105e18a033bSKonstantin Ananyev
106e18a033bSKonstantin Ananyev            ngx_memzero(&u, sizeof(ngx_url_t));
107e18a033bSKonstantin Ananyev
108e18a033bSKonstantin Ananyev            u.url.data = p + 7;
109e18a033bSKonstantin Ananyev            u.url.len = len - 7;
110e18a033bSKonstantin Ananyev            u.default_port = 514;
111e18a033bSKonstantin Ananyev
112e18a033bSKonstantin Ananyev            if (ngx_parse_url(cf->pool, &u) != NGX_OK) {
113e18a033bSKonstantin Ananyev                if (u.err) {
114e18a033bSKonstantin Ananyev                    ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
115e18a033bSKonstantin Ananyev                                       "%s in syslog server \"%V\"",
116e18a033bSKonstantin Ananyev                                       u.err, &u.url);
117e18a033bSKonstantin Ananyev                }
118e18a033bSKonstantin Ananyev
119e18a033bSKonstantin Ananyev                return NGX_CONF_ERROR;
120e18a033bSKonstantin Ananyev            }
121e18a033bSKonstantin Ananyev
122e18a033bSKonstantin Ananyev            peer->server = u.addrs[0];
123e18a033bSKonstantin Ananyev
124e18a033bSKonstantin Ananyev        } else if (ngx_strncmp(p, "facility=", 9) == 0) {
125e18a033bSKonstantin Ananyev
126e18a033bSKonstantin Ananyev            if (peer->facility != NGX_CONF_UNSET_UINT) {
127e18a033bSKonstantin Ananyev                ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
128e18a033bSKonstantin Ananyev                                   "duplicate syslog \"facility\"");
129e18a033bSKonstantin Ananyev                return NGX_CONF_ERROR;
130e18a033bSKonstantin Ananyev            }
131e18a033bSKonstantin Ananyev
132e18a033bSKonstantin Ananyev            for (i = 0; facilities[i] != NULL; i++) {
133e18a033bSKonstantin Ananyev
134e18a033bSKonstantin Ananyev                if (ngx_strcmp(p + 9, facilities[i]) == 0) {
135e18a033bSKonstantin Ananyev                    peer->facility = i;
136e18a033bSKonstantin Ananyev                    goto next;
137e18a033bSKonstantin Ananyev                }
138e18a033bSKonstantin Ananyev            }
139e18a033bSKonstantin Ananyev
140e18a033bSKonstantin Ananyev            ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
141e18a033bSKonstantin Ananyev                               "unknown syslog facility \"%s\"", p + 9);
142e18a033bSKonstantin Ananyev            return NGX_CONF_ERROR;
143e18a033bSKonstantin Ananyev
144e18a033bSKonstantin Ananyev        } else if (ngx_strncmp(p, "severity=", 9) == 0) {
145e18a033bSKonstantin Ananyev
146e18a033bSKonstantin Ananyev            if (peer->severity != NGX_CONF_UNSET_UINT) {
147e18a033bSKonstantin Ananyev                ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
148e18a033bSKonstantin Ananyev                                   "duplicate syslog \"severity\"");
149e18a033bSKonstantin Ananyev                return NGX_CONF_ERROR;
150e18a033bSKonstantin Ananyev            }
151e18a033bSKonstantin Ananyev
152e18a033bSKonstantin Ananyev            for (i = 0; severities[i] != NULL; i++) {
153e18a033bSKonstantin Ananyev
154e18a033bSKonstantin Ananyev                if (ngx_strcmp(p + 9, severities[i]) == 0) {
155e18a033bSKonstantin Ananyev                    peer->severity = i;
156e18a033bSKonstantin Ananyev                    goto next;
157e18a033bSKonstantin Ananyev                }
158e18a033bSKonstantin Ananyev            }
159e18a033bSKonstantin Ananyev
160e18a033bSKonstantin Ananyev            ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
161e18a033bSKonstantin Ananyev                               "unknown syslog severity \"%s\"", p + 9);
162e18a033bSKonstantin Ananyev            return NGX_CONF_ERROR;
163e18a033bSKonstantin Ananyev
164e18a033bSKonstantin Ananyev        } else if (ngx_strncmp(p, "tag=", 4) == 0) {
165e18a033bSKonstantin Ananyev
166e18a033bSKonstantin Ananyev            if (peer->tag.data != NULL) {
167e18a033bSKonstantin Ananyev                ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
168e18a033bSKonstantin Ananyev                                   "duplicate syslog \"tag\"");
169e18a033bSKonstantin Ananyev                return NGX_CONF_ERROR;
170e18a033bSKonstantin Ananyev            }
171e18a033bSKonstantin Ananyev
172e18a033bSKonstantin Ananyev            /*
173e18a033bSKonstantin Ananyev             * RFC 3164: the TAG is a string of ABNF alphanumeric characters
174e18a033bSKonstantin Ananyev             * that MUST NOT exceed 32 characters.
175e18a033bSKonstantin Ananyev             */
176e18a033bSKonstantin Ananyev            if (len - 4 > 32) {
177e18a033bSKonstantin Ananyev                ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
178e18a033bSKonstantin Ananyev                                   "syslog tag length exceeds 32");
179e18a033bSKonstantin Ananyev                return NGX_CONF_ERROR;
180e18a033bSKonstantin Ananyev            }
181e18a033bSKonstantin Ananyev
182e18a033bSKonstantin Ananyev            for (i = 4; i < len; i++) {
183e18a033bSKonstantin Ananyev                c = ngx_tolower(p[i]);
184e18a033bSKonstantin Ananyev
185e18a033bSKonstantin Ananyev                if (c < '0' || (c > '9' && c < 'a' && c != '_') || c > 'z') {
186e18a033bSKonstantin Ananyev                    ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
187e18a033bSKonstantin Ananyev                                       "syslog \"tag\" only allows "
188e18a033bSKonstantin Ananyev                                       "alphanumeric characters "
189e18a033bSKonstantin Ananyev                                       "and underscore");
190e18a033bSKonstantin Ananyev                    return NGX_CONF_ERROR;
191e18a033bSKonstantin Ananyev                }
192e18a033bSKonstantin Ananyev            }
193e18a033bSKonstantin Ananyev
194e18a033bSKonstantin Ananyev            peer->tag.data = p + 4;
195e18a033bSKonstantin Ananyev            peer->tag.len = len - 4;
196e18a033bSKonstantin Ananyev
197e18a033bSKonstantin Ananyev        } else if (len == 10 && ngx_strncmp(p, "nohostname", 10) == 0) {
198e18a033bSKonstantin Ananyev            peer->nohostname = 1;
199e18a033bSKonstantin Ananyev
200e18a033bSKonstantin Ananyev        } else {
201e18a033bSKonstantin Ananyev            ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
202e18a033bSKonstantin Ananyev                               "unknown syslog parameter \"%s\"", p);
203e18a033bSKonstantin Ananyev            return NGX_CONF_ERROR;
204e18a033bSKonstantin Ananyev        }
205e18a033bSKonstantin Ananyev
206e18a033bSKonstantin Ananyev    next:
207e18a033bSKonstantin Ananyev
208e18a033bSKonstantin Ananyev        if (comma == NULL) {
209e18a033bSKonstantin Ananyev            break;
210e18a033bSKonstantin Ananyev        }
211e18a033bSKonstantin Ananyev
212e18a033bSKonstantin Ananyev        p = comma + 1;
213e18a033bSKonstantin Ananyev    }
214e18a033bSKonstantin Ananyev
215e18a033bSKonstantin Ananyev    return NGX_CONF_OK;
216e18a033bSKonstantin Ananyev}
217e18a033bSKonstantin Ananyev
218e18a033bSKonstantin Ananyev
219e18a033bSKonstantin Ananyevu_char *
220e18a033bSKonstantin Ananyevngx_syslog_add_header(ngx_syslog_peer_t *peer, u_char *buf)
221e18a033bSKonstantin Ananyev{
222e18a033bSKonstantin Ananyev    ngx_uint_t  pri;
223e18a033bSKonstantin Ananyev
224e18a033bSKonstantin Ananyev    pri = peer->facility * 8 + peer->severity;
225e18a033bSKonstantin Ananyev
226e18a033bSKonstantin Ananyev    if (peer->nohostname) {
227e18a033bSKonstantin Ananyev        return ngx_sprintf(buf, "<%ui>%V %V: ", pri, &ngx_cached_syslog_time,
228e18a033bSKonstantin Ananyev                           &peer->tag);
229e18a033bSKonstantin Ananyev    }
230e18a033bSKonstantin Ananyev
231e18a033bSKonstantin Ananyev    return ngx_sprintf(buf, "<%ui>%V %V %V: ", pri, &ngx_cached_syslog_time,
232e18a033bSKonstantin Ananyev                       &ngx_cycle->hostname, &peer->tag);
233e18a033bSKonstantin Ananyev}
234e18a033bSKonstantin Ananyev
235e18a033bSKonstantin Ananyev
236e18a033bSKonstantin Ananyevvoid
237e18a033bSKonstantin Ananyevngx_syslog_writer(ngx_log_t *log, ngx_uint_t level, u_char *buf,
238e18a033bSKonstantin Ananyev    size_t len)
239e18a033bSKonstantin Ananyev{
240e18a033bSKonstantin Ananyev    u_char             *p, msg[NGX_SYSLOG_MAX_STR];
241e18a033bSKonstantin Ananyev    ngx_uint_t          head_len;
242e18a033bSKonstantin Ananyev    ngx_syslog_peer_t  *peer;
243e18a033bSKonstantin Ananyev
244e18a033bSKonstantin Ananyev    peer = log->wdata;
245e18a033bSKonstantin Ananyev
246e18a033bSKonstantin Ananyev    if (peer->busy) {
247e18a033bSKonstantin Ananyev        return;
248e18a033bSKonstantin Ananyev    }
249e18a033bSKonstantin Ananyev
250e18a033bSKonstantin Ananyev    peer->busy = 1;
251e18a033bSKonstantin Ananyev    peer->severity = level - 1;
252e18a033bSKonstantin Ananyev
253e18a033bSKonstantin Ananyev    p = ngx_syslog_add_header(peer, msg);
254e18a033bSKonstantin Ananyev    head_len = p - msg;
255e18a033bSKonstantin Ananyev
256e18a033bSKonstantin Ananyev    len -= NGX_LINEFEED_SIZE;
257e18a033bSKonstantin Ananyev
258e18a033bSKonstantin Ananyev    if (len > NGX_SYSLOG_MAX_STR - head_len) {
259e18a033bSKonstantin Ananyev        len = NGX_SYSLOG_MAX_STR - head_len;
260e18a033bSKonstantin Ananyev    }
261e18a033bSKonstantin Ananyev
262e18a033bSKonstantin Ananyev    p = ngx_snprintf(p, len, "%s", buf);
263e18a033bSKonstantin Ananyev
264e18a033bSKonstantin Ananyev    (void) ngx_syslog_send(peer, msg, p - msg);
265e18a033bSKonstantin Ananyev
266e18a033bSKonstantin Ananyev    peer->busy = 0;
267e18a033bSKonstantin Ananyev}
268e18a033bSKonstantin Ananyev
269e18a033bSKonstantin Ananyev
270e18a033bSKonstantin Ananyevssize_t
271e18a033bSKonstantin Ananyevngx_syslog_send(ngx_syslog_peer_t *peer, u_char *buf, size_t len)
272e18a033bSKonstantin Ananyev{
273e18a033bSKonstantin Ananyev    ssize_t  n;
274e18a033bSKonstantin Ananyev
275e18a033bSKonstantin Ananyev    if (peer->conn.fd == (ngx_socket_t) -1) {
276e18a033bSKonstantin Ananyev        if (ngx_syslog_init_peer(peer) != NGX_OK) {
277e18a033bSKonstantin Ananyev            return NGX_ERROR;
278e18a033bSKonstantin Ananyev        }
279e18a033bSKonstantin Ananyev    }
280e18a033bSKonstantin Ananyev
281e18a033bSKonstantin Ananyev    /* log syslog socket events with valid log */
282e18a033bSKonstantin Ananyev    peer->conn.log = ngx_cycle->log;
283e18a033bSKonstantin Ananyev
284e18a033bSKonstantin Ananyev    if (ngx_send) {
285e18a033bSKonstantin Ananyev        n = ngx_send(&peer->conn, buf, len);
286e18a033bSKonstantin Ananyev
287e18a033bSKonstantin Ananyev    } else {
288e18a033bSKonstantin Ananyev        /* event module has not yet set ngx_io */
289e18a033bSKonstantin Ananyev        n = ngx_os_io.send(&peer->conn, buf, len);
290e18a033bSKonstantin Ananyev    }
291e18a033bSKonstantin Ananyev
292e18a033bSKonstantin Ananyev#if (NGX_HAVE_UNIX_DOMAIN)
293e18a033bSKonstantin Ananyev
294e18a033bSKonstantin Ananyev    if (n == NGX_ERROR && peer->server.sockaddr->sa_family == AF_UNIX) {
295e18a033bSKonstantin Ananyev
296e18a033bSKonstantin Ananyev        if (ngx_close_socket(peer->conn.fd) == -1) {
297e18a033bSKonstantin Ananyev            ngx_log_error(NGX_LOG_ALERT, ngx_cycle->log, ngx_socket_errno,
298e18a033bSKonstantin Ananyev                          ngx_close_socket_n " failed");
299e18a033bSKonstantin Ananyev        }
300e18a033bSKonstantin Ananyev
301e18a033bSKonstantin Ananyev        peer->conn.fd = (ngx_socket_t) -1;
302e18a033bSKonstantin Ananyev    }
303e18a033bSKonstantin Ananyev
304e18a033bSKonstantin Ananyev#endif
305e18a033bSKonstantin Ananyev
306e18a033bSKonstantin Ananyev    return n;
307e18a033bSKonstantin Ananyev}
308e18a033bSKonstantin Ananyev
309e18a033bSKonstantin Ananyev
310e18a033bSKonstantin Ananyevstatic ngx_int_t
311e18a033bSKonstantin Ananyevngx_syslog_init_peer(ngx_syslog_peer_t *peer)
312e18a033bSKonstantin Ananyev{
313e18a033bSKonstantin Ananyev    ngx_socket_t         fd;
314e18a033bSKonstantin Ananyev    ngx_pool_cleanup_t  *cln;
315e18a033bSKonstantin Ananyev
316e18a033bSKonstantin Ananyev    peer->conn.read = &ngx_syslog_dummy_event;
317e18a033bSKonstantin Ananyev    peer->conn.write = &ngx_syslog_dummy_event;
318e18a033bSKonstantin Ananyev
319e18a033bSKonstantin Ananyev    ngx_syslog_dummy_event.log = &ngx_syslog_dummy_log;
320e18a033bSKonstantin Ananyev
321e18a033bSKonstantin Ananyev    fd = ngx_socket(peer->server.sockaddr->sa_family, SOCK_DGRAM, 0);
322e18a033bSKonstantin Ananyev    if (fd == (ngx_socket_t) -1) {
323e18a033bSKonstantin Ananyev        ngx_log_error(NGX_LOG_ALERT, ngx_cycle->log, ngx_socket_errno,
324e18a033bSKonstantin Ananyev                      ngx_socket_n " failed");
325e18a033bSKonstantin Ananyev        return NGX_ERROR;
326e18a033bSKonstantin Ananyev    }
327e18a033bSKonstantin Ananyev
328e18a033bSKonstantin Ananyev    if (ngx_nonblocking(fd) == -1) {
329e18a033bSKonstantin Ananyev        ngx_log_error(NGX_LOG_ALERT, ngx_cycle->log, ngx_socket_errno,
330e18a033bSKonstantin Ananyev                      ngx_nonblocking_n " failed");
331e18a033bSKonstantin Ananyev        goto failed;
332e18a033bSKonstantin Ananyev    }
333e18a033bSKonstantin Ananyev
334e18a033bSKonstantin Ananyev    if (connect(fd, peer->server.sockaddr, peer->server.socklen) == -1) {
335e18a033bSKonstantin Ananyev        ngx_log_error(NGX_LOG_ALERT, ngx_cycle->log, ngx_socket_errno,
336e18a033bSKonstantin Ananyev                      "connect() failed");
337e18a033bSKonstantin Ananyev        goto failed;
338e18a033bSKonstantin Ananyev    }
339e18a033bSKonstantin Ananyev
340e18a033bSKonstantin Ananyev    cln = ngx_pool_cleanup_add(peer->pool, 0);
341e18a033bSKonstantin Ananyev    if (cln == NULL) {
342e18a033bSKonstantin Ananyev        goto failed;
343e18a033bSKonstantin Ananyev    }
344e18a033bSKonstantin Ananyev
345e18a033bSKonstantin Ananyev    cln->data = peer;
346e18a033bSKonstantin Ananyev    cln->handler = ngx_syslog_cleanup;
347e18a033bSKonstantin Ananyev
348e18a033bSKonstantin Ananyev    peer->conn.fd = fd;
349e18a033bSKonstantin Ananyev
350e18a033bSKonstantin Ananyev    /* UDP sockets are always ready to write */
351e18a033bSKonstantin Ananyev    peer->conn.write->ready = 1;
352e18a033bSKonstantin Ananyev
353e18a033bSKonstantin Ananyev    return NGX_OK;
354e18a033bSKonstantin Ananyev
355e18a033bSKonstantin Ananyevfailed:
356e18a033bSKonstantin Ananyev
357e18a033bSKonstantin Ananyev    if (ngx_close_socket(fd) == -1) {
358e18a033bSKonstantin Ananyev        ngx_log_error(NGX_LOG_ALERT, ngx_cycle->log, ngx_socket_errno,
359e18a033bSKonstantin Ananyev                      ngx_close_socket_n " failed");
360e18a033bSKonstantin Ananyev    }
361e18a033bSKonstantin Ananyev
362e18a033bSKonstantin Ananyev    return NGX_ERROR;
363e18a033bSKonstantin Ananyev}
364e18a033bSKonstantin Ananyev
365e18a033bSKonstantin Ananyev
366e18a033bSKonstantin Ananyevstatic void
367e18a033bSKonstantin Ananyevngx_syslog_cleanup(void *data)
368e18a033bSKonstantin Ananyev{
369e18a033bSKonstantin Ananyev    ngx_syslog_peer_t  *peer = data;
370e18a033bSKonstantin Ananyev
371e18a033bSKonstantin Ananyev    /* prevents further use of this peer */
372e18a033bSKonstantin Ananyev    peer->busy = 1;
373e18a033bSKonstantin Ananyev
374e18a033bSKonstantin Ananyev    if (peer->conn.fd == (ngx_socket_t) -1) {
375e18a033bSKonstantin Ananyev        return;
376e18a033bSKonstantin Ananyev    }
377e18a033bSKonstantin Ananyev
378e18a033bSKonstantin Ananyev    if (ngx_close_socket(peer->conn.fd) == -1) {
379e18a033bSKonstantin Ananyev        ngx_log_error(NGX_LOG_ALERT, ngx_cycle->log, ngx_socket_errno,
380e18a033bSKonstantin Ananyev                      ngx_close_socket_n " failed");
381e18a033bSKonstantin Ananyev    }
382e18a033bSKonstantin Ananyev}
383