anope- supernets anope source code & configuration |
git clone git://git.acid.vegas/anope.git |
Log | Files | Refs | Archive | README |
sockets.cpp (12454B)
1 /* 2 * 3 * (C) 2003-2022 Anope Team 4 * Contact us at team@anope.org 5 * 6 * Please read COPYING and README for further details. 7 * 8 * Based on the original code of Epona by Lara. 9 * Based on the original code of Services by Andy Church. 10 */ 11 12 #include "services.h" 13 #include "sockets.h" 14 #include "socketengine.h" 15 #include "logger.h" 16 17 #ifndef _WIN32 18 #include <arpa/inet.h> 19 #include <errno.h> 20 #include <fcntl.h> 21 #endif 22 23 std::map<int, Socket *> SocketEngine::Sockets; 24 25 uint32_t TotalRead = 0; 26 uint32_t TotalWritten = 0; 27 28 SocketIO NormalSocketIO; 29 30 sockaddrs::sockaddrs(const Anope::string &address) 31 { 32 this->clear(); 33 if (!address.empty() && address.find_first_not_of_ci("0123456789abcdef.:") == Anope::string::npos) 34 this->pton(address.find(':') != Anope::string::npos ? AF_INET6 : AF_INET, address); 35 } 36 37 void sockaddrs::clear() 38 { 39 memset(this, 0, sizeof(*this)); 40 } 41 42 int sockaddrs::family() const 43 { 44 return sa.sa_family; 45 } 46 47 size_t sockaddrs::size() const 48 { 49 switch (sa.sa_family) 50 { 51 case AF_INET: 52 return sizeof(sa4); 53 case AF_INET6: 54 return sizeof(sa6); 55 default: 56 break; 57 } 58 59 return 0; 60 } 61 62 int sockaddrs::port() const 63 { 64 switch (sa.sa_family) 65 { 66 case AF_INET: 67 return ntohs(sa4.sin_port); 68 case AF_INET6: 69 return ntohs(sa6.sin6_port); 70 default: 71 break; 72 } 73 74 return -1; 75 } 76 77 Anope::string sockaddrs::addr() const 78 { 79 char address[INET6_ADDRSTRLEN]; 80 81 switch (sa.sa_family) 82 { 83 case AF_INET: 84 if (inet_ntop(AF_INET, &sa4.sin_addr, address, sizeof(address))) 85 return address; 86 break; 87 case AF_INET6: 88 if (inet_ntop(AF_INET6, &sa6.sin6_addr, address, sizeof(address))) 89 return address; 90 break; 91 default: 92 break; 93 } 94 95 return ""; 96 } 97 98 Anope::string sockaddrs::reverse() const 99 { 100 char address[128]; 101 102 switch (sa.sa_family) 103 { 104 case AF_INET6: 105 { 106 static const char hex[] = "0123456789abcdef"; 107 unsigned reverse_ip_count = 0; 108 for (int j = 15; j >= 0; --j) 109 { 110 address[reverse_ip_count++] = hex[sa6.sin6_addr.s6_addr[j] & 0xF]; 111 address[reverse_ip_count++] = '.'; 112 address[reverse_ip_count++] = hex[sa6.sin6_addr.s6_addr[j] >> 4]; 113 address[reverse_ip_count++] = '.'; 114 } 115 /* Remove the last '.' */ 116 address[reverse_ip_count - 1] = 0; 117 return address; 118 } 119 case AF_INET: 120 { 121 unsigned long forward = sa4.sin_addr.s_addr; 122 in_addr rev; 123 rev.s_addr = forward << 24 | (forward & 0xFF00) << 8 | (forward & 0xFF0000) >> 8 | forward >> 24; 124 if (inet_ntop(AF_INET, &rev, address, sizeof(address))) 125 return address; 126 break; 127 } 128 } 129 130 return ""; 131 } 132 133 bool sockaddrs::ipv6() const 134 { 135 return sa.sa_family == AF_INET6; 136 } 137 138 bool sockaddrs::valid() const 139 { 140 return size() != 0; 141 } 142 143 bool sockaddrs::operator==(const sockaddrs &other) const 144 { 145 if (sa.sa_family != other.sa.sa_family) 146 return false; 147 switch (sa.sa_family) 148 { 149 case AF_INET: 150 return (sa4.sin_port == other.sa4.sin_port) && (sa4.sin_addr.s_addr == other.sa4.sin_addr.s_addr); 151 case AF_INET6: 152 return (sa6.sin6_port == other.sa6.sin6_port) && !memcmp(sa6.sin6_addr.s6_addr, other.sa6.sin6_addr.s6_addr, 16); 153 default: 154 return !memcmp(this, &other, sizeof(*this)); 155 } 156 157 return false; 158 } 159 160 void sockaddrs::pton(int type, const Anope::string &address, int pport) 161 { 162 this->clear(); 163 164 switch (type) 165 { 166 case AF_INET: 167 { 168 int i = inet_pton(type, address.c_str(), &sa4.sin_addr); 169 if (i <= 0) 170 this->clear(); 171 else 172 { 173 sa4.sin_family = type; 174 sa4.sin_port = htons(pport); 175 } 176 break; 177 } 178 case AF_INET6: 179 { 180 int i = inet_pton(type, address.c_str(), &sa6.sin6_addr); 181 if (i <= 0) 182 this->clear(); 183 else 184 { 185 sa6.sin6_family = type; 186 sa6.sin6_port = htons(pport); 187 } 188 break; 189 } 190 default: 191 break; 192 } 193 } 194 195 void sockaddrs::ntop(int type, const void *src) 196 { 197 char buf[INET6_ADDRSTRLEN]; 198 199 if (inet_ntop(type, src, buf, sizeof(buf)) != buf) 200 { 201 this->clear(); 202 return; 203 } 204 205 switch (type) 206 { 207 case AF_INET: 208 sa4.sin_addr = *reinterpret_cast<const in_addr *>(src); 209 sa4.sin_family = type; 210 return; 211 case AF_INET6: 212 sa6.sin6_addr = *reinterpret_cast<const in6_addr *>(src); 213 sa6.sin6_family = type; 214 return; 215 default: 216 break; 217 } 218 219 this->clear(); 220 } 221 222 cidr::cidr(const Anope::string &ip) 223 { 224 bool ipv6 = ip.find(':') != Anope::string::npos; 225 size_t sl = ip.find_last_of('/'); 226 227 if (sl == Anope::string::npos) 228 { 229 this->cidr_ip = ip; 230 this->cidr_len = ipv6 ? 128 : 32; 231 this->addr.pton(ipv6 ? AF_INET6 : AF_INET, ip); 232 } 233 else 234 { 235 Anope::string real_ip = ip.substr(0, sl); 236 Anope::string cidr_range = ip.substr(sl + 1); 237 238 this->cidr_ip = real_ip; 239 this->cidr_len = ipv6 ? 128 : 32; 240 try 241 { 242 if (cidr_range.is_pos_number_only()) 243 this->cidr_len = convertTo<unsigned int>(cidr_range); 244 } 245 catch (const ConvertException &) { } 246 this->addr.pton(ipv6 ? AF_INET6 : AF_INET, real_ip); 247 } 248 } 249 250 cidr::cidr(const Anope::string &ip, unsigned char len) 251 { 252 bool ipv6 = ip.find(':') != Anope::string::npos; 253 this->addr.pton(ipv6 ? AF_INET6 : AF_INET, ip); 254 this->cidr_ip = ip; 255 this->cidr_len = len; 256 } 257 258 cidr::cidr(const sockaddrs &a, unsigned char len) : addr(a) 259 { 260 this->cidr_ip = a.addr(); 261 this->cidr_len = len; 262 } 263 264 Anope::string cidr::mask() const 265 { 266 if ((this->addr.ipv6() && this->cidr_len == 128) || (!this->addr.ipv6() && this->cidr_len == 32)) 267 return this->cidr_ip; 268 else 269 return Anope::printf("%s/%d", this->cidr_ip.c_str(), this->cidr_len); 270 } 271 272 bool cidr::match(const sockaddrs &other) 273 { 274 if (!valid() || !other.valid() || this->addr.sa.sa_family != other.sa.sa_family) 275 return false; 276 277 const uint8_t *ip, *their_ip; 278 uint8_t byte, len = this->cidr_len; 279 280 switch (this->addr.sa.sa_family) 281 { 282 case AF_INET: 283 ip = reinterpret_cast<const uint8_t *>(&this->addr.sa4.sin_addr); 284 if (len > 32) 285 len = 32; 286 byte = len / 8; 287 their_ip = reinterpret_cast<const uint8_t *>(&other.sa4.sin_addr); 288 break; 289 case AF_INET6: 290 ip = reinterpret_cast<const uint8_t *>(&this->addr.sa6.sin6_addr); 291 if (len > 128) 292 len = 128; 293 byte = len / 8; 294 their_ip = reinterpret_cast<const uint8_t *>(&other.sa6.sin6_addr); 295 break; 296 default: 297 return false; 298 } 299 300 if (memcmp(ip, their_ip, byte)) 301 return false; 302 303 ip += byte; 304 their_ip += byte; 305 306 byte = len % 8; 307 if (byte) 308 { 309 uint8_t m = ~0 << (8 - byte); 310 return (*ip & m) == (*their_ip & m); 311 } 312 313 return true; 314 } 315 316 bool cidr::operator<(const cidr &other) const 317 { 318 if (this->addr.sa.sa_family != other.addr.sa.sa_family) 319 return this->addr.sa.sa_family < other.addr.sa.sa_family; 320 321 switch (this->addr.sa.sa_family) 322 { 323 case AF_INET: 324 { 325 unsigned int m = 0xFFFFFFFFU >> (32 - this->cidr_len); 326 327 return (this->addr.sa4.sin_addr.s_addr & m) < (other.addr.sa4.sin_addr.s_addr & m); 328 } 329 case AF_INET6: 330 { 331 int i = memcmp(&this->addr.sa6.sin6_addr.s6_addr, &other.addr.sa6.sin6_addr.s6_addr, this->cidr_len / 8); 332 if (i || this->cidr_len >= 128) 333 return i < 0; 334 335 // Now all thats left is to compare 'remaining' bits at offset this->cidr_len / 8 336 int remaining = this->cidr_len % 8; 337 unsigned char m = 0xFF << (8 - remaining); 338 339 return (this->addr.sa6.sin6_addr.s6_addr[this->cidr_len / 8] & m) < (other.addr.sa6.sin6_addr.s6_addr[this->cidr_len / 8] & m); 340 } 341 default: 342 throw CoreException("Unknown AFTYPE for cidr"); 343 } 344 } 345 346 bool cidr::operator==(const cidr &other) const 347 { 348 return !(*this < other) && !(other < *this); 349 } 350 351 bool cidr::operator!=(const cidr &other) const 352 { 353 return !(*this == other); 354 } 355 356 bool cidr::valid() const 357 { 358 return this->addr.valid(); 359 } 360 361 size_t cidr::hash::operator()(const cidr &s) const 362 { 363 switch (s.addr.sa.sa_family) 364 { 365 case AF_INET: 366 { 367 unsigned int m = 0xFFFFFFFFU >> (32 - s.cidr_len); 368 return s.addr.sa4.sin_addr.s_addr & m; 369 } 370 case AF_INET6: 371 { 372 size_t h = 0; 373 374 for (unsigned i = 0; i < s.cidr_len / 8; ++i) 375 h ^= (s.addr.sa6.sin6_addr.s6_addr[i] << ((i * 8) % sizeof(size_t))); 376 377 int remaining = s.cidr_len % 8; 378 unsigned char m = 0xFF << (8 - remaining); 379 380 h ^= s.addr.sa6.sin6_addr.s6_addr[s.cidr_len / 8] & m; 381 382 return h; 383 } 384 default: 385 throw CoreException("Unknown AFTYPE for cidr"); 386 } 387 } 388 389 int SocketIO::Recv(Socket *s, char *buf, size_t sz) 390 { 391 int i = recv(s->GetFD(), buf, sz, 0); 392 if (i > 0) 393 TotalRead += i; 394 return i; 395 } 396 397 int SocketIO::Send(Socket *s, const char *buf, size_t sz) 398 { 399 int i = send(s->GetFD(), buf, sz, 0); 400 if (i > 0) 401 TotalWritten += i; 402 return i; 403 } 404 405 int SocketIO::Send(Socket *s, const Anope::string &buf) 406 { 407 return this->Send(s, buf.c_str(), buf.length()); 408 } 409 410 ClientSocket *SocketIO::Accept(ListenSocket *s) 411 { 412 sockaddrs conaddr; 413 414 socklen_t size = sizeof(conaddr); 415 int newsock = accept(s->GetFD(), &conaddr.sa, &size); 416 417 if (newsock >= 0) 418 { 419 ClientSocket *ns = s->OnAccept(newsock, conaddr); 420 ns->flags[SF_ACCEPTED] = true; 421 ns->OnAccept(); 422 return ns; 423 } 424 else 425 throw SocketException("Unable to accept connection: " + Anope::LastError()); 426 } 427 428 SocketFlag SocketIO::FinishAccept(ClientSocket *cs) 429 { 430 return SF_ACCEPTED; 431 } 432 433 void SocketIO::Bind(Socket *s, const Anope::string &ip, int port) 434 { 435 s->bindaddr.pton(s->IsIPv6() ? AF_INET6 : AF_INET, ip, port); 436 if (bind(s->GetFD(), &s->bindaddr.sa, s->bindaddr.size()) == -1) 437 throw SocketException("Unable to bind to address: " + Anope::LastError()); 438 } 439 440 void SocketIO::Connect(ConnectionSocket *s, const Anope::string &target, int port) 441 { 442 s->flags[SF_CONNECTING] = s->flags[SF_CONNECTED] = false; 443 s->conaddr.pton(s->IsIPv6() ? AF_INET6 : AF_INET, target, port); 444 int c = connect(s->GetFD(), &s->conaddr.sa, s->conaddr.size()); 445 if (c == -1) 446 { 447 if (!SocketEngine::IgnoreErrno()) 448 s->OnError(Anope::LastError()); 449 else 450 { 451 SocketEngine::Change(s, true, SF_WRITABLE); 452 s->flags[SF_CONNECTING] = true; 453 } 454 } 455 else 456 { 457 s->flags[SF_CONNECTED] = true; 458 s->OnConnect(); 459 } 460 } 461 462 SocketFlag SocketIO::FinishConnect(ConnectionSocket *s) 463 { 464 if (s->flags[SF_CONNECTED]) 465 return SF_CONNECTED; 466 else if (!s->flags[SF_CONNECTING]) 467 throw SocketException("SocketIO::FinishConnect called for a socket not connected nor connecting?"); 468 469 int optval = 0; 470 socklen_t optlen = sizeof(optval); 471 if (!getsockopt(s->GetFD(), SOL_SOCKET, SO_ERROR, reinterpret_cast<char *>(&optval), &optlen) && !optval) 472 { 473 s->flags[SF_CONNECTED] = true; 474 s->flags[SF_CONNECTING] = false; 475 s->OnConnect(); 476 return SF_CONNECTED; 477 } 478 else 479 { 480 errno = optval; 481 s->OnError(optval ? Anope::LastError() : ""); 482 return SF_DEAD; 483 } 484 } 485 486 Socket::Socket() 487 { 488 throw CoreException("Socket::Socket() ?"); 489 } 490 491 Socket::Socket(int s, bool i, int type) 492 { 493 this->io = &NormalSocketIO; 494 this->ipv6 = i; 495 if (s == -1) 496 this->sock = socket(this->ipv6 ? AF_INET6 : AF_INET, type, 0); 497 else 498 this->sock = s; 499 this->SetBlocking(false); 500 SocketEngine::Sockets[this->sock] = this; 501 SocketEngine::Change(this, true, SF_READABLE); 502 } 503 504 Socket::~Socket() 505 { 506 SocketEngine::Change(this, false, SF_READABLE); 507 SocketEngine::Change(this, false, SF_WRITABLE); 508 anope_close(this->sock); 509 this->io->Destroy(); 510 SocketEngine::Sockets.erase(this->sock); 511 } 512 513 int Socket::GetFD() const 514 { 515 return sock; 516 } 517 518 bool Socket::IsIPv6() const 519 { 520 return ipv6; 521 } 522 523 bool Socket::SetBlocking(bool state) 524 { 525 int f = fcntl(this->GetFD(), F_GETFL, 0); 526 if (state) 527 return !fcntl(this->GetFD(), F_SETFL, f & ~O_NONBLOCK); 528 else 529 return !fcntl(this->GetFD(), F_SETFL, f | O_NONBLOCK); 530 } 531 532 void Socket::Bind(const Anope::string &ip, int port) 533 { 534 this->io->Bind(this, ip, port); 535 } 536 537 bool Socket::Process() 538 { 539 return true; 540 } 541 542 bool Socket::ProcessRead() 543 { 544 return true; 545 } 546 547 bool Socket::ProcessWrite() 548 { 549 return true; 550 } 551 552 void Socket::ProcessError() 553 { 554 } 555 556 ListenSocket::ListenSocket(const Anope::string &bindip, int port, bool i) 557 { 558 this->SetBlocking(false); 559 560 const int op = 1; 561 setsockopt(this->GetFD(), SOL_SOCKET, SO_REUSEADDR, reinterpret_cast<const char *>(&op), sizeof(op)); 562 563 this->bindaddr.pton(i ? AF_INET6 : AF_INET, bindip, port); 564 this->io->Bind(this, bindip, port); 565 566 if (listen(sock, SOMAXCONN) == -1) 567 throw SocketException("Unable to listen: " + Anope::LastError()); 568 } 569 570 ListenSocket::~ListenSocket() 571 { 572 } 573 574 bool ListenSocket::ProcessRead() 575 { 576 try 577 { 578 this->io->Accept(this); 579 } 580 catch (const SocketException &ex) 581 { 582 Log() << ex.GetReason(); 583 } 584 return true; 585 } 586 587 int SocketEngine::GetLastError() 588 { 589 #ifndef _WIN32 590 return errno; 591 #else 592 return WSAGetLastError(); 593 #endif 594 } 595 596 void SocketEngine::SetLastError(int err) 597 { 598 #ifndef _WIN32 599 errno = err; 600 #else 601 WSASetLastError(err); 602 #endif 603 } 604 605 bool SocketEngine::IgnoreErrno() 606 { 607 return GetLastError() == EAGAIN 608 || GetLastError() == EWOULDBLOCK 609 || GetLastError() == EINTR 610 || GetLastError() == EINPROGRESS; 611 }