static int stats_origin(TSCont contp ATS_UNUSED, TSEvent event ATS_UNUSED, void *edata) { TSCont icontp; stats_state *my_state; TSHttpTxn txnp = (TSHttpTxn)edata; TSMBuffer reqp; TSMLoc hdr_loc = NULL, url_loc = NULL; TSEvent reenable = TS_EVENT_HTTP_CONTINUE; TSDebug(PLUGIN_NAME, "in the read stuff"); if (TSHttpTxnClientReqGet(txnp, &reqp, &hdr_loc) != TS_SUCCESS) { goto cleanup; } if (TSHttpHdrUrlGet(reqp, hdr_loc, &url_loc) != TS_SUCCESS) { goto cleanup; } int path_len = 0; const char *path = TSUrlPathGet(reqp, url_loc, &path_len); TSDebug(PLUGIN_NAME, "Path: %.*s", path_len, path); if (!(path_len != 0 && path_len == url_path_len && !memcmp(path, url_path, url_path_len))) { goto notforme; } TSSkipRemappingSet(txnp, 1); // not strictly necessary, but speed is everything these days /* This is us -- register our intercept */ TSDebug(PLUGIN_NAME, "Intercepting request"); icontp = TSContCreate(stats_dostuff, TSMutexCreate()); my_state = (stats_state *)TSmalloc(sizeof(*my_state)); memset(my_state, 0, sizeof(*my_state)); TSContDataSet(icontp, my_state); TSHttpTxnIntercept(icontp, txnp); goto cleanup; notforme: cleanup: if (url_loc) { TSHandleMLocRelease(reqp, hdr_loc, url_loc); } if (hdr_loc) { TSHandleMLocRelease(reqp, TS_NULL_MLOC, hdr_loc); } TSHttpTxnReenable(txnp, reenable); return 0; }
/* Read-request header continuation, used to kick off the server intercept if necessary */ static int health_check_origin(TSCont contp, TSEvent event, void *edata) { TSMBuffer reqp; TSMLoc hdr_loc = NULL, url_loc = NULL; TSCont icontp; HCState *my_state; TSHttpTxn txnp = (TSHttpTxn) edata; HCFileInfo *info = g_config; if ((TS_SUCCESS == TSHttpTxnClientReqGet(txnp, &reqp, &hdr_loc)) && (TS_SUCCESS == TSHttpHdrUrlGet(reqp, hdr_loc, &url_loc))) { int path_len = 0; const char* path = TSUrlPathGet(reqp, url_loc, &path_len); while (info) { if (info->p_len == path_len && !memcmp(info->path, path, path_len)) break; info = info->_next; } if (!info) goto cleanup; TSSkipRemappingSet(txnp, 1); /* not strictly necessary, but speed is everything these days */ /* This is us -- register our intercept */ icontp = TSContCreate(hc_intercept, TSMutexCreate()); my_state = (HCState *)TSmalloc(sizeof(*my_state)); memset(my_state, 0, sizeof(*my_state)); my_state->info = info; my_state->data = info->data; TSContDataSet(icontp, my_state); TSHttpTxnIntercept(icontp, txnp); } cleanup: if (url_loc) TSHandleMLocRelease(reqp, hdr_loc, url_loc); if (hdr_loc) TSHandleMLocRelease(reqp, TS_NULL_MLOC, hdr_loc); TSHttpTxnReenable(txnp, TS_EVENT_HTTP_CONTINUE); return 0; }
/* Read-request header continuation, used to kick off the server intercept if necessary */ static int acme_hook(TSCont contp ATS_UNUSED, TSEvent event ATS_UNUSED, void *edata) { TSMBuffer reqp; TSMLoc hdr_loc = NULL, url_loc = NULL; TSCont icontp; AcmeState *my_state; TSHttpTxn txnp = (TSHttpTxn)edata; TSDebug(PLUGIN_NAME, "kicking off ACME hook"); if ((TS_SUCCESS == TSHttpTxnClientReqGet(txnp, &reqp, &hdr_loc)) && (TS_SUCCESS == TSHttpHdrUrlGet(reqp, hdr_loc, &url_loc))) { int path_len = 0; const char *path = TSUrlPathGet(reqp, url_loc, &path_len); /* Short circuit the / path, common case */ if (!path || path_len < (int)(strlen(ACME_WK_PATH) + 2) || *path != '.' || memcmp(path, ACME_WK_PATH, strlen(ACME_WK_PATH))) { TSDebug(PLUGIN_NAME, "skipping URL path = %.*s", path_len, path); goto cleanup; } TSSkipRemappingSet(txnp, 1); /* not strictly necessary, but speed is everything these days */ /* This request is for us -- register our intercept */ icontp = TSContCreate(acme_intercept, TSMutexCreate()); my_state = make_acme_state(); open_acme_file(my_state, path + strlen(ACME_WK_PATH), path_len - strlen(ACME_WK_PATH)); TSContDataSet(icontp, my_state); TSHttpTxnIntercept(icontp, txnp); TSDebug(PLUGIN_NAME, "created intercept hook"); } cleanup: if (url_loc) { TSHandleMLocRelease(reqp, hdr_loc, url_loc); } if (hdr_loc) { TSHandleMLocRelease(reqp, TS_NULL_MLOC, hdr_loc); } TSHttpTxnReenable(txnp, TS_EVENT_HTTP_CONTINUE); return 0; }
static int regex_match(TSCont contp, TSHttpTxn txnp) { static char *url; TSMBuffer bufp; TSMLoc hdr_loc, url_loc; int url_length; regex_t *re; int ovector[30], res; if (TSHttpTxnClientReqGet(txnp, &bufp, &hdr_loc) != TS_SUCCESS) { TSError("couldn't retrieve client response header\n"); goto done; } if (TSHttpHdrUrlGet(bufp, hdr_loc, &url_loc) != TS_SUCCESS) { TSError("couldn't retrieve request url\n"); TSHandleMLocRelease(bufp, TS_NULL_MLOC, hdr_loc); goto done; } url = TSUrlStringGet(bufp, url_loc, &url_length); if (url == NULL) { TSError("couldn't get url"); goto done; } for (re = reg; re; re = re->next) { res = pcre_exec(re->re, NULL, url, strlen(url), 0, 0, ovector, 30); if (res <= 0) { goto done; } break; } TSContDataSet(contp, re->hdr); TSHttpTxnHookAdd(txnp, TS_HTTP_SEND_RESPONSE_HDR_HOOK, contp); done: TSfree(url); TSHandleMLocRelease(bufp, hdr_loc, url_loc); TSHandleMLocRelease(bufp, TS_NULL_MLOC, hdr_loc); TSHttpTxnReenable(txnp, TS_EVENT_HTTP_CONTINUE); return 0; }
static void handle_response(TSHttpTxn txnp, TSCont contp ATS_UNUSED) { TSMBuffer bufp; TSMLoc hdr_loc; TSMLoc url_loc; char *url_str; char *buf; int url_length; if (TSHttpTxnClientRespGet(txnp, &bufp, &hdr_loc) != TS_SUCCESS) { TSError("[%s] Couldn't retrieve client response header", PLUGIN_NAME); goto done; } TSHttpHdrStatusSet(bufp, hdr_loc, TS_HTTP_STATUS_FORBIDDEN); TSHttpHdrReasonSet(bufp, hdr_loc, TSHttpHdrReasonLookup(TS_HTTP_STATUS_FORBIDDEN), strlen(TSHttpHdrReasonLookup(TS_HTTP_STATUS_FORBIDDEN))); if (TSHttpTxnClientReqGet(txnp, &bufp, &hdr_loc) != TS_SUCCESS) { TSError("[%s] Couldn't retrieve client request header", PLUGIN_NAME); TSHandleMLocRelease(bufp, TS_NULL_MLOC, hdr_loc); goto done; } if (TSHttpHdrUrlGet(bufp, hdr_loc, &url_loc) != TS_SUCCESS) { TSError("[%s] Couldn't retrieve request url", PLUGIN_NAME); TSHandleMLocRelease(bufp, TS_NULL_MLOC, hdr_loc); goto done; } buf = (char *)TSmalloc(4096); url_str = TSUrlStringGet(bufp, url_loc, &url_length); sprintf(buf, "You are forbidden from accessing \"%s\"\n", url_str); TSfree(url_str); TSHandleMLocRelease(bufp, hdr_loc, url_loc); TSHandleMLocRelease(bufp, TS_NULL_MLOC, hdr_loc); TSHttpTxnErrorBodySet(txnp, buf, strlen(buf), NULL); done: TSHttpTxnReenable(txnp, TS_EVENT_HTTP_CONTINUE); }
static void handle_dns(TSHttpTxn txnp, TSCont contp) { TSMBuffer bufp; TSMLoc hdr_loc; TSMLoc url_loc; const char *host; int i; int host_length; if (TSHttpTxnClientReqGet(txnp, &bufp, &hdr_loc) != TS_SUCCESS) { TSError("[blacklist-0] Couldn't retrieve client request header"); goto done; } if (TSHttpHdrUrlGet(bufp, hdr_loc, &url_loc) != TS_SUCCESS) { TSError("[blacklist-0] Couldn't retrieve request url"); TSHandleMLocRelease(bufp, TS_NULL_MLOC, hdr_loc); goto done; } host = TSUrlHostGet(bufp, url_loc, &host_length); if (!host) { TSError("[blacklist-0] Couldn't retrieve request hostname"); TSHandleMLocRelease(bufp, hdr_loc, url_loc); TSHandleMLocRelease(bufp, TS_NULL_MLOC, hdr_loc); goto done; } for (i = 0; i < nsites; i++) { if (strncmp(host, sites[i], host_length) == 0) { printf("blacklisting site: %s\n", sites[i]); TSHttpTxnHookAdd(txnp, TS_HTTP_SEND_RESPONSE_HDR_HOOK, contp); TSHandleMLocRelease(bufp, hdr_loc, url_loc); TSHandleMLocRelease(bufp, TS_NULL_MLOC, url_loc); TSHttpTxnReenable(txnp, TS_EVENT_HTTP_ERROR); return; } } TSHandleMLocRelease(bufp, hdr_loc, url_loc); TSHandleMLocRelease(bufp, TS_NULL_MLOC, hdr_loc); done: TSHttpTxnReenable(txnp, TS_EVENT_HTTP_CONTINUE); }
bool should_push(TSHttpTxn txnp) { TSMBuffer mbuf; TSMLoc hdr, url; if (TSHttpTxnClientReqGet(txnp, &mbuf, &hdr) != TS_SUCCESS) { return false; } if (TSHttpHdrUrlGet(mbuf, hdr, &url) != TS_SUCCESS) { return false; } int len; TSUrlHttpQueryGet(mbuf, url, &len); TSHandleMLocRelease(mbuf, hdr, url); TSHandleMLocRelease(mbuf, TS_NULL_MLOC, hdr); if (len > 0) { return true; } else { return false; } }
static void handle_dns(TSHttpTxn txnp, TSCont contp) { TSMBuffer bufp; TSMLoc hdr_loc; TSMLoc url_loc; const char *host; int i; int host_length; if (TSHttpTxnClientReqGet(txnp, &bufp, &hdr_loc) != TS_SUCCESS) { TSError("[%s] Couldn't retrieve client request header", PLUGIN_NAME); goto done; } if (TSHttpHdrUrlGet(bufp, hdr_loc, &url_loc) != TS_SUCCESS) { TSError("[%s] Couldn't retrieve request url", PLUGIN_NAME); TSHandleMLocRelease(bufp, TS_NULL_MLOC, hdr_loc); goto done; } host = TSUrlHostGet(bufp, url_loc, &host_length); if (!host) { TSError("[%s] Couldn't retrieve request hostname", PLUGIN_NAME); TSHandleMLocRelease(bufp, hdr_loc, url_loc); TSHandleMLocRelease(bufp, TS_NULL_MLOC, hdr_loc); goto done; } /* We need to lock the sites_mutex as that is the mutex that is protecting the global list of all blacklisted sites. */ if (TSMutexLockTry(sites_mutex) != TS_SUCCESS) { TSDebug(PLUGIN_NAME, "Unable to get lock. Will retry after some time"); TSHandleMLocRelease(bufp, hdr_loc, url_loc); TSHandleMLocRelease(bufp, TS_NULL_MLOC, hdr_loc); TSContSchedule(contp, RETRY_TIME, TS_THREAD_POOL_DEFAULT); return; } for (i = 0; i < nsites; i++) { if (strncmp(host, sites[i], host_length) == 0) { if (log) { TSTextLogObjectWrite(log, "blacklisting site: %s", sites[i]); } else { TSDebug(PLUGIN_NAME, "blacklisting site: %s", sites[i]); } TSHttpTxnHookAdd(txnp, TS_HTTP_SEND_RESPONSE_HDR_HOOK, contp); TSHandleMLocRelease(bufp, hdr_loc, url_loc); TSHandleMLocRelease(bufp, TS_NULL_MLOC, hdr_loc); TSHttpTxnReenable(txnp, TS_EVENT_HTTP_ERROR); TSMutexUnlock(sites_mutex); return; } } TSMutexUnlock(sites_mutex); TSHandleMLocRelease(bufp, hdr_loc, url_loc); TSHandleMLocRelease(bufp, TS_NULL_MLOC, hdr_loc); done: TSHttpTxnReenable(txnp, TS_EVENT_HTTP_CONTINUE); }
static void handle_purge(TSHttpTxn txnp, PurgeInstance *purge) { TSMBuffer reqp; TSMLoc hdr_loc = NULL, url_loc = NULL; bool should_purge = false; if (TS_SUCCESS == TSHttpTxnClientReqGet(txnp, &reqp, &hdr_loc)) { int method_len = 0; const char *method = TSHttpHdrMethodGet(reqp, hdr_loc, &method_len); if ((TS_HTTP_METHOD_PURGE == method) || ((TS_HTTP_METHOD_GET == method) && purge->allow_get)) { /* First see if we require the "secret" to be passed in a header, and then use that */ if (purge->header) { TSMLoc field_loc = TSMimeHdrFieldFind(reqp, hdr_loc, purge->header, purge->header_len); if (field_loc) { const char *header; int header_len; header = TSMimeHdrFieldValueStringGet(reqp, hdr_loc, field_loc, -1, &header_len); TSDebug(PLUGIN_NAME, "Checking for %.*s == %s ?", header_len, header, purge->secret); if (header && (header_len == purge->secret_len) && !memcmp(header, purge->secret, header_len)) { should_purge = true; } TSHandleMLocRelease(reqp, hdr_loc, field_loc); } } else { /* We are matching on the path component instead of a header */ if (TS_SUCCESS == TSHttpHdrUrlGet(reqp, hdr_loc, &url_loc)) { int path_len = 0; const char *path = TSUrlPathGet(reqp, url_loc, &path_len); TSDebug(PLUGIN_NAME, "Checking PATH = %.*s", path_len, path); if (path && (path_len >= purge->secret_len)) { int s_path = path_len - 1; while ((s_path >= 0) && ('/' != path[s_path])) { /* No memrchr in OSX */ --s_path; } if (!memcmp(s_path > 0 ? path + s_path + 1 : path, purge->secret, purge->secret_len)) { should_purge = true; } } TSHandleMLocRelease(reqp, hdr_loc, url_loc); } } } TSHandleMLocRelease(reqp, TS_NULL_MLOC, hdr_loc); } /* Setup the continuation to handle this request if appropriate, if not, set the GenID if needed */ if (should_purge) { TSCont cont = TSContCreate(purge_cont, TSMutexCreate()); TSContDataSet(cont, purge); TSHttpTxnHookAdd(txnp, TS_HTTP_CACHE_LOOKUP_COMPLETE_HOOK, cont); TSHttpTxnHookAdd(txnp, TS_HTTP_SEND_RESPONSE_HDR_HOOK, cont); } else if (purge->gen_id > 0) { TSHttpTxnConfigIntSet(txnp, TS_CONFIG_HTTP_CACHE_GENERATION, purge->gen_id); } }
static int globalHookHandler(TSCont contp, TSEvent event ATS_UNUSED, void *edata) { TSHttpTxn txnp = (TSHttpTxn) edata; TSMBuffer bufp; TSMLoc hdr_loc; TSMLoc url_loc; int ret; uint64_t req_id; TSCont txn_contp; lua_State *l; ts_lua_main_ctx *main_ctx; ts_lua_http_ctx *http_ctx; ts_lua_instance_conf *conf = (ts_lua_instance_conf *) TSContDataGet(contp); req_id = __sync_fetch_and_add(&ts_lua_g_http_next_id, 1); main_ctx = &ts_lua_g_main_ctx_array[req_id % TS_LUA_MAX_STATE_COUNT]; TSDebug(TS_LUA_DEBUG_TAG, "[%s] req_id: %" PRId64, __FUNCTION__, req_id); TSMutexLock(main_ctx->mutexp); http_ctx = ts_lua_create_http_ctx(main_ctx, conf); http_ctx->txnp = txnp; http_ctx->remap = 0; http_ctx->has_hook = 0; if (!http_ctx->client_request_bufp) { if (TSHttpTxnClientReqGet(txnp, &bufp, &hdr_loc) == TS_SUCCESS) { http_ctx->client_request_bufp = bufp; http_ctx->client_request_hdrp = hdr_loc; if (TSHttpHdrUrlGet(bufp, hdr_loc, &url_loc) == TS_SUCCESS) { http_ctx->client_request_url = url_loc; } } } if (!http_ctx->client_request_hdrp) { TSHttpTxnReenable(txnp, TS_EVENT_HTTP_CONTINUE); return 0; } txn_contp = TSContCreate(ts_lua_http_cont_handler, NULL); TSContDataSet(txn_contp, http_ctx); http_ctx->main_contp = txn_contp; l = http_ctx->lua; switch (event) { case TS_EVENT_HTTP_READ_REQUEST_HDR: lua_getglobal(l, TS_LUA_FUNCTION_G_READ_REQUEST); break; case TS_EVENT_HTTP_SEND_REQUEST_HDR: lua_getglobal(l, TS_LUA_FUNCTION_G_SEND_REQUEST); break; case TS_EVENT_HTTP_READ_RESPONSE_HDR: lua_getglobal(l, TS_LUA_FUNCTION_G_READ_RESPONSE); break; case TS_EVENT_HTTP_SEND_RESPONSE_HDR: lua_getglobal(l, TS_LUA_FUNCTION_G_SEND_RESPONSE); break; case TS_EVENT_HTTP_CACHE_LOOKUP_COMPLETE: lua_getglobal(l, TS_LUA_FUNCTION_G_CACHE_LOOKUP_COMPLETE); break; case TS_EVENT_HTTP_TXN_START: lua_getglobal(l, TS_LUA_FUNCTION_G_TXN_START); break; case TS_EVENT_HTTP_PRE_REMAP: lua_getglobal(l, TS_LUA_FUNCTION_G_PRE_REMAP); break; case TS_EVENT_HTTP_POST_REMAP: lua_getglobal(l, TS_LUA_FUNCTION_G_POST_REMAP); break; case TS_EVENT_HTTP_SELECT_ALT: lua_getglobal(l, TS_LUA_FUNCTION_G_SELECT_ALT); break; case TS_EVENT_HTTP_OS_DNS: lua_getglobal(l, TS_LUA_FUNCTION_G_OS_DNS); break; case TS_EVENT_HTTP_READ_CACHE_HDR: lua_getglobal(l, TS_LUA_FUNCTION_G_READ_CACHE); break; case TS_EVENT_HTTP_TXN_CLOSE: lua_getglobal(l, TS_LUA_FUNCTION_G_TXN_CLOSE); break; default: TSHttpTxnReenable(txnp, TS_EVENT_HTTP_CONTINUE); return 0; break; } if (lua_type(l, -1) != LUA_TFUNCTION) { TSHttpTxnReenable(txnp, TS_EVENT_HTTP_CONTINUE); lua_pop(l, 1); return 0; } if (lua_pcall(l, 0, 1, 0) != 0) { TSError("lua_pcall failed: %s", lua_tostring(l, -1)); } ret = lua_tointeger(l, -1); lua_pop(l, 1); if(http_ctx->has_hook) { // add a hook to release resources for context TSDebug(TS_LUA_DEBUG_TAG, "[%s] has txn hook -> adding txn close hook handler to release resources", __FUNCTION__); TSHttpTxnHookAdd(txnp, TS_HTTP_TXN_CLOSE_HOOK, txn_contp); } else { TSDebug(TS_LUA_DEBUG_TAG, "[%s] no txn hook -> release resources now", __FUNCTION__); ts_lua_destroy_http_ctx(http_ctx); TSContDestroy(txn_contp); } TSMutexUnlock(main_ctx->mutexp); if(ret) { TSHttpTxnReenable(txnp, TS_EVENT_HTTP_ERROR); } else { TSHttpTxnReenable(txnp, TS_EVENT_HTTP_CONTINUE); } return 0; }
static void handle_client_lookup(TSHttpTxn txnp, TSCont contp) { TSMBuffer bufp; TSMLoc hdr_loc, url_loc; int host_length; in_addr_t clientip = 0; const char *host; if (TSIsDebugTagSet("redirect")) { struct sockaddr const *addr = TSHttpTxnClientAddrGet(txnp); if (addr) { socklen_t addr_size = 0; if (addr->sa_family == AF_INET) { addr_size = sizeof(struct sockaddr_in); } else if (addr->sa_family == AF_INET6) { addr_size = sizeof(struct sockaddr_in6); } if (addr_size > 0) { char clientstring[INET6_ADDRSTRLEN]; if (NULL != inet_ntop(addr->sa_family, addr, clientstring, addr_size)) { TSDebug(PLUGIN_NAME, "clientip is %s and block_ip is %s", clientstring, block_ip); } } } } if (TSHttpTxnClientReqGet(txnp, &bufp, &hdr_loc) != TS_SUCCESS) { TSError("[%s] Couldn't retrieve client request header", PLUGIN_NAME); goto done; } if (TSHttpHdrUrlGet(bufp, hdr_loc, &url_loc) != TS_SUCCESS) { TSError("[%s] Couldn't retrieve request url", PLUGIN_NAME); TSHandleMLocRelease(bufp, TS_NULL_MLOC, hdr_loc); goto done; } host = TSUrlHostGet(bufp, url_loc, &host_length); if (!host) { TSError("[%s] Couldn't retrieve request hostname", PLUGIN_NAME); TSHandleMLocRelease(bufp, hdr_loc, url_loc); TSHandleMLocRelease(bufp, TS_NULL_MLOC, hdr_loc); goto done; } /* * Check to see if the client is already headed to the redirect site. */ if (strncmp(host, url_redirect, host_length) == 0) { TSHandleMLocRelease(bufp, hdr_loc, url_loc); TSHandleMLocRelease(bufp, TS_NULL_MLOC, hdr_loc); goto done; } /* TODO: This is odd, clientip is never set ... */ if (ip_deny == clientip) { TSHttpTxnHookAdd(txnp, TS_HTTP_SEND_RESPONSE_HDR_HOOK, contp); update_redirected_method_stats(bufp, hdr_loc); TSHandleMLocRelease(bufp, hdr_loc, url_loc); TSHandleMLocRelease(bufp, TS_NULL_MLOC, hdr_loc); /* * Increment the local redirect stat and do global update: */ TSStatIntIncrement(requests_redirects, 1); TSHttpTxnReenable(txnp, TS_EVENT_HTTP_ERROR); return; } done: // Increment the local number unchanged stat and do global update: TSStatIntIncrement(requests_unchanged, 1); TSHttpTxnReenable(txnp, TS_EVENT_HTTP_CONTINUE); }
static void handle_client_lookup(TSHttpTxn txnp, TSCont contp) { TSMBuffer bufp; TSMLoc hdr_loc, url_loc; int host_length; in_addr_t clientip = 0; const char *host; /* * Here we declare local coupled statistics variables: */ INKCoupledStat local_request_outcomes; INKStat local_requests_all; INKStat local_requests_redirects; INKStat local_requests_unchanged; /* * Create local copy of the global coupled stat category: */ local_request_outcomes = INKStatCoupledLocalCopyCreate("local_request_outcomes", request_outcomes); /* * Create the local copies of the global coupled stats: */ local_requests_all = INKStatCoupledLocalAdd(local_request_outcomes, "requests.all.local", INKSTAT_TYPE_FLOAT); local_requests_redirects = INKStatCoupledLocalAdd(local_request_outcomes, "requests.redirects.local", INKSTAT_TYPE_INT64); local_requests_unchanged = INKStatCoupledLocalAdd(local_request_outcomes, "requests.unchanged.local", INKSTAT_TYPE_INT64); /* * Increment the count of total requests: * (it is more natural to treat the number of requests as an * integer, but we declare this a FLOAT in order to demonstrate * how to increment coupled FLOAT stats) */ INKStatFloatAddTo(local_requests_all, 1.0); if (TSIsDebugTagSet("redirect")) { struct sockaddr const* addr = TSHttpTxnClientAddrGet(txnp); if (addr) { socklen_t addr_size = 0; if (addr->sa_family == AF_INET) addr_size = sizeof(struct sockaddr_in); else if (addr->sa_family == AF_INET6) addr_size = sizeof(struct sockaddr_in6); if (addr_size > 0) { char clientstring[INET6_ADDRSTRLEN]; if (NULL != inet_ntop(addr->sa_family, addr, clientstring, addr_size)) TSDebug("redirect", "clientip is %s and block_ip is %s", clientstring, block_ip); } } } if (TSHttpTxnClientReqGet(txnp, &bufp, &hdr_loc) != TS_SUCCESS) { TSError("couldn't retrieve client request header\n"); goto done; } if (TSHttpHdrUrlGet(bufp, hdr_loc, &url_loc) != TS_SUCCESS) { TSError("couldn't retrieve request url\n"); TSHandleMLocRelease(bufp, TS_NULL_MLOC, hdr_loc); goto done; } host = TSUrlHostGet(bufp, url_loc, &host_length); if (!host) { TSError("couldn't retrieve request hostname\n"); TSHandleMLocRelease(bufp, hdr_loc, url_loc); TSHandleMLocRelease(bufp, TS_NULL_MLOC, hdr_loc); goto done; } /* * Check to see if the client is already headed to the redirect site. */ if (strncmp(host, url_redirect, host_length) == 0) { TSHandleMLocRelease(bufp, hdr_loc, url_loc); TSHandleMLocRelease(bufp, TS_NULL_MLOC, hdr_loc); goto done; } /* TODO: This is odd, clientip is never set ... */ if (ip_deny == clientip) { TSHttpTxnHookAdd(txnp, TS_HTTP_SEND_RESPONSE_HDR_HOOK, contp); update_redirected_method_stats(bufp, hdr_loc); TSHandleMLocRelease(bufp, hdr_loc, url_loc); TSHandleMLocRelease(bufp, TS_NULL_MLOC, hdr_loc); /* * Increment the local redirect stat and do global update: */ INKStatIncrement(local_requests_redirects); INKStatsCoupledUpdate(local_request_outcomes); INKStatCoupledLocalCopyDestroy(local_request_outcomes); TSHttpTxnReenable(txnp, TS_EVENT_HTTP_ERROR); return; } done: /* * Increment the local number unchanged stat and do global update: */ INKStatIncrement(local_requests_unchanged); INKStatsCoupledUpdate(local_request_outcomes); INKStatCoupledLocalCopyDestroy(local_request_outcomes); TSHttpTxnReenable(txnp, TS_EVENT_HTTP_CONTINUE); }
static int astats_origin(TSCont cont, TSEvent event, void *edata) { TSCont icontp; stats_state *my_state; config_t* config; TSHttpTxn txnp = (TSHttpTxn) edata; TSMBuffer reqp; TSMLoc hdr_loc = NULL, url_loc = NULL; TSEvent reenable = TS_EVENT_HTTP_CONTINUE; config = get_config(cont); TSDebug(PLUGIN_TAG, "in the read stuff"); if (TSHttpTxnClientReqGet(txnp, &reqp, &hdr_loc) != TS_SUCCESS) goto cleanup; if (TSHttpHdrUrlGet(reqp, hdr_loc, &url_loc) != TS_SUCCESS) goto cleanup; int path_len = 0; const char* path = TSUrlPathGet(reqp,url_loc,&path_len); TSDebug(PLUGIN_TAG,"Path: %.*s",path_len,path); TSDebug(PLUGIN_TAG,"Path: %.*s",path_len,path); if (!(path_len == config->stats_path_len && !memcmp(path, config->stats_path, config->stats_path_len))) { // TSDebug(PLUGIN_TAG, "not right path: %.*s",path_len,path); goto notforme; } const struct sockaddr *addr = TSHttpTxnClientAddrGet(txnp); if(!is_ip_allowed(config, addr)) { TSDebug(PLUGIN_TAG, "not right ip"); goto notforme; } // TSDebug(PLUGIN_TAG,"Path...: %.*s",path_len,path); int query_len; char *query = (char*)TSUrlHttpQueryGet(reqp,url_loc,&query_len); TSDebug(PLUGIN_TAG,"query: %.*s",query_len,query); TSSkipRemappingSet(txnp,1); //not strictly necessary, but speed is everything these days /* This is us -- register our intercept */ TSDebug(PLUGIN_TAG, "Intercepting request"); icontp = TSContCreate(stats_dostuff, TSMutexCreate()); my_state = (stats_state *) TSmalloc(sizeof(*my_state)); memset(my_state, 0, sizeof(*my_state)); my_state->recordTypes = config->recordTypes; if (query_len) { my_state->query = nstrl(query, query_len); TSDebug(PLUGIN_TAG,"new query: %s", my_state->query); stats_fillState(my_state, my_state->query, query_len); } TSContDataSet(icontp, my_state); TSHttpTxnIntercept(icontp, txnp); goto cleanup; notforme: cleanup: #if (TS_VERSION_NUMBER < 2001005) if (path) TSHandleStringRelease(reqp, url_loc, path); #endif if (url_loc) TSHandleMLocRelease(reqp, hdr_loc, url_loc); if (hdr_loc) TSHandleMLocRelease(reqp, TS_NULL_MLOC, hdr_loc); TSHttpTxnReenable(txnp, reenable); return 0; }
static int globalHookHandler(TSCont contp, TSEvent event ATS_UNUSED, void *edata) { TSHttpTxn txnp = (TSHttpTxn)edata; TSMBuffer bufp; TSMLoc hdr_loc; TSMLoc url_loc; int ret; uint64_t req_id; TSCont txn_contp; lua_State *l; ts_lua_main_ctx *main_ctx; ts_lua_http_ctx *http_ctx; ts_lua_cont_info *ci; ts_lua_instance_conf *conf = (ts_lua_instance_conf *)TSContDataGet(contp); req_id = __sync_fetch_and_add(&ts_lua_g_http_next_id, 1); main_ctx = &ts_lua_g_main_ctx_array[req_id % TS_LUA_MAX_STATE_COUNT]; TSDebug(TS_LUA_DEBUG_TAG, "[%s] req_id: %" PRId64, __FUNCTION__, req_id); TSMutexLock(main_ctx->mutexp); http_ctx = ts_lua_create_http_ctx(main_ctx, conf); http_ctx->txnp = txnp; http_ctx->rri = NULL; http_ctx->has_hook = 0; if (!http_ctx->client_request_bufp) { if (TSHttpTxnClientReqGet(txnp, &bufp, &hdr_loc) == TS_SUCCESS) { http_ctx->client_request_bufp = bufp; http_ctx->client_request_hdrp = hdr_loc; if (TSHttpHdrUrlGet(bufp, hdr_loc, &url_loc) == TS_SUCCESS) { http_ctx->client_request_url = url_loc; } } } if (!http_ctx->client_request_hdrp) { ts_lua_destroy_http_ctx(http_ctx); TSMutexUnlock(main_ctx->mutexp); TSHttpTxnReenable(txnp, TS_EVENT_HTTP_CONTINUE); return 0; } txn_contp = TSContCreate(ts_lua_http_cont_handler, NULL); TSContDataSet(txn_contp, http_ctx); ci = &http_ctx->cinfo; ci->contp = txn_contp; ci->mutex = TSContMutexGet((TSCont)txnp); l = ci->routine.lua; switch (event) { case TS_EVENT_HTTP_READ_REQUEST_HDR: lua_getglobal(l, TS_LUA_FUNCTION_G_READ_REQUEST); break; case TS_EVENT_HTTP_SEND_REQUEST_HDR: lua_getglobal(l, TS_LUA_FUNCTION_G_SEND_REQUEST); break; case TS_EVENT_HTTP_READ_RESPONSE_HDR: lua_getglobal(l, TS_LUA_FUNCTION_G_READ_RESPONSE); break; case TS_EVENT_HTTP_SEND_RESPONSE_HDR: // client response can be changed within a transaction // (e.g. due to the follow redirect feature). So, clearing the pointers // to allow API(s) to fetch the pointers again when it re-enters the hook if (http_ctx->client_response_hdrp != NULL) { TSHandleMLocRelease(http_ctx->client_response_bufp, TS_NULL_MLOC, http_ctx->client_response_hdrp); http_ctx->client_response_hdrp = NULL; } lua_getglobal(l, TS_LUA_FUNCTION_G_SEND_RESPONSE); break; case TS_EVENT_HTTP_CACHE_LOOKUP_COMPLETE: lua_getglobal(l, TS_LUA_FUNCTION_G_CACHE_LOOKUP_COMPLETE); break; case TS_EVENT_HTTP_TXN_START: lua_getglobal(l, TS_LUA_FUNCTION_G_TXN_START); break; case TS_EVENT_HTTP_PRE_REMAP: lua_getglobal(l, TS_LUA_FUNCTION_G_PRE_REMAP); break; case TS_EVENT_HTTP_POST_REMAP: lua_getglobal(l, TS_LUA_FUNCTION_G_POST_REMAP); break; case TS_EVENT_HTTP_SELECT_ALT: lua_getglobal(l, TS_LUA_FUNCTION_G_SELECT_ALT); break; case TS_EVENT_HTTP_OS_DNS: lua_getglobal(l, TS_LUA_FUNCTION_G_OS_DNS); break; case TS_EVENT_HTTP_READ_CACHE_HDR: lua_getglobal(l, TS_LUA_FUNCTION_G_READ_CACHE); break; case TS_EVENT_HTTP_TXN_CLOSE: lua_getglobal(l, TS_LUA_FUNCTION_G_TXN_CLOSE); break; default: ts_lua_destroy_http_ctx(http_ctx); TSMutexUnlock(main_ctx->mutexp); TSHttpTxnReenable(txnp, TS_EVENT_HTTP_CONTINUE); return 0; } if (lua_type(l, -1) != LUA_TFUNCTION) { lua_pop(l, 1); ts_lua_destroy_http_ctx(http_ctx); TSMutexUnlock(main_ctx->mutexp); TSHttpTxnReenable(txnp, TS_EVENT_HTTP_CONTINUE); return 0; } ts_lua_set_cont_info(l, NULL); if (lua_pcall(l, 0, 1, 0) != 0) { TSError("[ts_lua] lua_pcall failed: %s", lua_tostring(l, -1)); } ret = lua_tointeger(l, -1); lua_pop(l, 1); if (http_ctx->has_hook) { // add a hook to release resources for context TSDebug(TS_LUA_DEBUG_TAG, "[%s] has txn hook -> adding txn close hook handler to release resources", __FUNCTION__); TSHttpTxnHookAdd(txnp, TS_HTTP_TXN_CLOSE_HOOK, txn_contp); } else { TSDebug(TS_LUA_DEBUG_TAG, "[%s] no txn hook -> release resources now", __FUNCTION__); ts_lua_destroy_http_ctx(http_ctx); } TSMutexUnlock(main_ctx->mutexp); if (ret) { TSHttpTxnReenable(txnp, TS_EVENT_HTTP_ERROR); } else { TSHttpTxnReenable(txnp, TS_EVENT_HTTP_CONTINUE); } return 0; }
static int globalHookHandler(TSCont contp, TSEvent event, void *edata) { TSHttpTxn txnp = (TSHttpTxn) edata; int ret = 0; lua_State *l; ts_lua_http_ctx *http_ctx = (ts_lua_http_ctx *) TSContDataGet(contp); TSMBuffer bufp; TSMLoc hdr_loc; TSMLoc url_loc; if (!http_ctx->client_request_bufp) { if (TSHttpTxnClientReqGet(txnp, &bufp, &hdr_loc) == TS_SUCCESS) { http_ctx->client_request_bufp = bufp; http_ctx->client_request_hdrp = hdr_loc; if (TSHttpHdrUrlGet(bufp, hdr_loc, &url_loc) == TS_SUCCESS) { http_ctx->client_request_url = url_loc; } } } if (!http_ctx->client_request_hdrp) { TSHttpTxnReenable(txnp, TS_EVENT_HTTP_CONTINUE); return 0; } l = http_ctx->lua; switch (event) { case TS_EVENT_HTTP_READ_REQUEST_HDR: lua_getglobal(l, TS_LUA_FUNCTION_G_READ_REQUEST); break; case TS_EVENT_HTTP_SEND_REQUEST_HDR: lua_getglobal(l, TS_LUA_FUNCTION_G_SEND_REQUEST); break; case TS_EVENT_HTTP_READ_RESPONSE_HDR: lua_getglobal(l, TS_LUA_FUNCTION_G_READ_RESPONSE); break; case TS_EVENT_HTTP_SEND_RESPONSE_HDR: lua_getglobal(l, TS_LUA_FUNCTION_G_SEND_RESPONSE); break; case TS_EVENT_HTTP_CACHE_LOOKUP_COMPLETE: lua_getglobal(l, TS_LUA_FUNCTION_G_CACHE_LOOKUP_COMPLETE); break; case TS_EVENT_HTTP_TXN_START: lua_getglobal(l, TS_LUA_FUNCTION_G_TXN_START); break; case TS_EVENT_HTTP_PRE_REMAP: lua_getglobal(l, TS_LUA_FUNCTION_G_PRE_REMAP); break; case TS_EVENT_HTTP_POST_REMAP: lua_getglobal(l, TS_LUA_FUNCTION_G_POST_REMAP); break; case TS_EVENT_HTTP_SELECT_ALT: lua_getglobal(l, TS_LUA_FUNCTION_G_SELECT_ALT); break; case TS_EVENT_HTTP_OS_DNS: lua_getglobal(l, TS_LUA_FUNCTION_G_OS_DNS); break; case TS_EVENT_HTTP_READ_CACHE_HDR: lua_getglobal(l, TS_LUA_FUNCTION_G_READ_CACHE); break; case TS_EVENT_HTTP_TXN_CLOSE: lua_getglobal(l, TS_LUA_FUNCTION_G_TXN_CLOSE); break; default: TSHttpTxnReenable(txnp, TS_EVENT_HTTP_CONTINUE); return 0; break; } if (lua_type(l, -1) != LUA_TFUNCTION) { TSHttpTxnReenable(txnp, TS_EVENT_HTTP_CONTINUE); lua_pop(l, 1); return 0; } if (lua_pcall(l, 0, 1, 0) != 0) { fprintf(stderr, "lua_pcall failed: %s\n", lua_tostring(l, -1)); } ret = lua_tointeger(l, -1); lua_pop(l, 1); TSHttpTxnReenable(txnp, TS_EVENT_HTTP_CONTINUE); return ret; }