Permalink
Browse files

TS-988: IPv6 for ICP

git-svn-id: https://svn.apache.org/repos/asf/trafficserver/traffic/trunk@1187650 13f79535-47bb-0310-9956-ffa450edef68
  • Loading branch information...
1 parent b28f985 commit 9c8ed3aa32a5433e7a30c726e4d269b1aa661aa8 @SolidWallOfCode SolidWallOfCode committed Oct 22, 2011
View
@@ -1,5 +1,6 @@
-*- coding: utf-8 -*-
Changes with Apache Traffic Server 3.1.1
+ *) [TS-988] Updated ICP for IPv6.
*) [TS-994] Removed the extra splace from X-Forwarded-For.
@@ -120,7 +120,7 @@ struct Connection
/// @internal Used only by ICP.
void setRemote(
sockaddr const* remote_addr ///< Address and port.
- ) {
+ ) {
ink_inet_copy(&addr, remote_addr);
}
@@ -130,7 +130,7 @@ struct Connection
void setRemote(
in_addr_t ip,
int port
- ) {
+ ) {
ink_inet_ip4_set(&addr.sin, ip, htons(port));
}
View
@@ -293,3 +293,51 @@ ink_inet_to_hex(sockaddr const* src, char* dst, size_t len) {
return zret;
}
+sockaddr* ink_inet_ip_set(
+ sockaddr* dst,
+ InkInetAddr const& addr,
+ uint16_t port
+) {
+ if (AF_INET == addr._family) ink_inet_ip4_set(dst, addr._addr._ip4, port);
+ else if (AF_INET6 == addr._family) ink_inet_ip6_set(dst, addr._addr._ip6, port);
+ else ink_inet_invalidate(dst);
+ return dst;
+}
+
+int
+InkInetAddr::load(char const* text) {
+ ts_ip_endpoint ip;
+ int zret = ink_inet_pton(text, &ip);
+ *this = ip;
+ return zret;
+}
+
+char*
+InkInetAddr::toString(char* dest, size_t len) const {
+ ts_ip_endpoint ip;
+ ip.assign(*this);
+ ink_inet_ntop(&ip, dest, len);
+ return dest;
+}
+
+bool
+InkInetAddr::isMulticast() const {
+ return (AF_INET == _family && 0xe == _addr._byte[0]) ||
+ (AF_INET6 == _family && IN6_IS_ADDR_MULTICAST(&_addr._ip6))
+ ;
+}
+
+bool
+operator == (InkInetAddr const& lhs, sockaddr const* rhs) {
+ bool zret = false;
+ if (lhs._family == rhs->sa_family) {
+ if (AF_INET == lhs._family) {
+ zret = lhs._addr._ip4 == ink_inet_ip4_addr_cast(rhs);
+ } else if (AF_INET6 == lhs._family) {
+ zret = 0 == memcmp(&lhs._addr._ip6, &ink_inet_ip6_addr_cast(rhs), sizeof(in6_addr));
+ } else { // map all non-IP to the same thing.
+ zret = true;
+ }
+ } // else different families, not equal.
+ return zret;
+}
View
@@ -31,6 +31,8 @@
#define INK_GETHOSTBYNAME_R_DATA_SIZE 1024
#define INK_GETHOSTBYADDR_R_DATA_SIZE 1024
+class InkInetAddr; // forward declare.
+
/** A union to hold the standard IP address structures.
By standard we mean @c sockaddr compliant.
@@ -47,9 +49,23 @@
*/
union ts_ip_endpoint {
+ typedef ts_ip_endpoint self; ///< Self reference type.
+
+ struct sockaddr sa; ///< Generic address.
struct sockaddr_in sin; ///< IPv4
struct sockaddr_in6 sin6; ///< IPv6
- struct sockaddr sa; ///< Generic address.
+
+ self& assign(
+ sockaddr const* ip ///< Source address, family, port.
+ );
+ /// Construct from an @a addr and @a port.
+ self& assign(
+ InkInetAddr const& addr, ///< Address and address family.
+ uint16_t port = 0 ///< Port (network order).
+ );
+
+ /// Access to port.
+ uint16_t& port();
};
struct ink_gethostbyname_r_data
@@ -548,9 +564,9 @@ inline int ink_inet_cmp(
if (la < ra) zret = -1;
else if (la > ra) zret = 1;
else zret = 0;
- } else if (AF_INET6 == rtype) {
- zret = -1; // IPv4 addresses are before IPv6
- } else {
+ } else if (AF_INET6 == rtype) { // IPv4 < IPv6
+ zret = -1;
+ } else { // IP > not IP
zret = 1;
}
} else if (AF_INET6 == ltype) {
@@ -812,9 +828,7 @@ ink_inet_to_hex(
/** Storage for an IP address.
In some cases we want to store just the address and not the
- ancillary information (such as port, or flow data) in
- @c sockaddr_storage. There are a couple of cases where this
- makes sense.
+ ancillary information (such as port, or flow data).
@note This is not easily used as an address for system calls.
*/
struct InkInetAddr {
@@ -824,10 +838,16 @@ struct InkInetAddr {
InkInetAddr() : _family(AF_UNSPEC) {}
/// Construct as IPv4 @a addr.
explicit InkInetAddr(
- uint32_t addr ///< Address to assign.
+ in_addr_t addr ///< Address to assign.
) : _family(AF_INET) {
_addr._ip4 = addr;
}
+ /// Construct as IPv6 @a addr.
+ explicit InkInetAddr(
+ in6_addr const& addr ///< Address to assign.
+ ) : _family(AF_INET6) {
+ _addr._ip6 = addr;
+ }
/// Construct from @c sockaddr.
explicit InkInetAddr(sockaddr const* addr) { this->assign(addr); }
/// Construct from @c sockaddr_in6.
@@ -836,19 +856,41 @@ struct InkInetAddr {
explicit InkInetAddr(sockaddr_in6 const* addr) { this->assign(ink_inet_sa_cast(addr)); }
/// Construct from @c ts_ip_endpoint.
explicit InkInetAddr(ts_ip_endpoint const& addr) { this->assign(&addr.sa); }
+ /// Construct from @c ts_ip_endpoint.
+ explicit InkInetAddr(ts_ip_endpoint const* addr) { this->assign(&addr->sa); }
/// Assign sockaddr storage.
self& assign(sockaddr const* addr) {
_family = addr->sa_family;
if (ink_inet_is_ip4(addr)) {
_addr._ip4 = ink_inet_ip4_addr_cast(addr);
} else if (ink_inet_is_ip6(addr)) {
- memcpy(&_addr._ip6, &ink_inet_ip6_cast(addr)->sin6_addr, INK_IP6_SIZE);
+ _addr._ip6 = ink_inet_ip6_addr_cast(addr);
} else {
_family = AF_UNSPEC;
}
return *this;
}
+ /// Assign from end point.
+ self& operator = (ts_ip_endpoint const& ip) {
+ return this->assign(&ip.sa);
+ }
+
+ /** Load from string.
+ The address is copied to this object if the conversion is successful,
+ otherwise this object is invalidated.
+ @return 0 on success, non-zero on failure.
+ */
+ int load(
+ char const* str ///< Nul terminated input string.
+ );
+ /** Output to a string.
+ @return The string @a dest.
+ */
+ char* toString(
+ char* dest, ///< [out] Destination string buffer.
+ size_t len ///< [in] Size of buffer.
+ ) const;
/// Equality.
bool operator==(self const& that) {
@@ -869,14 +911,78 @@ struct InkInetAddr {
/// Test for validity.
bool isValid() const { return _family == AF_INET || _family == AF_INET6; }
+ /// Make invalid.
+ self& invalidate() { _family = AF_UNSPEC; return *this; }
+ /// Test for multicast
+ bool isMulticast() const;
- uint8_t _family; ///< Protocol family.
- uint8_t _pad[3]; ///< Pad it out.
+ uint16_t _family; ///< Protocol family.
/// Address data.
union {
in_addr_t _ip4; ///< IPv4 address storage.
in6_addr _ip6; ///< IPv6 address storage.
+ uint8_t _byte[INK_IP6_SIZE]; ///< As raw bytes.
} _addr;
};
+// Associated operators.
+bool operator == (InkInetAddr const& lhs, sockaddr const* rhs);
+inline bool operator == (sockaddr const* lhs, InkInetAddr const& rhs) {
+ return rhs == lhs;
+}
+inline bool operator != (InkInetAddr const& lhs, sockaddr const* rhs) {
+ return ! (lhs == rhs);
+}
+inline bool operator != (sockaddr const* lhs, InkInetAddr const& rhs) {
+ return ! (rhs == lhs);
+}
+inline bool operator == (InkInetAddr const& lhs, ts_ip_endpoint const& rhs) {
+ return lhs == &rhs.sa;
+}
+inline bool operator == (ts_ip_endpoint const& lhs, InkInetAddr const& rhs) {
+ return &lhs.sa == rhs;
+}
+inline bool operator != (InkInetAddr const& lhs, ts_ip_endpoint const& rhs) {
+ return ! (lhs == &rhs.sa);
+}
+inline bool operator != (ts_ip_endpoint const& lhs, InkInetAddr const& rhs) {
+ return ! (rhs == &lhs.sa);
+}
+
+/// Write IP @a addr to storage @a dst.
+/// @return @s dst.
+sockaddr* ink_inet_ip_set(
+ sockaddr* dst, ///< Destination storage.
+ InkInetAddr const& addr, ///< source address.
+ uint16_t port = 0 ///< port, network order.
+);
+
+/** Convert @a text to an IP address and write it to @a addr.
+ Convenience overload.
+ @return 0 on success, non-zero on failure.
+*/
+inline int ink_inet_pton(
+ char const* text, ///< [in] text.
+ InkInetAddr& addr ///< [out] address
+) {
+ return addr.load(text) ? 0 : -1;
+}
+
+inline ts_ip_endpoint&
+ts_ip_endpoint::assign(InkInetAddr const& addr, uint16_t port) {
+ ink_inet_ip_set(&sa, addr, port);
+ return *this;
+}
+
+inline ts_ip_endpoint&
+ts_ip_endpoint::assign(sockaddr const* ip) {
+ ink_inet_copy(&sa, ip);
+ return *this;
+}
+
+inline uint16_t&
+ts_ip_endpoint::port() {
+ return ink_inet_port_cast(&sa);
+}
+
#endif // _ink_inet.h
View
@@ -392,8 +392,8 @@ void
LocalManager::initCCom(int port, char *addr, int sport)
{
bool found;
- struct in_addr cluster_addr; // ip addr of the cluster interface
- char *clusterAddrStr; // cluster ip addr as a String
+ ts_ip_endpoint cluster_ip; // ip addr of the cluster interface
+ ip_text_buffer clusterAddrStr; // cluster ip addr as a String
char *intrName; // Name of the interface we are to use
char hostname[1024]; // hostname of this machine
const char envVar[] = "PROXY_CLUSTER_ADDR=";
@@ -406,12 +406,14 @@ LocalManager::initCCom(int port, char *addr, int sport)
intrName = REC_readString("proxy.config.cluster.ethernet_interface", &found);
ink_assert(intrName != NULL);
- found = mgmt_getAddrForIntr(intrName, &cluster_addr);
+ found = mgmt_getAddrForIntr(intrName, &cluster_ip.sa);
if (found == false) {
mgmt_fatal(stderr, "[LocalManager::initCCom] Unable to find network interface %s. Exiting...\n", intrName);
+ } else if (!ink_inet_is_ip4(&cluster_ip)) {
+ mgmt_fatal(stderr, "[LocalManager::initCCom] Unable to find IPv4 network interface %s. Exiting...\n", intrName);
}
- clusterAddrStr = inet_ntoa(cluster_addr);
+ ink_inet_ntop(&cluster_ip, clusterAddrStr, sizeof(clusterAddrStr));
Debug("ccom", "Cluster Interconnect is %s : %s\n", intrName, clusterAddrStr);
// This an awful hack but I could not come up with a better way to
@@ -434,8 +436,8 @@ LocalManager::initCCom(int port, char *addr, int sport)
ink_strlcat(envBuf, clusterAddrStr, envBuf_size);
ink_release_assert(putenv(envBuf) == 0);
- ccom = new ClusterCom(cluster_addr.s_addr, hostname, port, addr, sport, pserver_path);
- virt_map = new VMap(intrName, cluster_addr.s_addr, &lmgmt->ccom->mutex);
+ ccom = new ClusterCom(ink_inet_ip4_addr_cast(&cluster_ip), hostname, port, addr, sport, pserver_path);
+ virt_map = new VMap(intrName, ink_inet_ip4_addr_cast(&cluster_ip), &lmgmt->ccom->mutex);
virt_map->downAddrs(); // Just to be safe
ccom->establishChannels();
ats_free(intrName);
@@ -584,7 +584,7 @@ get_interface_mtu(int sock_fd, struct ifreq *ifr)
#endif
bool
-mgmt_getAddrForIntr(char *intrName, struct in_addr * addr, int *mtu)
+mgmt_getAddrForIntr(char *intrName, sockaddr* addr, int *mtu)
{
bool found = false;
@@ -645,7 +645,7 @@ mgmt_getAddrForIntr(char *intrName, struct in_addr * addr, int *mtu)
// Only look at the address if it an internet address
if (ifr->ifr_ifru.ifru_addr.sa_family == AF_INET) {
tmp = (struct sockaddr_in *) &ifr->ifr_ifru.ifru_addr;
- *addr = tmp->sin_addr;
+ ink_inet_ip4_cast(addr)->sin_addr = tmp->sin_addr;
found = true;
if (mtu)
@@ -58,7 +58,7 @@ void mgmt_cleanup();
struct in_addr *mgmt_sortipaddrs(int num, struct in_addr **list);
char *mgmt_localhost_ip();
-bool mgmt_getAddrForIntr(char *intrName, struct in_addr *addr, int *mtu = 0);
+bool mgmt_getAddrForIntr(char *intrName, sockaddr* addr, int *mtu = 0);
/* the following functions are all DEPRECATED. The Diags
interface should be used exclusively in the future */
Oops, something went wrong. Retry.

0 comments on commit 9c8ed3a

Please sign in to comment.