summaryrefslogtreecommitdiff
path: root/include/socket.h
blob: c7b87d583b862984f78ca9750681ebad69961493 (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
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
/*       +------------------------------------+
 *       | 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>
#include "socketengine.h"

/* 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
	{

		typedef union {
			struct sockaddr sa;
			struct sockaddr_in in4;
			struct sockaddr_in6 in6;
		} sockaddrs;

	/* macros to the relevant system address description structs */
#ifdef IPV6
		/** insp_sockaddr for ipv6
		 */
		typedef struct sockaddr_in6 insp_sockaddr;
		/** insp_inaddr for ipv6
		 */
		typedef struct in6_addr     insp_inaddr;
#define AF_FAMILY AF_INET6
#define PF_PROTOCOL PF_INET6

#else
		/** insp_sockaddr for ipv4
		 */
		typedef struct sockaddr_in  insp_sockaddr;
		/** insp_inaddr for ipv4
		 */
		typedef struct in_addr      insp_inaddr;
#define AF_FAMILY AF_INET
#define PF_PROTOCOL PF_INET

#endif
		/** Match raw binary data using CIDR rules.
		 *
		 * This function will use binary comparison to compare the
		 * two bit sequences, address and mask, up to mask_bits
		 * bits in size. If they match, it will return true.
		 * @param address The whole address, of 4 or 16 bytes in length
		 * @param mask The mask, from 1 to 16 bytes in length, anything
		 * from 1 to 128 bits of which is significant
		 * @param mask_Bits How many bits of the mask parameter are significant
		 * for this comparison.
		 * @returns True if the first mask_bits of address matches the first
		 * mask_bits of mask.
		 */
		CoreExport bool MatchCIDRBits(const unsigned char* address, const unsigned char* mask, unsigned int mask_bits);

		/** Match CIDR, without matching username/nickname parts.
		 *
		 * This function will compare a human-readable address against a human-
		 * readable CIDR mask, for example 1.2.3.4 against 1.2.0.0/16. This
		 * method supports both IPV4 and IPV6 addresses.
		 * @param address The human readable address, e.g. 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);

		/** 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);

		/** Convert an insp_inaddr into human readable form.
		 *
		 * @param n An insp_inaddr (IP address) structure
		 * @return A human-readable address. IPV6 addresses
		 * will be shortened to remove fields which are 0.
		 */
		CoreExport const char* insp_ntoa(insp_inaddr n);

		/** Convert a human-readable address into an insp_inaddr.
		 *
		 * @param a A human-readable address
		 * @param n An insp_inaddr struct which the result
		 * will be copied into on success.
		 * @return This method will return a negative value if address
		 * does not contain a valid address family. 0 if the address is
		 * does not contain a valid string representing a valid network
		 * address. A positive value is returned if the network address
		 * was successfully converted.

		 * or any other number upon failure.
		 */
		CoreExport int insp_aton(const char* a, insp_inaddr* n);

		/** Create a new valid file descriptor using socket()
		 * @return On return this function will return a value >= 0 for success,
		 * or a negative value upon failure (negative values are invalid file
		 * descriptors)
		 */
		CoreExport int OpenTCPSocket(const char* addr, int socktype = SOCK_STREAM);

		/** 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 int aptosa(const char* 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 int satoap(const irc::sockets::sockaddrs* sa, std::string& addr, int &port);
	}
}



/** 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 ListenSocketBase : public EventHandler
{
 protected:
	/** The creator/owner of this object
	 */
	InspIRCd* ServerInstance;
	/** Socket description (shown in stats p) */
	std::string desc;

	/** Address socket is bound to */
	std::string bind_addr;
	/** Port socket is bound to */
	int bind_port;

	/** The client address if the most recently connected client.
	 * Should only be used when accepting a new client.
	 */
	static irc::sockets::sockaddrs client;
	/** The server address used by the most recently connected client.
	 * This may differ from the bind address by having a nonzero address,
	 * if the port is wildcard bound, or being IPv4 on a 6to4 IPv6 port.
	 * The address family will always match that of "client"
	 */
	static irc::sockets::sockaddrs server;
 public:
	/** Create a new listening socket
	 */
	ListenSocketBase(InspIRCd* Instance, int port, const std::string &addr);
	/** Handle an I/O event
	 */
	void HandleEvent(EventType et, int errornum = 0);
	/** Close the socket
	 */
	~ListenSocketBase();
	/** Set descriptive text
	 */
	void SetDescription(const std::string &description)
	{
		desc = description;
	}
	/** Get description for socket
	 */
	const std::string& GetDescription()
	{
		return desc;
	}
	/** Get port number for socket
	 */
	int GetPort() { return bind_port; }

	/** Get IP address socket is bound to
	 */
	const std::string &GetIP() { return bind_addr; }

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

	/** Called when a new connection has successfully been accepted on this listener.
	 * @param ipconnectedto The IP address the connection arrived on
	 * @param fd The file descriptor of the new connection
	 * @param incomingip The IP from which the connection was made
	 */
	virtual void OnAcceptReady(const std::string &ipconnectedto, int fd, const std::string &incomingip) = 0;
};

class CoreExport ClientListenSocket : public ListenSocketBase
{
	virtual void OnAcceptReady(const std::string &ipconnectedto, int fd, const std::string &incomingip);
 public:
	ClientListenSocket(InspIRCd* Instance, int port, const std::string &addr) : ListenSocketBase(Instance, port, addr) { }
};

#endif