]> git.netwichtig.de Git - user/henk/code/inspircd.git/blob - src/connection.cpp
Authentication fixes
[user/henk/code/inspircd.git] / src / connection.cpp
1 #include <connection.h>
2 #include <unistd.h>
3 #include <fcntl.h>
4 #include <sys/errno.h>
5 #include <sys/ioctl.h>
6 #include <sys/utsname.h>
7 #include <vector>
8 #include <string>
9 #include <deque>
10 #include "inspircd.h"
11 #include "modules.h"
12
13 using namespace std;
14
15 extern std::vector<Module*> modules;
16 extern std::vector<ircd_module*> factory;
17
18 extern int MODCOUNT;
19
20
21 packet::packet()
22 {
23         srand(time(NULL));
24         id = random();
25 }
26
27 packet::~packet()
28 {
29 }
30
31 connection::connection()
32 {
33         key = GenKey();
34         fd = 0;
35 }
36
37
38 bool connection::CreateListener(char* host, int p)
39 {
40         sockaddr_in host_address;
41         int flags;
42         in_addr addy;
43         int on = 0;
44         struct linger linger = { 0 };
45         
46         fd = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
47         if (fd <= 0)
48         {
49                 return false;
50         }
51
52         memset((void*)&host_address, 0, sizeof(host_address));
53
54         host_address.sin_family = AF_INET;
55
56         if (!strcmp(host,""))
57         {
58                 host_address.sin_addr.s_addr = htonl(INADDR_ANY);
59         }
60         else
61         {
62                 inet_aton(host,&addy);
63                 host_address.sin_addr = addy;
64         }
65
66         host_address.sin_port = htons(p);
67
68         if (bind(fd,(sockaddr*)&host_address,sizeof(host_address))<0)
69         {
70                 return false;
71         }
72
73         // make the socket non-blocking
74         flags = fcntl(fd, F_GETFL, 0);
75         fcntl(fd, F_SETFL, flags | O_NONBLOCK);
76
77         this->port = p;
78
79         setsockopt(fd,SOL_SOCKET,SO_REUSEADDR,(const char*)&on,sizeof(on));
80         linger.l_onoff = 1;
81         linger.l_linger = 0;
82         setsockopt(fd,SOL_SOCKET,SO_LINGER,(const char*)&linger,sizeof(linger));
83         
84         // attempt to increase socket sendq and recvq as high as its possible
85         // to get them on linux.
86         int sendbuf = 32768;
87         int recvbuf = 32768;
88         setsockopt(fd,SOL_SOCKET,SO_SNDBUF,(const void *)&sendbuf,sizeof(sendbuf)); 
89         setsockopt(fd,SOL_SOCKET,SO_RCVBUF,(const void *)&recvbuf,sizeof(sendbuf));
90         
91         listen(this->fd,5);
92
93         return true;
94 }
95
96 bool ircd_connector::SetHostAddress(char* host, int port)
97 {
98         memset((void*)&addr, 0, sizeof(addr));
99         addr.sin_family = AF_INET;
100         inet_aton(host,&addr.sin_addr);
101         addr.sin_port = htons(port);
102         return true;
103 }
104
105 bool ircd_connector::MakeOutboundConnection(char* host, int port)
106 {
107         hostent* hoste = gethostbyname(host);
108         if (!hoste)
109         {
110                 WriteOpers("Failed to look up hostname for %s, using as an ip address",host);
111                 this->SetHostAddress(host,port);
112         }
113         else
114         {
115                 WriteOpers("Found hostname for %s",host);
116                 this->SetHostAddress(hoste->h_addr,port);
117         }
118
119         this->fd = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
120         if (this->fd >= 0)
121         {
122                 if(connect(this->fd, (sockaddr*)&addr,sizeof(addr)))
123                 {
124                         WriteOpers("connect() failed for %s",host);
125                         return false;
126                 }
127                 int flags = fcntl(this->fd, F_GETFL, 0);
128                 fcntl(this->fd, F_SETFL, flags | O_NONBLOCK);
129                 int sendbuf = 32768;
130                 int recvbuf = 32768;
131                 setsockopt(this->fd,SOL_SOCKET,SO_SNDBUF,(const void *)&sendbuf,sizeof(sendbuf)); 
132                 setsockopt(this->fd,SOL_SOCKET,SO_RCVBUF,(const void *)&recvbuf,sizeof(sendbuf));
133                 return true;
134         }
135         else
136         {
137                 WriteOpers("socket() failed!");
138         }
139
140         return false;
141 }
142
143
144 bool connection::BeginLink(char* targethost, int port, char* password, char* servername)
145 {
146         char connect[MAXBUF];
147         
148         ircd_connector connector;
149         
150         if (this->fd)
151         {
152                 if (connector.MakeOutboundConnection(targethost,port))
153                 {
154                         // targethost has been turned into an ip...
155                         // we dont want this as the server name.
156                         connector.SetServerName(servername);
157                         sprintf(connect,"S %s %s :%s",getservername().c_str(),password,getserverdesc().c_str());
158                         connector.SetState(STATE_NOAUTH_OUTBOUND);
159                         this->connectors.push_back(connector);
160                         return this->SendPacket(connect, servername);
161                 }
162                 else
163                 {
164                         WriteOpers("Could not create outbound connection to %s:%d",targethost,port);
165                 }
166         }
167         return false;
168 }
169
170 bool connection::AddIncoming(int fd,char* targethost)
171 {
172         char connect[MAXBUF];
173         
174         ircd_connector connector;
175         
176         // targethost has been turned into an ip...
177         // we dont want this as the server name.
178         connector.SetServerName(targethost);
179         connector.SetDescriptor(fd);
180         connector.SetState(STATE_NOAUTH_INBOUND);
181         this->connectors.push_back(connector);
182         return true;
183 }
184
185 void connection::TerminateLink(char* targethost)
186 {
187         // this locates the targethost in the connection::connectors vector of the class,
188         // and terminates it by sending it an SQUIT token and closing its descriptor.
189         // TerminateLink with a null string causes a terminate of ALL links
190 }
191
192
193 // Returns a pointer to the connector for 'host'
194 ircd_connector* connection::FindHost(std::string host)
195 {
196         for (int i = 0; i < this->connectors.size(); i++)
197         {
198                 if (this->connectors[i].GetServerName() == host)
199                 {
200                         return &this->connectors[i];
201                 }
202         }
203         return NULL;
204 }
205
206 std::string ircd_connector::GetServerName()
207 {
208         return this->servername;
209 }
210
211 void ircd_connector::SetServerName(std::string serv)
212 {
213         this->servername = serv;
214 }
215
216
217 int ircd_connector::GetDescriptor()
218 {
219         return this->fd;
220 }
221
222 int ircd_connector::GetState()
223 {
224         return this->state;
225 }
226
227
228 void ircd_connector::SetState(int state)
229 {
230         this->state = state;
231 }
232
233 void ircd_connector::SetDescriptor(int fd)
234 {
235         this->fd = fd;
236 }
237
238 bool connection::SendPacket(char *message, char* host)
239 {
240         ircd_connector* cn = this->FindHost(host);
241         
242         if (cn)
243         {
244                 log(DEBUG,"main: Connection::SendPacket() sent '%s' to %s",message,cn->GetServerName().c_str());
245
246                 strncat(message,"\n",MAXBUF);
247                 // returns false if the packet could not be sent (e.g. target host down)
248                 if (send(cn->GetDescriptor(),message,strlen(message),0)<0)
249                 {
250                         log(DEBUG,"send() failed for Connection::SendPacket(): %s",strerror(errno));
251                         return false;
252                 }
253                 return true;
254         }
255 }
256
257 // receives a packet from any where there is data waiting, first come, first served
258 // fills the message and host values with the host where the data came from.
259
260 bool connection::RecvPacket(std::deque<std::string> &messages, char* host)
261 {
262         char data[32767];
263         memset(data, 0, 32767);
264         for (int i = 0; i < this->connectors.size(); i++)
265         {
266                 // returns false if the packet could not be sent (e.g. target host down)
267                 int rcvsize = 0;
268                 if (rcvsize = recv(this->connectors[i].GetDescriptor(),data,32767,0))
269                 {
270                         if (rcvsize > 0)
271                         {
272                                 char* l = strtok(data,"\n");
273                                 while (l)
274                                 {
275                                         char sanitized[32767];
276                                         memset(sanitized, 0, 32767);
277                                         int ptt = 0;
278                                         for (int pt = 0; pt < strlen(l); pt++)
279                                         {
280                                                 if (l[pt] != '\r')
281                                                 {
282                                                         sanitized[ptt++] = l[pt];
283                                                 }
284                                         }
285                                         sanitized[ptt] = '\0';
286                                         if (strlen(sanitized))
287                                         {
288                                                 messages.push_back(sanitized);
289                                                 strncpy(host,this->connectors[i].GetServerName().c_str(),160);
290                                                 log(DEBUG,"main: Connection::RecvPacket() got '%s' from %s",sanitized,host);
291                                                 
292                                         }
293                                         l = strtok(NULL,"\n");
294                                 }
295                                 return true;
296                         }
297                 }
298         }
299         // nothing new yet -- message and host will be undefined
300         return false;
301 }
302
303 long connection::GenKey()
304 {
305         srand(time(NULL));
306         return (random()*time(NULL));
307 }
308