00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017 using namespace std;
00018
00019 #include "inspircd_config.h"
00020 #include "servers.h"
00021 #include "inspircd.h"
00022 #include <unistd.h>
00023 #include <fcntl.h>
00024 #include <poll.h>
00025 #include <sys/errno.h>
00026 #include <sys/ioctl.h>
00027 #include <sys/utsname.h>
00028 #include <vector>
00029 #include <string>
00030 #include <deque>
00031 #include <sstream>
00032 #include <map>
00033 #include "inspstring.h"
00034 #include "helperfuncs.h"
00035 #include "connection.h"
00036
00037 extern time_t TIME;
00038 extern int MaxConn;
00039
00040 std::deque<std::string> xsums;
00041
00042 serverrec::serverrec()
00043 {
00044 strlcpy(name,"",256);
00045 pingtime = 0;
00046 lastping = TIME;
00047 usercount_i = usercount = opercount = version = 0;
00048 hops_away = 1;
00049 signon = TIME;
00050 jupiter = false;
00051 fd = 0;
00052 sync_soon = false;
00053 strlcpy(nickserv,"",NICKMAX);
00054 connectors.clear();
00055 }
00056
00057
00058 serverrec::~serverrec()
00059 {
00060 }
00061
00062 serverrec::serverrec(char* n, long ver, bool jupe)
00063 {
00064 strlcpy(name,n,256);
00065 lastping = TIME;
00066 usercount_i = usercount = opercount = 0;
00067 version = ver;
00068 hops_away = 1;
00069 signon = TIME;
00070 jupiter = jupe;
00071 fd = 0;
00072 sync_soon = false;
00073 strlcpy(nickserv,"",NICKMAX);
00074 connectors.clear();
00075 }
00076
00077 bool serverrec::CreateListener(char* newhost, int p)
00078 {
00079 sockaddr_in host_address;
00080 int flags;
00081 in_addr addy;
00082 int on = 0;
00083 struct linger linger = { 0 };
00084
00085 this->port = p;
00086
00087 fd = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
00088 if (fd <= 0)
00089 {
00090 return false;
00091 }
00092
00093 setsockopt(fd,SOL_SOCKET,SO_REUSEADDR,(const char*)&on,sizeof(on));
00094 linger.l_onoff = 1;
00095 linger.l_linger = 1;
00096 setsockopt(fd,SOL_SOCKET,SO_LINGER,(const char*)&linger,sizeof(linger));
00097
00098
00099
00100 int sendbuf = 32768;
00101 int recvbuf = 32768;
00102 setsockopt(fd,SOL_SOCKET,SO_SNDBUF,(const void *)&sendbuf,sizeof(sendbuf));
00103 setsockopt(fd,SOL_SOCKET,SO_RCVBUF,(const void *)&recvbuf,sizeof(sendbuf));
00104
00105 memset((void*)&host_address, 0, sizeof(host_address));
00106
00107 host_address.sin_family = AF_INET;
00108
00109 if (!strcmp(newhost,""))
00110 {
00111 host_address.sin_addr.s_addr = htonl(INADDR_ANY);
00112 }
00113 else
00114 {
00115 inet_aton(newhost,&addy);
00116 host_address.sin_addr = addy;
00117 }
00118
00119 host_address.sin_port = htons(p);
00120
00121 if (bind(fd,(sockaddr*)&host_address,sizeof(host_address))<0)
00122 {
00123 return false;
00124 }
00125
00126
00127 flags = fcntl(fd, F_GETFL, 0);
00128 fcntl(fd, F_SETFL, flags | O_NONBLOCK);
00129
00130 this->port = p;
00131
00132 listen(this->fd, MaxConn);
00133
00134 return true;
00135 }
00136
00137
00138 bool serverrec::BeginLink(char* targethost, int newport, char* password, char* servername, int myport)
00139 {
00140 char connect[MAXBUF];
00141
00142 ircd_connector connector;
00143 ircd_connector *cn = this->FindHost(servername);
00144
00145
00146 if (cn)
00147 {
00148 WriteOpers("CONNECT aborted: Server %s already exists",servername);
00149 return false;
00150 }
00151
00152
00153 if (this->fd)
00154 {
00155 if (connector.MakeOutboundConnection(targethost,newport))
00156 {
00157
00158
00159 connector.SetServerName(servername);
00160 snprintf(connect,MAXBUF,"S %s %s %lu %s :%s",getservername().c_str(),password,(unsigned long)myport,GetRevision().c_str(),getserverdesc().c_str());
00161 connector.SetState(STATE_NOAUTH_OUTBOUND);
00162 connector.SetHostAndPort(targethost, newport);
00163 this->connectors.push_back(connector);
00164 return this->SendPacket(connect, servername);
00165 }
00166 else
00167 {
00168 connector.SetState(STATE_DISCONNECTED);
00169 WriteOpers("Could not create outbound connection to %s:%d",targethost,newport);
00170 }
00171 }
00172 return false;
00173 }
00174
00175
00176 bool serverrec::MeshCookie(char* targethost, int newport, unsigned long cookie, char* servername)
00177 {
00178 char connect[MAXBUF];
00179
00180 ircd_connector connector;
00181
00182 WriteOpers("Establishing meshed link to %s:%d",servername,newport);
00183
00184 if (this->fd)
00185 {
00186 if (connector.MakeOutboundConnection(targethost,newport))
00187 {
00188
00189
00190 connector.SetServerName(servername);
00191 snprintf(connect,MAXBUF,"- %lu %s :%s",cookie,getservername().c_str(),getserverdesc().c_str());
00192 connector.SetState(STATE_NOAUTH_OUTBOUND);
00193 connector.SetHostAndPort(targethost, newport);
00194 connector.SetState(STATE_CONNECTED);
00195 this->connectors.push_back(connector);
00196 return this->SendPacket(connect, servername);
00197 }
00198 else
00199 {
00200 connector.SetState(STATE_DISCONNECTED);
00201 WriteOpers("Could not create outbound connection to %s:%d",targethost,newport);
00202 }
00203 }
00204 return false;
00205 }
00206
00207 bool serverrec::AddIncoming(int newfd, char* targethost, int sourceport)
00208 {
00209 ircd_connector connector;
00210
00211
00212
00213 connector.SetServerName(targethost);
00214 connector.SetDescriptor(newfd);
00215 connector.SetState(STATE_NOAUTH_INBOUND);
00216 int flags = fcntl(newfd, F_GETFL, 0);
00217 fcntl(newfd, F_SETFL, flags | O_NONBLOCK);
00218 int sendbuf = 32768;
00219 int recvbuf = 32768;
00220 setsockopt(newfd,SOL_SOCKET,SO_SNDBUF,(const void *)&sendbuf,sizeof(sendbuf));
00221 setsockopt(newfd,SOL_SOCKET,SO_RCVBUF,(const void *)&recvbuf,sizeof(sendbuf));
00222 connector.SetHostAndPort(targethost, sourceport);
00223 connector.SetState(STATE_NOAUTH_INBOUND);
00224 log(DEBUG,"serverrec::AddIncoming() Added connection: %s:%d",targethost,sourceport);
00225 this->connectors.push_back(connector);
00226 return true;
00227 }
00228
00229 void serverrec::TerminateLink(char* targethost)
00230 {
00231
00232
00233
00234 }
00235
00236
00237 ircd_connector* serverrec::FindHost(std::string findhost)
00238 {
00239 for (int i = 0; i < this->connectors.size(); i++)
00240 {
00241 if (this->connectors[i].GetServerName() == findhost)
00242 {
00243 return &this->connectors[i];
00244 }
00245 }
00246 return NULL;
00247 }
00248
00249 void serverrec::FlushWriteBuffers()
00250 {
00251 for (int i = 0; i < this->connectors.size(); i++)
00252 {
00253 if (this->connectors[i].GetState() != STATE_DISCONNECTED)
00254 {
00255 if (!this->connectors[i].CheckPing())
00256 {
00257 WriteOpers("*** Lost single connection to %s: Ping timeout",this->connectors[i].GetServerName().c_str());
00258 this->connectors[i].CloseConnection();
00259 this->connectors[i].SetState(STATE_DISCONNECTED);
00260 }
00261 }
00262 if (this->connectors[i].HasBufferedOutput())
00263 {
00264 if (!this->connectors[i].FlushWriteBuf())
00265 {
00266
00267 WriteOpers("*** Lost single connection to %s, link inactive and retrying: %s",this->connectors[i].GetServerName().c_str(),this->connectors[i].GetWriteError().c_str());
00268 this->connectors[i].CloseConnection();
00269 this->connectors[i].SetState(STATE_DISCONNECTED);
00270 }
00271 }
00272 }
00273 }
00274
00275 bool serverrec::SendPacket(char *message, const char* sendhost)
00276 {
00277 if ((!message) || (!sendhost))
00278 return true;
00279
00280 ircd_connector* cn = this->FindHost(sendhost);
00281
00282 if (!strchr(message,'\n'))
00283 {
00284 strlcat(message,"\n",MAXBUF);
00285 }
00286
00287 if (cn)
00288 {
00289 log(DEBUG,"main: serverrec::SendPacket() sent '%s' to %s",message,cn->GetServerName().c_str());
00290
00291 if (cn->GetState() == STATE_DISCONNECTED)
00292 {
00293
00294 if (strncmp(message,"R ",2))
00295 {
00296 log(DEBUG,"Not a double reroute");
00297
00298 for (int k = 0; k < this->connectors.size(); k++)
00299 {
00300 log(DEBUG,"Check connector %d: %s",k,this->connectors[k].GetServerName().c_str());
00301
00302 for (int m = 0; m < this->connectors[k].routes.size(); m++)
00303 {
00304 if (!strcasecmp(this->connectors[k].routes[m].c_str(),sendhost))
00305 {
00306 log(DEBUG,"Found alternative route for packet: %s",this->connectors[k].GetServerName().c_str());
00307 char buffer[MAXBUF];
00308 snprintf(buffer,MAXBUF,"R %s %s",sendhost,message);
00309 this->SendPacket(buffer,this->connectors[k].GetServerName().c_str());
00310 return true;
00311 }
00312 }
00313 }
00314 }
00315 char buffer[MAXBUF];
00316 snprintf(buffer,MAXBUF,"& %s",sendhost);
00317 WriteOpers("*** All connections to %s lost.",sendhost);
00318 NetSendToAllExcept(sendhost,buffer);
00319 DoSplit(sendhost);
00320 return false;
00321 }
00322
00323
00324 if (!cn->AddWriteBuf(message))
00325 {
00326
00327 log(DEBUG,"cn->AddWriteBuf() failed for serverrec::SendPacket(): %s",cn->GetWriteError().c_str());
00328 log(DEBUG,"Disabling connector: %s",cn->GetServerName().c_str());
00329 cn->CloseConnection();
00330 cn->SetState(STATE_DISCONNECTED);
00331 WriteOpers("*** Lost single connection to %s, link inactive and retrying: %s",cn->GetServerName().c_str(),cn->GetWriteError().c_str());
00332
00333 return this->SendPacket(message,sendhost);
00334 }
00335 if (!cn->FlushWriteBuf())
00336 {
00337
00338 log(DEBUG,"cn->FlushWriteBuf() failed for serverrec::SendPacket(): %s",cn->GetWriteError().c_str());
00339 log(DEBUG,"Disabling connector: %s",cn->GetServerName().c_str());
00340 cn->CloseConnection();
00341 cn->SetState(STATE_DISCONNECTED);
00342 WriteOpers("*** Lost single connection to %s, link inactive and retrying: %s",cn->GetServerName().c_str(),cn->GetWriteError().c_str());
00343
00344 return this->SendPacket(message,sendhost);
00345 }
00346 return true;
00347 }
00348 }
00349
00350 bool already_have_sum(std::string sum)
00351 {
00352 for (int i = 0; i < xsums.size(); i++)
00353 {
00354 if (xsums[i] == sum)
00355 {
00356 return true;
00357 }
00358 }
00359 if (xsums.size() >= 128)
00360 {
00361 xsums.pop_front();
00362 }
00363 xsums.push_back(sum);
00364 return false;
00365 }
00366
00367
00368
00369
00370 bool serverrec::RecvPacket(std::deque<std::string> &messages, char* recvhost,std::deque<std::string> &sums)
00371 {
00372 char data[65536];
00373 memset(data, 0, 65536);
00374 for (int i = 0; i < this->connectors.size(); i++)
00375 {
00376 if (this->connectors[i].GetState() != STATE_DISCONNECTED)
00377 {
00378
00379 int rcvsize = 0;
00380
00381
00382
00383 pollfd polls;
00384 polls.fd = this->connectors[i].GetDescriptor();
00385 polls.events = POLLIN;
00386 int ret = poll(&polls,1,1);
00387 if (ret <= 0) continue;
00388
00389 rcvsize = recv(this->connectors[i].GetDescriptor(),data,65000,0);
00390 data[rcvsize] = '\0';
00391 if (rcvsize == -1)
00392 {
00393 if (errno != EAGAIN)
00394 {
00395 log(DEBUG,"recv() failed for serverrec::RecvPacket(): %s",strerror(errno));
00396 log(DEBUG,"Disabling connector: %s",this->connectors[i].GetServerName().c_str());
00397 this->connectors[i].CloseConnection();
00398 this->connectors[i].SetState(STATE_DISCONNECTED);
00399 }
00400 }
00401 int pushed = 0;
00402 if (rcvsize > 0)
00403 {
00404 if (!this->connectors[i].AddBuffer(data))
00405 {
00406 WriteOpers("*** Read buffer for %s exceeds maximum, closing connection!",this->connectors[i].GetServerName().c_str());
00407 this->connectors[i].CloseConnection();
00408 this->connectors[i].SetState(STATE_DISCONNECTED);
00409 }
00410 if (this->connectors[i].BufferIsComplete())
00411 {
00412 this->connectors[i].ResetPing();
00413 while (this->connectors[i].BufferIsComplete())
00414 {
00415 std::string text = this->connectors[i].GetBuffer();
00416 if (text != "")
00417 {
00418 if ((text[0] == ':') && (text.find(" ") != std::string::npos))
00419 {
00420 std::string orig = text;
00421 log(DEBUG,"Original: %s",text.c_str());
00422 std::string sum = text.substr(1,text.find(" ")-1);
00423 text = text.substr(text.find(" ")+1,text.length());
00424 std::string possible_token = text.substr(1,text.find(" ")-1);
00425 if (possible_token.length() > 1)
00426 {
00427 sums.push_back("*");
00428 text = orig;
00429 log(DEBUG,"Non-mesh, non-tokenized string passed up the chain");
00430 }
00431 else
00432 {
00433 log(DEBUG,"Packet sum: '%s'",sum.c_str());
00434 if ((already_have_sum(sum)) && (sum != "*"))
00435 {
00436
00437 continue;
00438 }
00439 sums.push_back(sum.c_str());
00440 }
00441 }
00442 else sums.push_back("*");
00443 messages.push_back(text.c_str());
00444 strlcpy(recvhost,this->connectors[i].GetServerName().c_str(),160);
00445 log(DEBUG,"serverrec::RecvPacket() %d:%s->%s",pushed++,recvhost,text.c_str());
00446 }
00447 }
00448 return true;
00449 }
00450 }
00451 }
00452 }
00453
00454 return false;
00455 }
00456