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 }