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