1 // NetAddress.cpp 2 3 #include <new> 4 #include <netdb.h> 5 #include <stdio.h> 6 #include <unistd.h> 7 8 #if defined(HAIKU_TARGET_PLATFORM_DANO) || defined(HAIKU_TARGET_PLATFORM_DANO) 9 # include <net/route.h> 10 # include <sys/sockio.h> 11 # include <stdlib.h> 12 #endif 13 14 #include <AutoLocker.h> 15 #include <ByteOrder.h> 16 #include <HashString.h> 17 #include <Referenceable.h> 18 19 #include "Compatibility.h" 20 #include "Locker.h" 21 #include "NetAddress.h" 22 23 // constructor 24 NetAddress::NetAddress() 25 { 26 fAddress.sin_family = AF_INET; 27 fAddress.sin_addr.s_addr = 0; 28 fAddress.sin_port = 0; 29 } 30 31 // constructor 32 NetAddress::NetAddress(const sockaddr_in& address) 33 { 34 fAddress = address; 35 } 36 37 // copy constructor 38 NetAddress::NetAddress(const NetAddress& address) 39 { 40 fAddress = address.fAddress; 41 } 42 43 // SetIP 44 void 45 NetAddress::SetIP(int32 address) 46 { 47 fAddress.sin_addr.s_addr = B_HOST_TO_BENDIAN_INT32(address); 48 } 49 50 // GetIP 51 int32 52 NetAddress::GetIP() const 53 { 54 return B_BENDIAN_TO_HOST_INT32(fAddress.sin_addr.s_addr); 55 } 56 57 // SetPort 58 void 59 NetAddress::SetPort(uint16 port) 60 { 61 fAddress.sin_port = B_HOST_TO_BENDIAN_INT32(port); 62 } 63 64 // GetPort 65 uint16 66 NetAddress::GetPort() const 67 { 68 return B_BENDIAN_TO_HOST_INT16(fAddress.sin_port); 69 } 70 71 // SetAddress 72 void 73 NetAddress::SetAddress(const sockaddr_in& address) 74 { 75 fAddress = address; 76 } 77 78 // GetAddress 79 const sockaddr_in& 80 NetAddress::GetAddress() const 81 { 82 return fAddress; 83 } 84 85 // IsLocal 86 bool 87 NetAddress::IsLocal() const 88 { 89 // special address? 90 if (fAddress.sin_addr.s_addr == INADDR_ANY 91 || fAddress.sin_addr.s_addr == INADDR_BROADCAST) { 92 return false; 93 } 94 // create a socket and try to bind it to a port of this address 95 int fd = socket(AF_INET, SOCK_DGRAM, 0); 96 if (fd < 0) 97 return false; 98 #if defined(HAIKU_TARGET_PLATFORM_DANO) 99 // BONE does allow you to bind to any address! 100 // Therefore, we iterate over all routes, and see if there are any local 101 // ones for this address. 102 103 bool result = false; 104 uint32 count; 105 if (ioctl(fd, SIOCGRTSIZE, &count) == 0) { 106 route_req_t* routes = (route_req_t*)malloc(count * sizeof(route_req_t)); 107 if (routes != NULL) { 108 route_table_req table; 109 table.rrtp = routes; 110 table.len = count * sizeof(route_req_t); 111 table.cnt = count; 112 if (ioctl(fd, SIOCGRTTABLE, &table) == 0) { 113 for (uint32 i = 0; i < table.cnt; i++) { 114 if ((routes[i].flags & RTF_LOCAL) == 0) 115 continue; 116 if (((sockaddr_in*)&routes[i].dst)->sin_addr.s_addr 117 == fAddress.sin_addr.s_addr) { 118 result = true; 119 break; 120 } 121 } 122 } 123 free(routes); 124 } 125 } 126 #else 127 // bind it to a port 128 sockaddr_in addr = fAddress; 129 addr.sin_port = 0; 130 bool result = (bind(fd, (sockaddr*)&addr, sizeof(addr)) == 0); 131 #endif 132 closesocket(fd); 133 134 return result; 135 } 136 137 138 // GetString 139 status_t 140 NetAddress::GetString(HashString* string, bool includePort) const 141 { 142 if (!string) 143 return B_BAD_VALUE; 144 char buffer[32]; 145 uint32 ip = GetIP(); 146 if (includePort) { 147 sprintf(buffer, "%lu.%lu.%lu.%lu:%hu", 148 ip >> 24, (ip >> 16) & 0xff, (ip >> 8) & 0xff, ip & 0xff, 149 GetPort()); 150 } else { 151 sprintf(buffer, "%lu.%lu.%lu.%lu", 152 ip >> 24, (ip >> 16) & 0xff, (ip >> 8) & 0xff, ip & 0xff); 153 } 154 return (string->SetTo(buffer) ? B_OK : B_NO_MEMORY); 155 } 156 157 // GetHashCode 158 uint32 159 NetAddress::GetHashCode() const 160 { 161 return (fAddress.sin_addr.s_addr * 31 + fAddress.sin_port); 162 } 163 164 // = 165 NetAddress& 166 NetAddress::operator=(const NetAddress& address) 167 { 168 fAddress = address.fAddress; 169 return *this; 170 } 171 172 // == 173 bool 174 NetAddress::operator==(const NetAddress& address) const 175 { 176 return (fAddress.sin_addr.s_addr == address.fAddress.sin_addr.s_addr 177 && fAddress.sin_port == address.fAddress.sin_port); 178 } 179 180 // != 181 bool 182 NetAddress::operator!=(const NetAddress& address) const 183 { 184 return !(*this == address); 185 } 186 187 188 // #pragma mark - 189 190 // Resolver 191 class NetAddressResolver::Resolver : public BReferenceable { 192 public: 193 Resolver() 194 : BReferenceable(false), 195 fLock() 196 { 197 } 198 199 status_t InitCheck() const 200 { 201 return (fLock.Sem() >= 0 ? B_OK : B_NO_INIT); 202 } 203 204 status_t GetHostAddress(const char* hostName, NetAddress* address) 205 { 206 AutoLocker<Locker> _(fLock); 207 struct hostent* host = gethostbyname(hostName); 208 if (!host) 209 return h_errno; 210 if (host->h_addrtype != AF_INET || !host->h_addr_list[0]) 211 return B_BAD_VALUE; 212 sockaddr_in addr; 213 addr.sin_family = AF_INET; 214 addr.sin_port = 0; 215 addr.sin_addr = *(in_addr*)host->h_addr_list[0]; 216 *address = addr; 217 return B_OK; 218 } 219 220 private: 221 Locker fLock; 222 }; 223 224 // constructor 225 NetAddressResolver::NetAddressResolver() 226 { 227 _Lock(); 228 // initialize static instance, if not done yet 229 if (sResolver) { 230 sResolver->AddReference(); 231 fResolver = sResolver; 232 } else { 233 sResolver = new(std::nothrow) Resolver; 234 if (sResolver) { 235 if (sResolver->InitCheck() != B_OK) { 236 delete sResolver; 237 sResolver = NULL; 238 } 239 } 240 fResolver = sResolver; 241 } 242 _Unlock(); 243 } 244 245 // destructor 246 NetAddressResolver::~NetAddressResolver() 247 { 248 if (fResolver) { 249 _Lock(); 250 if (sResolver->RemoveReference()) { 251 delete sResolver; 252 sResolver = NULL; 253 } 254 _Unlock(); 255 } 256 } 257 258 // InitCheck 259 status_t 260 NetAddressResolver::InitCheck() const 261 { 262 return (fResolver ? B_OK : B_NO_INIT); 263 } 264 265 // GetAddress 266 status_t 267 NetAddressResolver::GetHostAddress(const char* hostName, NetAddress* address) 268 { 269 if (!fResolver) 270 return B_NO_INIT; 271 if (!hostName || !address) 272 return B_BAD_VALUE; 273 return fResolver->GetHostAddress(hostName, address); 274 } 275 276 // _Lock 277 void 278 NetAddressResolver::_Lock() 279 { 280 while (atomic_add(&sLockCounter, 1) > 0) { 281 atomic_add(&sLockCounter, -1); 282 snooze(10000); 283 } 284 } 285 286 // _Unlock 287 void 288 NetAddressResolver::_Unlock() 289 { 290 atomic_add(&sLockCounter, -1); 291 } 292 293 294 // sResolver 295 NetAddressResolver::Resolver* volatile NetAddressResolver::sResolver = NULL; 296 297 // sLockCounter 298 vint32 NetAddressResolver::sLockCounter = 0; 299