Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Adds a new condition, %{IP:<part>} #1620

Merged
merged 1 commit into from
Apr 3, 2017
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
31 changes: 31 additions & 0 deletions doc/admin-guide/plugins/header_rewrite.en.rst
Original file line number Diff line number Diff line change
Expand Up @@ -179,6 +179,8 @@ CLIENT-IP
Remote IP address, as a string, of the client connection for the current
transaction.

This condition is *deprecated* as of ATS v7.2.x, please use %{IP:CLIENT} instead.

CLIENT-URL
~~~~~~~~~~
::
Expand Down Expand Up @@ -291,6 +293,35 @@ INCOMING-PORT
TCP port, as a decimal integer, on which the incoming client connection was
made.

IP
~~
::

cond %{IP:<part>} <operand>

This is one of four possible IPs associated with the transaction, with the
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

"IP" is "intellectual propety". I think you mean "IP addresses".

possible parts being
::

%{IP:CLIENT} Clients IP
%{IP:INBOUND} ATS's server IP the client connected to
%{IP:SERVER} Upstream (next-hop) server IP (typically origin, or parent)
%{IP:OUTBOUND} ATS's outbound IP, that was used to connect upstream (next-hop)

Note that both %{IP:SERVER} and %{IP:OUTBOUND} can be unset, in which case the
empty string is returned. The common use for this condition is
actually as a value to an operator, e.g.
::

cond %{SEND_RESPONSE_HDR_HOOK}
set-header X-Client-IP %{IP:CLIENT}
set-header X-Inbound-IP %{IP:INBOUND}
set-header X-Server-IP %{IP:SERVER}
set-header X-Outbound-IP %{IP:OUTBOUND}

Finally, this new condition replaces the old %{CLIENT-IP} condition, which is
now properly deprecated. It will be removed as of ATS v8.0.0.

INTERNAL-TRANSACTION
~~~~~~~~~~~~~~~~~~~~
::
Expand Down
70 changes: 70 additions & 0 deletions plugins/header_rewrite/conditions.cc
Original file line number Diff line number Diff line change
Expand Up @@ -581,6 +581,76 @@ ConditionClientIp::append_value(std::string &s, const Resources &res)
}
}

void
ConditionIp::initialize(Parser &p)
{
Condition::initialize(p);

MatcherType *match = new MatcherType(_cond_op);

match->set(p.get_arg());
_matcher = match;
}

void
ConditionIp::set_qualifier(const std::string &q)
{
Condition::set_qualifier(q);

TSDebug(PLUGIN_NAME, "\tParsing %%{IP:%s} qualifier", q.c_str());

if (q == "CLIENT") {
_ip_qual = IP_QUAL_CLIENT;
} else if (q == "INBOUND") {
_ip_qual = IP_QUAL_INBOUND;
} else if (q == "SERVER") {
_ip_qual = IP_QUAL_SERVER;
} else if (q == "OUTBOUND") {
_ip_qual = IP_QUAL_OUTBOUND;
} else {
TSError("[%s] Unknown IP() qualifier: %s", PLUGIN_NAME, q.c_str());
}
}

bool
ConditionIp::eval(const Resources &res)
{
std::string s;

append_value(s, res);
bool rval = static_cast<const Matchers<std::string> *>(_matcher)->test(s);

TSDebug(PLUGIN_NAME, "Evaluating IP(): %s - rval: %d", s.c_str(), rval);

return rval;
}

void
ConditionIp::append_value(std::string &s, const Resources &res)
{
bool ip_set = false;
char ip[INET6_ADDRSTRLEN];

switch (_ip_qual) {
case IP_QUAL_CLIENT:
ip_set = (nullptr != getIP(TSHttpTxnClientAddrGet(res.txnp), ip));
break;
case IP_QUAL_INBOUND:
ip_set = (nullptr != getIP(TSHttpTxnIncomingAddrGet(res.txnp), ip));
break;
case IP_QUAL_SERVER:
ip_set = (nullptr != getIP(TSHttpTxnServerAddrGet(res.txnp), ip));
break;
case IP_QUAL_OUTBOUND:
ip_set = (nullptr != getIP(TSHttpTxnOutgoingAddrGet(res.txnp), ip));
break;
}

if (ip_set) {
s.append(ip);
}
}

void
ConditionIncomingPort::initialize(Parser &p)
{
Expand Down
18 changes: 18 additions & 0 deletions plugins/header_rewrite/conditions.h
Original file line number Diff line number Diff line change
Expand Up @@ -359,6 +359,24 @@ class ConditionInternalTxn : public Condition
bool eval(const Resources &res);
};

class ConditionIp : public Condition
{
typedef Matchers<std::string> MatcherType;

public:
explicit ConditionIp() : _ip_qual(IP_QUAL_CLIENT) { TSDebug(PLUGIN_NAME_DBG, "Calling CTOR for ConditionIp"); };
void initialize(Parser &p);
void set_qualifier(const std::string &q);
void append_value(std::string &s, const Resources &res);

protected:
bool eval(const Resources &res);

private:
DISALLOW_COPY_AND_ASSIGN(ConditionIp);
IpQualifiers _ip_qual;
};

class ConditionClientIp : public Condition
{
typedef Matchers<std::string> MatcherType;
Expand Down
4 changes: 4 additions & 0 deletions plugins/header_rewrite/factory.cc
Original file line number Diff line number Diff line change
Expand Up @@ -123,7 +123,11 @@ condition_factory(const std::string &cond)
c = new ConditionInternalTxn();
} else if (c_name == "INTERNAL-TXN") {
c = new ConditionInternalTxn();
} else if (c_name == "IP") {
c = new ConditionIp();
} else if (c_name == "CLIENT-IP") {
TSDebug(PLUGIN_NAME, "\tWARNING: configuration uses deprecated condition, CLIENT-IP()");
TSError("warning: CLIENT-IP() is deprecated, use %%{IP:CLIENT} instead");
c = new ConditionClientIp();
} else if (c_name == "INCOMING-PORT") {
c = new ConditionIncomingPort();
Expand Down
9 changes: 9 additions & 0 deletions plugins/header_rewrite/lulu.cc
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@
*/

#include <string>
#include <netinet/in.h>

#include "ts/ts.h"
#include "lulu.h"
Expand All @@ -31,6 +32,14 @@ getIP(sockaddr const *s_sockaddr, char res[INET6_ADDRSTRLEN])
return nullptr;
}

// This is a little kludgy, but the TS APIs that returns sockadd's don't return
// nullptr's in general (it seems). Maybe that should be fixed, or maybe we should
// export lib/ts/ink_inet.h as C APIs... (according to amc). But without this check,
// we get ::1 even when the sockaddr isn't populated (e.g. server addr on a cache hit).
if (AF_UNSPEC == s_sockaddr->sa_family) {
return nullptr;
}

switch (s_sockaddr->sa_family) {
case AF_INET: {
const struct sockaddr_in *s_sockaddr_in = reinterpret_cast<const struct sockaddr_in *>(s_sockaddr);
Expand Down
9 changes: 9 additions & 0 deletions plugins/header_rewrite/statement.h
Original file line number Diff line number Diff line change
Expand Up @@ -72,6 +72,15 @@ enum IdQualifiers {
ID_QUAL_UNIQUE,
};

// IP
enum IpQualifiers {
IP_QUAL_CLIENT,
IP_QUAL_INBOUND,
// These two might not necessarily get populated, e.g. on a cache hit.
IP_QUAL_SERVER,
IP_QUAL_OUTBOUND,
};

class Statement
{
public:
Expand Down