示例#1
0
int
errorMapStart(const errormap * map, request_t * client_req, HttpReply * reply, const char *aclname, ERRMAPCB * callback, void *callback_data)
{
    char squid_error[100];
    int len = 0;
    const char *errorUrl;
    ErrorMapState *state;
    const char *tmp;
    http_status status;
    request_t *req;
    HttpHeaderPos hdrpos;
    HttpHeaderEntry *hdr;

    if (!client_req || !reply)
	return 0;

    status = reply->sline.status;

    tmp = httpHeaderGetStr(&reply->header, HDR_X_SQUID_ERROR);
    squid_error[0] = '\0';
    if (tmp) {
	xstrncpy(squid_error, tmp, sizeof(squid_error));
	len = strcspn(squid_error, " ");
    }
    squid_error[len] = '\0';
    errorUrl = getErrorMap(map, status, squid_error, aclname);
    if (!errorUrl)
	return 0;
    req = urlParse(urlMethodGetKnownByCode(METHOD_GET), (char *) errorUrl);
    if (!req) {
	debug(0, 0) ("errorMapStart: Invalid error URL '%s'\n", errorUrl);
	return 0;
    }
    req->urlgroup = xstrdup("error");

    state = cbdataAlloc(ErrorMapState);
    state->req = requestLink(req);
    state->e = storeCreateEntry(errorUrl, req->flags, req->method);
    state->sc = storeClientRegister(state->e, state);
    state->callback = callback;
    state->callback_data = callback_data;
    cbdataLock(callback_data);

    hdrpos = HttpHeaderInitPos;
    while ((hdr = httpHeaderGetEntry(&client_req->header, &hdrpos)) != NULL) {
	if (CBIT_TEST(client_headers, hdr->id))
	    httpHeaderAddClone(&req->header, hdr);
    }
    hdrpos = HttpHeaderInitPos;
    while ((hdr = httpHeaderGetEntry(&reply->header, &hdrpos)) != NULL) {
	if (CBIT_TEST(server_headers, hdr->id))
	    httpHeaderAddClone(&req->header, hdr);
    }
    httpHeaderPutInt(&req->header, HDR_X_ERROR_STATUS, (int) reply->sline.status);
    httpHeaderPutStr(&req->header, HDR_X_REQUEST_URI, urlCanonical(client_req));

    fwdStart(-1, state->e, req);
    storeClientRef(state->sc, state->e, 0, 0, SM_PAGE_SIZE, errorMapFetchHeaders, state);
    return 1;
}
示例#2
0
/* allocates and initializes an error response */
HttpReply *
errorBuildReply(ErrorState * err)
{
    HttpReply *rep = httpReplyCreate();
    const char *name = errorPageName(err->page_id);
    /* no LMT for error pages; error pages expire immediately */
    if (strchr(name, ':')) {
	/* Redirection */
	httpReplySetHeaders(rep, HTTP_MOVED_TEMPORARILY, NULL, "text/html", 0, -1, -1);
	if (err->request) {
	    char *quoted_url = rfc1738_escape_part(urlCanonical(err->request));
	    httpHeaderPutStrf(&rep->header, HDR_LOCATION, name, quoted_url);
	}
	httpHeaderPutStrf(&rep->header, HDR_X_SQUID_ERROR, "%d %s", err->http_status, "Access Denied");
    } else {
	MemBuf content = errorBuildContent(err);
	httpReplySetHeaders(rep, err->http_status, NULL, "text/html", content.size, -1, -1);
	/*
	 * include some information for downstream caches. Implicit
	 * replaceable content. This isn't quite sufficient. xerrno is not
	 * necessarily meaningful to another system, so we really should
	 * expand it. Additionally, we should identify ourselves. Someone
	 * might want to know. Someone _will_ want to know OTOH, the first
	 * X-CACHE-MISS entry should tell us who.
	 */
	httpHeaderPutStrf(&rep->header, HDR_X_SQUID_ERROR, "%s %d",
	    name, err->xerrno);
	httpBodySet(&rep->body, &content);
	/* do not memBufClean() the content, it was absorbed by httpBody */
    }
    return rep;
}
示例#3
0
static void asyncPrefetchTs(const char *url)
{
    debug(207, 1) ("start asyncPrefetchTs async prefetch: '%s'\n", url);
        
    request_t *request = NULL;
    StoreEntry *entry = NULL;
    request = modifyRequestUrlstoreUrl(url);
    request->flags.cachable = CACHE;
    
    if (storeGetPublicByRequest(request) != NULL) {
        debug(207, 3) ("this entry has already exist,give up async prefetch: '%s'\n", request->store_url);
        return;
    }
    
	entry = storeCreateEntry(urlCanonical(request),
			request->flags,
			request->method);
    if (request->store_url) 
        storeEntrySetStoreUrl(entry, request->store_url);

    if(Config.onoff.collapsed_forwarding)
    {
        EBIT_SET(entry->flags, KEY_EARLY_PUBLIC);
        storeSetPublicKey(entry);
    }

	fwdStart(-1, entry, request);
	requestUnlink(request);
}
示例#4
0
static inline void modify_request(clientHttpRequest * http)
{
	debug(97, 3)("modify_request: start, uri=[%s]\n", http->uri);
	request_t* old_request = http->request;
	request_t* new_request = urlParse(old_request->method, http->uri);
	safe_free(http->uri);

	if (new_request)
	{
		safe_free(http->uri);
		http->uri = xstrdup(urlCanonical(new_request));
		if(!http->log_uri)
			http->log_uri = xstrdup(urlCanonicalClean(old_request));
		new_request->http_ver = old_request->http_ver;
		httpHeaderAppend(&new_request->header, &old_request->header);
		new_request->client_addr = old_request->client_addr;
		new_request->client_port = old_request->client_port;
#if FOLLOW_X_FORWARDED_FOR
		new_request->indirect_client_addr = old_request->indirect_client_addr;
#endif /* FOLLOW_X_FORWARDED_FOR */
		new_request->my_addr = old_request->my_addr;
		new_request->my_port = old_request->my_port;
		new_request->flags = old_request->flags;
		new_request->flags.redirected = 1;
		if (old_request->auth_user_request)
		{
			new_request->auth_user_request = old_request->auth_user_request;
			authenticateAuthUserRequestLock(new_request->auth_user_request);
		}
		if (old_request->body_reader)
		{
			new_request->body_reader = old_request->body_reader;
			new_request->body_reader_data = old_request->body_reader_data;
			old_request->body_reader = NULL;
			old_request->body_reader_data = NULL;
		}
		new_request->content_length = old_request->content_length;
		if (strBuf(old_request->extacl_log))
			new_request->extacl_log = stringDup(&old_request->extacl_log);
		if (old_request->extacl_user)
			new_request->extacl_user = xstrdup(old_request->extacl_user);
		if (old_request->extacl_passwd)
			new_request->extacl_passwd = xstrdup(old_request->extacl_passwd);
		if(old_request->cc_request_private_data)
		{
			new_request->cc_request_private_data = old_request->cc_request_private_data;
			old_request->cc_request_private_data = NULL;
		}
		requestUnlink(old_request);
		http->request = requestLink(new_request);
	}
}
示例#5
0
static request_t *
modifyRequestUrlstoreUrl(const char *url)
{
    request_t *new_request = NULL;
    new_request = urlParse(METHOD_GET, (char*)url);
    char *new_storeurl = xstrdup((const char *)url);
    char* str = strchr(new_storeurl, '?');
    if (str) {
        debug(207, 3)("modify_request_url_storeurl rid_question: storeurl=[%s] have question\n", new_storeurl);
        *str = '\0';
    }
    
    new_request->store_url = xstrdup((const char *)new_storeurl); 
    
    debug(207, 3)("after modifyRequestUrlstoreUrl url=%s,storeurl=%s,uri=%s\n",urlCanonical(new_request),new_request->store_url,strBuf(new_request->urlpath));
    return requestLink(new_request);
}
/* packs debug info, canonical request-line and headers, appends <crlf> terminator */
void
httpRequestPackDebug(request_t * req, Packer * p)
{
    assert(req && p);
    /* Client info */
    packerPrintf(p, "Client: %s ", inet_ntoa(req->client_addr));
    packerPrintf(p, "http_port: %s:%d", inet_ntoa(req->my_addr), req->my_port);
    if (req->auth_user_request && authenticateUserRequestUsername(req->auth_user_request))
	packerPrintf(p, "user: %s", authenticateUserRequestUsername(req->auth_user_request));
    packerPrintf(p, "\n");
    /* pack request-line */
    packerPrintf(p, "%s %s HTTP/%d.%d\r\n",
	RequestMethodStr[req->method], urlCanonical(req), req->http_ver.major, req->http_ver.minor);
    /* headers */
    httpHeaderPackInto(&req->header, p);
    /* trailer */
    packerAppend(p, "\r\n", 2);
}
示例#7
0
peer *
carpSelectParent(request_t * request)
{
#define ROTATE_LEFT(x, n) (((x) << (n)) | ((x) >> ((sizeof(u_long)*8)-(n))))
    const char *c;
    peer *p = NULL;
    peer *tp;
    unsigned long url_hash = 0;
    unsigned long combined_hash;
    unsigned long high_score = 0;
    const char *url = urlCanonical(request);
    /* calculate url hash */
    debug(39, 2) ("carpSelectParent: CARP Calculating hash for %s\n", url);
    for (c = url; *c != 0; c++)
	url_hash += ROTATE_LEFT(url_hash, 19) + *c;
    /* select peer */
    for (tp = Config.peers; tp; tp = tp->next) {
	if (0.0 == tp->carp.load_factor)
	    continue;
	if (tp->tcp_up != PEER_TCP_MAGIC_COUNT)
	    continue;
	assert(tp->type == PEER_PARENT);
	combined_hash = (url_hash ^ tp->carp.hash);
	combined_hash += combined_hash * 0x62531965;
	combined_hash = ROTATE_LEFT(combined_hash, 21);
	combined_hash = combined_hash * tp->carp.load_multiplier;
	debug(39, 3) ("carpSelectParent: %s combined_hash %d\n",
	    tp->host, combined_hash);
	if ((combined_hash > high_score) && neighborUp(tp)) {
	    p = tp;
	    high_score = combined_hash;
	}
    }
    if (p)
	debug(39, 3) ("carpSelectParent: selected CARP %s\n", p->host);
    return p;
}
示例#8
0
static const char *
errorConvert(char token, ErrorState * err)
{
    request_t *r = err->request;
    static MemBuf mb = MemBufNULL;
    const char *p = NULL;	/* takes priority over mb if set */
    int do_quote = 1;

    memBufReset(&mb);
    switch (token) {
    case 'a':
	if (r && r->auth_user_request)
	    p = authenticateUserRequestUsername(r->auth_user_request);
	if (!p)
	    p = "-";
	break;
    case 'B':
	p = r ? ftpUrlWith2f(r) : "[no URL]";
	break;
    case 'c':
	p = errorPageName(err->type);
	break;
    case 'e':
	memBufPrintf(&mb, "%d", err->xerrno);
	break;
    case 'E':
	if (err->xerrno)
	    memBufPrintf(&mb, "(%d) %s", err->xerrno, strerror(err->xerrno));
	else
	    memBufPrintf(&mb, "[No Error]");
	break;
    case 'f':
	/* FTP REQUEST LINE */
	if (err->ftp.request)
	    p = err->ftp.request;
	else
	    p = "nothing";
	break;
    case 'F':
	/* FTP REPLY LINE */
	if (err->ftp.request)
	    p = err->ftp.reply;
	else
	    p = "nothing";
	break;
    case 'g':
	/* FTP SERVER MESSAGE */
	wordlistCat(err->ftp.server_msg, &mb);
	break;
    case 'h':
	memBufPrintf(&mb, "%s", getMyHostname());
	break;
    case 'H':
	if (r) {
	    if (r->hier.host)
		p = r->hier.host;
	    else
		p = r->host;
	} else
	    p = "[unknown host]";
	break;
    case 'i':
	memBufPrintf(&mb, "%s", inet_ntoa(err->src_addr));
	break;
    case 'I':
	if (r && r->hier.host) {
	    memBufPrintf(&mb, "%s", r->hier.host);
	} else
	    p = "[unknown]";
	break;
    case 'L':
	if (Config.errHtmlText) {
	    memBufPrintf(&mb, "%s", Config.errHtmlText);
	    do_quote = 0;
	} else
	    p = "[not available]";
	break;
    case 'm':
	p = authenticateAuthUserRequestMessage(err->auth_user_request) ? authenticateAuthUserRequestMessage(err->auth_user_request) : "[not available]";
	break;
    case 'M':
	p = r ? RequestMethods[r->method].str : "[unknown method]";
	break;
    case 'o':
	p = external_acl_message;
	if (!p)
	    p = "[not available]";
	break;
    case 'p':
	if (r) {
	    memBufPrintf(&mb, "%d", (int) r->port);
	} else {
	    p = "[unknown port]";
	}
	break;
    case 'P':
	p = r ? ProtocolStr[r->protocol] : "[unkown protocol]";
	break;
    case 'R':
	if (NULL != r) {
	    Packer p;
	    memBufPrintf(&mb, "%s %s HTTP/%d.%d\n",
		RequestMethods[r->method].str,
		strLen(r->urlpath) ? strBuf(r->urlpath) : "/",
		r->http_ver.major, r->http_ver.minor);
	    packerToMemInit(&p, &mb);
	    httpHeaderPackInto(&r->header, &p);
	    packerClean(&p);
	} else if (err->request_hdrs) {
	    p = err->request_hdrs;
	} else {
	    p = "[no request]";
	}
	break;
    case 's':
	p = visible_appname_string;
	break;
    case 'S':
	/* signature may contain %-escapes, recursion */
	if (err->page_id != ERR_SQUID_SIGNATURE) {
	    const int saved_id = err->page_id;
	    MemBuf sign_mb;
	    err->page_id = ERR_SQUID_SIGNATURE;
	    sign_mb = errorBuildContent(err);
	    memBufPrintf(&mb, "%s", sign_mb.buf);
	    memBufClean(&sign_mb);
	    err->page_id = saved_id;
	    do_quote = 0;
	} else {
	    /* wow, somebody put %S into ERR_SIGNATURE, stop recursion */
	    p = "[%S]";
	}
	break;
    case 't':
	memBufPrintf(&mb, "%s", mkhttpdlogtime(&squid_curtime));
	break;
    case 'T':
	memBufPrintf(&mb, "%s", mkrfc1123(squid_curtime));
	break;
    case 'U':
	p = r ? urlCanonicalClean(r) : err->url ? err->url : "[no URL]";
	break;
    case 'u':
	p = r ? urlCanonical(r) : err->url ? err->url : "[no URL]";
	break;
    case 'w':
	if (Config.adminEmail)
	    memBufPrintf(&mb, "%s", Config.adminEmail);
	else
	    p = "[unknown]";
	break;
    case 'z':
	if (err->dnsserver_msg)
	    p = err->dnsserver_msg;
	else
	    p = "[unknown]";
	break;
    case '%':
	p = "%";
	break;
    default:
	memBufPrintf(&mb, "%%%c", token);
	do_quote = 0;
	break;
    }
    if (!p)
	p = mb.buf;		/* do not use mb after this assignment! */
    assert(p);
    debug(4, 3) ("errorConvert: %%%c --> '%s'\n", token, p);
    if (do_quote)
	p = html_quote(p);
    return p;
}
/*  return 1 if the entry must be revalidated within delta seconds
 *         0 otherwise
 *
 *  note: request maybe null (e.g. for cache digests build)
 */
