• Main Page
  • Related Pages
  • Namespaces
  • Data Structures
  • Files
  • File List
  • Globals

ink_inet.h

Go to the documentation of this file.
00001 /** @file
00002 
00003   A brief file description
00004 
00005   @section license License
00006 
00007   Licensed to the Apache Software Foundation (ASF) under one
00008   or more contributor license agreements.  See the NOTICE file
00009   distributed with this work for additional information
00010   regarding copyright ownership.  The ASF licenses this file
00011   to you under the Apache License, Version 2.0 (the
00012   "License"); you may not use this file except in compliance
00013   with the License.  You may obtain a copy of the License at
00014 
00015       http://www.apache.org/licenses/LICENSE-2.0
00016 
00017   Unless required by applicable law or agreed to in writing, software
00018   distributed under the License is distributed on an "AS IS" BASIS,
00019   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
00020   See the License for the specific language governing permissions and
00021   limitations under the License.
00022 
00023  */
00024 
00025 #if !defined (_ink_inet_h_)
00026 #define _ink_inet_h_
00027 
00028 #include <netinet/in.h>
00029 #include <netdb.h>
00030 #include <ink_memory.h>
00031 #include <sys/socket.h>
00032 #include <ts/ink_apidefs.h>
00033 #include <ts/TsBuffer.h>
00034 
00035 #define INK_GETHOSTBYNAME_R_DATA_SIZE 1024
00036 #define INK_GETHOSTBYADDR_R_DATA_SIZE 1024
00037 
00038 #if ! TS_HAS_IN6_IS_ADDR_UNSPECIFIED
00039 #if defined(IN6_IS_ADDR_UNSPECIFIED)
00040 #undef IN6_IS_ADDR_UNSPECIFIED
00041 #endif
00042 static inline bool IN6_IS_ADDR_UNSPECIFIED(in6_addr const* addr) {
00043   uint64_t const* w = reinterpret_cast<uint64_t const*>(addr);
00044   return 0 == w[0] && 0 == w[1];
00045 }
00046 #endif
00047 
00048 struct IpAddr; // forward declare.
00049 
00050 /** A union to hold the standard IP address structures.
00051     By standard we mean @c sockaddr compliant.
00052 
00053     We use the term "endpoint" because these contain more than just the
00054     raw address, all of the data for an IP endpoint is present.
00055 
00056     @internal This might be useful to promote to avoid strict aliasing
00057     problems.  Experiment with it here to see how it works in the
00058     field.
00059 
00060     @internal @c sockaddr_storage is not present because it is so
00061     large and the benefits of including it are small. Use of this
00062     structure will make it easy to add if that becomes necessary.
00063 
00064  */
00065 union IpEndpoint {
00066   typedef IpEndpoint self; ///< Self reference type.
00067 
00068   struct sockaddr         sa; ///< Generic address.
00069   struct sockaddr_in      sin; ///< IPv4
00070   struct sockaddr_in6     sin6; ///< IPv6
00071 
00072   self& assign(
00073     sockaddr const* ip ///< Source address, family, port.
00074   );
00075   /// Construct from an @a addr and @a port.
00076   self& assign(
00077     IpAddr const& addr, ///< Address and address family.
00078     in_port_t port = 0 ///< Port (network order).
00079   );
00080 
00081   /// Test for valid IP address.
00082   bool isValid() const;
00083   /// Test for IPv4.
00084   bool isIp4() const;
00085   /// Test for IPv6.
00086   bool isIp6() const;
00087 
00088   uint16_t family() const;
00089 
00090   /// Set to be any address for family @a family.
00091   /// @a family must be @c AF_INET or @c AF_INET6.
00092   /// @return This object.
00093   self& setToAnyAddr(
00094     int family ///< Address family.
00095   );
00096   /// Set to be loopback for family @a family.
00097   /// @a family must be @c AF_INET or @c AF_INET6.
00098   /// @return This object.
00099   self& setToLoopback(
00100     int family ///< Address family.
00101   );
00102 
00103 
00104   /// Port in network order.
00105   in_port_t& port();
00106   /// Port in network order.
00107   in_port_t port() const;
00108 
00109   operator sockaddr* () { return &sa; }
00110   operator sockaddr const* () const { return &sa; }
00111 };
00112 
00113 struct ink_gethostbyname_r_data
00114 {
00115   int herrno;
00116   struct hostent ent;
00117   char buf[INK_GETHOSTBYNAME_R_DATA_SIZE];
00118 };
00119 
00120 struct ink_gethostbyaddr_r_data
00121 {
00122   int herrno;
00123   struct hostent ent;
00124   char buf[INK_GETHOSTBYADDR_R_DATA_SIZE];
00125 };
00126 
00127 /**
00128   Wrapper for gethostbyname_r(). If successful, returns a pointer
00129   to the hostent structure. Returns NULL and sets data->herrno to
00130   the appropriate error code on failure.
00131 
00132   @param hostname null-terminated host name string
00133   @param data pointer to ink_gethostbyname_r_data allocated by the caller
00134 
00135 */
00136 struct hostent *ink_gethostbyname_r(char *hostname, ink_gethostbyname_r_data * data);
00137 
00138 /**
00139   Wrapper for gethostbyaddr_r(). If successful, returns a pointer
00140   to the hostent structure. Returns NULL and sets data->herrno to
00141   the appropriate error code on failure.
00142 
00143   @param ip IP address of the host
00144   @param len length of the buffer indicated by ip
00145   @param type family of the address
00146   @param data pointer to ink_gethostbyname_r_data allocated by the caller
00147 
00148 */
00149 struct hostent *ink_gethostbyaddr_r(char *ip, int len, int type, ink_gethostbyaddr_r_data * data);
00150 
00151 /** Parse a string for pieces of an IP address.
00152 
00153     This doesn't parse the actual IP address, but picks it out from @a
00154     src. It is intended to deal with the brackets that can optionally
00155     surround an IP address (usually IPv6) which in turn are used to
00156     differentiate between an address and an attached port. E.g.
00157     @code
00158       [FE80:9312::192:168:1:1]:80
00159     @endcode
00160     @a addr or @a port can be @c NULL in which case that value isn't returned.
00161 
00162     @return 0 if an address was found, non-zero otherwise.
00163 */
00164 int
00165 ats_ip_parse(
00166              ts::ConstBuffer src, ///< [in] String to search.
00167              ts::ConstBuffer* addr, ///< [out] Range containing IP address.
00168              ts::ConstBuffer* port ///< [out] Range containing port.
00169 );
00170 
00171 /**  Check to see if a buffer contains only IP address characters.
00172      @return
00173     - AF_UNSPEC - not a numeric address.
00174     - AF_INET - only digits and dots.
00175     - AF_INET6 - colons found.
00176 */
00177 int
00178 ats_ip_check_characters(ts::ConstBuffer text);
00179 
00180 /**
00181   Wrapper for inet_addr().
00182 
00183   @param s IP address in the Internet standard dot notation.
00184 
00185 */
00186 inkcoreapi uint32_t ats_inet_addr(const char *s);
00187 
00188 const char *ats_ip_ntop(const struct sockaddr *addr, char *dst, size_t size);
00189 
00190 // --
00191 /// Size in bytes of an IPv6 address.
00192 static size_t const TS_IP6_SIZE = sizeof(in6_addr);
00193 
00194 /// Reset an address to invalid.
00195 /// @note Useful for marking a member as not yet set.
00196 inline void ats_ip_invalidate(sockaddr* addr) {
00197   addr->sa_family = AF_UNSPEC;
00198 }
00199 inline void ats_ip_invalidate(sockaddr_in6* addr) {
00200   addr->sin6_family = AF_UNSPEC;
00201 }
00202 inline void ats_ip_invalidate(IpEndpoint* ip) {
00203   ip->sa.sa_family = AF_UNSPEC;
00204 }
00205 
00206 /** Get a string name for an IP address family.
00207     @return The string name (never @c NULL).
00208 */
00209 char const*
00210 ats_ip_family_name(int family);
00211 
00212 /// Test for IP protocol.
00213 /// @return @c true if the address is IP, @c false otherwise.
00214 inline bool ats_is_ip(sockaddr const* addr) {
00215   return addr
00216     && (AF_INET == addr->sa_family || AF_INET6 == addr->sa_family);
00217 }
00218 /// @return @c true if the address is IP, @c false otherwise.
00219 inline bool ats_is_ip(IpEndpoint const* addr) {
00220   return addr
00221     && (AF_INET == addr->sa.sa_family || AF_INET6 == addr->sa.sa_family);
00222 }
00223 /// Test for IP protocol.
00224 /// @return @c true if the value is an IP address family, @c false otherwise.
00225 inline bool ats_is_ip(int family) {
00226   return AF_INET == family || AF_INET6 == family;
00227 }
00228 /// Test for IPv4 protocol.
00229 /// @return @c true if the address is IPv4, @c false otherwise.
00230 inline bool ats_is_ip4(sockaddr const* addr) {
00231   return addr && AF_INET == addr->sa_family;
00232 }
00233 /// Test for IPv4 protocol.
00234 /// @note Convenience overload.
00235 /// @return @c true if the address is IPv4, @c false otherwise.
00236 inline bool ats_is_ip4(IpEndpoint const* addr) {
00237   return addr && AF_INET == addr->sa.sa_family;
00238 }
00239 /// Test for IPv6 protocol.
00240 /// @return @c true if the address is IPv6, @c false otherwise.
00241 inline bool ats_is_ip6(sockaddr const* addr) {
00242   return addr && AF_INET6 == addr->sa_family;
00243 }
00244 /// Test for IPv6 protocol.
00245 /// @note Convenience overload.
00246 /// @return @c true if the address is IPv6, @c false otherwise.
00247 inline bool ats_is_ip6(IpEndpoint const* addr) {
00248   return addr && AF_INET6 == addr->sa.sa_family;
00249 }
00250 
00251 /// @return @c true if the address families are compatible.
00252 inline bool ats_ip_are_compatible(
00253   sockaddr const* lhs, ///< Address to test.
00254   sockaddr const* rhs  ///< Address to test.
00255 ) {
00256   return lhs->sa_family == rhs->sa_family;
00257 }
00258 /// @return @c true if the address families are compatible.
00259 inline bool ats_ip_are_compatible(
00260   IpEndpoint const* lhs, ///< Address to test.
00261   IpEndpoint const* rhs  ///< Address to test.
00262 ) {
00263   return ats_ip_are_compatible(&lhs->sa, &rhs->sa);
00264 }
00265 /// @return @c true if the address families are compatible.
00266 inline bool ats_ip_are_compatible(
00267   int lhs, ///< Address family to test.
00268   sockaddr const* rhs  ///< Address to test.
00269 ) {
00270   return lhs == rhs->sa_family;
00271 }
00272 /// @return @c true if the address families are compatible.
00273 inline bool ats_ip_are_compatible(
00274   sockaddr const* lhs, ///< Address to test.
00275   int rhs  ///< Family to test.
00276 ) {
00277   return lhs->sa_family == rhs;
00278 }
00279 
00280 // IP address casting.
00281 // sa_cast to cast to sockaddr*.
00282 // ss_cast to cast to sockaddr_storage*.
00283 // ip4_cast converts to sockaddr_in (because that's effectively an IPv4 addr).
00284 // ip6_cast converts to sockaddr_in6
00285 
00286 inline sockaddr* ats_ip_sa_cast(sockaddr_storage* a) {
00287   return static_cast<sockaddr*>(static_cast<void*>(a));
00288 }
00289 inline sockaddr const* ats_ip_sa_cast(sockaddr_storage const* a) {
00290   return static_cast<sockaddr const*>(static_cast<void const*>(a));
00291 }
00292 
00293 inline sockaddr* ats_ip_sa_cast(sockaddr_in* a) {
00294   return static_cast<sockaddr*>(static_cast<void*>(a));
00295 }
00296 inline sockaddr const* ats_ip_sa_cast(sockaddr_in const* a) {
00297   return static_cast<sockaddr const*>(static_cast<void const*>(a));
00298 }
00299 
00300 inline sockaddr* ats_ip_sa_cast(sockaddr_in6* a) {
00301   return static_cast<sockaddr*>(static_cast<void*>(a));
00302 }
00303 inline sockaddr const* ats_ip_sa_cast(sockaddr_in6 const* a) {
00304   return static_cast<sockaddr const*>(static_cast<void const*>(a));
00305 }
00306 
00307 inline sockaddr_storage* ats_ip_ss_cast(sockaddr* a) {
00308   return static_cast<sockaddr_storage*>(static_cast<void*>(a));
00309 }
00310 inline sockaddr_storage const* ats_ip_ss_cast(sockaddr const* a) {
00311   return static_cast<sockaddr_storage const*>(static_cast<void const*>(a));
00312 }
00313 
00314 inline sockaddr_in* ats_ip4_cast(sockaddr* a) {
00315   return static_cast<sockaddr_in*>(static_cast<void*>(a));
00316 }
00317 inline sockaddr_in const* ats_ip4_cast(sockaddr const* a) {
00318   return static_cast<sockaddr_in const*>(static_cast<void const*>(a));
00319 }
00320 
00321 inline sockaddr_in& ats_ip4_cast(sockaddr& a) {
00322   return *static_cast<sockaddr_in*>(static_cast<void*>(&a));
00323 }
00324 inline sockaddr_in const& ats_ip4_cast(sockaddr const& a) {
00325   return *static_cast<sockaddr_in const*>(static_cast<void const*>(&a));
00326 }
00327 
00328 inline sockaddr_in* ats_ip4_cast(sockaddr_in6* a) {
00329   return static_cast<sockaddr_in*>(static_cast<void*>(a));
00330 }
00331 inline sockaddr_in const* ats_ip4_cast(sockaddr_in6 const* a) {
00332   return static_cast<sockaddr_in const*>(static_cast<void const*>(a));
00333 }
00334 
00335 inline sockaddr_in& ats_ip4_cast(sockaddr_in6& a) {
00336   return *static_cast<sockaddr_in*>(static_cast<void*>(&a));
00337 }
00338 inline sockaddr_in const& ats_ip4_cast(sockaddr_in6 const& a) {
00339   return *static_cast<sockaddr_in const*>(static_cast<void const*>(&a));
00340 }
00341 
00342 inline sockaddr_in6* ats_ip6_cast(sockaddr* a) {
00343   return static_cast<sockaddr_in6*>(static_cast<void*>(a));
00344 }
00345 inline sockaddr_in6 const* ats_ip6_cast(sockaddr const* a) {
00346   return static_cast<sockaddr_in6 const*>(static_cast<void const*>(a));
00347 }
00348 inline sockaddr_in6& ats_ip6_cast(sockaddr& a) {
00349   return *static_cast<sockaddr_in6*>(static_cast<void*>(&a));
00350 }
00351 inline sockaddr_in6 const& ats_ip6_cast(sockaddr const& a) {
00352   return *static_cast<sockaddr_in6 const*>(static_cast<void const*>(&a));
00353 }
00354 
00355 /// @return The @c sockaddr size for the family of @a addr.
00356 inline size_t ats_ip_size(
00357   sockaddr const* addr ///< Address object.
00358 ) {
00359   return AF_INET == addr->sa_family ? sizeof(sockaddr_in)
00360     : AF_INET6 == addr->sa_family ? sizeof(sockaddr_in6)
00361     : 0
00362     ;
00363 }
00364 inline size_t ats_ip_size(
00365   IpEndpoint const* addr ///< Address object.
00366 ) {
00367   return AF_INET == addr->sa.sa_family ? sizeof(sockaddr_in)
00368     : AF_INET6 == addr->sa.sa_family ? sizeof(sockaddr_in6)
00369     : 0
00370     ;
00371 }
00372 /// @return The size of the IP address only.
00373 inline size_t ats_ip_addr_size(
00374   sockaddr const* addr ///< Address object.
00375 ) {
00376   return AF_INET == addr->sa_family ? sizeof(in_addr_t)
00377     : AF_INET6 == addr->sa_family ? sizeof(in6_addr)
00378     : 0
00379     ;
00380 }
00381 inline size_t ats_ip_addr_size(
00382   IpEndpoint const* addr ///< Address object.
00383 ) {
00384   return AF_INET == addr->sa.sa_family ? sizeof(in_addr_t)
00385     : AF_INET6 == addr->sa.sa_family ? sizeof(in6_addr)
00386     : 0
00387     ;
00388 }
00389 
00390 /** Get a reference to the port in an address.
00391     @note Because this is direct access, the port value is in network order.
00392     @see ats_ip_port_host_order.
00393     @return A reference to the port value in an IPv4 or IPv6 address.
00394     @internal This is primarily for internal use but it might be handy for
00395     clients so it is exposed.
00396 */
00397 inline in_port_t& ats_ip_port_cast(sockaddr* sa) {
00398   static in_port_t dummy = 0;
00399   return ats_is_ip4(sa)
00400     ? ats_ip4_cast(sa)->sin_port
00401     : ats_is_ip6(sa)
00402       ? ats_ip6_cast(sa)->sin6_port
00403       : (dummy = 0)
00404     ;
00405 }
00406 inline in_port_t const& ats_ip_port_cast(sockaddr const* sa) {
00407   return ats_ip_port_cast(const_cast<sockaddr*>(sa));
00408 }
00409 inline in_port_t const& ats_ip_port_cast(IpEndpoint const* ip) {
00410   return ats_ip_port_cast(const_cast<sockaddr*>(&ip->sa));
00411 }
00412 inline in_port_t& ats_ip_port_cast(IpEndpoint* ip) {
00413   return ats_ip_port_cast(&ip->sa);
00414 }
00415 
00416 /** Access the IPv4 address.
00417 
00418     If this is not an IPv4 address a zero valued address is returned.
00419     @note This is direct access to the address so it will be in
00420     network order.
00421 
00422     @return A reference to the IPv4 address in @a addr.
00423 */
00424 inline in_addr_t& ats_ip4_addr_cast(sockaddr* addr) {
00425   static in_addr_t dummy = 0;
00426   return ats_is_ip4(addr)
00427     ? ats_ip4_cast(addr)->sin_addr.s_addr
00428     : (dummy = 0)
00429     ;
00430 }
00431 
00432 /** Access the IPv4 address.
00433 
00434     If this is not an IPv4 address a zero valued address is returned.
00435     @note This is direct access to the address so it will be in
00436     network order.
00437 
00438     @return A reference to the IPv4 address in @a addr.
00439 */
00440 inline in_addr_t const& ats_ip4_addr_cast(sockaddr const* addr) {
00441   static in_addr_t dummy = 0;
00442   return ats_is_ip4(addr)
00443     ? ats_ip4_cast(addr)->sin_addr.s_addr
00444     : static_cast<in_addr_t const&>(dummy = 0)
00445     ;
00446 }
00447 
00448 /** Access the IPv4 address.
00449 
00450     If this is not an IPv4 address a zero valued address is returned.
00451     @note This is direct access to the address so it will be in
00452     network order.
00453     @note Convenience overload.
00454 
00455     @return A reference to the IPv4 address in @a addr.
00456 */
00457 inline in_addr_t& ats_ip4_addr_cast(IpEndpoint* ip) {
00458   return ats_ip4_addr_cast(&ip->sa);
00459 }
00460 
00461 /** Access the IPv4 address.
00462 
00463     If this is not an IPv4 address a zero valued address is returned.
00464     @note This is direct access to the address so it will be in
00465     network order.
00466     @note Convenience overload.
00467 
00468     @return A reference to the IPv4 address in @a addr.
00469 */
00470 inline in_addr_t const& ats_ip4_addr_cast(IpEndpoint const* ip) {
00471   return ats_ip4_addr_cast(&ip->sa);
00472 }
00473 
00474 /** Access the IPv6 address.
00475 
00476     If this is not an IPv6 address a zero valued address is returned.
00477     @note This is direct access to the address so it will be in
00478     network order.
00479 
00480     @return A reference to the IPv6 address in @a addr.
00481 */
00482 inline in6_addr& ats_ip6_addr_cast(sockaddr* addr) {
00483   return ats_ip6_cast(addr)->sin6_addr;
00484 }
00485 inline in6_addr const& ats_ip6_addr_cast(sockaddr const* addr) {
00486   return ats_ip6_cast(addr)->sin6_addr;
00487 }
00488 inline in6_addr& ats_ip6_addr_cast(IpEndpoint* ip) {
00489   return ip->sin6.sin6_addr;
00490 }
00491 inline in6_addr const& ats_ip6_addr_cast(IpEndpoint const* ip) {
00492   return ip->sin6.sin6_addr;
00493 }
00494 
00495 /** Cast an IP address to an array of @c uint32_t.
00496     @note The size of the array is dependent on the address type which
00497     must be checked independently of this function.
00498     @return A pointer to the address information in @a addr or @c NULL
00499     if @a addr is not an IP address.
00500 */
00501 inline uint32_t* ats_ip_addr32_cast(sockaddr* addr) {
00502   uint32_t* zret = 0;
00503   switch(addr->sa_family) {
00504   case AF_INET: zret = reinterpret_cast<uint32_t*>(&ats_ip4_addr_cast(addr)); break;
00505   case AF_INET6: zret = reinterpret_cast<uint32_t*>(&ats_ip6_addr_cast(addr)); break;
00506   }
00507   return zret;
00508 }
00509 inline uint32_t const* ats_ip_addr32_cast(sockaddr const* addr) {
00510   return ats_ip_addr32_cast(const_cast<sockaddr*>(addr));
00511 }
00512 
00513 /** Cast an IP address to an array of @c uint8_t.
00514     @note The size of the array is dependent on the address type which
00515     must be checked independently of this function.
00516     @return A pointer to the address information in @a addr or @c NULL
00517     if @a addr is not an IP address.
00518     @see ats_ip_addr_size
00519 */
00520 inline uint8_t* ats_ip_addr8_cast(sockaddr* addr) {
00521   uint8_t* zret = 0;
00522   switch(addr->sa_family) {
00523   case AF_INET: zret = reinterpret_cast<uint8_t*>(&ats_ip4_addr_cast(addr)); break;
00524   case AF_INET6: zret = reinterpret_cast<uint8_t*>(&ats_ip6_addr_cast(addr)); break;
00525   }
00526   return zret;
00527 }
00528 inline uint8_t const* ats_ip_addr8_cast(sockaddr const* addr) {
00529   return ats_ip_addr8_cast(const_cast<sockaddr*>(addr));
00530 }
00531 inline uint8_t* ats_ip_addr8_cast(IpEndpoint* ip) {
00532   return ats_ip_addr8_cast(&ip->sa);
00533 }
00534 inline uint8_t const* ats_ip_addr8_cast(IpEndpoint const* ip) {
00535   return ats_ip_addr8_cast(&ip->sa);
00536 }
00537 
00538 /// Check for loopback.
00539 /// @return @c true if this is an IP loopback address, @c false otherwise.
00540 inline bool ats_is_ip_loopback(sockaddr const* ip) {
00541   return ip
00542     && (
00543       (AF_INET == ip->sa_family && 0x7F == ats_ip_addr8_cast(ip)[0])
00544       ||
00545       (AF_INET6 == ip->sa_family && IN6_IS_ADDR_LOOPBACK(&ats_ip6_addr_cast(ip)))
00546     );
00547 }
00548 
00549 /// Check for loopback.
00550 /// @return @c true if this is an IP loopback address, @c false otherwise.
00551 inline bool ats_is_ip_loopback(IpEndpoint const* ip) {
00552   return ats_is_ip_loopback(&ip->sa);
00553 }
00554 
00555 /// Check for multicast.
00556 /// @return @true if @a ip is multicast.
00557 inline bool ats_is_ip_multicast(sockaddr const* ip) {
00558   return ip
00559     && (
00560       (AF_INET == ip->sa_family && 0xe == *ats_ip_addr8_cast(ip))
00561       ||
00562       (AF_INET6 == ip->sa_family && IN6_IS_ADDR_MULTICAST(&ats_ip6_addr_cast(ip)))
00563     );
00564 }
00565 /// Check for multicast.
00566 /// @return @true if @a ip is multicast.
00567 inline bool ats_is_ip_multicast(IpEndpoint const* ip) {
00568   return ats_is_ip_multicast(&ip->sa);
00569 }
00570 
00571 /// Check for Private.
00572 /// @return @true if @a ip is private.
00573 inline bool
00574 ats_is_ip_private(sockaddr const* ip) {
00575   bool zret = false;
00576   if (ats_is_ip4(ip)) {
00577     in_addr_t a = ats_ip4_addr_cast(ip);
00578     zret = ((a & htonl(0xFF000000)) == htonl(0x0A000000)) || // 10.0.0.0/8
00579       ((a & htonl(0xFFC00000)) == htonl(0x64400000)) ||      // 100.64.0.0/10
00580       ((a & htonl(0xFFF00000)) == htonl(0xAC100000)) ||      // 172.16.0.0/12
00581       ((a & htonl(0xFFFF0000)) == htonl(0xC0A80000))         // 192.168.0.0/16
00582       ;
00583   } else if (ats_is_ip6(ip)) {
00584     in6_addr a = ats_ip6_addr_cast(ip);
00585     zret = ((a.s6_addr[0] & 0xFE) == 0xFC) // fc00::/7
00586       ;
00587   }
00588   return zret;
00589 }
00590 
00591 /// Check for Private.
00592 /// @return @true if @a ip is private.
00593 inline bool
00594 ats_is_ip_private(IpEndpoint const* ip) {
00595   return ats_is_ip_private(&ip->sa);
00596 }
00597 
00598 /// Check for Link Local.
00599 /// @return @true if @a ip is link local.
00600 inline bool
00601 ats_is_ip_linklocal(sockaddr const* ip) {
00602   bool zret = false;
00603   if (ats_is_ip4(ip)) {
00604     in_addr_t a = ats_ip4_addr_cast(ip);
00605     zret = ((a & htonl(0xFFFF0000)) == htonl(0xA9FE0000)) // 169.254.0.0/16
00606       ;
00607   } else if (ats_is_ip6(ip)) {
00608     in6_addr a = ats_ip6_addr_cast(ip);
00609     zret = ((a.s6_addr[0] == 0xFE) && ((a.s6_addr[1] & 0xC0) == 0x80)) // fe80::/10
00610       ;
00611   }
00612   return zret;
00613 }
00614 
00615 /// Check for Link Local.
00616 /// @return @true if @a ip is link local.
00617 inline bool
00618 ats_is_ip_linklocal(IpEndpoint const* ip) {
00619   return ats_is_ip_linklocal(&ip->sa);
00620 }
00621 
00622 /// Check for being "any" address.
00623 /// @return @c true if @a ip is the any / unspecified address.
00624 inline bool ats_is_ip_any(sockaddr const* ip) {
00625   return (ats_is_ip4(ip) && INADDR_ANY == ats_ip4_addr_cast(ip)) ||
00626     (ats_is_ip6(ip) && IN6_IS_ADDR_UNSPECIFIED(&ats_ip6_addr_cast(ip)))
00627     ;
00628 }
00629   
00630 /// @name Address operators
00631 //@{
00632 
00633 /** Copy the address from @a src to @a dst if it's IP.
00634     This attempts to do a minimal copy based on the type of @a src.
00635     If @a src is not an IP address type it is @b not copied and
00636     @a dst is marked as invalid.
00637     @return @c true if @a src was an IP address, @c false otherwise.
00638 */
00639 inline bool ats_ip_copy(
00640   sockaddr* dst, ///< Destination object.
00641   sockaddr const* src ///< Source object.
00642 ) {
00643   size_t n = 0;
00644   if (src) {
00645     switch (src->sa_family) {
00646     case AF_INET: n = sizeof(sockaddr_in); break;
00647     case AF_INET6: n = sizeof(sockaddr_in6); break;
00648     }
00649   }
00650   if (n) {
00651     memcpy(dst, src, n);
00652 #if HAVE_STRUCT_SOCKADDR_SA_LEN
00653     dst->sa_len = n;
00654 #endif
00655   } else {
00656     ats_ip_invalidate(dst);
00657   }
00658   return n != 0;
00659 }
00660 
00661 inline bool ats_ip_copy(
00662   IpEndpoint* dst, ///< Destination object.
00663   sockaddr const* src ///< Source object.
00664 ) {
00665   return ats_ip_copy(&dst->sa, src);
00666 }
00667 inline bool ats_ip_copy(
00668   IpEndpoint* dst, ///< Destination object.
00669   IpEndpoint const* src ///< Source object.
00670 ) {
00671   return ats_ip_copy(&dst->sa, &src->sa);
00672 }
00673 inline bool ats_ip_copy(
00674   sockaddr* dst,
00675   IpEndpoint const* src
00676 ) {
00677   return ats_ip_copy(dst, &src->sa);
00678 }
00679 
00680 /** Compare two addresses.
00681     This is useful for IPv4, IPv6, and the unspecified address type.
00682     If the addresses are of different types they are ordered
00683 
00684     Non-IP < IPv4 < IPv6
00685 
00686      - all non-IP addresses are the same ( including @c AF_UNSPEC )
00687      - IPv4 addresses are compared numerically (host order)
00688      - IPv6 addresses are compared byte wise in network order (MSB to LSB)
00689 
00690     @return
00691       - -1 if @a lhs is less than @a rhs.
00692       - 0 if @a lhs is identical to @a rhs.
00693       - 1 if @a lhs is greater than @a rhs.
00694 
00695     @internal This looks like a lot of code for an inline but I think it
00696     should compile down to something reasonable.
00697 */
00698 inline int ats_ip_addr_cmp(
00699   sockaddr const* lhs, ///< Left hand operand.
00700   sockaddr const* rhs ///< Right hand operand.
00701 ) {
00702   int zret = 0;
00703   uint16_t rtype = rhs->sa_family;
00704   uint16_t ltype = lhs->sa_family;
00705 
00706   // We lump all non-IP addresses into a single equivalence class
00707   // that is less than an IP address. This includes AF_UNSPEC.
00708   if (AF_INET == ltype) {
00709     if (AF_INET == rtype) {
00710       in_addr_t la = ntohl(ats_ip4_cast(lhs)->sin_addr.s_addr);
00711       in_addr_t ra = ntohl(ats_ip4_cast(rhs)->sin_addr.s_addr);
00712       if (la < ra) zret = -1;
00713       else if (la > ra) zret = 1;
00714       else zret = 0;
00715     } else if (AF_INET6 == rtype) { // IPv4 < IPv6
00716       zret = -1;
00717     } else { // IP > not IP
00718       zret = 1;
00719     }
00720   } else if (AF_INET6 == ltype) {
00721     if (AF_INET6 == rtype) {
00722       sockaddr_in6 const* lhs_in6 = ats_ip6_cast(lhs);
00723       zret = memcmp(
00724         &lhs_in6->sin6_addr,
00725         &ats_ip6_cast(rhs)->sin6_addr,
00726         sizeof(lhs_in6->sin6_addr)
00727       );
00728     } else {
00729       zret = 1; // IPv6 greater than any other type.
00730     }
00731   } else if (AF_INET == rtype || AF_INET6 == rtype) {
00732     // ltype is non-IP so it's less than either IP type.
00733     zret = -1;
00734   } else {
00735     // Both types are non-IP so they're equal.
00736     zret = 0;
00737   }
00738 
00739   return zret;
00740 }
00741 
00742 /** Compare two addresses.
00743     @note Convenience overload.
00744     @see ats_ip_addr_cmp(sockaddr const* lhs, sockaddr const* rhs)
00745 */
00746 inline int ats_ip_addr_cmp(IpEndpoint const* lhs, IpEndpoint const* rhs) {
00747   return ats_ip_addr_cmp(&lhs->sa, &rhs->sa);
00748 }
00749 
00750 /** Check if two addresses are equal.
00751     @return @c true if @a lhs and @a rhs point to equal addresses,
00752     @c false otherwise.
00753 */
00754 inline bool ats_ip_addr_eq(sockaddr const* lhs, sockaddr const* rhs) {
00755   return 0 == ats_ip_addr_cmp(lhs, rhs);
00756 }
00757 inline bool ats_ip_addr_eq(IpEndpoint const* lhs, IpEndpoint const* rhs) {
00758   return 0 == ats_ip_addr_cmp(&lhs->sa, &rhs->sa);
00759 }
00760 
00761 inline bool operator == (IpEndpoint const& lhs, IpEndpoint const& rhs) {
00762   return 0 == ats_ip_addr_cmp(&lhs.sa, &rhs.sa);
00763 }
00764 inline bool operator != (IpEndpoint const& lhs, IpEndpoint const& rhs) {
00765   return 0 != ats_ip_addr_cmp(&lhs.sa, &rhs.sa);
00766 }
00767 
00768 /// Compare address and port for equality.
00769 inline bool ats_ip_addr_port_eq(sockaddr const* lhs, sockaddr const* rhs) {
00770   bool zret = false;
00771   if (lhs->sa_family == rhs->sa_family && ats_ip_port_cast(lhs) == ats_ip_port_cast(rhs)) {
00772     if (AF_INET == lhs->sa_family)
00773       zret = ats_ip4_cast(lhs)->sin_addr.s_addr == ats_ip4_cast(rhs)->sin_addr.s_addr;
00774     else if (AF_INET6 == lhs->sa_family)
00775       zret = 0 == memcmp(&ats_ip6_cast(lhs)->sin6_addr, &ats_ip6_cast(rhs)->sin6_addr, sizeof(in6_addr));
00776   }
00777   return zret;
00778 }
00779 
00780 //@}
00781 
00782 /// Get IP TCP/UDP port.
00783 /// @return The port in host order for an IPv4 or IPv6 address,
00784 /// or zero if neither.
00785 inline in_port_t ats_ip_port_host_order(
00786   sockaddr const* addr ///< Address with port.
00787 ) {
00788   // We can discard the const because this function returns
00789   // by value.
00790   return ntohs(ats_ip_port_cast(const_cast<sockaddr*>(addr)));
00791 }
00792 
00793 /// Get IP TCP/UDP port.
00794 /// @return The port in host order for an IPv4 or IPv6 address,
00795 /// or zero if neither.
00796 inline in_port_t ats_ip_port_host_order(
00797   IpEndpoint const* ip ///< Address with port.
00798 ) {
00799   // We can discard the const because this function returns
00800   // by value.
00801   return ntohs(ats_ip_port_cast(const_cast<sockaddr*>(&ip->sa)));
00802 }
00803 
00804 
00805 /** Extract the IPv4 address.
00806     @return Host order IPv4 address.
00807 */
00808 inline in_addr_t ats_ip4_addr_host_order(
00809   sockaddr const* addr ///< Address object.
00810 ) {
00811   return ntohl(ats_ip4_addr_cast(const_cast<sockaddr*>(addr)));
00812 }
00813 
00814 /// Write IPv4 data to storage @a dst.
00815 inline sockaddr* ats_ip4_set(
00816   sockaddr_in* dst, ///< Destination storage.
00817   in_addr_t addr, ///< address, IPv4 network order.
00818   in_port_t port = 0 ///< port, network order.
00819 ) {
00820   ink_zero(*dst);
00821 #if HAVE_STRUCT_SOCKADDR_IN_SIN_LEN
00822   dst->sin_len = sizeof(sockaddr_in);
00823 #endif
00824   dst->sin_family = AF_INET;
00825   dst->sin_addr.s_addr = addr;
00826   dst->sin_port = port;
00827   return ats_ip_sa_cast(dst);
00828 }
00829 
00830 /** Write IPv4 data to @a dst.
00831     @note Convenience overload.
00832 */
00833 inline sockaddr* ats_ip4_set(
00834   IpEndpoint* dst, ///< Destination storage.
00835   in_addr_t ip4, ///< address, IPv4 network order.
00836   in_port_t port = 0 ///< port, network order.
00837 ) {
00838   return ats_ip4_set(&dst->sin, ip4, port);
00839 }
00840 
00841 /** Write IPv4 data to storage @a dst.
00842 
00843     This is the generic overload. Caller must verify that @a dst is at
00844     least @c sizeof(sockaddr_in) bytes.
00845 */
00846 inline sockaddr* ats_ip4_set(
00847   sockaddr* dst, ///< Destination storage.
00848   in_addr_t ip4, ///< address, IPv4 network order.
00849   in_port_t port = 0 ///< port, network order.
00850 ) {
00851   return ats_ip4_set(ats_ip4_cast(dst), ip4, port);
00852 }
00853 /** Write IPv6 data to storage @a dst.
00854     @return @a dst cast to @c sockaddr*.
00855  */
00856 inline sockaddr* ats_ip6_set(
00857   sockaddr_in6* dst, ///< Destination storage.
00858   in6_addr const& addr, ///< address in network order.
00859   in_port_t port = 0 ///< Port, network order.
00860 ) {
00861   ink_zero(*dst);
00862 #if HAVE_STRUCT_SOCKADDR_IN_SIN_LEN
00863   dst->sin6_len = sizeof(sockaddr_in6);
00864 #endif
00865   dst->sin6_family = AF_INET6;
00866   memcpy(&dst->sin6_addr, &addr, sizeof addr);
00867   dst->sin6_port = port;
00868   return ats_ip_sa_cast(dst);
00869 }
00870 /** Write IPv6 data to storage @a dst.
00871     @return @a dst cast to @c sockaddr*.
00872  */
00873 inline sockaddr* ats_ip6_set(
00874   sockaddr* dst, ///< Destination storage.
00875   in6_addr const& addr, ///< address in network order.
00876   in_port_t port = 0 ///< Port, network order.
00877 ) {
00878   return ats_ip6_set(ats_ip6_cast(dst), addr, port);
00879 }
00880 /** Write IPv6 data to storage @a dst.
00881     @return @a dst cast to @c sockaddr*.
00882  */
00883 inline sockaddr* ats_ip6_set(
00884   IpEndpoint* dst, ///< Destination storage.
00885   in6_addr const& addr, ///< address in network order.
00886   in_port_t port = 0 ///< Port, network order.
00887 ) {
00888   return ats_ip6_set(&dst->sin6, addr, port);
00889 }
00890 
00891 /** Write a null terminated string for @a addr to @a dst.
00892     A buffer of size INET6_ADDRSTRLEN suffices, including a terminating nul.
00893  */
00894 char const* ats_ip_ntop(
00895   const sockaddr *addr, ///< Address.
00896   char *dst, ///< Output buffer.
00897   size_t size ///< Length of buffer.
00898 );
00899 
00900 /** Write a null terminated string for @a addr to @a dst.
00901     A buffer of size INET6_ADDRSTRLEN suffices, including a terminating nul.
00902  */
00903 inline char const* ats_ip_ntop(
00904   IpEndpoint const* addr, ///< Address.
00905   char *dst, ///< Output buffer.
00906   size_t size ///< Length of buffer.
00907 ) {
00908   return ats_ip_ntop(&addr->sa, dst, size);
00909 }
00910 
00911 /// Buffer size sufficient for IPv6 address and port.
00912 static size_t const INET6_ADDRPORTSTRLEN = INET6_ADDRSTRLEN + 6;
00913 /// Convenience type for address formatting.
00914 typedef char ip_text_buffer[INET6_ADDRSTRLEN];
00915 /// Convenience type for address formatting.
00916 typedef char ip_port_text_buffer[INET6_ADDRPORTSTRLEN];
00917 
00918 /** Write a null terminated string for @a addr to @a dst with port.
00919     A buffer of size INET6_ADDRPORTSTRLEN suffices, including a terminating nul.
00920  */
00921 char const* ats_ip_nptop(
00922   const sockaddr *addr, ///< Address.
00923   char *dst, ///< Output buffer.
00924   size_t size ///< Length of buffer.
00925 );
00926 
00927 /** Write a null terminated string for @a addr to @a dst with port.
00928     A buffer of size INET6_ADDRPORTSTRLEN suffices, including a terminating nul.
00929  */
00930 inline char const* ats_ip_nptop(
00931   IpEndpoint const*addr, ///< Address.
00932   char *dst, ///< Output buffer.
00933   size_t size ///< Length of buffer.
00934 ) {
00935   return ats_ip_nptop(&addr->sa, dst, size);
00936 }
00937 
00938 
00939 /** Convert @a text to an IP address and write it to @a addr.
00940 
00941     @a text is expected to be an explicit address, not a hostname.  No
00942     hostname resolution is done. The call must provide an @a ip large
00943     enough to hold the address value.
00944 
00945     This attempts to recognize and process a port value if
00946     present. The port in @a ip is set appropriately, or to zero if no
00947     port was found or it was malformed.
00948 
00949     @note The return values are logically reversed from @c inet_pton.
00950     @note This uses @c getaddrinfo internally and so involves memory
00951     allocation.
00952 
00953     @return 0 on success, non-zero on failure.
00954 */
00955 int ats_ip_pton(
00956   const ts::ConstBuffer& text, ///< [in] text.
00957   sockaddr* addr ///< [out] address
00958 );
00959 
00960 /** Convert @a text to an IP address and write it to @a addr.
00961 
00962     @a text is expected to be an explicit address, not a hostname.  No
00963     hostname resolution is done.
00964 
00965     @note This uses @c getaddrinfo internally and so involves memory
00966     allocation.
00967     @note Convenience overload.
00968 
00969     @return 0 on success, non-zero on failure.
00970 */
00971 inline int ats_ip_pton(
00972   char const* text, ///< [in] text.
00973   sockaddr_in6* addr ///< [out] address
00974 ) {
00975   return ats_ip_pton(ts::ConstBuffer(text, strlen(text)), ats_ip_sa_cast(addr));
00976 }
00977 
00978 inline int ats_ip_pton(
00979   const ts::ConstBuffer& text, ///< [in] text.
00980   IpEndpoint* addr ///< [out] address
00981 ) {
00982   return ats_ip_pton(text, &addr->sa);
00983 }
00984 
00985 inline int ats_ip_pton(
00986   const char * text, ///< [in] text.
00987   IpEndpoint* addr ///< [out] address
00988 ) {
00989   return ats_ip_pton(ts::ConstBuffer(text, strlen(text)), &addr->sa);
00990 }
00991 
00992 inline int ats_ip_pton(
00993   const char * text, ///< [in] text.
00994   sockaddr * addr ///< [out] address
00995 ) {
00996   return ats_ip_pton(ts::ConstBuffer(text, strlen(text)), addr);
00997 }
00998 
00999 /** Get the best address info for @a name.
01000 
01001     @name is passed to @c getaddrinfo which does a host lookup if @a
01002     name is not in IP address format. The results are examined for the
01003     "best" addresses. This is only significant for the host name case
01004     (for IP address data, there is at most one result). The preference is
01005     Global > Non-Routable > Multicast > Loopback.
01006 
01007     IPv4 and IPv4 results are handled independently and stored in @a
01008     ip4 and @a ip6 respectively. If @a name is known to be a numeric
01009     IP address @c ats_ip_pton is a better choice. Use this function
01010     if the type of @a name is not known. If you want to look at the
01011     addresses and not just get the "best", use @c getaddrinfo
01012     directly.
01013 
01014     @a ip4 or @a ip6 can be @c NULL and the result for that family is
01015     discarded. It is legal for both to be @c NULL in which case this
01016     is just a format check.
01017 
01018     @return 0 if an address was found, non-zero otherwise.
01019 
01020     @see ats_ip_pton
01021     @see getaddrinfo
01022  */
01023 
01024 int
01025 ats_ip_getbestaddrinfo(
01026   char const* name, ///< [in] Address name (IPv4, IPv6, or host name)
01027   IpEndpoint* ip4, ///< [out] Storage for IPv4 address.
01028   IpEndpoint* ip6 ///< [out] Storage for IPv6 address
01029 );
01030 
01031 /** Generic IP address hash function.
01032 */    
01033 uint32_t ats_ip_hash(sockaddr const* addr);
01034 
01035 /** Convert address to string as a hexidecimal value.
01036     The string is always nul terminated, the output string is clipped
01037     if @a dst is insufficient.
01038     @return The length of the resulting string (not including nul).
01039 */
01040 int
01041 ats_ip_to_hex(
01042   sockaddr const* addr, ///< Address to convert. Must be IP.
01043   char* dst, ///< Destination buffer.
01044   size_t len ///< Length of @a dst.
01045 );
01046 
01047 /** Storage for an IP address.
01048     In some cases we want to store just the address and not the
01049     ancillary information (such as port, or flow data).
01050     @note This is not easily used as an address for system calls.
01051 */
01052 struct IpAddr {
01053   typedef IpAddr self; ///< Self reference type.
01054 
01055   /// Default construct (invalid address).
01056   IpAddr() : _family(AF_UNSPEC) {}
01057   /// Construct as IPv4 @a addr.
01058   explicit IpAddr(
01059     in_addr_t addr ///< Address to assign.
01060   ) : _family(AF_INET) {
01061     _addr._ip4 = addr;
01062   }
01063   /// Construct as IPv6 @a addr.
01064   explicit IpAddr(
01065     in6_addr const& addr ///< Address to assign.
01066   ) : _family(AF_INET6) {
01067     _addr._ip6 = addr;
01068   }
01069   /// Construct from @c sockaddr.
01070   explicit IpAddr(sockaddr const* addr) { this->assign(addr); }
01071   /// Construct from @c sockaddr_in6.
01072   explicit IpAddr(sockaddr_in6 const& addr) { this->assign(ats_ip_sa_cast(&addr)); }
01073   /// Construct from @c sockaddr_in6.
01074   explicit IpAddr(sockaddr_in6 const* addr) { this->assign(ats_ip_sa_cast(addr)); }
01075   /// Construct from @c IpEndpoint.
01076   explicit IpAddr(IpEndpoint const& addr) { this->assign(&addr.sa); }
01077   /// Construct from @c IpEndpoint.
01078   explicit IpAddr(IpEndpoint const* addr) { this->assign(&addr->sa); }
01079 
01080   /// Assign sockaddr storage.
01081   self& assign(
01082                sockaddr const* addr ///< May be @c NULL
01083                );
01084 
01085   /// Assign from end point.
01086   self& operator = (IpEndpoint const& ip) {
01087     return this->assign(&ip.sa);
01088   }
01089   /// Assign from IPv4 raw address.
01090   self& operator = (
01091     in_addr_t ip ///< Network order IPv4 address.
01092   );
01093   /// Assign from IPv6 raw address.
01094   self& operator = (
01095     in6_addr const& ip
01096   );
01097 
01098   /** Load from string.
01099       The address is copied to this object if the conversion is successful,
01100       otherwise this object is invalidated.
01101       @return 0 on success, non-zero on failure.
01102   */
01103   int load(
01104     char const* str ///< Nul terminated input string.
01105   );
01106   /** Output to a string.
01107       @return The string @a dest.
01108   */
01109   char* toString(
01110     char* dest, ///< [out] Destination string buffer.
01111     size_t len ///< [in] Size of buffer.
01112   ) const;
01113 
01114   /// Equality.
01115   bool operator==(self const& that) const {
01116     return _family == AF_INET
01117       ? (that._family == AF_INET && _addr._ip4 == that._addr._ip4)
01118       : _family == AF_INET6
01119         ? (that._family == AF_INET6
01120           && 0 == memcmp(&_addr._ip6, &that._addr._ip6, TS_IP6_SIZE)
01121           )
01122         : (_family == AF_UNSPEC && that._family == AF_UNSPEC)
01123     ;
01124   }
01125 
01126   /// Inequality.
01127   bool operator!=(self const& that) {
01128     return ! (*this == that);
01129   }
01130 
01131   /// Test for same address family.
01132   /// @c return @c true if @a that is the same address family as @a this.
01133   bool isCompatibleWith(self const& that);
01134 
01135   /// Get the address family.
01136   /// @return The address family.
01137   uint16_t family() const;
01138   /// Test for IPv4.
01139   bool isIp4() const;
01140   /// Test for IPv6.
01141   bool isIp6() const;
01142 
01143   /// Test for validity.
01144   bool isValid() const { return _family == AF_INET || _family == AF_INET6; }
01145   /// Make invalid.
01146   self& invalidate() { _family = AF_UNSPEC; return *this; }
01147   /// Test for multicast
01148   bool isMulticast() const;
01149 
01150   uint16_t _family; ///< Protocol family.
01151   /// Address data.
01152   union {
01153     in_addr_t _ip4; ///< IPv4 address storage.
01154     in6_addr  _ip6; ///< IPv6 address storage.
01155     uint8_t   _byte[TS_IP6_SIZE]; ///< As raw bytes.
01156   } _addr;
01157 
01158   ///< Pre-constructed invalid instance.
01159   static self const INVALID;
01160 };
01161 
01162 inline IpAddr&
01163 IpAddr::operator = (in_addr_t ip) {
01164   _family = AF_INET;
01165   _addr._ip4 = ip;
01166   return *this;
01167 }
01168 
01169 inline IpAddr&
01170 IpAddr::operator = (in6_addr const& ip) {
01171   _family = AF_INET6;
01172   _addr._ip6 = ip;
01173   return *this;
01174 }
01175 
01176 inline uint16_t IpAddr::family() const { return _family; }
01177 
01178 inline bool
01179 IpAddr::isCompatibleWith(self const& that) {
01180   return this->isValid() && _family == that._family;
01181 }
01182 
01183 inline bool IpAddr::isIp4() const { return AF_INET == _family; }
01184 inline bool IpAddr::isIp6() const { return AF_INET6 == _family; }
01185   /// Assign sockaddr storage.
01186 inline IpAddr&
01187 IpAddr::assign(sockaddr const* addr) {
01188   if (addr) {
01189     _family = addr->sa_family;
01190     if (ats_is_ip4(addr)) {
01191       _addr._ip4 = ats_ip4_addr_cast(addr);
01192     } else if (ats_is_ip6(addr)) {
01193       _addr._ip6 = ats_ip6_addr_cast(addr);
01194     } else {
01195       _family = AF_UNSPEC;
01196     }
01197   } else {
01198     _family = AF_UNSPEC;
01199   }
01200   return *this;
01201 }
01202 
01203 // Associated operators.
01204 bool operator == (IpAddr const& lhs, sockaddr const* rhs);
01205 inline bool operator == (sockaddr const* lhs, IpAddr const& rhs) {
01206   return rhs == lhs;
01207 }
01208 inline bool operator != (IpAddr const& lhs, sockaddr const* rhs) {
01209   return ! (lhs == rhs);
01210 }
01211 inline bool operator != (sockaddr const* lhs, IpAddr const& rhs) {
01212   return ! (rhs == lhs);
01213 }
01214 inline bool operator == (IpAddr const& lhs, IpEndpoint const& rhs) {
01215   return lhs == &rhs.sa;
01216 }
01217 inline bool operator == (IpEndpoint const& lhs, IpAddr const& rhs) {
01218   return &lhs.sa == rhs;
01219 }
01220 inline bool operator != (IpAddr const& lhs, IpEndpoint const& rhs) {
01221   return ! (lhs == &rhs.sa);
01222 }
01223 inline bool operator != (IpEndpoint const& lhs, IpAddr const& rhs) {
01224   return ! (rhs == &lhs.sa);
01225 }
01226 
01227 /// Write IP @a addr to storage @a dst.
01228 /// @return @s dst.
01229 sockaddr* ats_ip_set(
01230   sockaddr* dst, ///< Destination storage.
01231   IpAddr const& addr, ///< source address.
01232   in_port_t port = 0 ///< port, network order.
01233 );
01234 
01235 /** Convert @a text to an IP address and write it to @a addr.
01236     Convenience overload.
01237     @return 0 on success, non-zero on failure.
01238 */
01239 inline int ats_ip_pton(
01240   char const* text, ///< [in] text.
01241   IpAddr& addr ///< [out] address
01242 ) {
01243   return addr.load(text) ? 0 : -1;
01244 }
01245 
01246 inline IpEndpoint&
01247 IpEndpoint::assign(IpAddr const& addr, in_port_t port) {
01248   ats_ip_set(&sa, addr, port); 
01249   return *this;
01250 }
01251 
01252 inline IpEndpoint&
01253 IpEndpoint::assign(sockaddr const* ip) {
01254   ats_ip_copy(&sa, ip);
01255   return *this;
01256 }
01257 
01258 inline in_port_t&
01259 IpEndpoint::port() {
01260   return ats_ip_port_cast(&sa);
01261 }
01262 
01263 inline in_port_t
01264 IpEndpoint::port() const {
01265   return ats_ip_port_cast(&sa);
01266 }
01267 
01268 inline bool
01269 IpEndpoint::isValid() const {
01270   return ats_is_ip(this);
01271 }
01272 
01273 inline bool IpEndpoint::isIp4() const { return AF_INET == sa.sa_family; }
01274 inline bool IpEndpoint::isIp6() const { return AF_INET6 == sa.sa_family; }
01275 inline uint16_t IpEndpoint::family() const { return sa.sa_family; }
01276 
01277 inline IpEndpoint&
01278 IpEndpoint::setToAnyAddr(int family) {
01279   ink_zero(*this);
01280   sa.sa_family = family;
01281   if (AF_INET == family) {
01282     sin.sin_addr.s_addr = INADDR_ANY;
01283 #if HAVE_STRUCT_SOCKADDR_IN_SIN_LEN
01284     sin.sin_len = sizeof(sockaddr_in);
01285 #endif
01286   } else if (AF_INET6 == family) {
01287     sin6.sin6_addr = in6addr_any;
01288 #if HAVE_STRUCT_SOCKADDR_IN6_SIN6_LEN
01289     sin6.sin6_len = sizeof(sockaddr_in6);
01290 #endif
01291   }
01292   return *this;
01293 }
01294 
01295 inline IpEndpoint&
01296 IpEndpoint::setToLoopback(int family) {
01297   ink_zero(*this);
01298   sa.sa_family = family;
01299   if (AF_INET == family) {
01300     sin.sin_addr.s_addr = htonl(INADDR_LOOPBACK);
01301 #if HAVE_STRUCT_SOCKADDR_IN_SIN_LEN
01302     sin.sin_len = sizeof(sockaddr_in);
01303 #endif
01304   } else if (AF_INET6 == family) {
01305     sin6.sin6_addr = in6addr_loopback;
01306 #if HAVE_STRUCT_SOCKADDR_IN6_SIN6_LEN
01307     sin6.sin6_len = sizeof(sockaddr_in6);
01308 #endif
01309   }
01310   return *this;
01311 }
01312 
01313 #endif // _ink_inet.h

Generated by  doxygen 1.7.1