static njs_ret_t ngx_http_js_ext_get_variable(njs_vm_t *vm, njs_value_t *value, void *obj, uintptr_t data) { nxt_str_t *v; ngx_str_t name; ngx_uint_t key; ngx_http_request_t *r; ngx_http_variable_value_t *vv; r = (ngx_http_request_t *) obj; v = (nxt_str_t *) data; name.data = v->start; name.len = v->length; key = ngx_hash_strlow(name.data, name.data, name.len); vv = ngx_http_get_variable(r, &name, key); if (vv == NULL || vv->not_found) { return njs_string_create(vm, value, NULL, 0, 0); } return njs_string_create(vm, value, vv->data, vv->len, 0); }
static mrb_value ngx_http_mruby_variable_get(mrb_state *mrb, mrb_value self, const char *c_name) { ngx_http_request_t *r; ngx_http_variable_value_t *var; ngx_str_t ngx_name; u_char *low; size_t len; ngx_uint_t key; r = ngx_http_mruby_get_request(); ngx_name.len = ngx_strlen(c_name); ngx_name.data = (u_char *)c_name; len = ngx_name.len; if (len) { low = ngx_pnalloc(r->pool, len); if (low == NULL) { return mrb_nil_value(); } } else { return mrb_nil_value(); } key = ngx_hash_strlow(low, ngx_name.data, len); var = ngx_http_get_variable(r, &ngx_name, key); if (var->not_found) { return mrb_nil_value(); } return mrb_str_new(mrb, (char *)var->data, var->len); }
/** * Get nginx internal variables content * * @retval Always return a string or nil on Lua stack. Return nil when failed to get * content, and actual content string when found the specified variable. * @seealso ngx_http_lua_var_set * */ int ngx_http_lua_var_get(lua_State *L) { ngx_http_request_t *r; u_char *p, *lowcase; size_t len; ngx_uint_t hash; ngx_str_t name; ngx_http_variable_value_t *vv; lua_getglobal(L, GLOBALS_SYMBOL_REQUEST); r = lua_touserdata(L, -1); lua_pop(L, 1); if (r == NULL) { return luaL_error(L, "no request object found"); } p = (u_char*) luaL_checklstring(L, -1, &len); lowcase = ngx_pnalloc(r->pool, len); if (lowcase == NULL) { return luaL_error(L, "memory allocation error"); } hash = ngx_hash_strlow(lowcase, p, len); name.len = len; name.data = lowcase; #if defined(nginx_version) && \ (nginx_version >= 8036 || \ (nginx_version < 8000 && nginx_version >= 7066)) vv = ngx_http_get_variable(r, &name, hash); #else vv = ngx_http_get_variable(r, &name, hash, 1); #endif if (vv == NULL || vv->not_found) { lua_pushnil(L); return 1; } lua_pushlstring(L, (const char*) vv->data, (size_t) vv->len); return 1; }
static jlong JNICALL jni_ngx_http_clojure_mem_get_variable(JNIEnv *env, jclass cls, jlong r, jlong nname, jlong varlenPtr) { ngx_http_request_t *req = (ngx_http_request_t *) r; ngx_str_t *name = (ngx_str_t *)nname; ngx_http_variable_value_t *vp = ngx_http_get_variable(req, name, ngx_hash_key(name->data, name->len)); if (vp->not_found) { return 0; } *((u_int *)varlenPtr) = vp->len; return (uintptr_t)vp; }
static int ngx_http_lua_var_get(lua_State *l) { ngx_http_request_t *r; u_char *p, *lowcase; size_t len; ngx_uint_t hash; ngx_str_t var; ngx_http_variable_value_t *vv; int got = 0; lua_getglobal(l, GLOBALS_SYMBOL_REQUEST); r = lua_touserdata(l, -1); lua_pop(l, 1); p = (u_char*)luaL_checklstring(l, -1, &len); if(r != NULL && p != NULL) { lowcase = ngx_pnalloc(r->pool, len); if(lowcase == NULL) { ngx_log_error(NGX_LOG_ERR, r->connection->log, 0, "(lua-var-get) can't allocate memory to hold lower-cased variable name: varname='%.*s', len=%d", len, p, len); } hash = ngx_hash_strlow(lowcase, p, len); var.len = len; var.data = lowcase; vv = ngx_http_get_variable(r, &var, hash); if(vv == NULL || vv->not_found) { ngx_log_error(NGX_LOG_ERR, r->connection->log, 0, "(lua-var-get) no such a nginx variable: varname='%.*s', len=%d", len, lowcase, len); } else { // found the specified var lua_pushlstring(l, (const char*)vv->data, (size_t)vv->len); got = 1; } } else { dd("(lua-var-get) no valid nginx request pointer or variable name: r=%p, p=%p", r, p); } // return nil if no data were found if(!got) { lua_pushnil(l); } return 1; }
static ngx_int_t nchan_process_legacy_channel_id(ngx_http_request_t *r, nchan_loc_conf_t *cf, ngx_str_t **ret_id) { static ngx_str_t channel_id_var_name = ngx_string("push_channel_id"); ngx_uint_t key = ngx_hash_key(channel_id_var_name.data, channel_id_var_name.len); ngx_http_variable_value_t *vv = NULL; ngx_str_t *group = &cf->channel_group; ngx_str_t tmpid; ngx_str_t *id; size_t sz; u_char *cur; nchan_request_ctx_t *ctx = ngx_http_get_module_ctx(r, nchan_module); ctx->channel_id_count = 0; vv = ngx_http_get_variable(r, &channel_id_var_name, key); if (vv == NULL || vv->not_found || vv->len == 0) { //ngx_log_error(NGX_LOG_WARN, r->connection->log, 0, "nchan: the legacy $push_channel_id variable is not set"); return NGX_ABORT; } else { tmpid.len = vv->len; tmpid.data = vv->data; } if(validate_id(r, &tmpid, cf) != NGX_OK) { *ret_id = NULL; return NGX_DECLINED; } sz = group->len + 1 + tmpid.len; if((id = ngx_palloc(r->pool, sizeof(*id) + sz)) == NULL) { ngx_log_error(NGX_LOG_ERR, r->connection->log, 0, "nchan: can't allocate space for legacy channel id"); *ret_id = NULL; return NGX_ERROR; } id->len = sz; id->data = (u_char *)&id[1]; cur = id->data; ngx_memcpy(cur, group->data, group->len); cur += group->len; cur[0]='/'; cur++; ngx_memcpy(cur, tmpid.data, tmpid.len); ctx->channel_id_count = 1; ctx->channel_id[0] = *id; *ret_id = id; return NGX_OK; }
int ngx_http_tcl_getv_cmd(ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *const objv[]) { ngx_http_request_t *r = getrequest(clientData); ngx_http_variable_value_t *vv; Tcl_Obj *varObj; ngx_str_t varname; int rc; int len; if (objc < 2 || objc > 3) { Tcl_WrongNumArgs(interp, 1, objv, "varname ?default?"); return TCL_ERROR; } varObj = objv[1]; /* TODO: check return */ rc = SetVarFromAny(interp, varObj); if (rc != TCL_OK) { return rc; } Tcl_GetStringFromObj(varObj, &len); varname.len = len; varname.data = (u_char*)varObj->internalRep.ptrAndLongRep.ptr; vv = ngx_http_get_variable(r, &varname, vartype_get_hash(varObj)); if (vv->not_found) { if (objc == 3) { Tcl_SetObjResult(interp, objv[2]); return TCL_OK; } Tcl_ResetResult(interp); Tcl_AppendResult(interp, "variable \"", Tcl_GetString(varObj), "\" doesn't exist", NULL); return TCL_ERROR; } Tcl_SetObjResult(interp, Tcl_NewStringObj((char*)vv->data, vv->len)); return TCL_OK; }
static mrb_value ngx_mrb_var_get(mrb_state *mrb, mrb_value self, const char *c_name, size_t c_len, ngx_http_request_t *r) { ngx_http_variable_value_t *var; ngx_str_t ngx_name; size_t len; ngx_uint_t key; ngx_name.len = c_len; ngx_name.data = (u_char *)c_name; len = ngx_name.len; key = ngx_hash_strlow(ngx_name.data, ngx_name.data, len); var = ngx_http_get_variable(r, &ngx_name, key); if (var == NULL) { ngx_log_error(NGX_LOG_ERR , r->connection->log , 0 , "%s ERROR %s:%d: %s is NULL" , MODULE_NAME , __func__ , __LINE__ , c_name ); return mrb_nil_value(); } // return variable value wraped with mruby string if (!var->not_found) { return mrb_str_new(mrb, (char *)var->data, var->len); } else { ngx_log_error(NGX_LOG_ERR , r->connection->log , 0 , "%s ERROR %s:%d: %s not found" , MODULE_NAME , __func__ , __LINE__ , c_name ); return mrb_nil_value(); } }
static int ngx_http_pbmsgpack_get_cmd ( ngx_http_request_t* r) { static ngx_str_t cmd_var_name = ngx_string("arg_cmd"); ngx_http_variable_value_t* res_value; if(NULL == (res_value = ngx_http_get_variable(r,&cmd_var_name,0))) { return -1; } if(res_value->valid && 0 == res_value->not_found) { int cmd = ngx_atoi(res_value->data, res_value->len); ngx_log_debug1(NGX_LOG_DEBUG_HTTP, r->connection->log, 0, "[pagecache] get varaibale success![cmd:%d]" , cmd); return cmd; } else { return -1; } return -1; }
/** * Get nginx internal variables content * * @retval Always return a string or nil on Lua stack. Return nil when failed * to get content, and actual content string when found the specified variable. * @seealso ngx_http_lua_var_set * */ static int ngx_http_lua_var_get(lua_State *L) { ngx_http_request_t *r; u_char *p, *lowcase; size_t len; ngx_uint_t hash; ngx_str_t name; ngx_http_variable_value_t *vv; #if (NGX_PCRE) u_char *val; ngx_uint_t n; LUA_NUMBER index; int *cap; #endif r = ngx_http_lua_get_req(L); if (r == NULL) { return luaL_error(L, "no request object found"); } ngx_http_lua_check_fake_request(L, r); #if (NGX_PCRE) if (lua_type(L, -1) == LUA_TNUMBER) { /* it is a regex capturing variable */ index = lua_tonumber(L, -1); if (index <= 0) { lua_pushnil(L); return 1; } n = (ngx_uint_t) index * 2; dd("n = %d, ncaptures = %d", (int) n, (int) r->ncaptures); if (r->captures == NULL || r->captures_data == NULL || n >= r->ncaptures) { lua_pushnil(L); return 1; } /* n >= 0 && n < r->ncaptures */ cap = r->captures; p = r->captures_data; val = &p[cap[n]]; lua_pushlstring(L, (const char *) val, (size_t) (cap[n + 1] - cap[n])); return 1; } #endif if (lua_type(L, -1) != LUA_TSTRING) { return luaL_error(L, "bad variable name"); } p = (u_char *) lua_tolstring(L, -1, &len); lowcase = lua_newuserdata(L, len); hash = ngx_hash_strlow(lowcase, p, len); name.len = len; name.data = lowcase; vv = ngx_http_get_variable(r, &name, hash); if (vv == NULL || vv->not_found) { lua_pushnil(L); return 1; } lua_pushlstring(L, (const char *) vv->data, (size_t) vv->len); return 1; }
int ngx_http_lua_ffi_var_get(ngx_http_request_t *r, u_char *name_data, size_t name_len, u_char *lowcase_buf, int capture_id, u_char **value, size_t *value_len, char **err) { ngx_uint_t hash; ngx_str_t name; ngx_http_variable_value_t *vv; #if (NGX_PCRE) u_char *p; ngx_uint_t n; int *cap; #endif if (r == NULL) { *err = "no request object found"; return NGX_ERROR; } if ((r)->connection->fd == -1) { *err = "API disabled in the current context"; return NGX_ERROR; } #if (NGX_PCRE) if (name_data == 0) { if (capture_id <= 0) { return NGX_DECLINED; } /* it is a regex capturing variable */ n = (ngx_uint_t) capture_id * 2; dd("n = %d, ncaptures = %d", (int) n, (int) r->ncaptures); if (r->captures == NULL || r->captures_data == NULL || n >= r->ncaptures) { return NGX_DECLINED; } /* n >= 0 && n < r->ncaptures */ cap = r->captures; p = r->captures_data; *value = &p[cap[n]]; *value_len = (size_t) (cap[n + 1] - cap[n]); return NGX_OK; } #endif hash = ngx_hash_strlow(lowcase_buf, name_data, name_len); name.data = lowcase_buf; name.len = name_len; dd("variable name: %.*s", (int) name_len, lowcase_buf); vv = ngx_http_get_variable(r, &name, hash); if (vv == NULL || vv->not_found) { return NGX_DECLINED; } *value = vv->data; *value_len = vv->len; return NGX_OK; }
//get the index static ngx_http_dclass_kvdata_str *ngx_http_dclass_index(ngx_http_request_t *r) { ngx_uint_t i; u_char *hfield=NULL; ngx_uint_t key; ngx_str_t str; ngx_http_variable_value_t *val; const dclass_keyvalue *kvd; ngx_list_part_t *part; ngx_table_elt_t *header; ngx_http_dclass_conf_t *cf; ngx_http_dclass_kvdata_str *kvs; cf = ngx_http_get_module_loc_conf(r,ngx_http_dclass_module); if(!cf->enable || !cf->head[0]) return NULL; ngx_str_set(&str,"dclass_ptr"); key=ngx_hash_key(str.data,str.len); val=ngx_http_get_variable(r, &str, key); if(val && val->valid && val->data && !ngx_rstrncmp((u_char*)"ptr",val->data,3)) { kvs=(ngx_http_dclass_kvdata_str*)val->data; ngx_log_error(NGX_HTTP_DCLASS_LOGLEVEL,r->connection->log,0,"dClass: classify cache: '%s'",kvs->kvd[0]->id); return kvs; } if(!*cf->hfield.data) { if(r->headers_in.user_agent) hfield = r->headers_in.user_agent->value.data; } else { part=&r->headers_in.headers.part; header=part->elts; for (i=0;;i++) { if(i>=part->nelts) { if(part->next==NULL) break; part=part->next; header=part->elts; i=0; } if(!ngx_strcasecmp(cf->hfield.data,header[i].key.data)) { hfield=header[i].value.data; break; } } } if(hfield==NULL) return NULL; kvs=(ngx_http_dclass_kvdata_str*)ngx_pcalloc(r->pool,sizeof(ngx_http_dclass_kvdata_str)); if(kvs==NULL) return NULL; for(i=0;i<NGX_HTTP_DCLASS_INDEXES && cf->head[i];i++) { kvd=dclass_classify(cf->head[i],(char*)hfield); kvs->kvd[i]=kvd; ngx_cpystrn(kvs->data,(u_char*)"ptr",4); ngx_log_error(NGX_HTTP_DCLASS_LOGLEVEL,r->connection->log,0,"dClass: classify %d: '%s' => '%s'",i,hfield,kvd->id); } return kvs; }
//#define mechanics_debug //naxsi_modifiers_debug static ngx_int_t ngx_http_dummy_access_handler(ngx_http_request_t *r) { ngx_http_request_ctx_t *ctx; ngx_int_t rc; ngx_http_dummy_loc_conf_t *cf; ngx_http_core_loc_conf_t *clcf; struct tms tmsstart, tmsend; clock_t start, end; ngx_http_variable_value_t *lookup; static ngx_str_t learning_flag = ngx_string(RT_LEARNING); static ngx_str_t enable_flag = ngx_string(RT_ENABLE); static ngx_str_t post_action_flag = ngx_string(RT_POST_ACTION); ctx = ngx_http_get_module_ctx(r, ngx_http_naxsi_module); cf = ngx_http_get_module_loc_conf(r, ngx_http_naxsi_module); clcf = ngx_http_get_module_loc_conf(r, ngx_http_core_module); /* ngx_log_debug(NGX_LOG_DEBUG_HTTP, r->connection->log, 0, */ /* "naxsi_entry_point"); */ if (ctx && ctx->over) return (NGX_DECLINED); if (ctx && ctx->wait_for_body) { #ifdef mechanics_debug ngx_log_debug(NGX_LOG_DEBUG_HTTP, r->connection->log, 0, "naxsi:NGX_AGAIN"); #endif return (NGX_DONE); } if (!cf) return (NGX_ERROR); /* the module is not enabled here */ if (!cf->enabled || cf->force_disabled) return (NGX_DECLINED); /* don't process internal requests. */ if (r->internal) { #ifdef mechanics_debug ngx_log_debug(NGX_LOG_DEBUG_HTTP, r->connection->log, 0, "XX-DON'T PROCESS (%V)|CTX:%p|ARGS:%V|METHOD=%s|INTERNAL:%d", &(r->uri), ctx, &(r->args), r->method == NGX_HTTP_POST ? "POST" : r->method == NGX_HTTP_PUT ? "PUT" : r->method == NGX_HTTP_GET ? "GET" : "UNKNOWN!!", r->internal); #endif return (NGX_DECLINED); } #ifdef mechanics_debug ngx_log_debug(NGX_LOG_DEBUG_HTTP, r->connection->log, 0, "XX-processing (%V)|CTX:%p|ARGS:%V|METHOD=%s|INTERNAL:%d", &(r->uri), ctx, &(r->args), r->method == NGX_HTTP_POST ? "POST" : r->method == NGX_HTTP_PUT ? "PUT" : r->method == NGX_HTTP_GET ? "GET" : "UNKNOWN!!", r->internal); #endif if (!ctx) { ctx = ngx_pcalloc(r->pool, sizeof(ngx_http_request_ctx_t)); /* might have been set by a previous trigger */ if (ctx->learning) { clcf->post_action.data = 0; //cf->denied_url->data; clcf->post_action.len = 0; //cf->denied_url->len; } if (ctx == NULL) return NGX_ERROR; ngx_http_set_ctx(r, ctx, ngx_http_naxsi_module); #ifdef naxsi_modifiers_debug ngx_log_debug(NGX_LOG_DEBUG_HTTP, r->connection->log, 0, "XX-dummy : orig learning : %d", cf->learning ? 1 : 0); #endif ctx->learning = cf->learning; lookup = ngx_http_get_variable(r, &learning_flag, cf->flag_learning_h); if (lookup && !lookup->not_found) { ctx->learning = lookup->data[0] - '0'; #ifdef naxsi_modifiers_debug ngx_log_debug(NGX_LOG_DEBUG_HTTP, r->connection->log, 0, "XX-dummy : override learning : %d", ctx->learning ? 1 : 0); #endif } #ifdef naxsi_modifiers_debug ngx_log_debug(NGX_LOG_DEBUG_HTTP, r->connection->log, 0, "XX-dummy : [final] learning : %d", ctx->learning ? 1 : 0); #endif ctx->enabled = cf->enabled; #ifdef naxsi_modifiers_debug ngx_log_debug(NGX_LOG_DEBUG_HTTP, r->connection->log, 0, "XX-dummy : orig enabled : %d", ctx->enabled ? 1 : 0); #endif lookup = ngx_http_get_variable(r, &enable_flag, cf->flag_enable_h); if (lookup && !lookup->not_found) { ctx->enabled = lookup->data[0] - '0'; #ifdef naxsi_modifiers_debug ngx_log_debug(NGX_LOG_DEBUG_HTTP, r->connection->log, 0, "XX-dummy : override enable : %d", ctx->enabled ? 1 : 0); #endif } #ifdef naxsi_modifiers_debug ngx_log_debug(NGX_LOG_DEBUG_HTTP, r->connection->log, 0, "XX-dummy : [final] enabled : %d", ctx->enabled ? 1 : 0); #endif if (cf->learning) ctx->post_action = 1; else ctx->post_action = 0; #ifdef naxsi_modifiers_debug ngx_log_debug(NGX_LOG_DEBUG_HTTP, r->connection->log, 0, "XX-dummy : orig post_action : %d", ctx->post_action ? 1 : 0); #endif lookup = ngx_http_get_variable(r, &post_action_flag, cf->flag_post_action_h); if (lookup && !lookup->not_found) { ctx->post_action = lookup->data[0] - '0'; #ifdef naxsi_modifier_debug ngx_log_debug(NGX_LOG_DEBUG_HTTP, r->connection->log, 0, "XX-dummy : override post_action : %d", ctx->post_action ? 1 : 0); #endif } #ifdef naxsi_modifiers_debug ngx_log_debug(NGX_LOG_DEBUG_HTTP, r->connection->log, 0, "XX-dummy : [final] post_action : %d", ctx->post_action ? 1 : 0); #endif //--- /* the module is not enabled here */ if (!ctx->enabled) return (NGX_DECLINED); if ((r->method == NGX_HTTP_POST || r->method == NGX_HTTP_PUT) && !ctx->ready) { #ifdef mechanics_debug ngx_log_debug(NGX_LOG_DEBUG_HTTP, r->connection->log, 0, "XX-dummy : body_request : before !"); #endif rc = ngx_http_read_client_request_body(r, ngx_http_dummy_payload_handler); /* this might happen quite often, especially with big files / ** low network speed. our handler is called when headers are read, ** but, often, the full body request hasn't yet, so ** read client request body will return ngx_again. Then we need ** to return ngx_done, wait for our handler to be called once ** body request arrived, and let him call core_run_phases ** to be able to process the request. */ if (rc == NGX_AGAIN) { ctx->wait_for_body = 1; #ifdef mechanics_debug ngx_log_debug(NGX_LOG_DEBUG_HTTP, r->connection->log, 0, "XX-dummy : body_request : NGX_AGAIN !"); #endif return (NGX_DONE); } else if (rc >= NGX_HTTP_SPECIAL_RESPONSE) { /* this debug print should be commented, but the thing is that ** according to what I read into nginx src code, it may happen ** and I haven't been abble to trigger this, so I just let it ** here to know when this special case will be triggered */ ngx_log_debug(NGX_LOG_DEBUG_HTTP, r->connection->log, 0, "XX-dummy : SPECIAL RESPONSE !!!!"); return rc; } } else ctx->ready = 1; } if (ctx && ctx->ready && !ctx->over) { if ((start = times(&tmsstart)) == (clock_t)-1) ngx_log_debug(NGX_LOG_DEBUG_HTTP, r->connection->log, 0, "XX-dummy : Failed to get time"); ngx_http_dummy_data_parse(ctx, r); cf->request_processed++; if ((end = times(&tmsend)) == (clock_t)-1) ngx_log_debug(NGX_LOG_DEBUG_HTTP, r->connection->log, 0, "XX-dummy : Failed to get time"); if (end - start > 0) ngx_log_debug(NGX_LOG_DEBUG_HTTP, r->connection->log, 0, "[MORE THAN 1MS] times : start:%l end:%l diff:%l", start, end, (end-start)); ctx->over = 1; if (ctx->block) { cf->request_blocked++; rc = ngx_http_output_forbidden_page(ctx, r); //nothing: return (NGX_OK); //redirect : return (NGX_HTTP_OK); return (rc); } else if (ctx->log) rc = ngx_http_output_forbidden_page(ctx, r); } #ifdef mechanics_debug ngx_log_debug(NGX_LOG_DEBUG_HTTP, r->connection->log, 0, "NGX_FINISHED !"); #endif return (NGX_DECLINED); }
/*----------------------------------------------------------------------------*/ ngx_int_t rp_bazaar_cmd_handler(ngx_http_request_t *r) { ngx_http_rp_loc_conf_t *lc; rp_bazaar_ctx_t *ctx; size_t i = 0; ctx = ngx_pcalloc(r->pool, sizeof(rp_bazaar_ctx_t)); if (ctx == NULL) { return NGX_ERROR; } ctx->redirect = ngx_pcalloc(r->pool, c_redirect_len); if (ctx->redirect == NULL) { return NGX_ERROR; } ctx->json_root = NULL; ctx->finalize_on_post_handler = 0; ctx->in_buffer = NULL; ctx->in_buffer_len = 0; ctx->in_status = 0; ngx_http_set_ctx(r, ctx, ngx_http_rp_module); lc = ngx_http_get_module_loc_conf(r, ngx_http_rp_module); /* Just test local directory here - we would need to check it for almost * all calls anyway */ if(lc->bazaar_dir.data == NULL) { fprintf(stderr, "Bazaar local directory not found\n"); return NGX_HTTP_INTERNAL_SERVER_ERROR; } ctx->json_root = cJSON_CreateObject(r->pool); if(ctx->json_root == NULL) { fprintf(stderr, "Cannot allocate cJSON object\n"); return NGX_HTTP_INTERNAL_SERVER_ERROR; } /* Bazaar commands */ for(i = 0; bazaar_cmds[i].name != NULL; i++) { ngx_str_t arg_name = { strlen(bazaar_cmds[i].name), (u_char *)bazaar_cmds[i].name }; ngx_uint_t arg_key = ngx_hash_key(arg_name.data, arg_name.len); ngx_http_variable_value_t *arg_val = NULL; int rc; char **arg_argv = NULL; int arg_argc = 0; arg_val = ngx_http_get_variable(r, &arg_name, arg_key); /* check validity of the specified http variables * note: not all attributes of arg_value are set within ngx_http_get_variable, thus * the order of the following checks are important otherwise it could come to the usage * of uninitialized value what would lead to invalid processing */ if (!arg_val) continue; if (arg_val->not_found == 1) continue; if (arg_val->valid == 0) continue; arg_val->data[arg_val->len] = '\0'; arg_argc = rp_module_cmd_parse_args((const char *)arg_val->data, arg_val->len, &arg_argv); fprintf(stderr, "Calling application: %s\n", &bazaar_cmds[i].name[4]); /* Install/Remove special case */ if ( !strncmp(&bazaar_cmds[i].name[4], "install", 7) || !strncmp(&bazaar_cmds[i].name[4], "remove", 6) ) { if(arg_argv) { for(i = 0; i < (size_t)arg_argc; i++) { if(arg_argv[i]) { free(arg_argv[i]); arg_argv[i] = NULL; } } free(arg_argv); } return rp_bazaar_install(r); } if((rc = bazaar_cmds[i].func(r, &ctx->json_root, arg_argc, arg_argv)) < 0) { /* error - fill the output buffer and send it back */ fprintf(stderr, "Application %s failed: %d\n", bazaar_cmds[i].name, rc); } if(arg_argv) { for(i = 0; i < (size_t)arg_argc; i++) { if(arg_argv[i]) { free(arg_argv[i]); arg_argv[i] = NULL; } } free(arg_argv); } /* Prepare response header & body */ return rp_module_send_response(r, &ctx->json_root); } int ret = 0; /* Unknown command response */ if (i >= sizeof(bazaar_cmds)/sizeof(rp_module_cmd_t)) { rp_module_cmd_error(&ctx->json_root, "Unknown command.", NULL, r->pool); return rp_module_send_response(r, &ctx->json_root); } /* Default Bazaar entry point - list of applications with versions */ cJSON *json_tok = NULL; char *host = (char *)r->headers_in.server.data; char mac[18]; sprintf(mac, "00:00:00:00:00:00"); if (rp_bazaar_get_mac("/sys/class/net/eth0/address", mac)) { fprintf(stderr, "Cannot obtain MAC address.\n"); } static unsigned long long dna = 0; if (!dna || dna == 1) { if (rp_bazaar_get_dna(&dna)) { fprintf(stderr, "Cannot obtain DNA number.\n"); } } char dna_s[64]; sprintf(dna_s, "%016llx", dna); /* Get Ecosystem version */ char ecoversion[64]; sprintf(ecoversion, "unknown"); cJSON *ecoinfo = NULL; if (!get_info(&ecoinfo, (const char *)lc->bazaar_dir.data, "", r->pool)) { fprintf(stderr, "Cannot obtain Ecosystem version.\n"); } else { if (ecoinfo != NULL) { cJSON *j_ver = cJSON_GetObjectItem(ecoinfo, "version"); if(j_ver == NULL) { fprintf(stderr, "Cannot get version from ecoinfo JSON.\n"); } else { strncpy(ecoversion, j_ver->valuestring, sizeof ecoversion); cJSON_Delete(j_ver, r->pool); } cJSON_Delete(ecoinfo, r->pool); } } /* Populate JSON */ cJSON_AddItemToObject(ctx->json_root, "version", cJSON_CreateString(ecoversion, r->pool), r->pool); cJSON_AddItemToObject(ctx->json_root, "dna", cJSON_CreateString(dna_s, r->pool), r->pool); cJSON_AddItemToObject(ctx->json_root, "mac", cJSON_CreateString(mac, r->pool), r->pool); // TODO: Serial number? cJSON_AddItemToObject(ctx->json_root, "host", cJSON_CreateString(host, r->pool), r->pool); cJSON *apps_root; cJSON_AddItemToObject(ctx->json_root, "apps", apps_root=cJSON_CreateObject(r->pool), r->pool); if(apps_root == NULL) { fprintf(stderr, "Can not allocate cJSON object\n"); return NGX_HTTP_INTERNAL_SERVER_ERROR; } fprintf(stderr, "Making list of apps\n"); /* Add the non-verbose list of apps */ rp_bazaar_app_get_local_list((const char *)lc->bazaar_dir.data, &apps_root, r->pool, 0); /* Issue a POST with JSON defined above to Bazaar server */ char *js = cJSON_Print(ctx->json_root, r->pool); cJSON_Minify(js); fprintf(stderr, "Bazaar handshake:\n%s", js); char *jse = NULL; char *jsp = NULL; char *bazaar_dv = NULL; const char *c_payload = "payload="; const char *c_device = "/device"; jse = url_encode(js); jsp = malloc(strlen(jse) + strlen(c_payload) + 1); if (!jsp) { fprintf(stderr, "Cannot malloc() payload.\n"); ret = NGX_HTTP_INTERNAL_SERVER_ERROR; goto out; } sprintf(jsp, "%s%s", c_payload, jse); bazaar_dv = (char *)malloc(strlen((char *)lc->bazaar_server.data) + strlen(c_device) + 1); if (!bazaar_dv) { fprintf(stderr, "Cannot malloc() device.\n"); ret = NGX_HTTP_INTERNAL_SERVER_ERROR; goto out; } sprintf(bazaar_dv, "%s%s", lc->bazaar_server.data, c_device); fprintf(stderr, "post bazaar_dv %s\n", bazaar_dv); post_resp_t resp = { NULL, 0 }; if (post(jsp, bazaar_dv, &resp)) { if (resp.data) free(resp.data); /* Redirect to Bazaar access error */ fprintf(stderr, "Cannot access %s.\n", bazaar_dv); snprintf(ctx->redirect, c_redirect_len, "http://%s/error_bazaar_access.html", host); goto out; } /* Get token from POST response */ if (resp.data) { fprintf(stderr,"Bazaar handshake response:\n%s", resp.data); json_tok = cJSON_Parse(resp.data, r->pool); if (!json_tok) { /* Redirect to Bazaar protocol error */ fprintf(stderr,"No JSON found in the following response:\n\"%s\"\n", resp.data); snprintf(ctx->redirect, c_redirect_len, "http://%s/error_bazaar_proto.html", host); } else { cJSON *jtok = cJSON_GetObjectItem(json_tok, "token"); if (!jtok) { /* Redirect to Bazaar protocol error */ fprintf(stderr, "No token found in the following JSON:\n\"%s\"\n", resp.data); snprintf(ctx->redirect, c_redirect_len, "http://%s/error_bazaar_proto.html", host); } else { /* Redirect to Bazaar with token */ snprintf(ctx->redirect, c_redirect_len, "%s/token/%s", lc->bazaar_server.data, jtok->valuestring); /* Store token for session control */ strncpy(g_token, jtok->valuestring, c_token_len); g_token[c_token_len - 1] = '\0'; } } free(resp.data); } out: if (jsp) free(jsp); if (jse) free(jse); if (bazaar_dv) free(bazaar_dv); //TODO: Is ctx->json_root handled by the pool deallocator? //if (ctx->json_root) cJSON_Delete(ctx->json_root, r->pool); if (json_tok) cJSON_Delete(json_tok, r->pool); if (ret) return ret; fprintf(stderr, "Redirecting to: %s\n", ctx->redirect); return rp_module_redirect(r, ctx->redirect); }
static ngx_int_t ngx_http_touch_handler(ngx_http_request_t *r) { //main config ngx_http_upstream_main_conf_t * umcf = ngx_http_get_module_main_conf(r, ngx_http_upstream_module); //server config //ngx_http_upstream_srv_conf_t * umsf = r->srv_conf[ngx_http_upstream_module.ctx_index]; //location config //ngx_http_core_loc_conf_t * hclf = (*(r->loc_conf)); ngx_http_upstream_srv_conf_t **uscfp, *uscf; ngx_uint_t i, j, len; u_char *p, *b; ngx_chain_t *cl; ngx_http_upstream_server_t *us; ngx_log_debug0(NGX_LOG_DEBUG_HTTP, r->connection->log, 0, "ngx_http_touch_handler"); ngx_log_debug1(NGX_LOG_DEBUG_HTTP, r->connection->log, 0, "umcfaddress=%d", umcf); if (umcf == NULL || umcf->upstreams.nelts <= 0) { ngx_log_debug0(NGX_LOG_DEBUG_HTTP, r->connection->log, 0, "NGX_HTTP_NO_CONTENT"); return NGX_HTTP_NO_CONTENT; } //response content buffer length len = 1024 * 16; p = b = ngx_palloc(r->pool, len); ngx_log_debug1(NGX_LOG_DEBUG_HTTP, r->connection->log, 0, "umcf->upstreams.nelts=%ui\n", umcf->upstreams.nelts); ngx_http_variable_value_t *upstreamname, *servername; ngx_uint_t hash; hash = ngx_hash_key(arg_upstream.data, arg_upstream.len); upstreamname = ngx_http_get_variable(r, &arg_upstream, hash); hash = ngx_hash_key(arg_server.data, arg_server.len); servername = ngx_http_get_variable(r, &arg_server, hash); p = ngx_slprintf(p, b + len, "Worker id: %P\n", ngx_pid); uscfp = umcf->upstreams.elts; for (i = 0; i < umcf->upstreams.nelts; i++) { ngx_log_debug1(NGX_LOG_DEBUG_HTTP, r->connection->log, 0, "i=%d", i); uscf = uscfp[i]; // ngx_slprintf(start, last, fmt, args) p = ngx_slprintf(p, b + len, "upstream name: %V\n", &uscf->host); ngx_log_debug1(NGX_LOG_DEBUG_HTTP, r->connection->log, 0, "upstream name:%V", &uscf->host); if(uscf->servers != NULL && uscf->servers->nelts > 0) { ngx_log_debug1(NGX_LOG_DEBUG_HTTP, r->connection->log, 0, "uscf->servers->nelts = %ui", uscf->servers->nelts); ngx_log_debug1(NGX_LOG_DEBUG_HTTP, r->connection->log, 0, "uscf->servers->size = %ui", uscf->servers->size); for (j = 0; j < uscf->servers->nelts; j++) { ngx_log_debug1(NGX_LOG_DEBUG_HTTP, r->connection->log, 0, "j=%d", j); //us = (ngx_http_upstream_server_t *)(uscf->servers->elts + j * uscf->servers->size); us = (ngx_http_upstream_server_t *)uscf->servers->elts + j; ngx_log_debug1(NGX_LOG_DEBUG_HTTP, r->connection->log, 0, "us=%d", us); if (us != NULL) { if (upstreamname && upstreamname->not_found == 0 && servername && servername->not_found == 0 && ngx_strncmp(upstreamname->data, uscf->host.data, upstreamname->len) == 0 && ngx_strncmp(servername->data, us->addrs->name.data, servername->len) == 0) { ngx_http_touch_set_upstream_server(r, us, uscf); } ngx_log_debug6(NGX_LOG_DEBUG_HTTP, r->connection->log, 0, "usaddress=%d, weight=%d, max_fails=%d, fail_timeout=%d, down=%d, backup=%d", us, us->weight, us->max_fails, us->fail_timeout, us->down, us->backup); ngx_log_debug1(NGX_LOG_DEBUG_HTTP, r->connection->log, 0, "server name=%V", &us->addrs->name); if (us->addrs != NULL) { // socket to string // parameters :sockaddr, start, max_length, port print? p += ngx_sock_ntop(us->addrs->sockaddr, p, b - p + len, 1); } p = ngx_slprintf(p, b + len, " weight=%d, max_fails=%d, fail_timeout=%d, down=%d, backup=%d\n", us->weight, us->max_fails, us->fail_timeout, us->down, us->backup); } } } } ngx_log_debug0(NGX_LOG_DEBUG_HTTP, r->connection->log, 1, "ngx_alloc_chain_link"); cl = ngx_alloc_chain_link(r->pool); if (cl == NULL) { ngx_log_debug0(NGX_LOG_DEBUG_HTTP, r->connection->log, 1, "ngx_alloc_chain_link error"); return NGX_ERROR; } cl->next = NULL; cl->buf = ngx_calloc_buf(r->pool); ngx_log_debug0(NGX_LOG_DEBUG_HTTP, r->connection->log, 1, "ngx_calloc_buf"); if (cl->buf == NULL) { ngx_log_debug0(NGX_LOG_DEBUG_HTTP, r->connection->log, 1, "ngx_calloc_buf error"); return NGX_ERROR; } cl->buf->pos = b; cl->buf->last = p; cl->buf->last_buf = 1;/* this is last , and there will be no more buffers in the request */ cl->buf->memory = 1; /* content is in read-only memory */ /* (i.e., filters should copy it rather than rewrite in place) */ r->headers_out.content_length_n = p - b; r->headers_out.status = NGX_HTTP_OK; ngx_log_debug0(NGX_LOG_DEBUG_HTTP, r->connection->log, 1, "ngx_http_send_header(r)"); if (ngx_http_send_header(r) != NGX_OK) { ngx_log_debug0(NGX_LOG_DEBUG_HTTP, r->connection->log, 1, "ngx_http_send_header(r) error"); return NGX_ERROR; } ngx_log_debug0(NGX_LOG_DEBUG_HTTP, r->connection->log, 1, "ngx_http_output_filter"); return ngx_http_output_filter(r, cl); }
ngx_int_t ngx_http_pinba_handler(ngx_http_request_t *r) /* {{{ */ { ngx_http_pinba_loc_conf_t *lcf; ngx_uint_t status, i, *pcode; ngx_http_variable_value_t *request_uri; ngx_http_variable_value_t *request_schema; ngx_log_debug0(NGX_LOG_DEBUG_HTTP, r->connection->log, 0, "http pinba handler"); lcf = ngx_http_get_module_loc_conf(r, ngx_http_pinba_module); /* bail out right away if disabled */ if (lcf->enable == 0) { return NGX_OK; } status = 0; if (r->err_status) { status = r->err_status; } else if (r->headers_out.status) { status = r->headers_out.status; } /* first check if the status is ignored */ if (status > 0 && lcf->ignore_codes) { pcode = lcf->ignore_codes->elts; for (i = 0; i < lcf->ignore_codes->nelts; i++) { if (status == pcode[i]) { /* this status is ignored, so just get outta here */ return NGX_OK; } } } if (lcf->socket.fd < 0) { /* no socket -> no data */ return NGX_OK; /* doesn't matter, the return status is ignored anyway */ } /* ok, we may proceed then.. */ { char hostname[PINBA_STR_BUFFER_SIZE] = {0}, server_name[PINBA_STR_BUFFER_SIZE] = {0}, script_name[PINBA_STR_BUFFER_SIZE] = {0}; ngx_time_t *tp; ngx_msec_int_t ms; size_t packed_size; Pinba__Request *request; request = malloc(sizeof(Pinba__Request)); pinba__request__init(request); if (lcf->hostname[0] == '\0') { if (gethostname(hostname, sizeof(hostname)) == 0) { memcpy(lcf->hostname, hostname, PINBA_STR_BUFFER_SIZE); } else { memcpy(lcf->hostname, "unknown", sizeof("unknown")); } } /* hostname */ request->hostname = strdup(lcf->hostname); memcpy(server_name, r->headers_in.server.data, (r->headers_in.server.len > PINBA_STR_BUFFER_SIZE) ? PINBA_STR_BUFFER_SIZE : r->headers_in.server.len); request->server_name = strdup(server_name); request_uri = ngx_http_get_variable(r, &request_uri_name, request_uri_key); if (request_uri && !request_uri->not_found && request_uri->len > 0) { /* try variable first */ memcpy(script_name, request_uri->data, (request_uri->len > PINBA_STR_BUFFER_SIZE) ? PINBA_STR_BUFFER_SIZE : request_uri->len); } else { u_char *q = NULL; int uri_len = r->unparsed_uri.len; /* default script_name is $request_uri with GET parameters cut off */ if (r->unparsed_uri.data && r->unparsed_uri.len) { q = (u_char *)ngx_strchr(r->unparsed_uri.data, '?'); if (q) { uri_len = q - r->unparsed_uri.data; } } memcpy(script_name, r->unparsed_uri.data, (uri_len > PINBA_STR_BUFFER_SIZE) ? PINBA_STR_BUFFER_SIZE : uri_len); } request->script_name = strdup(script_name); request_schema = ngx_http_get_variable(r, &request_schema_name, request_schema_key); if (request_schema && !request_schema->not_found && request_schema->len) { request->schema = malloc(request_schema->len + 1); if (request->schema) { memcpy(request->schema, request_schema->data, request_schema->len); request->schema[request_schema->len] = '\0'; } } else { #if (NGX_HTTP_SSL) if (r->connection->ssl) request->schema = strdup("https"); else #endif request->schema = strdup("http"); } request->document_size = r->connection->sent; tp = ngx_timeofday(); ms = (ngx_msec_int_t) ((tp->sec - r->start_sec) * 1000 + (tp->msec - r->start_msec)); ms = (ms >= 0) ? ms : 0; request->request_time = (float)ms/1000; request->status = r->headers_out.status; request->has_status = 1; /* just nullify other fields for now */ request->request_count = 0; request->memory_peak = 0; request->ru_utime = 0; request->ru_stime = 0; packed_size = pinba__request__get_packed_size(request); if (ngx_http_pinba_push_into_buffer(lcf, r, request, packed_size) < 0) { ngx_http_pinba_send_data(lcf, r, request, packed_size); pinba__request__free_unpacked(request, NULL); } } return NGX_OK; }
static ngx_inline ngx_int_t ngx_http_modsecurity_save_request_body(ngx_http_request_t *r) { ngx_http_modsecurity_ctx_t *ctx; apr_off_t content_length; ngx_buf_t *buf; ngx_http_core_srv_conf_t *cscf; size_t size; ngx_http_connection_t *hc; ctx = ngx_http_get_module_ctx(r, ngx_http_modsecurity); apr_brigade_length(ctx->brigade, 0, &content_length); if (r->header_in->end - r->header_in->last >= content_length) { /* use r->header_in */ if (ngx_buf_size(r->header_in)) { /* move to the end */ ngx_memmove(r->header_in->pos + content_length, r->header_in->pos, ngx_buf_size(r->header_in)); } if (apr_brigade_flatten(ctx->brigade, (char *)r->header_in->pos, (apr_size_t *)&content_length) != APR_SUCCESS) { return NGX_ERROR; } apr_brigade_cleanup(ctx->brigade); r->header_in->last += content_length; return NGX_OK; } if (ngx_buf_size(r->header_in)) { /* * ngx_http_set_keepalive will reuse r->header_in if * (r->header_in != c->buffer && r->header_in.last != r->header_in.end), * so we need this code block. * see ngx_http_set_keepalive, ngx_http_alloc_large_header_buffer */ cscf = ngx_http_get_module_srv_conf(r, ngx_http_core_module); size = ngx_max(cscf->large_client_header_buffers.size, (size_t)content_length + ngx_buf_size(r->header_in)); hc = r->http_connection; #if defined(nginx_version) && nginx_version >= 1011011 if (hc->free && size == cscf->large_client_header_buffers.size) { buf = hc->free->buf; #else if (hc->nfree && size == cscf->large_client_header_buffers.size) { buf = hc->free[--hc->nfree]; #endif ngx_log_debug2(NGX_LOG_DEBUG_HTTP, r->connection->log, 0, "ModSecurity: use http free large header buffer: %p %uz", buf->pos, buf->end - buf->last); } else if (hc->nbusy < cscf->large_client_header_buffers.num) { if (hc->busy == NULL) { hc->busy = ngx_palloc(r->connection->pool, cscf->large_client_header_buffers.num * sizeof(ngx_buf_t *)); } if (hc->busy == NULL) { return NGX_ERROR; } else { buf = ngx_create_temp_buf(r->connection->pool, size); } } else { /* TODO: how to deal this case ? */ return NGX_ERROR; } } else { buf = ngx_create_temp_buf(r->pool, (size_t) content_length); } if (buf == NULL) { return NGX_ERROR; } if (apr_brigade_flatten(ctx->brigade, (char *)buf->pos, (apr_size_t *)&content_length) != APR_SUCCESS) { return NGX_ERROR; } apr_brigade_cleanup(ctx->brigade); buf->last += content_length; ngx_memcpy(buf->last, r->header_in->pos, ngx_buf_size(r->header_in)); buf->last += ngx_buf_size(r->header_in); r->header_in = buf; return NGX_OK; } static ngx_inline ngx_int_t ngx_http_modsecurity_load_headers_out(ngx_http_request_t *r) { ngx_http_modsecurity_ctx_t *ctx; char *data; request_rec *req; ngx_http_variable_value_t *vv; ngx_list_part_t *part; ngx_table_elt_t *h; ngx_uint_t i; char *key, *value; u_char *buf = NULL; size_t size = 0; ctx = ngx_http_get_module_ctx(r, ngx_http_modsecurity); req = ctx->req; req->status = r->headers_out.status; req->status_line = (char *)ngx_pstrdup0(r->pool, &r->headers_out.status_line); /* deep copy */ part = &r->headers_out.headers.part; h = part->elts; for (i = 0; ; i++) { if (i >= part->nelts) { if (part->next == NULL) break; part = part->next; h = part->elts; i = 0; } size += h[i].key.len + h[i].value.len + 2; buf = ngx_palloc(r->pool, size); if (buf == NULL) { return NGX_ERROR; } key = (char *)buf; buf = ngx_cpymem(buf, h[i].key.data, h[i].key.len); *buf++ = '\0'; value = (char *)buf; buf = ngx_cpymem(buf, h[i].value.data, h[i].value.len); *buf++ = '\0'; apr_table_addn(req->headers_out, key, value); ngx_log_debug2(NGX_LOG_DEBUG_HTTP, r->connection->log, 0, "ModSecurity: load headers out: \"%V: %V\"", &h[i].key, &h[i].value); } for (i = 0; special_headers_out[i].name; i++) { vv = ngx_http_get_variable(r, &special_headers_out[i].variable_name, ngx_hash_key(special_headers_out[i].variable_name.data, special_headers_out[i].variable_name.len)); if (vv && !vv->not_found) { data = ngx_palloc(r->pool, vv->len + 1); if (data == NULL) { return NGX_ERROR; } ngx_memcpy(data,vv->data, vv->len); data[vv->len] = '\0'; apr_table_setn(req->headers_out, special_headers_out[i].name, data); ngx_log_debug2(NGX_LOG_DEBUG_HTTP, r->connection->log, 0, "ModSecurity: load headers out: \"%s: %s\"", special_headers_out[i].name, data); } } req->content_type = apr_table_get(ctx->req->headers_out, "Content-Type"); req->content_encoding = apr_table_get(ctx->req->headers_out, "Content-Encoding"); data = (char *)apr_table_get(ctx->req->headers_out, "Content-Languages"); if(data != NULL) { ctx->req->content_languages = apr_array_make(ctx->req->pool, 1, sizeof(const char *)); *(const char **)apr_array_push(ctx->req->content_languages) = data; } /* req->chunked = r->chunked; may be useless */ req->clength = r->headers_out.content_length_n; req->mtime = apr_time_make(r->headers_out.last_modified_time, 0); ngx_log_debug0(NGX_LOG_DEBUG_HTTP, r->connection->log, 0, "ModSecurity: load headers out done"); return NGX_OK; }
ngx_int_t ngx_dynamic_upstream_build_op(ngx_http_request_t *r, ngx_dynamic_upstream_op_t *op) { ngx_uint_t i; size_t args_size; u_char *low; ngx_uint_t key; ngx_str_t *args; ngx_http_variable_value_t *var; ngx_memzero(op, sizeof(ngx_dynamic_upstream_op_t)); /* default setting for op */ op->op = NGX_DYNAMIC_UPSTEAM_OP_LIST; op->status = NGX_HTTP_OK; ngx_str_null(&op->upstream); op->weight = 1; op->max_fails = 1; op->fail_timeout = 10; args = (ngx_str_t *)&ngx_dynamic_upstream_params; args_size = sizeof(ngx_dynamic_upstream_params) / sizeof(ngx_str_t); for (i=0;i<args_size;i++) { low = ngx_pnalloc(r->pool, args[i].len); if (low == NULL) { op->status = NGX_HTTP_INTERNAL_SERVER_ERROR; ngx_log_error(NGX_LOG_ERR, r->connection->log, 0, "failed to allocate memory from r->pool %s:%d", __FUNCTION__, __LINE__); return NGX_ERROR; } key = ngx_hash_strlow(low, args[i].data, args[i].len); var = ngx_http_get_variable(r, &args[i], key); if (!var->not_found) { if (ngx_strcmp("arg_upstream", args[i].data) == 0) { op->upstream.data = var->data; op->upstream.len = var->len; } else if (ngx_strcmp("arg_verbose", args[i].data) == 0) { op->verbose = 1; } else if (ngx_strcmp("arg_add", args[i].data) == 0) { op->op |= NGX_DYNAMIC_UPSTEAM_OP_ADD; } else if (ngx_strcmp("arg_remove", args[i].data) == 0) { op->op |= NGX_DYNAMIC_UPSTEAM_OP_REMOVE; } else if (ngx_strcmp("arg_backup", args[i].data) == 0) { op->backup = 1; } else if (ngx_strcmp("arg_server", args[i].data) == 0) { op->server.data = var->data; op->server.len = var->len; } else if (ngx_strcmp("arg_weight", args[i].data) == 0) { op->weight = ngx_atoi(var->data, var->len); if (op->weight == NGX_ERROR) { op->status = NGX_HTTP_BAD_REQUEST; ngx_log_error(NGX_LOG_ERR, r->connection->log, 0, "weight is not number. %s:%d", __FUNCTION__, __LINE__); return NGX_ERROR; } op->op |= NGX_DYNAMIC_UPSTEAM_OP_PARAM; op->op_param |= NGX_DYNAMIC_UPSTEAM_OP_PARAM_WEIGHT; op->verbose = 1; } else if (ngx_strcmp("arg_max_fails", args[i].data) == 0) { op->max_fails = ngx_atoi(var->data, var->len); if (op->max_fails == NGX_ERROR) { op->status = NGX_HTTP_BAD_REQUEST; ngx_log_error(NGX_LOG_ERR, r->connection->log, 0, "max_fails is not number. %s:%d", __FUNCTION__, __LINE__); return NGX_ERROR; } op->op |= NGX_DYNAMIC_UPSTEAM_OP_PARAM; op->op_param |= NGX_DYNAMIC_UPSTEAM_OP_PARAM_MAX_FAILS; op->verbose = 1; } else if (ngx_strcmp("arg_fail_timeout", args[i].data) == 0) { op->fail_timeout = ngx_atoi(var->data, var->len); if (op->fail_timeout == NGX_ERROR) { op->status = NGX_HTTP_BAD_REQUEST; ngx_log_error(NGX_LOG_ERR, r->connection->log, 0, "fail_timeout is not number. %s:%d", __FUNCTION__, __LINE__); return NGX_ERROR; } op->op |= NGX_DYNAMIC_UPSTEAM_OP_PARAM; op->op_param |= NGX_DYNAMIC_UPSTEAM_OP_PARAM_FAIL_TIMEOUT; op->verbose = 1; } else if (ngx_strcmp("arg_up", args[i].data) == 0) { op->up = 1; op->op |= NGX_DYNAMIC_UPSTEAM_OP_PARAM; op->op_param |= NGX_DYNAMIC_UPSTEAM_OP_PARAM_UP; op->verbose = 1; } else if (ngx_strcmp("arg_down", args[i].data) == 0) { op->down = 1; op->op |= NGX_DYNAMIC_UPSTEAM_OP_PARAM; op->op_param |= NGX_DYNAMIC_UPSTEAM_OP_PARAM_DOWN; op->verbose = 1; } } } /* can not add and remove at once */ if ((op->op & NGX_DYNAMIC_UPSTEAM_OP_ADD) && (op->op & NGX_DYNAMIC_UPSTEAM_OP_REMOVE)) { op->status = NGX_HTTP_BAD_REQUEST; ngx_log_error(NGX_LOG_ERR, r->connection->log, 0, "add and remove at once are not allowed. %s:%d", __FUNCTION__, __LINE__); return NGX_ERROR; } if (op->op & NGX_DYNAMIC_UPSTEAM_OP_ADD) { op->op = NGX_DYNAMIC_UPSTEAM_OP_ADD; } else if (op->op & NGX_DYNAMIC_UPSTEAM_OP_REMOVE) { op->op = NGX_DYNAMIC_UPSTEAM_OP_REMOVE; } /* can not up and down at once */ if (op->up && op->down) { op->status = NGX_HTTP_BAD_REQUEST; ngx_log_error(NGX_LOG_ERR, r->connection->log, 0, "down and up at once are not allowed. %s:%d", __FUNCTION__, __LINE__); return NGX_ERROR; } return NGX_OK; }
/** * Set nginx internal variable content * * @retval Always return a boolean on Lua stack. Return true when variable * content was modified successfully, false otherwise. * @seealso ngx_http_lua_var_get * */ int ngx_http_lua_var_set(lua_State *L) { ngx_http_variable_value_t *vv; u_char *p, *lowcase, *val; size_t len; ngx_str_t name; ngx_uint_t hash; ngx_http_request_t *r; lua_getglobal(L, GLOBALS_SYMBOL_REQUEST); r = lua_touserdata(L, -1); lua_pop(L, 1); if (r == NULL) { return luaL_error(L, "no request object found"); } /* we skip the first argument that is the table */ p = (u_char*) luaL_checklstring(L, 2, &len); lowcase = ngx_palloc(r->pool, len + 1); if (lowcase == NULL) { return luaL_error(L, "memory allocation error"); } lowcase[len] = '\0'; hash = ngx_hash_strlow(lowcase, p, len); name.len = len; name.data = lowcase; #if defined(nginx_version) && \ (nginx_version >= 8036 || \ (nginx_version < 8000 && nginx_version >= 7066)) vv = ngx_http_get_variable(r, &name, hash); #else vv = ngx_http_get_variable(r, &name, hash, 1); #endif if (vv == NULL || vv->not_found) { return luaL_error(L, "variable \"%s\" not defined yet; " "you sould have used \"set $%s '';\" earlier " "in the config file", lowcase, lowcase); } p = (u_char*) luaL_checklstring(L, 3, &len); val = ngx_palloc(r->pool, len); if (val == NULL) { return luaL_error(L, "memory allocation erorr"); } ngx_memcpy(val, p, len); vv->valid = 1; vv->not_found = 0; vv->data = val; vv->len = len; return 0; }
static ngx_inline ngx_int_t ngx_http_modsecurity_load_headers_out(ngx_http_request_t *r) { ngx_http_modsecurity_ctx_t *ctx; char *data; request_rec *req; u_char *content_type; ngx_uint_t content_type_len; ngx_http_variable_value_t *vv; ngx_list_part_t *part; ngx_table_elt_t *h; ngx_uint_t i; char *key, *value; u_char *buf = NULL; size_t size = 0; ctx = ngx_http_get_module_ctx(r, ngx_http_modsecurity); req = ctx->req; req->status = r->headers_out.status; req->status_line = (char *)ngx_pstrdup0(r->pool, &r->headers_out.status_line); if (r->headers_out.charset.len) { content_type_len = r->headers_out.content_type.len + r->headers_out.charset.len + ngx_strlen("; charset=") + 1; content_type = ngx_palloc(r->pool, content_type_len); if (content_type == NULL) { return NGX_ERROR; } ngx_snprintf(content_type, content_type_len, "%V; charset=%V%Z", &r->headers_out.content_type, &r->headers_out.charset); r->headers_out.content_type.data = content_type; r->headers_out.content_type.len = content_type_len; } /* deep copy */ part = &r->headers_out.headers.part; h = part->elts; for (i = 0; ; i++) { if (i >= part->nelts) { if (part->next == NULL) break; part = part->next; h = part->elts; i = 0; } size += h[i].key.len + h[i].value.len + 2; buf = ngx_palloc(r->pool, size); if (buf == NULL) { return NGX_ERROR; } key = (char *)buf; buf = ngx_cpymem(buf, h[i].key.data, h[i].key.len); *buf++ = '\0'; value = (char *)buf; buf = ngx_cpymem(buf, h[i].value.data, h[i].value.len); *buf++ = '\0'; apr_table_addn(req->headers_out, key, value); ngx_log_debug2(NGX_LOG_DEBUG_HTTP, r->connection->log, 0, "ModSecurity: load headers out: \"%V: %V\"", &h[i].key, &h[i].value); } for (i = 0; special_headers_out[i].name; i++) { vv = ngx_http_get_variable(r, &special_headers_out[i].variable_name, ngx_hash_key(special_headers_out[i].variable_name.data, special_headers_out[i].variable_name.len)); if (vv && !vv->not_found) { data = ngx_palloc(r->pool, vv->len + 1); if (data == NULL) { return NGX_ERROR; } ngx_memcpy(data,vv->data, vv->len); data[vv->len] = '\0'; apr_table_setn(req->headers_out, special_headers_out[i].name, data); ngx_log_debug2(NGX_LOG_DEBUG_HTTP, r->connection->log, 0, "ModSecurity: load headers out: \"%s: %s\"", special_headers_out[i].name, data); } } req->content_type = apr_table_get(ctx->req->headers_out, "Content-Type"); req->content_encoding = apr_table_get(ctx->req->headers_out, "Content-Encoding"); data = (char *)apr_table_get(ctx->req->headers_out, "Content-Languages"); if(data != NULL) { ctx->req->content_languages = apr_array_make(ctx->req->pool, 1, sizeof(const char *)); *(const char **)apr_array_push(ctx->req->content_languages) = data; } /* req->chunked = r->chunked; may be useless */ req->clength = r->headers_out.content_length_n; req->mtime = apr_time_make(r->headers_out.last_modified_time, 0); ngx_log_debug0(NGX_LOG_DEBUG_HTTP, r->connection->log, 0, "ModSecurity: load headers out done"); return NGX_OK; }
/* ** [ENTRY POINT] does : this is the function called by nginx : ** - Set up the context for the request ** - Check if the job is done and we're called again ** - if it's a POST/PUT request, setup hook for body dataz ** - call dummy_data_parse ** - check our context struct (with scores & stuff) against custom check rules ** - check if the request should be denied */ static ngx_int_t ngx_http_dummy_access_handler(ngx_http_request_t *r) { ngx_http_request_ctx_t *ctx; ngx_int_t rc; ngx_http_dummy_loc_conf_t *cf; struct tms tmsstart, tmsend; clock_t start, end; ngx_http_variable_value_t *lookup; static ngx_str_t learning_flag = ngx_string(RT_LEARNING); static ngx_str_t enable_flag = ngx_string(RT_ENABLE); static ngx_str_t post_action_flag = ngx_string(RT_POST_ACTION); static ngx_str_t extensive_log_flag = ngx_string(RT_EXTENSIVE_LOG); static ngx_str_t libinjection_sql_flag = ngx_string(RT_LIBINJECTION_SQL); static ngx_str_t libinjection_xss_flag = ngx_string(RT_LIBINJECTION_XSS); ctx = ngx_http_get_module_ctx(r, ngx_http_naxsi_module); cf = ngx_http_get_module_loc_conf(r, ngx_http_naxsi_module); if (ctx && ctx->over) return (NGX_DECLINED); if (ctx && ctx->wait_for_body) { NX_DEBUG(_debug_mechanics, NGX_LOG_DEBUG_HTTP, r->connection->log, 0, "naxsi:NGX_AGAIN"); return (NGX_DONE); } if (!cf) return (NGX_ERROR); /* the module is not enabled here */ /* if enable directive is not present at all in the location, don't try to do dynamic lookup for "live" enabled naxsi, this would be very rude. */ if (!cf->enabled) return (NGX_DECLINED); /* On the other hand, if naxsi has been explicitly disabled in this location (using naxsi directive), user is probably trying to do something. */ if (cf->force_disabled) { /* Look if the user did not try to enable naxsi dynamically */ lookup = ngx_http_get_variable(r, &enable_flag, cf->flag_enable_h); if (lookup && !lookup->not_found && lookup->len > 0) { ngx_log_debug(NGX_LOG_DEBUG_HTTP, r->connection->log, 0, "live enable is present %d", lookup->data[0] - '0'); if (lookup->data[0] - '0' != 1) { return (NGX_DECLINED);} } else return (NGX_DECLINED); } /* don't process internal requests. */ if (r->internal) { NX_DEBUG(_debug_mechanics, NGX_LOG_DEBUG_HTTP, r->connection->log, 0, "XX-DON'T PROCESS (%V)|CTX:%p|ARGS:%V|METHOD=%s|INTERNAL:%d", &(r->uri), ctx, &(r->args), r->method == NGX_HTTP_POST ? "POST" : r->method == NGX_HTTP_PUT ? "PUT" : r->method == NGX_HTTP_GET ? "GET" : "UNKNOWN!!", r->internal); return (NGX_DECLINED); } NX_DEBUG(_debug_mechanics, NGX_LOG_DEBUG_HTTP, r->connection->log, 0, "XX-processing (%V)|CTX:%p|ARGS:%V|METHOD=%s|INTERNAL:%d", &(r->uri), ctx, &(r->args), r->method == NGX_HTTP_POST ? "POST" : r->method == NGX_HTTP_PUT ? "PUT" : r->method == NGX_HTTP_GET ? "GET" : "UNKNOWN!!", r->internal); if (!ctx) { ctx = ngx_pcalloc(r->pool, sizeof(ngx_http_request_ctx_t)); if (ctx == NULL) return NGX_ERROR; ngx_http_set_ctx(r, ctx, ngx_http_naxsi_module); NX_DEBUG(_debug_modifier, NGX_LOG_DEBUG_HTTP, r->connection->log, 0, "XX-dummy : orig learning : %d", cf->learning ? 1 : 0); /* it seems that nginx will - in some cases - have a variable with empty content but with lookup->not_found set to 0, so check len as well */ ctx->learning = cf->learning; lookup = ngx_http_get_variable(r, &learning_flag, cf->flag_learning_h); if (lookup && !lookup->not_found && lookup->len > 0) { ctx->learning = lookup->data[0] - '0'; NX_DEBUG(_debug_modifier, NGX_LOG_DEBUG_HTTP, r->connection->log, 0, "XX-dummy : override learning : %d (raw=%d)", ctx->learning ? 1 : 0, lookup->len); } NX_DEBUG( _debug_modifier, NGX_LOG_DEBUG_HTTP, r->connection->log, 0, "XX-dummy : [final] learning : %d", ctx->learning ? 1 : 0); ctx->enabled = cf->enabled; NX_DEBUG( _debug_modifier, NGX_LOG_DEBUG_HTTP, r->connection->log, 0, "XX-dummy : orig enabled : %d", ctx->enabled ? 1 : 0); lookup = ngx_http_get_variable(r, &enable_flag, cf->flag_enable_h); if (lookup && !lookup->not_found && lookup->len > 0) { ctx->enabled = lookup->data[0] - '0'; NX_DEBUG( _debug_modifier, NGX_LOG_DEBUG_HTTP, r->connection->log, 0, "XX-dummy : override enable : %d", ctx->enabled ? 1 : 0); } NX_DEBUG( _debug_modifier, NGX_LOG_DEBUG_HTTP, r->connection->log, 0, "XX-dummy : [final] enabled : %d", ctx->enabled ? 1 : 0); /* ** LIBINJECTION_SQL */ ctx->libinjection_sql = cf->libinjection_sql_enabled; NX_DEBUG( _debug_modifier, NGX_LOG_DEBUG_HTTP, r->connection->log, 0, "XX-dummy : orig libinjection_sql : %d", ctx->libinjection_sql ? 1 : 0); lookup = ngx_http_get_variable(r, &libinjection_sql_flag, cf->flag_libinjection_sql_h); if (lookup && !lookup->not_found && lookup->len > 0) { ctx->libinjection_sql = lookup->data[0] - '0'; NX_DEBUG( _debug_modifier, NGX_LOG_DEBUG_HTTP, r->connection->log, 0, "XX-dummy : override libinjection_sql : %d", ctx->libinjection_sql ? 1 : 0); } NX_DEBUG( _debug_modifier, NGX_LOG_DEBUG_HTTP, r->connection->log, 0, "XX-dummy : [final] libinjection_sql : %d", ctx->libinjection_sql ? 1 : 0); /* ** LIBINJECTION_XSS */ ctx->libinjection_xss = cf->libinjection_xss_enabled; NX_DEBUG( _debug_modifier, NGX_LOG_DEBUG_HTTP, r->connection->log, 0, "XX-dummy : orig libinjection_xss : %d", ctx->libinjection_xss ? 1 : 0); lookup = ngx_http_get_variable(r, &libinjection_xss_flag, cf->flag_libinjection_xss_h); if (lookup && !lookup->not_found && lookup->len > 0) { ctx->libinjection_xss = lookup->data[0] - '0'; NX_DEBUG( _debug_modifier, NGX_LOG_DEBUG_HTTP, r->connection->log, 0, "XX-dummy : override libinjection_xss : %d", ctx->libinjection_xss ? 1 : 0); } NX_DEBUG( _debug_modifier, NGX_LOG_DEBUG_HTTP, r->connection->log, 0, "XX-dummy : [final] libinjection_xss : %d", ctx->libinjection_xss ? 1 : 0); /* post_action is off by default. */ ctx->post_action = 0; NX_DEBUG( _debug_modifier , NGX_LOG_DEBUG_HTTP, r->connection->log, 0, "XX-dummy : orig post_action : %d", ctx->post_action ? 1 : 0); lookup = ngx_http_get_variable(r, &post_action_flag, cf->flag_post_action_h); if (lookup && !lookup->not_found && lookup->len > 0) { ctx->post_action = lookup->data[0] - '0'; NX_DEBUG( _debug_modifier, NGX_LOG_DEBUG_HTTP, r->connection->log, 0, "XX-dummy : override post_action : %d", ctx->post_action ? 1 : 0); } NX_DEBUG( _debug_modifier, NGX_LOG_DEBUG_HTTP, r->connection->log, 0, "XX-dummy : [final] post_action : %d", ctx->post_action ? 1 : 0); NX_DEBUG( _debug_modifier , NGX_LOG_DEBUG_HTTP, r->connection->log, 0, "XX-dummy : orig extensive_log : %d", ctx->extensive_log ? 1 : 0); lookup = ngx_http_get_variable(r, &extensive_log_flag, cf->flag_extensive_log_h); if (lookup && !lookup->not_found && lookup->len > 0) { ctx->extensive_log = lookup->data[0] - '0'; NX_DEBUG( _debug_modifier, NGX_LOG_DEBUG_HTTP, r->connection->log, 0, "XX-dummy : override extensive_log : %d", ctx->extensive_log ? 1 : 0); } NX_DEBUG( _debug_modifier, NGX_LOG_DEBUG_HTTP, r->connection->log, 0, "XX-dummy : [final] extensive_log : %d", ctx->extensive_log ? 1 : 0); /* the module is not enabled here */ if (!ctx->enabled) return (NGX_DECLINED); if ((r->method == NGX_HTTP_POST || r->method == NGX_HTTP_PUT) && !ctx->ready) { NX_DEBUG( _debug_mechanics, NGX_LOG_DEBUG_HTTP, r->connection->log, 0, "XX-dummy : body_request : before !"); rc = ngx_http_read_client_request_body(r, ngx_http_dummy_payload_handler); /* this might happen quite often, especially with big files / ** low network speed. our handler is called when headers are read, ** but, often, the full body request hasn't yet, so ** read client request body will return ngx_again. Then we need ** to return ngx_done, wait for our handler to be called once ** body request arrived, and let him call core_run_phases ** to be able to process the request. */ if (rc == NGX_AGAIN) { ctx->wait_for_body = 1; NX_DEBUG( _debug_mechanics, NGX_LOG_DEBUG_HTTP, r->connection->log, 0, "XX-dummy : body_request : NGX_AGAIN !"); return (NGX_DONE); } else if (rc >= NGX_HTTP_SPECIAL_RESPONSE) { /* ** might happen but never saw it, let the debug print. */ ngx_log_debug(NGX_LOG_DEBUG_HTTP, r->connection->log, 0, "XX-dummy : SPECIAL RESPONSE !!!!"); return rc; } } else ctx->ready = 1; } if (ctx && ctx->ready && !ctx->over) { if ((start = times(&tmsstart)) == (clock_t)-1) ngx_log_debug(NGX_LOG_DEBUG_HTTP, r->connection->log, 0, "XX-dummy : Failed to get time"); ngx_http_dummy_data_parse(ctx, r); cf->request_processed++; if ((end = times(&tmsend)) == (clock_t)-1) ngx_log_debug(NGX_LOG_DEBUG_HTTP, r->connection->log, 0, "XX-dummy : Failed to get time"); if (end - start > 10) ngx_log_debug(NGX_LOG_DEBUG_HTTP, r->connection->log, 0, "[MORE THAN 10MS] times : start:%l end:%l diff:%l", start, end, (end-start)); ctx->over = 1; if (ctx->block || ctx->drop) { cf->request_blocked++; rc = ngx_http_output_forbidden_page(ctx, r); //nothing: return (NGX_OK); //redirect : return (NGX_HTTP_OK); return rc; } } NX_DEBUG(_debug_mechanics, NGX_LOG_DEBUG_HTTP, r->connection->log, 0, "NGX_FINISHED !"); return NGX_DECLINED; }
static ngx_int_t ngx_http_touch_set_upstream_server(ngx_http_request_t *r, ngx_http_upstream_server_t *us, ngx_http_upstream_srv_conf_t *uscf) { ngx_int_t weight = us->weight; ngx_int_t max_fails = us->max_fails; ngx_int_t fail_timeout = us->fail_timeout; ngx_int_t down = us->down; ngx_int_t backup = us->backup; ngx_http_variable_value_t *value; ngx_uint_t hash, i; ngx_str_t s; ngx_http_upstream_rr_peers_t *peers, *backup_peers; hash = ngx_hash_key(arg_weight.data, arg_weight.len); value = ngx_http_get_variable(r, &arg_weight, hash); ngx_log_debug2(NGX_LOG_DEBUG_HTTP, r->connection->log, 1, "value->len=%d, value->not_found=%d\n", value->len, value->not_found); if (value && value->not_found == 0) { weight = ngx_atoi(value->data, value->len); ngx_log_debug1(NGX_LOG_DEBUG_HTTP, r->connection->log, 1, "new weight=%d\n", weight); if (weight > 0) { us->weight = weight; } } hash = ngx_hash_key(arg_max_fails.data, arg_max_fails.len); value = ngx_http_get_variable(r, &arg_max_fails, hash); if (value && value->not_found == 0) { max_fails = ngx_atoi(value->data, value->len); ngx_log_debug1(NGX_LOG_DEBUG_HTTP, r->connection->log, 1, "new max_fails=%d\n", max_fails); if (max_fails != NGX_ERROR) { us->max_fails = max_fails; } } hash = ngx_hash_key(arg_down.data, arg_down.len); value = ngx_http_get_variable(r, &arg_down, hash); if (value && value->not_found == 0) { down = ngx_atoi(value->data, value->len); ngx_log_debug1(NGX_LOG_DEBUG_HTTP, r->connection->log, 1, "new down=%d\n", down); if (down != NGX_ERROR) { us->down = down; } } hash = ngx_hash_key(arg_backup.data, arg_backup.len); value = ngx_http_get_variable(r, &arg_backup, hash); if (value && value->not_found == 0) { backup = ngx_atoi(value->data, value->len); ngx_log_debug1(NGX_LOG_DEBUG_HTTP, r->connection->log, 1, "new backup=%d\n", backup); if (backup != NGX_ERROR) { us->backup = backup; } } hash = ngx_hash_key(arg_fail_timeout.data, arg_fail_timeout.len); value = ngx_http_get_variable(r, &arg_fail_timeout, hash); s.len = value->len; s.data = value->data; ngx_log_debug2(NGX_LOG_DEBUG_HTTP, r->connection->log, 1, "value=%V, value->not_found=%d", &s, value->not_found); if (value && value->not_found == 0) { s.len = value->len; s.data = value->data; fail_timeout = ngx_parse_time(&s, 1); ngx_log_debug1(NGX_LOG_DEBUG_HTTP, r->connection->log, 1, "new fail_timeout=%d\n", fail_timeout); if (fail_timeout != NGX_ERROR) { us->fail_timeout = fail_timeout; } } peers = uscf->peer.data; ngx_uint_t found = 0; if(peers != NULL) { backup_peers = peers->next; for(i = 0; i < peers->number; i ++) { ngx_log_debug1(NGX_LOG_DEBUG_HTTP, r->connection->log, 1, "=== peers->peer[i].name=%V\n", &peers->peer[i].name); if (backup_peers->peer[i].name.len == us->addrs->name.len && ngx_strncmp(us->addrs->name.data, peers->peer[i].name.data, us->addrs->name.len) == 0) { peers->peer[i].max_fails = us->max_fails; peers->peer[i].fail_timeout = us->fail_timeout; peers->peer[i].down = us->down; peers->peer[i].weight = us->weight; found = 1; break; } } if (backup_peers !=NULL && !found) { for(i = 0; i < backup_peers->number; i ++) { ngx_log_debug1(NGX_LOG_DEBUG_HTTP, r->connection->log, 1, "=== backup_peers->peer[i].name=%V\n", &backup_peers->peer[i].name); if (backup_peers->peer[i].name.len == us->addrs->name.len && ngx_strncmp(us->addrs->name.data, backup_peers->peer[i].name.data, us->addrs->name.len) == 0) { backup_peers->peer[i].max_fails = us->max_fails; backup_peers->peer[i].fail_timeout = us->fail_timeout; backup_peers->peer[i].down = us->down; backup_peers->peer[i].weight = us->weight; found = 1; break; } } } } return NGX_OK; }