diff options
| author | Adam <Adam@anope.org> | 2010-09-09 23:43:11 -0400 |
|---|---|---|
| committer | Adam <Adam@anope.org> | 2010-09-09 23:43:11 -0400 |
| commit | 46813ccb8c6ab572b8a9ff0a39afb1d92dc4482b (patch) | |
| tree | 562da502a102230ce207bbe921fdc978ee71e20c /include | |
| parent | fdd196e50b4616ac377bd0ee0ae5ce6c57b657ee (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.h | 5 | ||||
| -rw-r--r-- | include/dns.h | 181 | ||||
| -rw-r--r-- | include/extern.h | 6 | ||||
| -rw-r--r-- | include/services.h | 7 | ||||
| -rw-r--r-- | include/socketengine.h | 4 | ||||
| -rw-r--r-- | include/sockets.h | 76 | ||||
| -rw-r--r-- | include/sysconf.h.cmake | 1 | ||||
| -rw-r--r-- | include/users.h | 8 |
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? */ |
