├── LICENCE ├── LICENCE.ru ├── README ├── config └── ngx_http_udplog_module.c /LICENCE: -------------------------------------------------------------------------------- 1 | * Copyright (c) 2010, Valery Kholodkov 2 | * All rights reserved. 3 | * 4 | * Redistribution and use in source and binary forms, with or without 5 | * modification, are permitted provided that the following conditions are met: 6 | * * Redistributions of source code must retain the above copyright 7 | * notice, this list of conditions and the following disclaimer. 8 | * * Redistributions in binary form must reproduce the above copyright 9 | * notice, this list of conditions and the following disclaimer in the 10 | * documentation and/or other materials provided with the distribution. 11 | * * Neither the name of the Valery Kholodkov nor the 12 | * names of its contributors may be used to endorse or promote products 13 | * derived from this software without specific prior written permission. 14 | * 15 | * THIS SOFTWARE IS PROVIDED BY VALERY KHOLODKOV ''AS IS'' AND ANY 16 | * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 17 | * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 18 | * DISCLAIMED. IN NO EVENT SHALL VALERY KHOLODKOV BE LIABLE FOR ANY 19 | * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 20 | * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 21 | * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND 22 | * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 23 | * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 24 | * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 25 | -------------------------------------------------------------------------------- /LICENCE.ru: -------------------------------------------------------------------------------- 1 | * Copyright (c) 2010, Валерий Холодков 2 | * 3 | * Разрешается повторное распространение и использование как в виде исходного 4 | * кода, так и в двоичной форме, с изменениями или без, при соблюдении 5 | * следующих условий: 6 | * 7 | * * При повторном распространении исходного кода должно оставаться 8 | * указанное выше уведомление об авторском праве, этот список условий и 9 | * последующий отказ от гарантий. 10 | * * При повторном распространении двоичного кода должна сохраняться 11 | * указанная выше информация об авторском праве, этот список условий и 12 | * последующий отказ от гарантий в документации и/или в других 13 | * материалах, поставляемых при распространении. 14 | * * Ни имя Валерия Холодкова, ни имена вкладчиков не могут быть 15 | * использованы в качестве поддержки или продвижения продуктов, 16 | * основанных на этом ПО без предварительного письменного разрешения. 17 | * 18 | * ЭТА ПРОГРАММА ПРЕДОСТАВЛЕНА ВЛАДЕЛЬЦАМИ АВТОРСКИХ ПРАВ И/ИЛИ ДРУГИМИ 19 | * СТОРОНАМИ "КАК ОНА ЕСТЬ" БЕЗ КАКОГО-ЛИБО ВИДА ГАРАНТИЙ, ВЫРАЖЕННЫХ ЯВНО 20 | * ИЛИ ПОДРАЗУМЕВАЕМЫХ, ВКЛЮЧАЯ, НО НЕ ОГРАНИЧИВАЯСЬ ИМИ, ПОДРАЗУМЕВАЕМЫЕ 21 | * ГАРАНТИИ КОММЕРЧЕСКОЙ ЦЕННОСТИ И ПРИГОДНОСТИ ДЛЯ КОНКРЕТНОЙ ЦЕЛИ. НИ В 22 | * КОЕМ СЛУЧАЕ, ЕСЛИ НЕ ТРЕБУЕТСЯ СООТВЕТСТВУЮЩИМ ЗАКОНОМ, ИЛИ НЕ УСТАНОВЛЕНО 23 | * В УСТНОЙ ФОРМЕ, НИ ОДИН ВЛАДЕЛЕЦ АВТОРСКИХ ПРАВ И НИ ОДНО ДРУГОЕ ЛИЦО, 24 | * КОТОРОЕ МОЖЕТ ИЗМЕНЯТЬ И/ИЛИ ПОВТОРНО РАСПРОСТРАНЯТЬ ПРОГРАММУ, КАК БЫЛО 25 | * СКАЗАНО ВЫШЕ, НЕ НЕСЁТ ОТВЕТСТВЕННОСТИ, ВКЛЮЧАЯ ЛЮБЫЕ ОБЩИЕ, СЛУЧАЙНЫЕ, 26 | * СПЕЦИАЛЬНЫЕ ИЛИ ПОСЛЕДОВАВШИЕ УБЫТКИ, ВСЛЕДСТВИЕ ИСПОЛЬЗОВАНИЯ ИЛИ 27 | * НЕВОЗМОЖНОСТИ ИСПОЛЬЗОВАНИЯ ПРОГРАММЫ (ВКЛЮЧАЯ, НО НЕ ОГРАНИЧИВАЯСЬ 28 | * ПОТЕРЕЙ ДАННЫХ, ИЛИ ДАННЫМИ, СТАВШИМИ НЕПРАВИЛЬНЫМИ, ИЛИ ПОТЕРЯМИ 29 | * ПРИНЕСЕННЫМИ ИЗ-ЗА ВАС ИЛИ ТРЕТЬИХ ЛИЦ, ИЛИ ОТКАЗОМ ПРОГРАММЫ РАБОТАТЬ 30 | * СОВМЕСТНО С ДРУГИМИ ПРОГРАММАМИ), ДАЖЕ ЕСЛИ ТАКОЙ ВЛАДЕЛЕЦ ИЛИ ДРУГОЕ 31 | * ЛИЦО БЫЛИ ИЗВЕЩЕНЫ О ВОЗМОЖНОСТИ ТАКИХ УБЫТКОВ. 32 | 33 | -------------------------------------------------------------------------------- /README: -------------------------------------------------------------------------------- 1 | Two differences from the original work: 2 | - the default for udplog is off. 3 | - access_udplog takes an optional 3rd argument "bare": 4 | access_udplog 1.1.1.1:100 loghost bare; 5 | 6 | If bare is specified, the message is sent exactly as specified in the logformat directive without any change. 7 | This can be used for udp logging to non-syslog hosts. 8 | 9 | 10 | Documentation for this module could be found under following URLs: 11 | 12 | * English: 13 | 14 | http://www.grid.net.ru/nginx/udplog.en.html 15 | 16 | * Russian: 17 | 18 | http://www.grid.net.ru/nginx/udplog.ru.html 19 | -------------------------------------------------------------------------------- /config: -------------------------------------------------------------------------------- 1 | ngx_addon_name=ngx_http_udplog_module 2 | HTTP_MODULES="$HTTP_MODULES ngx_http_udplog_module" 3 | NGX_ADDON_SRCS="$NGX_ADDON_SRCS $ngx_addon_dir/ngx_http_udplog_module.c" 4 | -------------------------------------------------------------------------------- /ngx_http_udplog_module.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2010 Valery Kholodkov 3 | * 4 | * NOTE: Some small fragments have been copied from original nginx log module due to exports problem. 5 | */ 6 | 7 | 8 | #include 9 | #include 10 | #include 11 | #include 12 | 13 | #define NGX_UDPLOG_FACILITY_LOCAL7 23 14 | #define NGX_UDPLOG_SEVERITY_INFO 6 15 | 16 | #if defined nginx_version && nginx_version >= 8021 17 | typedef ngx_addr_t ngx_udplog_addr_t; 18 | #else 19 | typedef ngx_peer_addr_t ngx_udplog_addr_t; 20 | #endif 21 | 22 | typedef struct ngx_http_log_op_s ngx_http_log_op_t; 23 | 24 | typedef u_char *(*ngx_http_log_op_run_pt) (ngx_http_request_t *r, u_char *buf, 25 | ngx_http_log_op_t *op); 26 | 27 | typedef size_t (*ngx_http_log_op_getlen_pt) (ngx_http_request_t *r, 28 | uintptr_t data); 29 | 30 | 31 | struct ngx_http_log_op_s { 32 | size_t len; 33 | ngx_http_log_op_getlen_pt getlen; 34 | ngx_http_log_op_run_pt run; 35 | uintptr_t data; 36 | }; 37 | 38 | typedef struct { 39 | ngx_str_t name; 40 | #if defined nginx_version && nginx_version >= 7018 41 | ngx_array_t *flushes; 42 | #endif 43 | ngx_array_t *ops; /* array of ngx_http_log_op_t */ 44 | } ngx_http_log_fmt_t; 45 | 46 | typedef struct { 47 | ngx_str_t value; 48 | ngx_array_t *lengths; 49 | ngx_array_t *values; 50 | } ngx_http_log_tag_template_t; 51 | 52 | typedef struct { 53 | ngx_array_t formats; /* array of ngx_http_log_fmt_t */ 54 | ngx_uint_t combined_used; /* unsigned combined_used:1 */ 55 | } ngx_http_log_main_conf_t; 56 | 57 | typedef struct { 58 | ngx_str_t name; 59 | ngx_uint_t number; 60 | } ngx_udplog_facility_t; 61 | 62 | typedef ngx_udplog_facility_t ngx_udplog_severity_t; 63 | 64 | typedef struct { 65 | ngx_udplog_addr_t peer_addr; 66 | ngx_udp_connection_t *udp_connection; 67 | } ngx_udp_endpoint_t; 68 | 69 | typedef struct { 70 | ngx_udp_endpoint_t *endpoint; 71 | ngx_http_log_fmt_t *format; 72 | ngx_uint_t bare:1; 73 | } ngx_http_udplog_t; 74 | 75 | typedef struct { 76 | ngx_array_t *endpoints; 77 | } ngx_http_udplog_main_conf_t; 78 | 79 | typedef struct { 80 | ngx_array_t *logs; /* array of ngx_http_udplog_t */ 81 | unsigned off; 82 | ngx_http_log_tag_template_t *tag; 83 | ngx_uint_t facility; 84 | ngx_uint_t severity; 85 | } ngx_http_udplog_conf_t; 86 | 87 | ngx_int_t ngx_udp_connect(ngx_udp_connection_t *uc); 88 | 89 | static void ngx_udplogger_cleanup(void *data); 90 | static ngx_int_t ngx_http_udplogger_send(ngx_udp_endpoint_t *l, u_char *buf, size_t len); 91 | 92 | static void *ngx_http_udplog_create_main_conf(ngx_conf_t *cf); 93 | static void *ngx_http_udplog_create_loc_conf(ngx_conf_t *cf); 94 | static char *ngx_http_udplog_merge_loc_conf(ngx_conf_t *cf, void *parent, 95 | void *child); 96 | 97 | static char *ngx_http_udplog_set_log(ngx_conf_t *cf, ngx_command_t *cmd, void *conf); 98 | static char *ngx_http_udplog_set_priority(ngx_conf_t *cf, ngx_command_t *cmd, void *conf); 99 | static char *ngx_http_udplog_set_tag(ngx_conf_t *cf, ngx_command_t *cmd, void *conf); 100 | 101 | static ngx_int_t ngx_http_udplog_init(ngx_conf_t *cf); 102 | 103 | 104 | static ngx_command_t ngx_http_udplog_commands[] = { 105 | 106 | { ngx_string("access_udplog"), 107 | NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_HTTP_LIF_CONF 108 | |NGX_HTTP_LMT_CONF|NGX_CONF_TAKE1234, 109 | ngx_http_udplog_set_log, 110 | NGX_HTTP_LOC_CONF_OFFSET, 111 | 0, 112 | NULL }, 113 | 114 | { ngx_string("udplog_priority"), 115 | NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE12, 116 | ngx_http_udplog_set_priority, 117 | NGX_HTTP_LOC_CONF_OFFSET, 118 | 0, 119 | NULL }, 120 | 121 | { ngx_string("udplog_tag"), 122 | NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE1, 123 | ngx_http_udplog_set_tag, 124 | NGX_HTTP_LOC_CONF_OFFSET, 125 | offsetof(ngx_http_udplog_conf_t, tag), 126 | NULL }, 127 | 128 | ngx_null_command 129 | }; 130 | 131 | 132 | static ngx_http_module_t ngx_http_udplog_module_ctx = { 133 | NULL, /* preconfiguration */ 134 | ngx_http_udplog_init, /* postconfiguration */ 135 | 136 | ngx_http_udplog_create_main_conf, /* create main configuration */ 137 | NULL, /* init main configuration */ 138 | 139 | NULL, /* create server configuration */ 140 | NULL, /* merge server configuration */ 141 | 142 | ngx_http_udplog_create_loc_conf, /* create location configration */ 143 | ngx_http_udplog_merge_loc_conf /* merge location configration */ 144 | }; 145 | 146 | extern ngx_module_t ngx_http_log_module; 147 | 148 | ngx_module_t ngx_http_udplog_module = { 149 | NGX_MODULE_V1, 150 | &ngx_http_udplog_module_ctx, /* module context */ 151 | ngx_http_udplog_commands, /* module directives */ 152 | NGX_HTTP_MODULE, /* module type */ 153 | NULL, /* init master */ 154 | NULL, /* init module */ 155 | NULL, /* init process */ 156 | NULL, /* init thread */ 157 | NULL, /* exit thread */ 158 | NULL, /* exit process */ 159 | NULL, /* exit master */ 160 | NGX_MODULE_V1_PADDING 161 | }; 162 | 163 | static ngx_udplog_facility_t ngx_udplog_facilities[] = { 164 | { ngx_string("kern"), 0 }, 165 | { ngx_string("user"), 1 }, 166 | { ngx_string("mail"), 2 }, 167 | { ngx_string("daemon"), 3 }, 168 | { ngx_string("auth"), 4 }, 169 | { ngx_string("intern"), 5 }, 170 | { ngx_string("lpr"), 6 }, 171 | { ngx_string("news"), 7 }, 172 | { ngx_string("uucp"), 8 }, 173 | { ngx_string("clock"), 9 }, 174 | { ngx_string("authpriv"), 10 }, 175 | { ngx_string("ftp"), 11 }, 176 | { ngx_string("ntp"), 12 }, 177 | { ngx_string("audit"), 13 }, 178 | { ngx_string("alert"), 14 }, 179 | { ngx_string("cron"), 15 }, 180 | { ngx_string("local0"), 16 }, 181 | { ngx_string("local1"), 17 }, 182 | { ngx_string("local2"), 18 }, 183 | { ngx_string("local3"), 19 }, 184 | { ngx_string("local4"), 20 }, 185 | { ngx_string("local5"), 21 }, 186 | { ngx_string("local6"), 22 }, 187 | { ngx_string("local7"), 23 }, 188 | 189 | { ngx_null_string, 0 } 190 | }; 191 | 192 | static ngx_udplog_severity_t ngx_udplog_severities[] = { 193 | { ngx_string("emerg"), 0 }, 194 | { ngx_string("alert"), 1 }, 195 | { ngx_string("crit"), 2 }, 196 | { ngx_string("err"), 3 }, 197 | { ngx_string("warning"), 4 }, 198 | { ngx_string("notice"), 5 }, 199 | { ngx_string("info"), 6 }, 200 | { ngx_string("debug"), 7 }, 201 | 202 | { ngx_null_string, 0 } 203 | }; 204 | 205 | /* 206 | * See RFC 3164 chapter 4.1.2 207 | */ 208 | static char *months[] = { "Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec" }; 209 | 210 | ngx_int_t 211 | ngx_http_udplog_handler(ngx_http_request_t *r) 212 | { 213 | u_char *line, *p; 214 | size_t len; 215 | ngx_uint_t i, l, pri; 216 | ngx_str_t tag; 217 | ngx_http_udplog_t *log; 218 | ngx_http_log_op_t *op; 219 | ngx_http_udplog_conf_t *ulcf; 220 | time_t time; 221 | ngx_tm_t tm; 222 | 223 | ngx_log_debug0(NGX_LOG_DEBUG_HTTP, r->connection->log, 0, 224 | "http udplog handler"); 225 | 226 | ulcf = ngx_http_get_module_loc_conf(r, ngx_http_udplog_module); 227 | 228 | if(ulcf->off) { 229 | return NGX_OK; 230 | } 231 | 232 | if(ulcf->tag != NULL) 233 | { 234 | if(ulcf->tag->lengths == NULL) { 235 | tag = ulcf->tag->value; 236 | } 237 | else{ 238 | if (ngx_http_script_run(r, &tag, ulcf->tag->lengths->elts, 0, ulcf->tag->values->elts) 239 | == NULL) 240 | { 241 | return NGX_ERROR; 242 | } 243 | } 244 | } 245 | else { 246 | tag.data = (u_char*)"nginx"; 247 | tag.len = sizeof("nginx") - 1; 248 | } 249 | 250 | time = ngx_time(); 251 | ngx_gmtime(time, &tm); 252 | 253 | log = ulcf->logs->elts; 254 | pri = ulcf->facility * 8 + ulcf->severity; 255 | 256 | for (l = 0; l < ulcf->logs->nelts; l++) { 257 | 258 | if(pri > 255) { 259 | pri = NGX_UDPLOG_FACILITY_LOCAL7 * 8 + NGX_UDPLOG_SEVERITY_INFO; 260 | } 261 | 262 | #if defined nginx_version && nginx_version >= 7018 263 | ngx_http_script_flush_no_cacheable_variables(r, log[l].format->flushes); 264 | #endif 265 | 266 | len = 0; 267 | op = log[l].format->ops->elts; 268 | for (i = 0; i < log[l].format->ops->nelts; i++) { 269 | if (op[i].len == 0) { 270 | len += op[i].getlen(r, op[i].data); 271 | 272 | } else { 273 | len += op[i].len; 274 | } 275 | } 276 | 277 | len += sizeof("<255>") - 1 + sizeof("Jan 31 00:00:00") - 1 + 1 + ngx_cycle->hostname.len + 1 278 | + tag.len + 2; 279 | 280 | #if defined nginx_version && nginx_version >= 7003 281 | line = ngx_pnalloc(r->pool, len); 282 | #else 283 | line = ngx_palloc(r->pool, len); 284 | #endif 285 | if (line == NULL) { 286 | return NGX_ERROR; 287 | } 288 | 289 | /* 290 | * BSD syslog message header (see RFC 3164) 291 | */ 292 | if(!log[l].bare){ 293 | p = ngx_sprintf(line, "<%ui>%s %2d %02d:%02d:%02d %V %V: ", pri, months[tm.ngx_tm_mon - 1], tm.ngx_tm_mday, 294 | tm.ngx_tm_hour, tm.ngx_tm_min, tm.ngx_tm_sec, &ngx_cycle->hostname, &tag); 295 | }else{ 296 | p = line; 297 | } 298 | for (i = 0; i < log[l].format->ops->nelts; i++) { 299 | p = op[i].run(r, p, &op[i]); 300 | } 301 | 302 | ngx_http_udplogger_send(log[l].endpoint, line, p - line); 303 | } 304 | 305 | return NGX_OK; 306 | } 307 | 308 | static ngx_int_t ngx_udplog_init_endpoint(ngx_conf_t *cf, ngx_udp_endpoint_t *endpoint) { 309 | ngx_pool_cleanup_t *cln; 310 | ngx_udp_connection_t *uc; 311 | 312 | cln = ngx_pool_cleanup_add(cf->pool, 0); 313 | if(cln == NULL) { 314 | return NGX_ERROR; 315 | } 316 | 317 | cln->handler = ngx_udplogger_cleanup; 318 | cln->data = endpoint; 319 | 320 | uc = ngx_calloc(sizeof(ngx_udp_connection_t), cf->log); 321 | if (uc == NULL) { 322 | return NGX_ERROR; 323 | } 324 | 325 | endpoint->udp_connection = uc; 326 | 327 | uc->sockaddr = endpoint->peer_addr.sockaddr; 328 | uc->socklen = endpoint->peer_addr.socklen; 329 | uc->server = endpoint->peer_addr.name; 330 | #if defined nginx_version && ( nginx_version >= 7054 && nginx_version < 8032 ) 331 | uc->log = &cf->cycle->new_log; 332 | #else 333 | uc->log = cf->cycle->new_log; 334 | #if defined nginx_version && nginx_version >= 8032 335 | uc->log.handler = NULL; 336 | uc->log.data = NULL; 337 | uc->log.action = "logging"; 338 | #endif 339 | #endif 340 | 341 | return NGX_OK; 342 | } 343 | 344 | static void 345 | ngx_udplogger_cleanup(void *data) 346 | { 347 | ngx_udp_endpoint_t *e = data; 348 | 349 | ngx_log_debug0(NGX_LOG_DEBUG_CORE, ngx_cycle->log, 0, 350 | "cleanup udplogger"); 351 | 352 | if(e->udp_connection) { 353 | if(e->udp_connection->connection) { 354 | ngx_close_connection(e->udp_connection->connection); 355 | } 356 | 357 | ngx_free(e->udp_connection); 358 | } 359 | } 360 | 361 | static void ngx_http_udplogger_dummy_handler(ngx_event_t *ev) 362 | { 363 | } 364 | 365 | static ngx_int_t 366 | ngx_http_udplogger_send(ngx_udp_endpoint_t *l, u_char *buf, size_t len) 367 | { 368 | ssize_t n; 369 | ngx_udp_connection_t *uc; 370 | 371 | uc = l->udp_connection; 372 | 373 | if (uc->connection == NULL) { 374 | if(ngx_udp_connect(uc) != NGX_OK) { 375 | if(uc->connection != NULL) { 376 | ngx_free_connection(uc->connection); 377 | uc->connection = NULL; 378 | } 379 | 380 | return NGX_ERROR; 381 | } 382 | 383 | uc->connection->data = l; 384 | uc->connection->read->handler = ngx_http_udplogger_dummy_handler; 385 | uc->connection->read->resolver = 0; 386 | } 387 | 388 | n = ngx_send(uc->connection, buf, len); 389 | 390 | if (n == -1) { 391 | return NGX_ERROR; 392 | } 393 | 394 | if ((size_t) n != (size_t) len) { 395 | #if defined nginx_version && nginx_version >= 8032 396 | ngx_log_error(NGX_LOG_CRIT, &uc->log, 0, "send() incomplete"); 397 | #else 398 | ngx_log_error(NGX_LOG_CRIT, uc->log, 0, "send() incomplete"); 399 | #endif 400 | return NGX_ERROR; 401 | } 402 | 403 | return NGX_OK; 404 | } 405 | 406 | static void * 407 | ngx_http_udplog_create_main_conf(ngx_conf_t *cf) 408 | { 409 | ngx_http_udplog_main_conf_t *conf; 410 | 411 | conf = ngx_pcalloc(cf->pool, sizeof(ngx_http_udplog_main_conf_t)); 412 | if (conf == NULL) { 413 | return NGX_CONF_ERROR; 414 | } 415 | 416 | return conf; 417 | } 418 | 419 | static void * 420 | ngx_http_udplog_create_loc_conf(ngx_conf_t *cf) 421 | { 422 | ngx_http_udplog_conf_t *conf; 423 | 424 | conf = ngx_pcalloc(cf->pool, sizeof(ngx_http_udplog_conf_t)); 425 | if (conf == NULL) { 426 | return NGX_CONF_ERROR; 427 | } 428 | conf->off = 1; 429 | conf->facility = NGX_CONF_UNSET_UINT; 430 | conf->severity = NGX_CONF_UNSET_UINT; 431 | 432 | return conf; 433 | } 434 | 435 | static char * 436 | ngx_http_udplog_merge_loc_conf(ngx_conf_t *cf, void *parent, void *child) 437 | { 438 | ngx_http_udplog_conf_t *prev = parent; 439 | ngx_http_udplog_conf_t *conf = child; 440 | 441 | if(conf->tag == NULL) { 442 | conf->tag = prev->tag; 443 | } 444 | 445 | ngx_conf_merge_uint_value(conf->facility, 446 | prev->facility, NGX_UDPLOG_FACILITY_LOCAL7); 447 | ngx_conf_merge_uint_value(conf->severity, 448 | prev->severity, NGX_UDPLOG_SEVERITY_INFO); 449 | 450 | if(conf->logs || conf->off) { 451 | return NGX_CONF_OK; 452 | } 453 | 454 | conf->logs = prev->logs; 455 | conf->off = prev->off; 456 | 457 | return NGX_CONF_OK; 458 | } 459 | 460 | static ngx_udp_endpoint_t * 461 | ngx_http_udplog_add_endpoint(ngx_conf_t *cf, ngx_udplog_addr_t *peer_addr) 462 | { 463 | ngx_http_udplog_main_conf_t *umcf; 464 | ngx_udp_endpoint_t *endpoint; 465 | 466 | umcf = ngx_http_conf_get_module_main_conf(cf, ngx_http_udplog_module); 467 | 468 | if(umcf->endpoints == NULL) { 469 | umcf->endpoints = ngx_array_create(cf->pool, 2, sizeof(ngx_udp_endpoint_t)); 470 | if (umcf->endpoints == NULL) { 471 | return NULL; 472 | } 473 | } 474 | 475 | endpoint = ngx_array_push(umcf->endpoints); 476 | if (endpoint == NULL) { 477 | return NULL; 478 | } 479 | 480 | endpoint->peer_addr = *peer_addr; 481 | 482 | return endpoint; 483 | } 484 | 485 | static char * 486 | ngx_http_udplog_set_log(ngx_conf_t *cf, ngx_command_t *cmd, void *conf) 487 | { 488 | ngx_http_udplog_conf_t *ulcf = conf; 489 | 490 | ngx_uint_t i; 491 | ngx_str_t *value, name; 492 | ngx_http_udplog_t *log; 493 | ngx_http_log_fmt_t *fmt; 494 | ngx_http_log_main_conf_t *lmcf; 495 | ngx_url_t u; 496 | 497 | value = cf->args->elts; 498 | 499 | if (ngx_strcmp(value[1].data, "off") == 0) { 500 | ulcf->off = 1; 501 | return NGX_CONF_OK; 502 | } 503 | ulcf->off = 0; 504 | 505 | if (ulcf->logs == NULL) { 506 | ulcf->logs = ngx_array_create(cf->pool, 2, sizeof(ngx_http_udplog_t)); 507 | if (ulcf->logs == NULL) { 508 | return NGX_CONF_ERROR; 509 | } 510 | } 511 | 512 | lmcf = ngx_http_conf_get_module_main_conf(cf, ngx_http_log_module); 513 | 514 | if(lmcf == NULL) { 515 | ngx_conf_log_error(NGX_LOG_EMERG, cf, 0, 516 | "udplog module requires log module to be compiled in"); 517 | return NGX_CONF_ERROR; 518 | } 519 | 520 | log = ngx_array_push(ulcf->logs); 521 | if (log == NULL) { 522 | return NGX_CONF_ERROR; 523 | } 524 | 525 | ngx_memzero(log, sizeof(ngx_http_udplog_t)); 526 | 527 | ngx_memzero(&u, sizeof(ngx_url_t)); 528 | 529 | u.url = value[1]; 530 | u.default_port = 514; 531 | u.no_resolve = 0; 532 | 533 | if(ngx_parse_url(cf->pool, &u) != NGX_OK) { 534 | ngx_conf_log_error(NGX_LOG_EMERG, cf, 0, "%V: %s", &u.host, u.err); 535 | return NGX_CONF_ERROR; 536 | } 537 | 538 | log->endpoint = ngx_http_udplog_add_endpoint(cf, &u.addrs[0]); 539 | 540 | if(log->endpoint == NULL) { 541 | return NGX_CONF_ERROR; 542 | } 543 | log->bare = 0; 544 | if (cf->args->nelts >= 3) { 545 | name = value[2]; 546 | 547 | if (ngx_strcmp(name.data, "combined") == 0) { 548 | lmcf->combined_used = 1; 549 | } 550 | } else { 551 | name.len = sizeof("combined") - 1; 552 | name.data = (u_char *) "combined"; 553 | lmcf->combined_used = 1; 554 | } 555 | if (cf->args->nelts >= 4) { 556 | if (ngx_strcmp(value[3].data, "bare") == 0) { 557 | log->bare = 1; 558 | } 559 | } 560 | fmt = lmcf->formats.elts; 561 | for (i = 0; i < lmcf->formats.nelts; i++) { 562 | if (fmt[i].name.len == name.len 563 | && ngx_strcasecmp(fmt[i].name.data, name.data) == 0) 564 | { 565 | log->format = &fmt[i]; 566 | goto done; 567 | } 568 | } 569 | 570 | ngx_conf_log_error(NGX_LOG_EMERG, cf, 0, 571 | "unknown log format \"%V\"", &name); 572 | return NGX_CONF_ERROR; 573 | 574 | done: 575 | 576 | return NGX_CONF_OK; 577 | } 578 | 579 | 580 | static char * 581 | ngx_http_udplog_set_priority(ngx_conf_t *cf, ngx_command_t *cmd, void *conf) 582 | { 583 | ngx_http_udplog_conf_t *ulcf = conf; 584 | ngx_str_t *value; 585 | ngx_udplog_facility_t *f; 586 | ngx_udplog_severity_t *s; 587 | 588 | value = cf->args->elts; 589 | 590 | f = ngx_udplog_facilities; 591 | 592 | while(f->name.data != NULL) { 593 | if(ngx_strncmp(f->name.data, value[1].data, f->name.len) == 0) 594 | break; 595 | 596 | f++; 597 | } 598 | 599 | if(f->name.data != NULL) { 600 | ulcf->facility = f->number; 601 | } 602 | else { 603 | ngx_conf_log_error(NGX_LOG_EMERG, cf, 0, 604 | "unknown facility \"%V\"", &value[1]); 605 | return NGX_CONF_ERROR; 606 | } 607 | 608 | if (cf->args->nelts == 3) { 609 | s = ngx_udplog_severities; 610 | 611 | while(s->name.data != NULL) { 612 | if(ngx_strncmp(s->name.data, value[2].data, s->name.len) == 0) 613 | break; 614 | 615 | s++; 616 | } 617 | 618 | if(s->name.data != NULL) { 619 | ulcf->severity = s->number; 620 | } 621 | else { 622 | ngx_conf_log_error(NGX_LOG_EMERG, cf, 0, 623 | "unknown severity \"%V\"", &value[2]); 624 | return NGX_CONF_ERROR; 625 | } 626 | } 627 | 628 | return NGX_CONF_OK; 629 | } 630 | 631 | static char * 632 | ngx_http_udplog_set_tag(ngx_conf_t *cf, ngx_command_t *cmd, void *conf) 633 | { 634 | ngx_int_t n; 635 | ngx_str_t *value; 636 | ngx_http_script_compile_t sc; 637 | ngx_http_log_tag_template_t **field, *h; 638 | 639 | field = (ngx_http_log_tag_template_t**) (((u_char*)conf) + cmd->offset); 640 | 641 | value = cf->args->elts; 642 | 643 | if (*field == NULL) { 644 | *field = ngx_palloc(cf->pool, sizeof(ngx_http_log_tag_template_t)); 645 | if (*field == NULL) { 646 | return NGX_CONF_ERROR; 647 | } 648 | } 649 | 650 | h = *field; 651 | 652 | h->value = value[1]; 653 | h->lengths = NULL; 654 | h->values = NULL; 655 | 656 | /* 657 | * Compile field name 658 | */ 659 | n = ngx_http_script_variables_count(&value[1]); 660 | 661 | if (n > 0) { 662 | ngx_memzero(&sc, sizeof(ngx_http_script_compile_t)); 663 | 664 | sc.cf = cf; 665 | sc.source = &value[1]; 666 | sc.lengths = &h->lengths; 667 | sc.values = &h->values; 668 | sc.variables = n; 669 | sc.complete_lengths = 1; 670 | sc.complete_values = 1; 671 | 672 | if (ngx_http_script_compile(&sc) != NGX_OK) { 673 | return NGX_CONF_ERROR; 674 | } 675 | } 676 | 677 | return NGX_CONF_OK; 678 | } 679 | 680 | static ngx_int_t 681 | ngx_http_udplog_init(ngx_conf_t *cf) 682 | { 683 | ngx_int_t rc; 684 | ngx_uint_t i; 685 | ngx_http_core_main_conf_t *cmcf; 686 | ngx_http_udplog_main_conf_t *umcf; 687 | ngx_http_handler_pt *h; 688 | ngx_udp_endpoint_t *e; 689 | 690 | umcf = ngx_http_conf_get_module_main_conf(cf, ngx_http_udplog_module); 691 | 692 | if(umcf->endpoints != NULL) { 693 | e = umcf->endpoints->elts; 694 | for(i = 0;i < umcf->endpoints->nelts;i++) { 695 | rc = ngx_udplog_init_endpoint(cf, e + i); 696 | 697 | if(rc != NGX_OK) { 698 | return NGX_ERROR; 699 | } 700 | } 701 | 702 | cmcf = ngx_http_conf_get_module_main_conf(cf, ngx_http_core_module); 703 | 704 | h = ngx_array_push(&cmcf->phases[NGX_HTTP_LOG_PHASE].handlers); 705 | if (h == NULL) { 706 | return NGX_ERROR; 707 | } 708 | 709 | *h = ngx_http_udplog_handler; 710 | } 711 | 712 | return NGX_OK; 713 | } 714 | --------------------------------------------------------------------------------