static ngx_int_t ngx_lua_http_btt_check_args(ngx_http_request_t *r, ngx_btt_ctx_t *ctx) { u_char *p; struct sockaddr_in *sin; /* TODO: IPv6 */ ctx->external_ip = ngx_inet_addr(r->connection->addr_text.data, r->connection->addr_text.len); if (ctx->external_ip == INADDR_NONE) { ngx_log_error(NGX_LOG_ALERT, r->connection->log, 0, "invalid external ip"); return NGX_ERROR; } sin = (struct sockaddr_in *) r->connection->sockaddr; ctx->external_port = ntohs(sin->sin_port); if (ctx->internal_ip == 0) { ctx->internal_ip = ctx->external_ip; } /* TODO: connection_id */ p = ngx_cpymem(&ctx->connection_id, &ctx->external_ip, sizeof(ctx->external_ip)); ngx_memcpy(p, &ctx->internal_port, sizeof(ctx->internal_port)); return NGX_OK; }
static in_addr_t ngx_http_qqwry_real_addr(ngx_http_request_t *r, ngx_http_qqwry_ctx_t *qqwry) { struct sockaddr_in *sin; ngx_http_variable_value_t *v; if (qqwry->index == -1) { ngx_log_debug1(NGX_LOG_DEBUG_HTTP, r->connection->log, 0, "http qqwry started: %V", &r->connection->addr_text); if (r->connection->sockaddr->sa_family != AF_INET) { return 0; } sin = (struct sockaddr_in *) r->connection->sockaddr; return ntohl(sin->sin_addr.s_addr); } v = ngx_http_get_flushed_variable(r, qqwry->index); if (v == NULL || v->not_found) { ngx_log_debug0(NGX_LOG_DEBUG_HTTP, r->connection->log, 0, "http qqwry not found"); return 0; } ngx_log_debug1(NGX_LOG_DEBUG_HTTP, r->connection->log, 0, "http qqwry started: %v", v); return ntohl(ngx_inet_addr(v->data, v->len)); }
ngx_resolver_ctx_t * ngx_resolve_start(ngx_resolver_t *r, ngx_resolver_ctx_t *temp) { in_addr_t addr; ngx_resolver_ctx_t *ctx; if (temp) { addr = ngx_inet_addr(temp->name.data, temp->name.len); if (addr != INADDR_NONE) { temp->resolver = r; temp->state = NGX_OK; temp->naddrs = 1; temp->addrs = &temp->addr; temp->addr = addr; temp->quick = 1; return temp; } } if (r->udp_connections.nelts == 0) { return NGX_NO_RESOLVER; } ctx = ngx_resolver_calloc(r, sizeof(ngx_resolver_ctx_t)); if (ctx) { ctx->resolver = r; } return ctx; }
static ngx_http_google_ctx_t * ngx_http_google_create_ctx(ngx_http_request_t * r) { ngx_http_google_loc_conf_t * glcf; glcf = ngx_http_get_module_loc_conf(r, ngx_http_google_filter_module); ngx_http_google_ctx_t * ctx; ctx = ngx_pcalloc(r->pool, sizeof(ngx_http_google_ctx_t)); if (!ctx) return NULL; ctx->host = ngx_pcalloc(r->pool, sizeof(ngx_str_t)); if (!ctx->host) return NULL; ctx->pass = ngx_pcalloc(r->pool, sizeof(ngx_str_t)); if (!ctx->pass) return NULL; ctx->arg = ngx_pcalloc(r->pool, sizeof(ngx_str_t)); if (!ctx->arg) return NULL; ctx->domain = ngx_pcalloc(r->pool, sizeof(ngx_str_t)); if (!ctx->domain) return NULL; ctx->uri = &r->unparsed_uri; ctx->host = &r->headers_in.host->value; ctx->lang = &glcf->language; ctx->type = ngx_http_google_type_main; ngx_str_t domain = *ctx->host; u_char * last = domain.data + domain.len, * find; if ((find = ngx_strlchr(domain.data, last, ':'))) { domain.len = find - domain.data; } ctx->domain->len = domain.len + 1; ctx->domain->data = ngx_pcalloc(r->pool, ctx->domain->len); if (!ctx->domain->data) return NULL; ngx_snprintf(ctx->domain->data, ctx->domain->len, ".%V", &domain); if (ngx_inet_addr(domain.data, domain.len) != INADDR_NONE) { ctx->domain->data++; ctx->domain->len --; } // default language if (!ctx->lang->len) { ngx_str_set(ctx->lang, "zh-CN"); } ctx->robots = (ctx->uri->len == 11 && !ngx_strncmp(ctx->uri->data, "/robots.txt", 11)); #if (NGX_HTTP_SSL) ngx_http_ssl_srv_conf_t * sscf; sscf = ngx_http_get_module_srv_conf(r, ngx_http_ssl_module); if (sscf->enable == 1) ctx->ssl = 1; #endif return ctx; }
static void ngx_http_authen_pass(ngx_http_authen_conf_t *cf, ngx_http_request_t *r) { // pid_t pid; char address[64]; struct sockaddr_in sa; socklen_t salen; ngx_str_t *addr; addr = &r->connection->addr_text; if (cf->addr.len == 0 || cf->addr.data == NULL) { ngx_log_stderr(NGX_OK, "Missing Authen IP address"); return; } if (addr->len >= sizeof(address)) { ngx_log_stderr(NGX_OK, "%V too long", addr); return; } ngx_memcpy(address, (char *)addr->data, addr->len); address[addr->len] = '\0'; salen = sizeof(sa); ngx_memzero(&sa, salen); sa.sin_family = AF_INET; if (cf->port == NGX_CONF_UNSET) { sa.sin_port = htons((uint16_t)NGX_HTTP_AUTHEN_PORT_DEFAULT); } else { sa.sin_port = htons((uint16_t)cf->port); } sa.sin_addr.s_addr = ngx_inet_addr(cf->addr.data, cf->addr.len); // if ((pid = fork()) < 0) { // ngx_log_stderr(NGX_OK, "Fork() failed."); // return; // } else if (pid == 0) { // /* 子进程,通知设备开启认证 */ ngx_http_authen_pass_do(&sa, address, r); // exit(0); // } else { // /* 父进程无操作 */ // } return; }
static in_addr_t ngx_http_qqwry_addr(ngx_http_request_t *r, ngx_http_qqwry_ctx_t *qqwry) { u_char *ip; u_char *p; u_char *pe; size_t len; in_addr_t addr; in_addr_t addr_tmp; ngx_table_elt_t *xfwd; addr = ngx_http_qqwry_real_addr(r, qqwry); //if (ngx_http_qqwry_is_public_addr(addr)) { // return addr; //} xfwd = r->headers_in.x_forwarded_for; if (xfwd == NULL) { return addr; } for (pe = xfwd->value.data + xfwd->value.len; pe > xfwd->value.data && (*pe < '0' || *pe > '9'); pe--); p = pe - 1; while (p >= xfwd->value.data) { if ((*p < '0' || *p > '9') && *p != '.') { len = pe - p; ip = p + 1; } else if (p == xfwd->value.data) { len = pe - p + 1; ip = p; } else { p--; continue; } addr_tmp = ntohl(ngx_inet_addr(ip, len)); if (ngx_http_qqwry_is_public_addr(addr_tmp)) { return addr_tmp; } for (pe = p; pe > xfwd->value.data && (*pe < '0' || *pe > '9'); pe--); p = pe - 1; } return addr; }
static ngx_int_t ngx_http_upstream_init_dynamic(ngx_conf_t *cf, ngx_http_upstream_srv_conf_t *us) { ngx_uint_t i; ngx_http_upstream_dynamic_srv_conf_t *dcf; ngx_http_upstream_server_t *server; ngx_str_t host; ngx_log_debug0(NGX_LOG_DEBUG_HTTP, cf->log, 0, "init dynamic resolve"); dcf = ngx_http_conf_upstream_srv_conf(us, ngx_http_upstream_dynamic_module); if (dcf->original_init_upstream(cf, us) != NGX_OK) { return NGX_ERROR; } if (us->servers) { server = us->servers->elts; for (i = 0; i < us->servers->nelts; i++) { host = server[i].host; if (ngx_inet_addr(host.data, host.len) == INADDR_NONE) { break; } } if (i == us->servers->nelts) { dcf->enabled = 0; return NGX_OK; } } dcf->original_init_peer = us->peer.init; us->peer.init = ngx_http_upstream_init_dynamic_peer; dcf->enabled = 1; return NGX_OK; }
static char *ngx_conf_set_authen_config(ngx_conf_t *cf, ngx_command_t *cmd, void *conf) { ngx_http_authen_conf_t *authencf = conf; ngx_str_t *value = cf->args->elts; if (cf->args->nelts > 1) { authencf->addr = value[1]; if (ngx_inet_addr(authencf->addr.data, authencf->addr.len) == INADDR_NONE) { return "Invalid: Authen IP address"; } } if (cf->args->nelts > 2) { authencf->port = ngx_atoi(value[2].data, value[2].len); if (authencf->port == NGX_ERROR) { return "Invalid: Authen UDP port"; } } return NGX_CONF_OK; }
static void ngx_mail_auth_http_process_headers(ngx_mail_session_t *s, ngx_mail_auth_http_ctx_t *ctx) { u_char *p; time_t timer; size_t len, size; ngx_int_t rc, port, n; ngx_addr_t *peer; struct sockaddr_in *sin; ngx_log_debug0(NGX_LOG_DEBUG_MAIL, s->connection->log, 0, "mail auth http process headers"); for ( ;; ) { rc = ngx_mail_auth_http_parse_header_line(s, ctx); if (rc == NGX_OK) { #if (NGX_DEBUG) { ngx_str_t key, value; key.len = ctx->header_name_end - ctx->header_name_start; key.data = ctx->header_name_start; value.len = ctx->header_end - ctx->header_start; value.data = ctx->header_start; ngx_log_debug2(NGX_LOG_DEBUG_MAIL, s->connection->log, 0, "mail auth http header: \"%V: %V\"", &key, &value); } #endif len = ctx->header_name_end - ctx->header_name_start; if (len == sizeof("Auth-Status") - 1 && ngx_strncasecmp(ctx->header_name_start, (u_char *) "Auth-Status", sizeof("Auth-Status") - 1) == 0) { len = ctx->header_end - ctx->header_start; if (len == 2 && ctx->header_start[0] == 'O' && ctx->header_start[1] == 'K') { continue; } if (len == 4 && ctx->header_start[0] == 'W' && ctx->header_start[1] == 'A' && ctx->header_start[2] == 'I' && ctx->header_start[3] == 'T') { s->auth_wait = 1; continue; } ctx->errmsg.len = len; ctx->errmsg.data = ctx->header_start; switch (s->protocol) { case NGX_MAIL_POP3_PROTOCOL: size = sizeof("-ERR ") - 1 + len + sizeof(CRLF) - 1; break; case NGX_MAIL_IMAP_PROTOCOL: size = s->tag.len + sizeof("NO ") - 1 + len + sizeof(CRLF) - 1; break; default: /* NGX_MAIL_SMTP_PROTOCOL */ ctx->err = ctx->errmsg; continue; } p = ngx_pnalloc(s->connection->pool, size); if (p == NULL) { ngx_close_connection(ctx->peer.connection); ngx_destroy_pool(ctx->pool); ngx_mail_session_internal_server_error(s); return; } ctx->err.data = p; switch (s->protocol) { case NGX_MAIL_POP3_PROTOCOL: *p++ = '-'; *p++ = 'E'; *p++ = 'R'; *p++ = 'R'; *p++ = ' '; break; case NGX_MAIL_IMAP_PROTOCOL: p = ngx_cpymem(p, s->tag.data, s->tag.len); *p++ = 'N'; *p++ = 'O'; *p++ = ' '; break; default: /* NGX_MAIL_SMTP_PROTOCOL */ break; } p = ngx_cpymem(p, ctx->header_start, len); *p++ = CR; *p++ = LF; ctx->err.len = p - ctx->err.data; continue; } if (len == sizeof("Auth-Server") - 1 && ngx_strncasecmp(ctx->header_name_start, (u_char *) "Auth-Server", sizeof("Auth-Server") - 1) == 0) { ctx->addr.len = ctx->header_end - ctx->header_start; ctx->addr.data = ctx->header_start; continue; } if (len == sizeof("Auth-Port") - 1 && ngx_strncasecmp(ctx->header_name_start, (u_char *) "Auth-Port", sizeof("Auth-Port") - 1) == 0) { ctx->port.len = ctx->header_end - ctx->header_start; ctx->port.data = ctx->header_start; continue; } if (len == sizeof("Auth-User") - 1 && ngx_strncasecmp(ctx->header_name_start, (u_char *) "Auth-User", sizeof("Auth-User") - 1) == 0) { s->login.len = ctx->header_end - ctx->header_start; s->login.data = ngx_pnalloc(s->connection->pool, s->login.len); if (s->login.data == NULL) { ngx_close_connection(ctx->peer.connection); ngx_destroy_pool(ctx->pool); ngx_mail_session_internal_server_error(s); return; } ngx_memcpy(s->login.data, ctx->header_start, s->login.len); continue; } if (len == sizeof("Auth-Pass") - 1 && ngx_strncasecmp(ctx->header_name_start, (u_char *) "Auth-Pass", sizeof("Auth-Pass") - 1) == 0) { s->passwd.len = ctx->header_end - ctx->header_start; s->passwd.data = ngx_pnalloc(s->connection->pool, s->passwd.len); if (s->passwd.data == NULL) { ngx_close_connection(ctx->peer.connection); ngx_destroy_pool(ctx->pool); ngx_mail_session_internal_server_error(s); return; } ngx_memcpy(s->passwd.data, ctx->header_start, s->passwd.len); continue; } if (len == sizeof("Auth-Wait") - 1 && ngx_strncasecmp(ctx->header_name_start, (u_char *) "Auth-Wait", sizeof("Auth-Wait") - 1) == 0) { n = ngx_atoi(ctx->header_start, ctx->header_end - ctx->header_start); if (n != NGX_ERROR) { ctx->sleep = n; } continue; } if (len == sizeof("Auth-Error-Code") - 1 && ngx_strncasecmp(ctx->header_name_start, (u_char *) "Auth-Error-Code", sizeof("Auth-Error-Code") - 1) == 0) { ctx->errcode.len = ctx->header_end - ctx->header_start; ctx->errcode.data = ngx_pnalloc(s->connection->pool, ctx->errcode.len); if (ctx->errcode.data == NULL) { ngx_close_connection(ctx->peer.connection); ngx_destroy_pool(ctx->pool); ngx_mail_session_internal_server_error(s); return; } ngx_memcpy(ctx->errcode.data, ctx->header_start, ctx->errcode.len); continue; } /* ignore other headers */ continue; } if (rc == NGX_DONE) { ngx_log_debug0(NGX_LOG_DEBUG_MAIL, s->connection->log, 0, "mail auth http header done"); ngx_close_connection(ctx->peer.connection); if (ctx->err.len) { ngx_log_error(NGX_LOG_INFO, s->connection->log, 0, "client login failed: \"%V\"", &ctx->errmsg); if (s->protocol == NGX_MAIL_SMTP_PROTOCOL) { if (ctx->errcode.len == 0) { ctx->errcode = ngx_mail_smtp_errcode; } ctx->err.len = ctx->errcode.len + ctx->errmsg.len + sizeof(" " CRLF) - 1; p = ngx_pnalloc(s->connection->pool, ctx->err.len); if (p == NULL) { ngx_close_connection(ctx->peer.connection); ngx_destroy_pool(ctx->pool); ngx_mail_session_internal_server_error(s); return; } ctx->err.data = p; p = ngx_cpymem(p, ctx->errcode.data, ctx->errcode.len); *p++ = ' '; p = ngx_cpymem(p, ctx->errmsg.data, ctx->errmsg.len); *p++ = CR; *p = LF; } s->out = ctx->err; timer = ctx->sleep; ngx_destroy_pool(ctx->pool); if (timer == 0) { s->quit = 1; ngx_mail_send(s->connection->write); return; } ngx_add_timer(s->connection->read, (ngx_msec_t) (timer * 1000)); s->connection->read->handler = ngx_mail_auth_sleep_handler; return; } if (s->auth_wait) { timer = ctx->sleep; ngx_destroy_pool(ctx->pool); if (timer == 0) { ngx_mail_auth_http_init(s); return; } ngx_add_timer(s->connection->read, (ngx_msec_t) (timer * 1000)); s->connection->read->handler = ngx_mail_auth_sleep_handler; return; } if (ctx->addr.len == 0 || ctx->port.len == 0) { ngx_log_error(NGX_LOG_ERR, s->connection->log, 0, "auth http server %V did not send server or port", ctx->peer.name); ngx_destroy_pool(ctx->pool); ngx_mail_session_internal_server_error(s); return; } if (s->passwd.data == NULL && s->protocol != NGX_MAIL_SMTP_PROTOCOL) { ngx_log_error(NGX_LOG_ERR, s->connection->log, 0, "auth http server %V did not send password", ctx->peer.name); ngx_destroy_pool(ctx->pool); ngx_mail_session_internal_server_error(s); return; } peer = ngx_pcalloc(s->connection->pool, sizeof(ngx_addr_t)); if (peer == NULL) { ngx_destroy_pool(ctx->pool); ngx_mail_session_internal_server_error(s); return; } /* AF_INET only */ sin = ngx_pcalloc(s->connection->pool, sizeof(struct sockaddr_in)); if (sin == NULL) { ngx_destroy_pool(ctx->pool); ngx_mail_session_internal_server_error(s); return; } sin->sin_family = AF_INET; port = ngx_atoi(ctx->port.data, ctx->port.len); if (port == NGX_ERROR || port < 1 || port > 65535) { ngx_log_error(NGX_LOG_ERR, s->connection->log, 0, "auth http server %V sent invalid server " "port:\"%V\"", ctx->peer.name, &ctx->port); ngx_destroy_pool(ctx->pool); ngx_mail_session_internal_server_error(s); return; } sin->sin_port = htons((in_port_t) port); sin->sin_addr.s_addr = ngx_inet_addr(ctx->addr.data, ctx->addr.len); if (sin->sin_addr.s_addr == INADDR_NONE) { ngx_log_error(NGX_LOG_ERR, s->connection->log, 0, "auth http server %V sent invalid server " "address:\"%V\"", ctx->peer.name, &ctx->addr); ngx_destroy_pool(ctx->pool); ngx_mail_session_internal_server_error(s); return; } peer->sockaddr = (struct sockaddr *) sin; peer->socklen = sizeof(struct sockaddr_in); len = ctx->addr.len + 1 + ctx->port.len; peer->name.len = len; peer->name.data = ngx_pnalloc(s->connection->pool, len); if (peer->name.data == NULL) { ngx_destroy_pool(ctx->pool); ngx_mail_session_internal_server_error(s); return; } len = ctx->addr.len; ngx_memcpy(peer->name.data, ctx->addr.data, len); peer->name.data[len++] = ':'; ngx_memcpy(peer->name.data + len, ctx->port.data, ctx->port.len); ngx_destroy_pool(ctx->pool); ngx_mail_proxy_init(s, peer); return; } if (rc == NGX_AGAIN ) { return; } /* rc == NGX_ERROR */ ngx_log_error(NGX_LOG_ERR, s->connection->log, 0, "auth http server %V sent invalid header in response", ctx->peer.name); ngx_close_connection(ctx->peer.connection); ngx_destroy_pool(ctx->pool); ngx_mail_session_internal_server_error(s); return; } }
static ngx_int_t ngx_lua_http_btt_parse_args(ngx_http_request_t *r, ngx_btt_ctx_t *ctx) { size_t nlen, vlen; u_char *p, *last, *name, *val, *dst, *src; ngx_log_debug0(NGX_LOG_DEBUG_HTTP, r->connection->log, 0, "lua http btt parse args"); if (r->args.len == 0) { ngx_log_error(NGX_LOG_ALERT, r->connection->log, 0, "invalid uri \"%V\"", &r->args); return NGX_ERROR; } p = r->args.data; last = p + r->args.len; for ( /* void */ ; p < last; p++) { name = p; p = ngx_strlchr(p, last, '&'); if (p == NULL) { p = last; } val = ngx_strlchr(name, p, '='); if (val == NULL) { val = p; } nlen = val - name; vlen = (++val < p) ? p - val : 0; dst = ngx_pnalloc(r->pool, vlen); if (dst == NULL) { return NGX_ERROR; } src = val; val = dst; ngx_unescape_uri(&dst, &src, vlen, 0); vlen = dst - val; ngx_log_debug4(NGX_LOG_ALERT, r->connection->log, 0, "%*s=%*s", nlen, name, vlen, val); /* * BT Client: * * BitComet: localip, natmapped, port_type * NetTransport: supportcrypto * uTorrent: corrupt * XunLei: ip */ switch (nlen) { case 2: if (ngx_strncmp(name, "ip", nlen) == 0) { ctx->internal_ip = ngx_inet_addr(val, vlen); if (ctx->internal_ip == INADDR_NONE) { goto invalid; } break; } break; case 3: if (ngx_strncmp(name, "key", nlen) == 0) { ngx_memcpy(ctx->key, val, vlen); break; } break; case 4: if (ngx_strncmp(name, "port", nlen) == 0) { ctx->internal_port = (in_port_t) ngx_atoi(val, vlen); if (ctx->internal_port == NGX_ERROR) { goto invalid; } break; } if (ngx_strncmp(name, "left", nlen) == 0) { ctx->left = ngx_atoof(val, vlen); if (ctx->left == NGX_ERROR) { goto invalid; } break; } break; case 5: if (ngx_strncmp(name, "event", nlen) == 0) { if (ngx_strncmp(val, "none", sizeof("none") - 1) == 0) { ctx->event = NGX_BTT_EVENT_NONE; } else if (ngx_strncmp(val, "completed", sizeof("completed") - 1) == 0) { ctx->event = NGX_BTT_EVENT_COMPLETED; } else if (ngx_strncmp(val, "started", sizeof("started") - 1) == 0) { ctx->event = NGX_BTT_EVENT_STARTED; } else if (ngx_strncmp(val, "stopped", sizeof("stopped") - 1) == 0) { ctx->event = NGX_BTT_EVENT_STOPPED; } else { goto invalid; } break; } break; case 7: if (ngx_strncmp(name, "peer_id", nlen) == 0) { ngx_memcpy(ctx->peer_id, val, vlen); break; } if (ngx_strncmp(name, "localip", nlen) == 0) { ctx->internal_ip = ngx_inet_addr(val, vlen); if (ctx->internal_ip == INADDR_NONE) { goto invalid; } break; } if (ngx_strncmp(name, "numwant", nlen) == 0) { ctx->numwant = ngx_atoi(val, vlen); if (ctx->numwant == NGX_ERROR) { goto invalid; } break; } if (ngx_strncmp(name, "compact", nlen) == 0) { ctx->compact = ngx_atoi(val, vlen); if (ctx->compact == NGX_ERROR) { goto invalid; } break; } if (ngx_strncmp(name, "corrupt", nlen) == 0) { ctx->corrupt = ngx_atoi(val, vlen); if (ctx->corrupt == NGX_ERROR) { goto invalid; } break; } break; case 8: if (ngx_strncmp(name, "uploaded", nlen) == 0) { ctx->uploaded = ngx_atoof(val, vlen); if (ctx->uploaded == NGX_ERROR) { goto invalid; } break; } break; case 9: if (ngx_strncmp(name, "info_hash ", nlen) == 0) { ngx_memcpy(ctx->info_hash, val, vlen); break; } if (ngx_strncmp(name, "natmapped ", nlen) == 0) { ctx->natmapped = ngx_atoi(val, vlen); if (ctx->natmapped == NGX_ERROR) { goto invalid; } break; } if (ngx_strncmp(name, "port_type", nlen) == 0) { ngx_memcpy(ctx->port_type, val, vlen); break; } break; case 10: if (ngx_strncmp(name, "downloaded", nlen) == 0) { ctx->downloaded = ngx_atoof(val, vlen); if (ctx->downloaded == NGX_ERROR) { goto invalid; } break; } if (ngx_strncmp(name, "no_peer_id ", nlen) == 0) { ctx->no_peer_id = ngx_atoi(val, vlen); if (ctx->no_peer_id == NGX_ERROR) { goto invalid; } break; } break; case 13: if (ngx_strncmp(name, "supportcrypto", nlen) == 0) { ctx->supportcrypto = ngx_atoi(val, vlen); if (ctx->supportcrypto == NGX_ERROR) { goto invalid; } break; } break; default: break; } } return NGX_OK; invalid: ngx_log_error(NGX_LOG_ALERT, r->connection->log, 0, "invalid value \"%*s\" of the key \"%*s\"", nlen, name, vlen, val); return NGX_ERROR; }
static ngx_int_t ngx_stream_proxy_ssl_name(ngx_stream_session_t *s) { u_char *p, *last; ngx_str_t name; ngx_stream_upstream_t *u; ngx_stream_proxy_srv_conf_t *pscf; pscf = ngx_stream_get_module_srv_conf(s, ngx_stream_proxy_module); u = s->upstream; name = pscf->ssl_name; if (name.len == 0) { name = pscf->upstream->host; } if (name.len == 0) { goto done; } /* * ssl name here may contain port, strip it for compatibility * with the http module */ p = name.data; last = name.data + name.len; if (*p == '[') { p = ngx_strlchr(p, last, ']'); if (p == NULL) { p = name.data; } } p = ngx_strlchr(p, last, ':'); if (p != NULL) { name.len = p - name.data; } if (!pscf->ssl_server_name) { goto done; } #ifdef SSL_CTRL_SET_TLSEXT_HOSTNAME /* as per RFC 6066, literal IPv4 and IPv6 addresses are not permitted */ if (name.len == 0 || *name.data == '[') { goto done; } if (ngx_inet_addr(name.data, name.len) != INADDR_NONE) { goto done; } /* * SSL_set_tlsext_host_name() needs a null-terminated string, * hence we explicitly null-terminate name here */ p = ngx_pnalloc(s->connection->pool, name.len + 1); if (p == NULL) { return NGX_ERROR; } (void) ngx_cpystrn(p, name.data, name.len + 1); name.data = p; ngx_log_debug1(NGX_LOG_DEBUG_STREAM, s->connection->log, 0, "upstream SSL server name: \"%s\"", name.data); if (SSL_set_tlsext_host_name(u->peer.connection->ssl->connection, name.data) == 0) { ngx_ssl_error(NGX_LOG_ERR, s->connection->log, 0, "SSL_set_tlsext_host_name(\"%s\") failed", name.data); return NGX_ERROR; } #endif done: u->ssl_name = name; return NGX_OK; }
static ngx_int_t ngx_http_upstream_get_dynamic_peer(ngx_peer_connection_t *pc, void *data) { ngx_http_upstream_dynamic_peer_data_t *bp = data; ngx_http_request_t *r; ngx_http_core_loc_conf_t *clcf; ngx_resolver_ctx_t *ctx, temp; ngx_http_upstream_t *u; ngx_int_t rc; ngx_http_upstream_dynamic_srv_conf_t *dscf; ngx_log_debug0(NGX_LOG_DEBUG_HTTP, pc->log, 0, "get dynamic peer"); /* The "get" function will be called twice if * one host is resolved into an IP address. * (via 'ngx_http_upstream_connect' if resolved successfully) * * So here we need to determine if it is the first * time call or the second time call. */ if (pc->resolved == NGX_HTTP_UPSTREAM_DR_OK) { return NGX_OK; } dscf = bp->conf; r = bp->request; u = r->upstream; if (pc->resolved == NGX_HTTP_UPSTREAM_DR_FAILED) { ngx_log_debug1(NGX_LOG_DEBUG_HTTP, pc->log, 0, "resolve failed! fallback: %ui", dscf->fallback); switch (dscf->fallback) { case NGX_HTTP_UPSTREAM_DYN_RESOLVE_STALE: return NGX_OK; case NGX_HTTP_UPSTREAM_DYN_RESOLVE_SHUTDOWN: ngx_http_upstream_finalize_request(r, u, NGX_HTTP_BAD_GATEWAY); return NGX_YIELD; default: /* default fallback action: check next upstream */ return NGX_DECLINED; } return NGX_DECLINED; } if (dscf->fail_check && (ngx_time() - dscf->fail_check < dscf->fail_timeout)) { ngx_log_debug1(NGX_LOG_DEBUG_HTTP, pc->log, 0, "in fail timeout period, fallback: %ui", dscf->fallback); switch (dscf->fallback) { case NGX_HTTP_UPSTREAM_DYN_RESOLVE_STALE: return bp->original_get_peer(pc, bp->data); case NGX_HTTP_UPSTREAM_DYN_RESOLVE_SHUTDOWN: ngx_http_upstream_finalize_request(r, u, NGX_HTTP_BAD_GATEWAY); return NGX_YIELD; default: /* default fallback action: check next upstream, still need * to get peer in fail timeout period */ return bp->original_get_peer(pc, bp->data); } return NGX_DECLINED; } /* NGX_HTTP_UPSTREAM_DYN_RESOLVE_INIT, ask balancer */ rc = bp->original_get_peer(pc, bp->data); if (rc != NGX_OK) { return rc; } /* resolve name */ if (pc->host == NULL) { ngx_log_debug0(NGX_LOG_DEBUG_HTTP, pc->log, 0, "load balancer doesn't support dyn resolve!"); return NGX_OK; } if (ngx_inet_addr(pc->host->data, pc->host->len) != INADDR_NONE) { ngx_log_debug0(NGX_LOG_DEBUG_HTTP, pc->log, 0, "host is an IP address, connect directly!"); return NGX_OK; } clcf = ngx_http_get_module_loc_conf(r, ngx_http_core_module); if (clcf->resolver == NULL) { ngx_log_error(NGX_LOG_ERR, r->connection->log, 0, "resolver has not been configured!"); return NGX_OK; } temp.name = *pc->host; ctx = ngx_resolve_start(clcf->resolver, &temp); if (ctx == NULL) { ngx_log_error(NGX_LOG_ERR, r->connection->log, 0, "resolver start failed!"); return NGX_OK; } if (ctx == NGX_NO_RESOLVER) { ngx_log_error(NGX_LOG_ERR, r->connection->log, 0, "resolver started but no resolver!"); return NGX_OK; } ctx->name = *pc->host; /* TODO remove */ // ctx->type = NGX_RESOLVE_A; /* END */ ctx->handler = ngx_http_upstream_dynamic_handler; ctx->data = r; ctx->timeout = clcf->resolver_timeout; u->dyn_resolve_ctx = ctx; if (ngx_resolve_name(ctx) != NGX_OK) { ngx_log_error(NGX_LOG_ERR, pc->log, 0, "resolver name failed!\n"); u->dyn_resolve_ctx = NULL; return NGX_OK; } return NGX_YIELD; }
ngx_int_t ngx_http_upstream_init_round_robin(ngx_conf_t *cf, ngx_http_upstream_srv_conf_t *us) { ngx_url_t u; ngx_uint_t i, j, n, w, color; ngx_uint_t dyn_resolve = 0; ngx_http_upstream_server_t *server; ngx_http_upstream_rr_peers_t *peers, *backup; u_char addr6[NGX_INET6_ADDRSTRLEN]; us->peer.init = ngx_http_upstream_init_round_robin_peer; if (us->servers) { server = us->servers->elts; n = 0; w = 0; for (i = 0; i < us->servers->nelts; i++) { if (server[i].backup) { continue; } n += server[i].naddrs; w += server[i].naddrs * server[i].weight; } if (n == 0) { ngx_log_error(NGX_LOG_EMERG, cf->log, 0, "no servers in upstream \"%V\" in %s:%ui", &us->host, us->file_name, us->line); return NGX_ERROR; } peers = ngx_pcalloc(cf->pool, sizeof(ngx_http_upstream_rr_peers_t) + sizeof(ngx_http_upstream_rr_peer_t) * (n - 1)); if (peers == NULL) { return NGX_ERROR; } peers->single = (n == 1); peers->number = n; peers->weighted = (w != n); peers->total_weight = w; peers->name = &us->host; n = 0; color = 1; for (i = 0; i < us->servers->nelts; i++) { if (server[i].backup) { continue; } #if (NGX_HAVE_INET6) dyn_resolve = (ngx_inet6_addr(server[i].host.data, server[i].host.len, addr6) == NGX_ERROR) ? 1 : 0; if (dyn_resolve) /* host is not an ipv6 address, check ipv4 */ #endif { dyn_resolve = (ngx_inet_addr(server[i].host.data, server[i].host.len) == INADDR_NONE) ? 1 : 0; } for (j = 0; j < server[i].naddrs; j++) { peers->peer[n].sockaddr = server[i].addrs[j].sockaddr; peers->peer[n].socklen = server[i].addrs[j].socklen; peers->peer[n].name = server[i].addrs[j].name; peers->peer[n].host = server[i].host; peers->peer[n].weight = server[i].weight; peers->peer[n].effective_weight = server[i].weight; peers->peer[n].current_weight = 0; peers->peer[n].max_fails = server[i].max_fails; peers->peer[n].fail_timeout = server[i].fail_timeout; peers->peer[n].down = server[i].down; peers->peer[n].color = color; peers->peer[n].dyn_resolve = dyn_resolve; #if (NGX_HTTP_UPSTREAM_CHECK) if (!server[i].down) { peers->peer[n].check_index = ngx_http_upstream_check_add_peer(cf, us, &server[i].addrs[j]); } else { peers->peer[n].check_index = (ngx_uint_t) NGX_ERROR; } #endif n++; } color++; } us->peer.data = peers; /* backup servers */ n = 0; w = 0; for (i = 0; i < us->servers->nelts; i++) { if (!server[i].backup) { continue; } n += server[i].naddrs; w += server[i].naddrs * server[i].weight; } if (n == 0) { return NGX_OK; } backup = ngx_pcalloc(cf->pool, sizeof(ngx_http_upstream_rr_peers_t) + sizeof(ngx_http_upstream_rr_peer_t) * (n - 1)); if (backup == NULL) { return NGX_ERROR; } peers->single = 0; backup->single = 0; backup->number = n; backup->weighted = (w != n); backup->total_weight = w; backup->name = &us->host; n = 0; for (i = 0; i < us->servers->nelts; i++) { if (!server[i].backup) { continue; } #if (NGX_HAVE_INET6) dyn_resolve = (ngx_inet6_addr(server[i].host.data, server[i].host.len, addr6) == NGX_ERROR) ? 1 : 0; if (dyn_resolve) /* host is not an ipv6 address, check ipv4 */ #endif { dyn_resolve = (ngx_inet_addr(server[i].host.data, server[i].host.len) == INADDR_NONE) ? 1 : 0; } for (j = 0; j < server[i].naddrs; j++) { backup->peer[n].sockaddr = server[i].addrs[j].sockaddr; backup->peer[n].socklen = server[i].addrs[j].socklen; backup->peer[n].name = server[i].addrs[j].name; backup->peer[n].host = server[i].host; backup->peer[n].weight = server[i].weight; backup->peer[n].effective_weight = server[i].weight; backup->peer[n].current_weight = 0; backup->peer[n].max_fails = server[i].max_fails; backup->peer[n].fail_timeout = server[i].fail_timeout; backup->peer[n].down = server[i].down; backup->peer[n].color = color; backup->peer[n].dyn_resolve = dyn_resolve; #if (NGX_HTTP_UPSTREAM_CHECK) if (!server[i].down) { backup->peer[n].check_index = ngx_http_upstream_check_add_peer(cf, us, &server[i].addrs[j]); } else { backup->peer[n].check_index = (ngx_uint_t) NGX_ERROR; } #endif n++; } color++; } peers->next = backup; return NGX_OK; } /* an upstream implicitly defined by proxy_pass, etc. */ if (us->port == 0) { ngx_log_error(NGX_LOG_EMERG, cf->log, 0, "no port in upstream \"%V\" in %s:%ui", &us->host, us->file_name, us->line); return NGX_ERROR; } ngx_memzero(&u, sizeof(ngx_url_t)); u.host = us->host; u.port = us->port; if (ngx_inet_resolve_host(cf->pool, &u) != NGX_OK) { if (u.err) { ngx_log_error(NGX_LOG_EMERG, cf->log, 0, "%s in upstream \"%V\" in %s:%ui", u.err, &us->host, us->file_name, us->line); } return NGX_ERROR; } n = u.naddrs; peers = ngx_pcalloc(cf->pool, sizeof(ngx_http_upstream_rr_peers_t) + sizeof(ngx_http_upstream_rr_peer_t) * (n - 1)); if (peers == NULL) { return NGX_ERROR; } peers->single = (n == 1); peers->number = n; peers->weighted = 0; peers->total_weight = n; peers->name = &us->host; #if (NGX_HAVE_INET6) dyn_resolve = (ngx_inet6_addr(u.host.data, u.host.len, addr6) == NGX_ERROR) ? 1 : 0; if (dyn_resolve) /* host is not an ipv6 address, check ipv4 */ #endif { dyn_resolve = (ngx_inet_addr(u.host.data, u.host.len) == INADDR_NONE) ? 1 : 0; } for (i = 0; i < u.naddrs; i++) { peers->peer[i].sockaddr = u.addrs[i].sockaddr; peers->peer[i].socklen = u.addrs[i].socklen; peers->peer[i].name = u.addrs[i].name; peers->peer[i].host = u.host; peers->peer[i].weight = 1; peers->peer[i].effective_weight = 1; peers->peer[i].current_weight = 0; peers->peer[i].max_fails = 1; peers->peer[i].fail_timeout = 10; #if (NGX_HTTP_UPSTREAM_CHECK) peers->peer[i].check_index = (ngx_uint_t) NGX_ERROR; #endif peers->peer[i].color = 0; peers->peer[i].dyn_resolve = dyn_resolve; } us->peer.data = peers; /* implicitly defined upstream has no backup servers */ return NGX_OK; }
void ngx_http_cloudrouter_peer_preconnect(ngx_http_request_t *r, ngx_http_upstream_t *u) { ngx_int_t rc; ngx_peer_connection_t *c; struct sockaddr_in *sin; ngx_http_cloudrouter_peer_preconnect_data_t *pcd; ngx_http_cleanup_t *cln; ngx_http_cloudrouter_peer_t *peer; r->connection->log->action = "connecting to cloudrouter agent"; ngx_log_debug0(NGX_LOG_DEBUG_HTTP, r->connection->log, 0, "preconnect"); c = ngx_pcalloc(r->connection->pool, sizeof(ngx_peer_connection_t)); sin = ngx_pcalloc(r->connection->pool, sizeof(struct sockaddr_in)); pcd = ngx_pcalloc(r->connection->pool, sizeof(ngx_http_cloudrouter_peer_preconnect_data_t)); peer = (ngx_http_cloudrouter_peer_t*)u->peer.data; if (sin==NULL || c==NULL || pcd==NULL) { ngx_log_error(NGX_LOG_ERR, r->connection->log, 0, "preconnect: cannot allocate sin/c/pcd"); return; } /* FIXME: should cache this */ sin->sin_family = AF_INET; sin->sin_port = htons(9091); ngx_str_t localhost; ngx_str_set(&localhost, "127.0.0.1"); sin->sin_addr.s_addr = ngx_inet_addr(localhost.data, localhost.len); c->sockaddr = (struct sockaddr *)sin; c->socklen = sizeof(struct sockaddr_in); c->get = ngx_event_get_peer; // dummy method returning the peer itself. c->log = r->connection->log; c->log_error = r->connection->log_error; c->name = ngx_pcalloc(r->connection->pool, sizeof *c->name); if (c->name == NULL) { ngx_log_error(NGX_LOG_ERR, r->connection->log, 0, "preconnect: cannot allocate c->name"); return; } ngx_str_set(c->name, "127.0.0.1:9091"); rc = ngx_event_connect_peer(c); if (rc==NGX_ERROR || rc==NGX_BUSY || rc==NGX_DECLINED) { ngx_log_debug(NGX_LOG_DEBUG_HTTP, r->connection->log, 0, "preconnect very much unsuccessful."); if (c->connection) { ngx_close_connection(c->connection); c->connection->destroyed = 1; } ngx_http_upstream_next(r,u,NGX_HTTP_UPSTREAM_FT_ERROR); return; } r->main->count++; pcd->r = r; pcd->u = u; pcd->sendbufpos = 0; if (peer->route==NULL) { ngx_log_error(NGX_LOG_ERR, r->connection->log, 0, "ROUTE is null in preconnect!"); ngx_log_debug(NGX_LOG_ERR, r->connection->log, 0, "ROUTE is null in preconnect!"); ngx_http_upstream_next(r,u,NGX_HTTP_UPSTREAM_FT_ERROR); return; } (void)ngx_copy(&pcd->route,peer->route, sizeof(hs_route_t)); pcd->c = c->connection; c->connection->data = pcd; c->connection->pool = r->connection->pool; c->connection->read->handler = ngx_http_cloudrouter_peer_preconnect_read; c->connection->write->handler = ngx_http_cloudrouter_peer_preconnect_write; ngx_log_debug(NGX_LOG_DEBUG_HTTP, r->connection->log, 0, "preconnect successful."); ngx_add_timer(c->connection->read, 10000); ngx_add_timer(c->connection->write, 10000); cln = ngx_http_cleanup_add(r, 0); cln->data = pcd; cln->handler = ngx_http_cloudrouter_preconnect_cleanup; }
static void ngx_http_cloudrouter_peer_preconnect_read(ngx_event_t *rev) { ngx_connection_t *c; ngx_http_cloudrouter_peer_preconnect_data_t *pcd; ngx_http_upstream_t *u; ngx_http_request_t *r; int i; hs_route_t *route; c = rev->data; pcd = c->data; r = pcd->r; u = pcd->u; route = &pcd->route; ngx_log_debug(NGX_LOG_DEBUG_HTTP, r->connection->log, 0, "preconnect: read"); if (pcd->done>0) { return; } if (r->main==NULL||r->request_complete||r->pool==NULL||r!=r->main) { ngx_close_connection(c); c->destroyed = 1; return; } if (rev->timedout) { ngx_log_error(NGX_LOG_ERR, rev->log, NGX_ETIMEDOUT, "cloudrouter preconnect server timed out"); return ngx_http_cloudrouter_peer_preconnect_close(c, pcd, NGX_ERROR); } if (pcd->buf==NULL) { int size = sizeof(char)*1000; ngx_log_debug(NGX_LOG_DEBUG_HTTP, r->connection->log, 0, "creating buf"); pcd->buf = ngx_pcalloc(r->pool, size); pcd->bufend = pcd->buf+size; pcd->bufpos = pcd->buf; if (pcd->buf==NULL) { ngx_log_error(NGX_LOG_ERR, rev->log, NGX_ENOMEM, "preconnect: read: could not allocate buf"); return ngx_http_cloudrouter_peer_preconnect_close(c, pcd, NGX_ERROR); } } /* * Protocol format: * IP1\nPORT1\n * (optional) IPz\nPORTz\n * -- */ int bufsize = pcd->bufend - pcd->bufpos; ngx_int_t received; if (bufsize > 0) { received = ngx_recv(c, pcd->bufpos, bufsize); } else { received = 0; } if (received==NGX_AGAIN) { return; } else if (received>=0) { pcd->bufpos += received; for (i=0;i<(pcd->bufpos-pcd->buf);i++) { if (*(pcd->buf + i )=='-') { pcd->end_marker_count++; } } if (pcd->end_marker_count>=2) { ngx_log_debug0(NGX_LOG_DEBUG_HTTP, rev->log, 0, "CloudRouter preconnect: message complete"); ngx_http_cloudrouter_peer_t *peer = (ngx_http_cloudrouter_peer_t *)u->peer.data; unsigned char* next = pcd->buf; int new_node = 0; ngx_shmtx_lock(&ngx_http_cloudrouter_shpool->mutex); ngx_http_cloudrouter_node_t *e = ngx_http_cloudrouter_get_locked(route); if (e == NULL) { /* likely() */ e = ngx_slab_alloc_locked(ngx_http_cloudrouter_shpool, sizeof *e); new_node = 1; e->node.key = ngx_http_cloudrouter_hash_route(route); (void)ngx_copy(e->di_name, route->di_name, sizeof(route->di_name)); e->di_nlen = route->di_nlen; } else { ngx_log_debug0(NGX_LOG_DEBUG_HTTP, rev->log, 0, "CloudRouter preconnect: reusing existing node"); } e->timestamp = time(NULL); ngx_http_cloudrouter_clear_remotes_locked(e, rev->log); while (next < pcd->bufpos) { ngx_log_debug0(NGX_LOG_DEBUG_HTTP, rev->log, 0, "CloudRouter preconnect: parsing message"); unsigned char *ip = NULL; unsigned char *port = NULL; ip = next; while (++next < pcd->bufpos) { if (*(next-1) == '\n') { if (ip && port) break; port = next; } } if (ip && port) { ngx_http_cloudrouter_remote_t *remote = ngx_http_cloudrouter_add_remote_locked(e); int iplen = port-ip-1; iplen = iplen > 16 ? 16 : iplen; remote->inet_addr = ngx_inet_addr(ip, iplen); if (remote->inet_addr == INADDR_NONE) { ngx_log_error(NGX_LOG_ERR, rev->log, NGX_EINVAL, "CloudRouter preconnect: IP address from Agent invalid for route %s", e->di_name); goto failure; } int portlen = next-port-1; remote->port_n = htons(ngx_atoi(port,portlen)); ngx_log_debug7(NGX_LOG_DEBUG_HTTP, rev->log, 0, "CloudRouter preconnect: cached values SET: e=%p rem=%p ts=%d %s[%d] %uxD:%d", e, remote, e->timestamp, e->di_name, e->di_nlen, remote->inet_addr, remote->port_n); } } if (!e->remote) { ngx_log_debug(NGX_LOG_DEBUG_HTTP, rev->log, 0, "CloudRouter preconnect: Agent sent no remotes"); goto failure; } ngx_http_cloudrouter_set_hostandport(r, peer, e); if (new_node) { ngx_rbtree_insert(ngx_http_cloudrouter_rbtree, &e->node); } ngx_shmtx_unlock(&ngx_http_cloudrouter_shpool->mutex); return ngx_http_cloudrouter_peer_preconnect_close(c, pcd, NGX_OK); failure: if (!new_node) { ngx_log_debug0(NGX_LOG_DEBUG_HTTP, pcd->r->connection->log, 0, "peer_preconnect_read: calling rbtree_delete"); ngx_rbtree_delete(ngx_http_cloudrouter_rbtree, &e->node); } ngx_log_debug0(NGX_LOG_DEBUG_HTTP, pcd->r->connection->log, 0, "peer_preconnect_read: calling free_node_locked"); ngx_http_cloudrouter_free_node_locked(e, rev->log); ngx_log_debug0(NGX_LOG_DEBUG_HTTP, pcd->r->connection->log, 0, "peer_preconnect_read: calling shmtx_unlock"); ngx_shmtx_unlock(&ngx_http_cloudrouter_shpool->mutex); ngx_log_debug0(NGX_LOG_DEBUG_HTTP, pcd->r->connection->log, 0, "peer_preconnect_read: calling peer_preconnect_close"); return ngx_http_cloudrouter_peer_preconnect_close(c, pcd, NGX_ERROR); } return; } /* unknown error condition from ngx_recv */ return; }
static ngx_int_t ngx_http_cloudrouter_init_upstream_peer(ngx_http_request_t *r, ngx_http_upstream_srv_conf_t *us) { struct sockaddr_in* sin; ngx_http_hs_main_conf_t *hscf; ngx_http_cloudrouter_peer_t *peer; hs_route_t *route; int tcb_s; hscf = ngx_http_get_module_main_conf(r, ngx_http_hs_module); if (hscf == NULL || hscf->tcb_route_db == NULL) { return NGX_ERROR; } peer = ngx_pcalloc(r->pool, sizeof(ngx_http_cloudrouter_peer_t)); if (peer == NULL) { ngx_log_error(NGX_LOG_NOTICE, r->connection->log, 0, "NULL peer"); return NGX_ERROR; } peer->route = NULL; peer->socklen = sizeof(struct sockaddr_in); peer->sockaddr = (struct sockaddr*)ngx_pcalloc(r->pool, peer->socklen); if (peer->sockaddr == NULL) { ngx_log_error(NGX_LOG_NOTICE, r->connection->log, 0, "ALERT: peer->sockaddr alloc failed"); return NGX_ERROR; } ngx_log_debug0(NGX_LOG_DEBUG_HTTP, r->connection->log, 0, "init_peer"); /* fallback = 404 host */ ngx_str_set(&peer->name, "127.0.0.1"); peer->inet_addr = ngx_inet_addr(peer->name.data, peer->name.len); peer->port_n = htons(8404); r->upstream->peer.data = peer; r->upstream->peer.free = ngx_http_cloudrouter_free_upstream_peer; r->upstream->peer.get = ngx_http_cloudrouter_get_upstream_peer; r->upstream->peer.tries = 1; // fetch config for client-supplied Host if (r->headers_in.server.len > 0) { route = (hs_route_t*)tcbdbget(hscf->tcb_route_db, r->headers_in.server.data, r->headers_in.server.len, &tcb_s); } else { route = NULL; } if (route == NULL) { // send user to 404 host ngx_log_debug0(NGX_LOG_DEBUG_HTTP, r->connection->log, 0, "CloudRouter: no route matched"); return NGX_OK; } else { /* copy route into peer, managed memory */ peer->route = ngx_pcalloc(r->pool, sizeof(hs_route_t)); if (peer->route==NULL) { ngx_log_error(NGX_LOG_NOTICE, r->connection->log, 0, "ALERT: alloc failed"); free(route); return NGX_ERROR; } (void)ngx_copy(peer->route, route, sizeof(hs_route_t)); free(route); // gets malloc()'d by TC route = peer->route; peer->name.len = route->di_nlen; peer->name.data = ngx_pcalloc(r->pool, peer->name.len); (void)ngx_copy(peer->name.data, route->di_name, peer->name.len); ngx_shmtx_lock(&ngx_http_cloudrouter_shpool->mutex); ngx_http_cloudrouter_node_t *e = ngx_http_cloudrouter_get_locked(route); if (e && e->timestamp > (r->start_sec - NGX_HTTP_HS_CACHE_TIMEOUT)) { ngx_log_debug(NGX_LOG_DEBUG_HTTP, r->connection->log, 0, "cache hit"); ngx_http_cloudrouter_remote_t *remote = e->remote; ngx_log_debug6(NGX_LOG_DEBUG_HTTP, r->connection->log, 0, "cached values READ: %p:%d:%s[%d],(%uxD,%d)", e, e->timestamp, e->di_name, e->di_nlen, remote->inet_addr, remote->port_n); ngx_http_cloudrouter_set_hostandport(r,peer,e); ngx_shmtx_unlock(&ngx_http_cloudrouter_shpool->mutex); } else { /* entry has expired. * pretend it does not exist, the preconnect handler will overwrite it. */ int current = 0; if (e) { ngx_http_cloudrouter_remote_t *remote = e->remote; while (remote != NULL) { current += remote->current; remote = remote->next; } ngx_log_debug0(NGX_LOG_DEBUG_HTTP, r->connection->log, 0, "CloudRouter: cache entry expired"); } else { ngx_log_debug0(NGX_LOG_DEBUG_HTTP, r->connection->log, 0, "CloudRouter: no entry in cache"); } ngx_shmtx_unlock(&ngx_http_cloudrouter_shpool->mutex); peer->sendbuf.data = ngx_pcalloc(r->pool, NGX_HTTP_CLOUDROUTER_PRECONNECT_SENDBUFSIZE); if (peer->sendbuf.data == NULL) { ngx_log_error(NGX_LOG_DEBUG_HTTP, r->connection->log, 0, "alloc peer->sendbuf.data failed, aborting request"); return NGX_ERROR; } peer->sendbuf.len = ngx_sprintf(peer->sendbuf.data, "BLNC %*s %ud", peer->route->di_nlen, peer->route->di_name, current) - peer->sendbuf.data; ngx_shmtx_unlock(&ngx_http_cloudrouter_shpool->mutex); r->upstream->peer.preconnect = (ngx_event_preconnect_pt)ngx_http_cloudrouter_peer_preconnect; } return NGX_OK; } /* never reached */ }
static ngx_int_t ngx_http_repsheet_handler(ngx_http_request_t *r) { char temp_address[INET_ADDRSTRLEN]; repsheet_loc_conf_t *conf; int length; conf = ngx_http_get_module_loc_conf(r, ngx_http_repsheet_module); if (!conf->enabled) { return NGX_DECLINED; } if (r->main->internal) { return NGX_DECLINED; } r->main->internal = 1; redisContext *context = get_redis_context(r); if (context == NULL) { return NGX_DECLINED; } actor_t actor; repsheet_init_actor(&actor); ngx_table_elt_t *xfwd = NULL; #if (nginx_version >= 1004000) ngx_array_t *ngx_array = &r->headers_in.x_forwarded_for; if (ngx_array != NULL && ngx_array->nelts > 0) { ngx_table_elt_t **first_elt = ngx_array->elts; xfwd = first_elt[0]; } #else xfwd = r->headers_in.x_forwarded_for; #endif if (xfwd != NULL && xfwd->value.data != NULL) { in_addr_t addr; u_char *p; /* Get the first value from the XFF list. * Note that xfwd->value.data already has any extra whitespace removed. */ for (p=xfwd->value.data; p < (xfwd->value.data + xfwd->value.len); p++) { if (*p == ' ' || *p == ',') break; } /* Validate it is a valid IP */ length = p - xfwd->value.data; addr = ngx_inet_addr(xfwd->value.data, length); if (addr != INADDR_NONE && length <= INET_ADDRSTRLEN) { strncpy(temp_address, (char *)xfwd->value.data, length); temp_address[length] = '\0'; actor.address = temp_address; } } if (actor.address == NULL) { length = r->connection->addr_text.len; strncpy(temp_address, (char *)r->connection->addr_text.data, length); temp_address[length] = '\0'; actor.address = temp_address; } if (actor.address) { ngx_log_error(NGX_LOG_ERR, r->connection->log, 0, "%s address : %s", "[repsheet]", actor.address); } else { ngx_log_error(NGX_LOG_ERR, r->connection->log, 0, "%s Could not fetch address", "[repsheet]"); } repsheet_score_actor(context, &actor); if (actor.whitelisted) { ngx_log_error(NGX_LOG_ERR, r->connection->log, 0, "%s %s was allowed by the repsheet whitelist", "[repsheet]", actor.address); redisFree(context); return NGX_DECLINED; } if (actor.blacklisted) { ngx_log_error(NGX_LOG_ERR, r->connection->log, 0, "%s %s was blocked by the repsheet blacklist", "[repsheet]", actor.address); redisFree(context); return NGX_HTTP_FORBIDDEN; } if (actor.offender) { ngx_log_error(NGX_LOG_ERR, r->connection->log, 0, "%s %s was found on the repsheet", "[repsheet]", actor.address); ngx_table_elt_t *h; ngx_str_t label = ngx_string("X-Repsheet"); ngx_str_t val = ngx_string("true"); h = ngx_list_push(&r->headers_in.headers); h->hash = 1; h->key = label; h->value = val; } redisFree(context); return NGX_DECLINED; }