00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024 #include "libts.h"
00025 #include "I_Machine.h"
00026
00027 #if HAVE_IFADDRS_H
00028 # include <ifaddrs.h>
00029 #endif
00030
00031
00032 Machine* Machine::_instance = NULL;
00033
00034 Machine*
00035 Machine::instance() {
00036 ink_assert(_instance || !"Machine instance accessed before initialization");
00037 return Machine::_instance;
00038 }
00039
00040 Machine*
00041 Machine::init(char const* name, sockaddr const* ip) {
00042 ink_assert(!_instance || !"Machine instance initialized twice.");
00043 Machine::_instance = new Machine(name, ip);
00044 return Machine::_instance;
00045 }
00046
00047 Machine::Machine(char const* the_hostname, sockaddr const* addr)
00048 : hostname(0), hostname_len(0)
00049 , ip_string_len(0)
00050 , ip_hex_string_len(0)
00051 {
00052 char localhost[1024];
00053 int status;
00054
00055 ip_string[0] = 0;
00056 ip_hex_string[0] = 0;
00057 ink_zero(ip);
00058 ink_zero(ip4);
00059 ink_zero(ip6);
00060
00061 localhost[sizeof(localhost)-1] = 0;
00062
00063 if (!ats_is_ip(addr)) {
00064 if (!the_hostname) {
00065 ink_release_assert(!gethostname(localhost, sizeof(localhost)-1));
00066 the_hostname = localhost;
00067 }
00068 hostname = ats_strdup(the_hostname);
00069
00070 #if HAVE_IFADDRS_H
00071 ifaddrs* ifa_addrs = 0;
00072 status = getifaddrs(&ifa_addrs);
00073 #else
00074 int s = socket(AF_INET, SOCK_DGRAM, 0);
00075
00076
00077
00078
00079 static const int N_REQ = 1024;
00080 ifconf conf;
00081 ifreq req[N_REQ];
00082 if (0 <= s) {
00083 conf.ifc_len = sizeof(req);
00084 conf.ifc_req = req;
00085 status = ioctl(s, SIOCGIFCONF, &conf);
00086 } else {
00087 status = -1;
00088 }
00089 #endif
00090
00091 if (0 != status) {
00092 Warning("Unable to determine local host '%s' address information - %s"
00093 , hostname
00094 , strerror(errno)
00095 );
00096 } else {
00097
00098 enum {
00099 NA,
00100 LO,
00101 LL,
00102 PR,
00103 MC,
00104 GL
00105 } spot_type = NA, ip4_type = NA, ip6_type = NA;
00106 sockaddr const* ifip;
00107 unsigned int ifflags;
00108 for (
00109 #if HAVE_IFADDRS_H
00110 ifaddrs* spot = ifa_addrs ; spot ; spot = spot->ifa_next
00111 #else
00112 ifreq* spot = req, *req_limit = req + (conf.ifc_len/sizeof(*req)) ; spot < req_limit ; ++spot
00113 #endif
00114 ) {
00115 #if HAVE_IFADDRS_H
00116 ifip = spot->ifa_addr;
00117 ifflags = spot->ifa_flags;
00118 #else
00119 ifip = &spot->ifr_addr;
00120
00121
00122 struct ifreq ifr;
00123 ink_strlcpy(ifr.ifr_name, spot->ifr_name, IFNAMSIZ);
00124 if (ioctl(s, SIOCGIFFLAGS, &ifr) == 0) ifflags = ifr.ifr_flags;
00125 else ifflags = 0;
00126 #endif
00127 if (!ats_is_ip(ifip)) spot_type = NA;
00128 else if (ats_is_ip_loopback(ifip) || (IFF_LOOPBACK & ifflags)) spot_type = LO;
00129 else if (ats_is_ip_linklocal(ifip)) spot_type = LL;
00130 else if (ats_is_ip_private(ifip)) spot_type = PR;
00131 else if (ats_is_ip_multicast(ifip)) spot_type = MC;
00132 else spot_type = GL;
00133 if (spot_type == NA) continue;
00134
00135 if (ats_is_ip4(ifip)) {
00136 if (spot_type > ip4_type) {
00137 ats_ip_copy(&ip4, ifip);
00138 ip4_type = spot_type;
00139 }
00140 } else if (ats_is_ip6(ifip)) {
00141 if (spot_type > ip6_type) {
00142 ats_ip_copy(&ip6, ifip);
00143 ip6_type = spot_type;
00144 }
00145 }
00146 }
00147
00148 #if HAVE_IFADDRS_H
00149 freeifaddrs(ifa_addrs);
00150 #endif
00151
00152
00153 if (ip4_type >= ip6_type)
00154 ats_ip_copy(&ip.sa, &ip4.sa);
00155 else
00156 ats_ip_copy(&ip.sa, &ip6.sa);
00157 }
00158 #if ! HAVE_IFADDRS_H
00159 close(s);
00160 #endif
00161 } else {
00162 ats_ip_copy(&ip, addr);
00163 if (ats_is_ip4(addr)) ats_ip_copy(&ip4, addr);
00164 else if (ats_is_ip6(addr)) ats_ip_copy(&ip6, addr);
00165
00166 status = getnameinfo(
00167 addr, ats_ip_size(addr),
00168 localhost, sizeof(localhost) - 1,
00169 0, 0,
00170 0
00171 );
00172
00173 if (0 != status) {
00174 ip_text_buffer ipbuff;
00175 Warning("Failed to find hostname for address '%s' - %s"
00176 , ats_ip_ntop(addr, ipbuff, sizeof(ipbuff))
00177 , gai_strerror(status)
00178 );
00179 } else
00180 hostname = ats_strdup(localhost);
00181 }
00182
00183 hostname_len = hostname ? strlen(hostname) : 0;
00184
00185 ats_ip_ntop(&ip.sa, ip_string, sizeof(ip_string));
00186 ip_string_len = strlen(ip_string);
00187 ip_hex_string_len = ats_ip_to_hex(&ip.sa, ip_hex_string, sizeof(ip_hex_string));
00188 }
00189
00190 Machine::~Machine()
00191 {
00192 ats_free(hostname);
00193 }