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