Skip to content

Commit

Permalink
Adds a new condition, %{IP:<part>}
Browse files Browse the repository at this point in the history
This replaces the old %{CLIENT-IP}, and generalizes the access to
all four IP addresses. 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}

In the case of a sockaddr not being populated, e.g. IP:SERVER on
a cache hit, the string is "" (empty).
  • Loading branch information
zwoop committed Apr 3, 2017
1 parent bd03e60 commit 9746ceb
Show file tree
Hide file tree
Showing 6 changed files with 141 additions and 0 deletions.
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
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

0 comments on commit 9746ceb

Please sign in to comment.