summaryrefslogtreecommitdiff
path: root/include/socket.h
blob: f79d9166e50d1450750c99cdb4510236df6f77dc (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
/*       +------------------------------------+
 *       | Inspire Internet Relay Chat Daemon |
 *       +------------------------------------+
 *
 *  InspIRCd: (C) 2002-2009 InspIRCd Development Team
 * See: http://wiki.inspircd.org/Credits
 *
 * This program is free but copyrighted software; see
 *            the file COPYING for details.
 *
 * ---------------------------------------------------
 */

#ifndef INSPIRCD_SOCKET_H
#define INSPIRCD_SOCKET_H

#ifndef WIN32

#include <arpa/inet.h>
#include <sys/time.h>
#include <sys/resource.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <sys/stat.h>
#include <netinet/in.h>
#include <unistd.h>
#include <fcntl.h>
#include <netdb.h>

#else

#include "inspircd_win32wrapper.h"

#endif

#include <cerrno>

/* Contains irc-specific definitions */
namespace irc
{
	/** This namespace contains various protocol-independent helper classes.
	 * It also contains some types which are often used by the core and modules
	 * in place of inet_* functions and types.
	 */
	namespace sockets
	{
		union CoreExport sockaddrs {
			struct sockaddr sa;
			struct sockaddr_in in4;
			struct sockaddr_in6 in6;
			/** Return the size of the structure for syscall passing */
			int sa_size() const;
			/** Return port number or -1 if invalid */
			int port() const;
			/** Return IP only */
			std::string addr() const;
			/** Return human-readable IP/port pair */
			std::string str() const;
		};

		struct cidr_mask
		{
			/** Type, AF_INET or AF_INET6 */
			unsigned char type;
			/** Length of the mask in bits (0-128) */
			unsigned char length;
			/** Raw bits. Unused bits must be zero */
			unsigned char bits[16];

			cidr_mask() {}
			/** Construct a CIDR mask from the string. Will normalize (127.0.0.1/8 => 127.0.0.0/8). */
			cidr_mask(const std::string& mask);
			/** Construct a CIDR mask of a given length from the given address */
			cidr_mask(const irc::sockets::sockaddrs& addr, int len);
			/** Equality of bits, type, and length */
			bool operator==(const cidr_mask& other) const;
			/** Ordering defined for maps */
			bool operator<(const cidr_mask& other) const;
			/** Match within this CIDR? */
			bool match(const irc::sockets::sockaddrs& addr) const;
			/** Human-readable string */
			std::string str() const;
		};

		/** Match CIDR, including an optional username/nickname part.
		 *
		 * This function will compare a human-readable address (plus
		 * optional username and nickname) against a human-readable
		 * CIDR mask, for example joe!bloggs\@1.2.3.4 against
		 * *!bloggs\@1.2.0.0/16. This method supports both IPV4 and
		 * IPV6 addresses.
		 * @param address The human readable address, e.g. fred\@1.2.3.4
		 * @param cidr_mask The human readable mask, e.g. *\@1.2.0.0/16
		 * @return True if the mask matches the address
		 */
		CoreExport bool MatchCIDR(const std::string &address, const std::string &cidr_mask, bool match_with_username);

		/** Return the size of the structure for syscall passing */
		inline int sa_size(const irc::sockets::sockaddrs& sa) { return sa.sa_size(); }

		/** Convert an address-port pair into a binary sockaddr
		 * @param addr The IP address, IPv4 or IPv6
		 * @param port The port, 0 for unspecified
		 * @param sa The structure to place the result in. Will be zeroed prior to conversion
		 * @return true if the conversion was successful, false if not.
		 */
		CoreExport bool aptosa(const std::string& addr, int port, irc::sockets::sockaddrs& sa);

		/** Convert a binary sockaddr to an address-port pair
		 * @param sa The structure to convert
		 * @param addr the IP address
		 * @param port the port
		 * @return true if the conversion was successful, false if unknown address family
		 */
		CoreExport bool satoap(const irc::sockets::sockaddrs& sa, std::string& addr, int &port);

		/** Convert a binary sockaddr to a user-readable string.
		 * This means IPv6 addresses are written as [::1]:6667, and *:6668 is used for 0.0.0.0:6668
		 * @param sa The structure to convert
		 * @return The string; "<unknown>" if not a valid address
		 */
		inline std::string satouser(const irc::sockets::sockaddrs& sa) { return sa.str(); }
	}
}

#include "socketengine.h"
/** This class handles incoming connections on client ports.
 * It will create a new User for every valid connection
 * and assign it a file descriptor.
 */
class CoreExport ListenSocket : public EventHandler
{
 public:
	const reference<ConfigTag> bind_tag;
	std::string bind_addr;
	int bind_port;
	/** Human-readable bind description */
	std::string bind_desc;
	/** Create a new listening socket
	 */
	ListenSocket(ConfigTag* tag, const std::string& addr, int port);
	/** Handle an I/O event
	 */
	void HandleEvent(EventType et, int errornum = 0);
	/** Close the socket
	 */
	~ListenSocket();

	/** Handles sockets internals crap of a connection, convenience wrapper really
	 */
	void AcceptInternal();
};

#endif