Back to home page

Nginx displayed by LXR

Source navigation ]
Diff markup ]
Identifier search ]
general search ]
 
 
Version: nginx-1.15.12 ]​[ nginx-1.16.0 ]​

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