summaryrefslogtreecommitdiff
path: root/include
diff options
context:
space:
mode:
authorAdam <Adam@anope.org>2010-09-09 23:43:11 -0400
committerAdam <Adam@anope.org>2010-09-09 23:43:11 -0400
commit46813ccb8c6ab572b8a9ff0a39afb1d92dc4482b (patch)
tree562da502a102230ce207bbe921fdc978ee71e20c /include
parentfdd196e50b4616ac377bd0ee0ae5ce6c57b657ee (diff)
Added an asynchronous DNS system and m_dnsbl, which checks clients against DNS blacklists.
Rewrote internal handling of IPs, we now properly support users using IPv6. Fixed a few problems with the UnrealIRCd protocol module.
Diffstat (limited to 'include')
-rw-r--r--include/config.h5
-rw-r--r--include/dns.h181
-rw-r--r--include/extern.h6
-rw-r--r--include/services.h7
-rw-r--r--include/socketengine.h4
-rw-r--r--include/sockets.h76
-rw-r--r--include/sysconf.h.cmake1
-rw-r--r--include/users.h8
8 files changed, 265 insertions, 23 deletions
diff --git a/include/config.h b/include/config.h
index 11969707f..4ea2aae23 100644
--- a/include/config.h
+++ b/include/config.h
@@ -572,6 +572,11 @@ class ServerConfig
/* Don't quote the To: address */
bool DontQuoteAddresses;
+ /* Nameserver to use for resolving hostnames */
+ Anope::string NameServer;
+ /* TIme before a DNS query is considered dead */
+ time_t DNSTimeout;
+
/* Prefix of guest nicks when a user gets forced off of a nick */
Anope::string NSGuestNickPrefix;
/* Allow users to set kill immed on */
diff --git a/include/dns.h b/include/dns.h
new file mode 100644
index 000000000..a8ef82d44
--- /dev/null
+++ b/include/dns.h
@@ -0,0 +1,181 @@
+#ifndef DNS_H
+#define DNS_H
+
+/** Valid query types
+ */
+enum QueryType
+{
+ /* Nothing */
+ DNS_QUERY_NONE,
+ /* A simple A lookup */
+ DNS_QUERY_A = 1,
+ /* A CNAME lookup */
+ DNS_QUERY_CNAME = 5,
+ /* Reverse DNS lookup */
+ DNS_QUERY_PTR = 12,
+ /* IPv6 AAAA lookup */
+ DNS_QUERY_AAAA = 28
+};
+
+/** Flags that can be AND'd into DNSPacket::flags to receive certain values
+ */
+enum QueryFlags
+{
+ DNS_QUERYFLAGS_QR = 0x8000,
+ DNS_QUERYFLAGS_OPCODE = 0x7800,
+ DNS_QUERYFLAGS_AA = 0x400,
+ DBS_QUERYFLAGS_TC = 0x200,
+ DNS_QUERYFLAGS_RD = 0x100,
+ DNS_QUERYFLAGS_RA = 0x80,
+ DNS_QUERYFLAGS_Z = 0x70,
+ DNS_QUERYFLAGS_RCODE = 0xF
+};
+
+enum DNSError
+{
+ DNS_ERROR_UNKNOWN,
+ DNS_ERROR_TIMEOUT,
+ DNS_ERROR_NOT_AN_ANSWER,
+ DNS_ERROR_NONSTANDARD_QUERY,
+ DNS_ERROR_FORMAT_ERROR,
+ DNS_ERROR_SERVER_FAILURE,
+ DNS_ERROR_DOMAIN_NOT_FOUND,
+ DNS_ERROR_NOT_IMPLEMENTED,
+ DNS_ERROR_REFUSED,
+ DNS_ERROR_NO_RECORDS,
+ DNS_ERROR_INVALID_TYPE
+};
+
+class DNSRequestTimeout; // Forward declarations
+struct DNSRecord;
+
+/** The request
+ */
+class DNSRequest
+{
+ /* Timeout timer for this request */
+ DNSRequestTimeout *timeout;
+
+ public:
+ /* Address we're looking up */
+ Anope::string address;
+ /* QueryType, A, AAAA, PTR etc */
+ QueryType QT;
+
+ DNSRequest(const Anope::string &addr, QueryType qt, bool cache = false);
+
+ virtual ~DNSRequest();
+
+ virtual void OnLookupComplete(const DNSRecord *r) = 0;
+
+ virtual void OnError(DNSError error, const Anope::string &message);
+};
+
+/** A full packet sent to the nameserver, may contain multiple queries
+ */
+struct DNSPacket
+{
+ /* Our 16-bit id for this header */
+ unsigned short id;
+ /* Flags on the query */
+ unsigned short flags;
+ /* Number of queries */
+ unsigned short qdcount;
+ /* Number of resource records in answer */
+ unsigned short ancount;
+ /* Number of NS resource records in authority records section */
+ unsigned short nscount;
+ /* Number of resource records in the additional records section */
+ unsigned short arcount;
+ /* How many of the bytes of the payload are in use */
+ unsigned short payload_count;
+ /* The queries, at most can be 512 bytes */
+ unsigned char payload[512];
+
+ inline DNSPacket();
+
+ bool AddQuestion(const Anope::string &address, QueryType qt);
+
+ inline void FillPacket(const unsigned char *input, const size_t length);
+
+ inline void FillBuffer(unsigned char *buffer);
+};
+
+struct DNSRecord
+{
+ /* Name of the initial lookup */
+ Anope::string name;
+ /* Result of the lookup */
+ Anope::string result;
+ /* Type of query this was */
+ QueryType type;
+ /* Record class, should always be 1 */
+ unsigned short record_class;
+ /* Time to live */
+ unsigned long ttl;
+ /* Record length */
+ unsigned short rdlength;
+
+ inline DNSRecord();
+ time_t created;
+};
+
+/** The socket used to talk to the nameserver, uses UDP
+ */
+class DNSSocket : public ClientSocket
+{
+ private:
+ sockaddrs server_addr;
+
+ int SendTo(const unsigned char *buf, size_t len) const;
+ int RecvFrom(char *buf, size_t size, sockaddrs &addrs) const;
+ public:
+ DNSSocket(const Anope::string &nTargetHost, int nPort);
+ virtual ~DNSSocket();
+
+ bool ProcessRead();
+
+ bool ProcessWrite();
+};
+
+/** DNS manager, manages the connection and all requests
+ */
+class DNSManager : public Timer
+{
+ std::multimap<Anope::string, DNSRecord *> cache;
+ public:
+ DNSSocket *sock;
+
+ std::deque<DNSPacket *> packets;
+ std::map<short, DNSRequest *> requests;
+
+ static const int DNSPort = 53;
+
+ DNSManager();
+
+ ~DNSManager();
+
+ void AddCache(DNSRecord *rr);
+ bool CheckCache(DNSRequest *request);
+ void Tick(time_t now);
+};
+
+/** A DNS timeout, one is made for every DNS request to detect timeouts
+ */
+class DNSRequestTimeout : public Timer
+{
+ DNSRequest *request;
+ public:
+ bool done;
+
+ DNSRequestTimeout(DNSRequest *r, time_t timeout);
+
+ ~DNSRequestTimeout();
+
+ void Tick(time_t);
+};
+
+extern DNSManager *DNSEngine;
+
+#endif // DNS_H
+
diff --git a/include/extern.h b/include/extern.h
index 48336be5f..2294c3f28 100644
--- a/include/extern.h
+++ b/include/extern.h
@@ -276,7 +276,6 @@ E uint16 netmask_to_cidr(uint32 mask);
E bool str_is_wildcard(const Anope::string &str);
E bool str_is_pure_wildcard(const Anope::string &str);
-E uint32 str_is_ip(const Anope::string &str);
E bool str_is_cidr(const Anope::string &str, uint32 &ip, uint32 &mask, Anope::string &host);
/**** modes.cpp ****/
@@ -362,7 +361,7 @@ E User *finduser(const Anope::string &nick);
E Anope::string TS6SID;
-E User *do_nick(const Anope::string &source, const Anope::string &nick, const Anope::string &username, const Anope::string &host, const Anope::string &server, const Anope::string &realname, time_t ts, uint32 ip, const Anope::string &vhost, const Anope::string &uid);
+E User *do_nick(const Anope::string &source, const Anope::string &nick, const Anope::string &username, const Anope::string &host, const Anope::string &server, const Anope::string &realname, time_t ts, const Anope::string &ip, const Anope::string &vhost, const Anope::string &uid);
E void do_umode(const Anope::string &source, int ac, const char **av);
E void do_quit(const Anope::string &source, int ac, const char **av);
@@ -382,9 +381,6 @@ E void UserSetInternalModes(User *user, int ac, const char **av);
E void b64_encode(const Anope::string &src, Anope::string &target);
E void b64_decode(const Anope::string &src, Anope::string &target);
-E int decode_ip(const Anope::string &buf);
-
-E Anope::string host_resolve(const Anope::string &host);
#ifdef _WIN32
E Anope::string GetWindowsVersion();
diff --git a/include/services.h b/include/services.h
index f44425656..63e2492b2 100644
--- a/include/services.h
+++ b/include/services.h
@@ -363,6 +363,9 @@ template<typename T, size_t Size = 32> class Flags
#include "sockets.h"
#include "socketengine.h"
+#include "extensible.h"
+#include "timers.h"
+#include "dns.h"
/*************************************************************************/
@@ -427,7 +430,6 @@ class Server;
struct EList;
struct Session;
-#include "extensible.h"
#include "threadengine.h"
#include "opertype.h"
#include "modes.h"
@@ -457,7 +459,6 @@ struct IRCDVar
int vident; /* Supports vidents */
int svshold; /* Supports svshold */
int tsonmode; /* Timestamp on mode changes */
- int nickip; /* Sends IP on NICK */
int omode; /* On the fly o:lines */
int umode; /* change user modes */
int nickvhost; /* Users vhost sent during NICK */
@@ -1054,8 +1055,6 @@ struct Uplink
Uplink(const Anope::string &_host, int _port, const Anope::string &_password, bool _ipv6) : host(_host), port(_port), password(_password), ipv6(_ipv6) { }
};
-#include "timers.h"
-
/** Timer for colliding nicks to force people off of nicknames
*/
class NickServCollide : public Timer
diff --git a/include/socketengine.h b/include/socketengine.h
index 7279ba3ad..c45249810 100644
--- a/include/socketengine.h
+++ b/include/socketengine.h
@@ -43,12 +43,12 @@ class CoreExport SocketEngineBase
/** Mark a socket as writeable
* @param s The socket
*/
- virtual void MarkWriteable(Socket *s) { }
+ virtual void MarkWritable(Socket *s) { }
/** Unmark a socket as writeable
* @param s The socket
*/
- virtual void ClearWriteable(Socket *s) { }
+ virtual void ClearWritable(Socket *s) { }
/** Read from sockets and do things
*/
diff --git a/include/sockets.h b/include/sockets.h
index 6eeb3bf3d..772a08a65 100644
--- a/include/sockets.h
+++ b/include/sockets.h
@@ -22,6 +22,49 @@
# define CloseSocket close
#endif
+/** A sockaddr union used to combine IPv4 and IPv6 sockaddrs
+ */
+union CoreExport sockaddrs
+{
+ sockaddr sa;
+ sockaddr_in sa4;
+ sockaddr_in6 sa6;
+
+ /** Get the size of the sockaddr we represent
+ * @return The size
+ */
+ size_t size() const;
+
+ /** Get the port represented by this addr
+ * @return The port, or -1 on fail
+ */
+ int port() const;
+
+ /** Get the address represented by this addr
+ * @return The address
+ */
+ Anope::string addr() const;
+
+ /** Construct the object, sets everything to 0
+ */
+ sockaddrs();
+
+ /** Check if this sockaddr has data in it
+ */
+ bool operator()() const;
+
+ /** Compares with sockaddr with another. Compares address type, port, and address
+ * @return true if they are the same
+ */
+ bool operator==(const sockaddrs &other) const;
+ /* The same as above but not */
+ inline bool operator!=(const sockaddrs &other) const { return !(*this == other); }
+
+ void pton(int type, const Anope::string &address, int pport = 0);
+
+ void ntop(int type, const void *src);
+};
+
class SocketException : public CoreException
{
public:
@@ -44,12 +87,13 @@ enum SocketType
enum SocketFlag
{
- SF_DEAD
+ SF_DEAD,
+ SF_WRITABLE
};
-class CoreExport Socket : public Flags<SocketFlag, 1>
+class CoreExport Socket : public Flags<SocketFlag, 2>
{
- private:
+ protected:
/** Really recieve something from the buffer
* @param buf The buf to read to
* @param sz How much to read
@@ -63,7 +107,6 @@ class CoreExport Socket : public Flags<SocketFlag, 1>
*/
virtual int SendInternal(const Anope::string &buf) const;
- protected:
/* Socket FD */
int Sock;
/* Port we're connected to */
@@ -88,8 +131,9 @@ class CoreExport Socket : public Flags<SocketFlag, 1>
/** Default constructor
* @param nsock The socket to use, 0 if we need to create our own
* @param nIPv6 true if using ipv6
+ * @param type The socket type, defaults to SOCK_STREAM
*/
- Socket(int nsock, bool nIPv6);
+ Socket(int nsock, bool nIPv6, int type = SOCK_STREAM);
/** Default destructor
*/
@@ -130,7 +174,7 @@ class CoreExport Socket : public Flags<SocketFlag, 1>
*/
virtual bool ProcessRead();
- /** Called when there is something to be written to this socket
+ /** Called when the socket is ready to be written to
* @return true on success, false to drop this socket
*/
virtual bool ProcessWrite();
@@ -156,20 +200,37 @@ class CoreExport Socket : public Flags<SocketFlag, 1>
class CoreExport Pipe : public Socket
{
private:
+ /** The FD of the write pipe (if this isn't evenfd)
+ * this->Sock is the readfd
+ */
int WritePipe;
+ /** Our overloaded RecvInternal call
+ */
int RecvInternal(char *buf, size_t sz) const;
+ /** Our overloaded SendInternal call
+ */
int SendInternal(const Anope::string &buf) const;
public:
+ /** Constructor
+ */
Pipe();
+ /** Called when data is to be read
+ */
bool ProcessRead();
+ /** Function that calls OnNotify
+ */
bool Read(const Anope::string &);
+ /** Called when this pipe needs to be woken up
+ */
void Notify();
+ /** Should be overloaded to do something useful
+ */
virtual void OnNotify();
};
@@ -190,8 +251,9 @@ class CoreExport ClientSocket : public Socket
* @param nPort The target port to connect to
* @param nBindHost The host to bind to for connecting
* @param nIPv6 true to use IPv6
+ * @param type The socket type, defaults to SOCK_STREAM
*/
- ClientSocket(const Anope::string &nTargetHost, int nPort, const Anope::string &nBindHost, bool nIPv6);
+ ClientSocket(const Anope::string &nTargetHost, int nPort, const Anope::string &nBindHost = "", bool nIPv6 = false, int type = SOCK_STREAM);
/** Default destructor
*/
diff --git a/include/sysconf.h.cmake b/include/sysconf.h.cmake
index 0184c5359..2d278e3dd 100644
--- a/include/sysconf.h.cmake
+++ b/include/sysconf.h.cmake
@@ -8,7 +8,6 @@
#cmakedefine HAVE_STDINT_H 1
#cmakedefine HAVE_STDDEF_H 1
#cmakedefine HAVE_BACKTRACE 1
-#cmakedefine HAVE_GETHOSTBYNAME 1
#cmakedefine HAVE_GETTIMEOFDAY 1
#cmakedefine HAVE_SETGRENT 1
#cmakedefine HAVE_STRCASECMP 1
diff --git a/include/users.h b/include/users.h
index 596f5ee39..b880a197a 100644
--- a/include/users.h
+++ b/include/users.h
@@ -51,10 +51,10 @@ class CoreExport User : public Extensible
Anope::string nick; /* User's current nick */
Anope::string host; /* User's real hostname */
- Anope::string hostip; /* User's IP number */
- Anope::string vhost; /* User's virtual hostname */
- Anope::string chost; /* User's cloaked hostname */
- Anope::string realname; /* Realname */
+ Anope::string vhost; /* User's virtual hostname */
+ Anope::string chost; /* User's cloaked hostname */
+ Anope::string realname; /* Realname */
+ sockaddrs ip; /* User's IP */
Server *server; /* Server user is connected to */
time_t timestamp; /* Timestamp of the nick */
time_t my_signon; /* When did _we_ see the user? */