static int
refreshCheck(const StoreEntry * entry, request_t * request, time_t delta)
{
    const refresh_t *R;
    const char *uri = NULL;
    time_t age = 0;
    time_t check_time = squid_curtime;
    int staleness;
    stale_flags sf;
    if (entry->mem_obj)
	uri = entry->mem_obj->url;
    else if (request)
	uri = urlCanonical(request);

    debug(22, 3) ("refreshCheck: '%s'\n", uri ? uri : "<none>");

    if (delta > 0)
	check_time += delta;
    if (check_time > entry->timestamp)
	age = check_time - entry->timestamp;
    R = uri ? refreshLimits(uri) : refreshUncompiledPattern(".");
    if (NULL == R)
	R = &DefaultRefresh;
    memset(&sf, '\0', sizeof(sf));
    staleness = refreshStaleness(entry, check_time, age, R, &sf);
    debug(22, 3) ("Staleness = %d\n", staleness);

    debug(22, 3) ("refreshCheck: Matched '%s %d %d%% %d'\n",
	R->pattern, (int) R->min, (int) (100.0 * R->pct), (int) R->max);
    debug(22, 3) ("refreshCheck: age = %d\n", (int) age);
    debug(22, 3) ("\tcheck_time:\t%s\n", mkrfc1123(check_time));
    debug(22, 3) ("\tentry->timestamp:\t%s\n", mkrfc1123(entry->timestamp));

    if (EBIT_TEST(entry->flags, ENTRY_REVALIDATE) && staleness > -1) {
	debug(22, 3) ("refreshCheck: YES: Must revalidate stale response\n");
	return STALE_MUST_REVALIDATE;
    }
    /* request-specific checks */
    if (request) {
	HttpHdrCc *cc = request->cache_control;
#if HTTP_VIOLATIONS
	if (!request->flags.nocache_hack) {
	    (void) 0;
	} else if (R->flags.ignore_reload) {
	    /* The clients no-cache header is ignored */
	    debug(22, 3) ("refreshCheck: MAYBE: ignore-reload\n");
	} else if (R->flags.reload_into_ims || Config.onoff.reload_into_ims) {
	    /* The clients no-cache header is changed into a IMS query */
	    debug(22, 3) ("refreshCheck: YES: reload-into-ims\n");
	    return STALE_RELOAD_INTO_IMS;
	} else {
	    /* The clients no-cache header is not overridden on this request */
	    debug(22, 3) ("refreshCheck: YES: client reload\n");
	    request->flags.nocache = 1;
	    return STALE_FORCED_RELOAD;
	}
#endif
	if (NULL != cc) {
	    if (cc->max_age > -1) {
#if HTTP_VIOLATIONS
		if (R->flags.ignore_reload && cc->max_age == 0) {
		} else
#endif
		if (age > cc->max_age) {
		    debug(22, 3) ("refreshCheck: YES: age > client-max-age\n");
		    return STALE_EXCEEDS_REQUEST_MAX_AGE_VALUE;
		}
	    }
	    if (EBIT_TEST(cc->mask, CC_MAX_STALE) && staleness >= 0) {
		if (cc->max_stale < 0) {
		    /* max-stale directive without a value */
		    debug(22, 3) ("refreshCheck: NO: max-stale wildcard\n");
		    return FRESH_REQUEST_MAX_STALE_ALL;
		} else if (staleness < cc->max_stale) {
		    debug(22, 3) ("refreshCheck: NO: staleness < max-stale\n");
		    return FRESH_REQUEST_MAX_STALE_VALUE;
		}
	    }
	}
    }
    if (staleness < 0) {
	if (sf.expires)
	    return FRESH_EXPIRES;
	assert(!sf.max);
	if (sf.lmfactor)
	    return FRESH_LMFACTOR_RULE;
	assert(sf.min);
	return FRESH_MIN_RULE;
    }
    /*
     * At this point the response is stale, unless one of
     * the override options kicks in.
     */
    if (delta < 0 && staleness + delta < 0) {
	return STALE_WITHIN_DELTA;
    }
    if (sf.expires) {
#if HTTP_VIOLATIONS
	if (R->flags.override_expire && age < R->min) {
	    debug(22, 3) ("refreshCheck: NO: age < min && override-expire\n");
	    return FRESH_OVERRIDE_EXPIRES;
	}
#endif
	return STALE_EXPIRES;
    }
    if (sf.max)
	return STALE_MAX_RULE;
    if (sf.lmfactor) {
#if HTTP_VIOLATIONS
	if (R->flags.override_lastmod && age < R->min) {
	    debug(22, 3) ("refreshCheck: NO: age < min && override-lastmod\n");
	    return FRESH_OVERRIDE_LASTMOD;
	}
#endif
	return STALE_LMFACTOR_RULE;
    }
    return STALE_DEFAULT;
}