Back to home page

Nginx displayed by LXR

Source navigation ]
Diff markup ]
Identifier search ]
general search ]
 
 
Version: nginx-1.13.12 ]​[ nginx-1.12.2 ]​

0001 
0002 /*
0003  * Copyright (C) Nginx, Inc.
0004  */
0005 
0006 
0007 #include <ngx_config.h>
0008 #include <ngx_core.h>
0009 #include <ngx_event.h>
0010 
0011 
0012 #define NGX_SYSLOG_MAX_STR                                                    \
0013     NGX_MAX_ERROR_STR + sizeof("<255>Jan 01 00:00:00 ") - 1                   \
0014     + (NGX_MAXHOSTNAMELEN - 1) + 1 /* space */                                \
0015     + 32 /* tag */ + 2 /* colon, space */
0016 
0017 
0018 static char *ngx_syslog_parse_args(ngx_conf_t *cf, ngx_syslog_peer_t *peer);
0019 static ngx_int_t ngx_syslog_init_peer(ngx_syslog_peer_t *peer);
0020 static void ngx_syslog_cleanup(void *data);
0021 
0022 
0023 static char  *facilities[] = {
0024     "kern", "user", "mail", "daemon", "auth", "intern", "lpr", "news", "uucp",
0025     "clock", "authpriv", "ftp", "ntp", "audit", "alert", "cron", "local0",
0026     "local1", "local2", "local3", "local4", "local5", "local6", "local7",
0027     NULL
0028 };
0029 
0030 /* note 'error/warn' like in nginx.conf, not 'err/warning' */
0031 static char  *severities[] = {
0032     "emerg", "alert", "crit", "error", "warn", "notice", "info", "debug", NULL
0033 };
0034 
0035 static ngx_log_t    ngx_syslog_dummy_log;
0036 static ngx_event_t  ngx_syslog_dummy_event;
0037 
0038 
0039 char *
0040 ngx_syslog_process_conf(ngx_conf_t *cf, ngx_syslog_peer_t *peer)
0041 {
0042     peer->pool = cf->pool;
0043     peer->facility = NGX_CONF_UNSET_UINT;
0044     peer->severity = NGX_CONF_UNSET_UINT;
0045 
0046     if (ngx_syslog_parse_args(cf, peer) != NGX_CONF_OK) {
0047         return NGX_CONF_ERROR;
0048     }
0049 
0050     if (peer->server.sockaddr == NULL) {
0051         ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
0052                            "no syslog server specified");
0053         return NGX_CONF_ERROR;
0054     }
0055 
0056     if (peer->facility == NGX_CONF_UNSET_UINT) {
0057         peer->facility = 23; /* local7 */
0058     }
0059 
0060     if (peer->severity == NGX_CONF_UNSET_UINT) {
0061         peer->severity = 6; /* info */
0062     }
0063 
0064     if (peer->tag.data == NULL) {
0065         ngx_str_set(&peer->tag, "nginx");
0066     }
0067 
0068     peer->conn.fd = (ngx_socket_t) -1;
0069 
0070     return NGX_CONF_OK;
0071 }
0072 
0073 
0074 static char *
0075 ngx_syslog_parse_args(ngx_conf_t *cf, ngx_syslog_peer_t *peer)
0076 {
0077     u_char      *p, *comma, c;
0078     size_t       len;
0079     ngx_str_t   *value;
0080     ngx_url_t    u;
0081     ngx_uint_t   i;
0082 
0083     value = cf->args->elts;
0084 
0085     p = value[1].data + sizeof("syslog:") - 1;
0086 
0087     for ( ;; ) {
0088         comma = (u_char *) ngx_strchr(p, ',');
0089 
0090         if (comma != NULL) {
0091             len = comma - p;
0092             *comma = '\0';
0093 
0094         } else {
0095             len = value[1].data + value[1].len - p;
0096         }
0097 
0098         if (ngx_strncmp(p, "server=", 7) == 0) {
0099 
0100             if (peer->server.sockaddr != NULL) {
0101                 ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
0102                                    "duplicate syslog \"server\"");
0103                 return NGX_CONF_ERROR;
0104             }
0105 
0106             ngx_memzero(&u, sizeof(ngx_url_t));
0107 
0108             u.url.data = p + 7;
0109             u.url.len = len - 7;
0110             u.default_port = 514;
0111 
0112             if (ngx_parse_url(cf->pool, &u) != NGX_OK) {
0113                 if (u.err) {
0114                     ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
0115                                        "%s in syslog server \"%V\"",
0116                                        u.err, &u.url);
0117                 }
0118 
0119                 return NGX_CONF_ERROR;
0120             }
0121 
0122             peer->server = u.addrs[0];
0123 
0124         } else if (ngx_strncmp(p, "facility=", 9) == 0) {
0125 
0126             if (peer->facility != NGX_CONF_UNSET_UINT) {
0127                 ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
0128                                    "duplicate syslog \"facility\"");
0129                 return NGX_CONF_ERROR;
0130             }
0131 
0132             for (i = 0; facilities[i] != NULL; i++) {
0133 
0134                 if (ngx_strcmp(p + 9, facilities[i]) == 0) {
0135                     peer->facility = i;
0136                     goto next;
0137                 }
0138             }
0139 
0140             ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
0141                                "unknown syslog facility \"%s\"", p + 9);
0142             return NGX_CONF_ERROR;
0143 
0144         } else if (ngx_strncmp(p, "severity=", 9) == 0) {
0145 
0146             if (peer->severity != NGX_CONF_UNSET_UINT) {
0147                 ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
0148                                    "duplicate syslog \"severity\"");
0149                 return NGX_CONF_ERROR;
0150             }
0151 
0152             for (i = 0; severities[i] != NULL; i++) {
0153 
0154                 if (ngx_strcmp(p + 9, severities[i]) == 0) {
0155                     peer->severity = i;
0156                     goto next;
0157                 }
0158             }
0159 
0160             ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
0161                                "unknown syslog severity \"%s\"", p + 9);
0162             return NGX_CONF_ERROR;
0163 
0164         } else if (ngx_strncmp(p, "tag=", 4) == 0) {
0165 
0166             if (peer->tag.data != NULL) {
0167                 ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
0168                                    "duplicate syslog \"tag\"");
0169                 return NGX_CONF_ERROR;
0170             }
0171 
0172             /*
0173              * RFC 3164: the TAG is a string of ABNF alphanumeric characters
0174              * that MUST NOT exceed 32 characters.
0175              */
0176             if (len - 4 > 32) {
0177                 ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
0178                                    "syslog tag length exceeds 32");
0179                 return NGX_CONF_ERROR;
0180             }
0181 
0182             for (i = 4; i < len; i++) {
0183                 c = ngx_tolower(p[i]);
0184 
0185                 if (c < '0' || (c > '9' && c < 'a' && c != '_') || c > 'z') {
0186                     ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
0187                                        "syslog \"tag\" only allows "
0188                                        "alphanumeric characters "
0189                                        "and underscore");
0190                     return NGX_CONF_ERROR;
0191                 }
0192             }
0193 
0194             peer->tag.data = p + 4;
0195             peer->tag.len = len - 4;
0196 
0197         } else if (len == 10 && ngx_strncmp(p, "nohostname", 10) == 0) {
0198             peer->nohostname = 1;
0199 
0200         } else {
0201             ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
0202                                "unknown syslog parameter \"%s\"", p);
0203             return NGX_CONF_ERROR;
0204         }
0205 
0206     next:
0207 
0208         if (comma == NULL) {
0209             break;
0210         }
0211 
0212         p = comma + 1;
0213     }
0214 
0215     return NGX_CONF_OK;
0216 }
0217 
0218 
0219 u_char *
0220 ngx_syslog_add_header(ngx_syslog_peer_t *peer, u_char *buf)
0221 {
0222     ngx_uint_t  pri;
0223 
0224     pri = peer->facility * 8 + peer->severity;
0225 
0226     if (peer->nohostname) {
0227         return ngx_sprintf(buf, "<%ui>%V %V: ", pri, &ngx_cached_syslog_time,
0228                            &peer->tag);
0229     }
0230 
0231     return ngx_sprintf(buf, "<%ui>%V %V %V: ", pri, &ngx_cached_syslog_time,
0232                        &ngx_cycle->hostname, &peer->tag);
0233 }
0234 
0235 
0236 void
0237 ngx_syslog_writer(ngx_log_t *log, ngx_uint_t level, u_char *buf,
0238     size_t len)
0239 {
0240     u_char             *p, msg[NGX_SYSLOG_MAX_STR];
0241     ngx_uint_t          head_len;
0242     ngx_syslog_peer_t  *peer;
0243 
0244     peer = log->wdata;
0245 
0246     if (peer->busy) {
0247         return;
0248     }
0249 
0250     peer->busy = 1;
0251     peer->severity = level - 1;
0252 
0253     p = ngx_syslog_add_header(peer, msg);
0254     head_len = p - msg;
0255 
0256     len -= NGX_LINEFEED_SIZE;
0257 
0258     if (len > NGX_SYSLOG_MAX_STR - head_len) {
0259         len = NGX_SYSLOG_MAX_STR - head_len;
0260     }
0261 
0262     p = ngx_snprintf(p, len, "%s", buf);
0263 
0264     (void) ngx_syslog_send(peer, msg, p - msg);
0265 
0266     peer->busy = 0;
0267 }
0268 
0269 
0270 ssize_t
0271 ngx_syslog_send(ngx_syslog_peer_t *peer, u_char *buf, size_t len)
0272 {
0273     ssize_t  n;
0274 
0275     if (peer->conn.fd == (ngx_socket_t) -1) {
0276         if (ngx_syslog_init_peer(peer) != NGX_OK) {
0277             return NGX_ERROR;
0278         }
0279     }
0280 
0281     /* log syslog socket events with valid log */
0282     peer->conn.log = ngx_cycle->log;
0283 
0284     if (ngx_send) {
0285         n = ngx_send(&peer->conn, buf, len);
0286 
0287     } else {
0288         /* event module has not yet set ngx_io */
0289         n = ngx_os_io.send(&peer->conn, buf, len);
0290     }
0291 
0292 #if (NGX_HAVE_UNIX_DOMAIN)
0293 
0294     if (n == NGX_ERROR && peer->server.sockaddr->sa_family == AF_UNIX) {
0295 
0296         if (ngx_close_socket(peer->conn.fd) == -1) {
0297             ngx_log_error(NGX_LOG_ALERT, ngx_cycle->log, ngx_socket_errno,
0298                           ngx_close_socket_n " failed");
0299         }
0300 
0301         peer->conn.fd = (ngx_socket_t) -1;
0302     }
0303 
0304 #endif
0305 
0306     return n;
0307 }
0308 
0309 
0310 static ngx_int_t
0311 ngx_syslog_init_peer(ngx_syslog_peer_t *peer)
0312 {
0313     ngx_socket_t         fd;
0314     ngx_pool_cleanup_t  *cln;
0315 
0316     peer->conn.read = &ngx_syslog_dummy_event;
0317     peer->conn.write = &ngx_syslog_dummy_event;
0318 
0319     ngx_syslog_dummy_event.log = &ngx_syslog_dummy_log;
0320 
0321     fd = ngx_socket(peer->server.sockaddr->sa_family, SOCK_DGRAM, 0);
0322     if (fd == (ngx_socket_t) -1) {
0323         ngx_log_error(NGX_LOG_ALERT, ngx_cycle->log, ngx_socket_errno,
0324                       ngx_socket_n " failed");
0325         return NGX_ERROR;
0326     }
0327 
0328     if (ngx_nonblocking(fd) == -1) {
0329         ngx_log_error(NGX_LOG_ALERT, ngx_cycle->log, ngx_socket_errno,
0330                       ngx_nonblocking_n " failed");
0331         goto failed;
0332     }
0333 
0334     if (connect(fd, peer->server.sockaddr, peer->server.socklen) == -1) {
0335         ngx_log_error(NGX_LOG_ALERT, ngx_cycle->log, ngx_socket_errno,
0336                       "connect() failed");
0337         goto failed;
0338     }
0339 
0340     cln = ngx_pool_cleanup_add(peer->pool, 0);
0341     if (cln == NULL) {
0342         goto failed;
0343     }
0344 
0345     cln->data = peer;
0346     cln->handler = ngx_syslog_cleanup;
0347 
0348     peer->conn.fd = fd;
0349 
0350     /* UDP sockets are always ready to write */
0351     peer->conn.write->ready = 1;
0352 
0353     return NGX_OK;
0354 
0355 failed:
0356 
0357     if (ngx_close_socket(fd) == -1) {
0358         ngx_log_error(NGX_LOG_ALERT, ngx_cycle->log, ngx_socket_errno,
0359                       ngx_close_socket_n " failed");
0360     }
0361 
0362     return NGX_ERROR;
0363 }
0364 
0365 
0366 static void
0367 ngx_syslog_cleanup(void *data)
0368 {
0369     ngx_syslog_peer_t  *peer = data;
0370 
0371     /* prevents further use of this peer */
0372     peer->busy = 1;
0373 
0374     if (peer->conn.fd == (ngx_socket_t) -1) {
0375         return;
0376     }
0377 
0378     if (ngx_close_socket(peer->conn.fd) == -1) {
0379         ngx_log_error(NGX_LOG_ALERT, ngx_cycle->log, ngx_socket_errno,
0380                       ngx_close_socket_n " failed");
0381     }
0382 }