1 #include <connection.h>
6 #include <sys/utsname.h>
10 extern std::vector<Module*> modules;
11 extern std::vector<ircd_module*> factory;
25 connection::connection()
32 bool connection::CreateListener(char* host, int p)
34 sockaddr_in host_address;
38 struct linger linger = { 0 };
40 fd = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP);
46 memset((void*)&host_address, 0, sizeof(host_address));
48 host_address.sin_family = AF_INET;
52 host_address.sin_addr.s_addr = htonl(INADDR_ANY);
56 inet_aton(host,&addy);
57 host_address.sin_addr = addy;
60 host_address.sin_port = htons(p);
62 if (bind(fd,(sockaddr*)&host_address,sizeof(host_address))<0)
67 // make the socket non-blocking
68 flags = fcntl(fd, F_GETFL, 0);
69 fcntl(fd, F_SETFL, flags | O_NONBLOCK);
73 setsockopt(fd,SOL_SOCKET,SO_REUSEADDR,(const char*)&on,sizeof(on));
76 setsockopt(fd,SOL_SOCKET,SO_LINGER,(const char*)&linger,sizeof(linger));
78 // attempt to increase socket sendq and recvq as high as its possible
79 // to get them on linux.
82 setsockopt(fd,SOL_SOCKET,SO_SNDBUF,(const void *)&sendbuf,sizeof(sendbuf));
83 setsockopt(fd,SOL_SOCKET,SO_RCVBUF,(const void *)&recvbuf,sizeof(sendbuf));
89 bool connection::BeginLink(char* targethost, int port, char* password)
95 sprintf(connect,"S %s %s :%s",getservername().c_str(),password,getserverdesc().c_str());
96 this->haspassed = false;
97 return this->SendPacket(connect, targethost, port, 0);
102 // targethost: in dot notation a.b.c.d
103 void connection::TerminateLink(char* targethost)
107 // host: in dot notation a.b.c.d
108 // port: host byte order
109 bool connection::SendPacket(char *message, char* host, int port, long ourkey)
111 sockaddr_in host_address;
115 memset((void*)&host_address, 0, sizeof(host_address));
117 host_address.sin_family = AF_INET;
118 inet_aton(host,&addy);
119 host_address.sin_addr = addy;
121 host_address.sin_port = htons(port);
123 strcpy(p.data,message);
124 p.type = PT_SYN_WITH_DATA;
128 FOREACH_MOD OnPacketTransmit(p.data);
130 log(DEBUG,"main: Connection::SendPacket() sent '%s' to %s:%d",p.data,host,port);
132 // returns false if the packet could not be sent (e.g. target host down)
133 if (sendto(this->fd,&p,sizeof(p),0,(sockaddr*)&host_address,sizeof(host_address))<0)
135 log(DEBUG,"sendto() failed for Connection::SendPacket() with a packet of size %d",sizeof(p));
142 bool connection::SendSYN(char* host, int port)
144 sockaddr_in host_address;
148 memset((void*)&host_address, 0, sizeof(host_address));
150 host_address.sin_family = AF_INET;
151 inet_aton(host,&addy);
152 host_address.sin_addr = addy;
154 host_address.sin_port = htons(port);
156 p.type = PT_SYN_ONLY;
160 if (sendto(fd,&p,sizeof(p),0,(sockaddr*)&host_address,sizeof(host_address))<0)
168 bool connection::SendACK(char* host, int port, int reply_id)
170 sockaddr_in host_address;
174 memset((void*)&host_address, 0, sizeof(host_address));
176 host_address.sin_family = AF_INET;
177 inet_aton(host,&addy);
178 host_address.sin_addr = addy;
180 host_address.sin_port = htons(port);
182 p.type = PT_ACK_ONLY;
187 if (sendto(fd,&p,sizeof(p),0,(sockaddr*)&host_address,sizeof(host_address))<0)
196 // Generates a server key. This is pseudo-random.
197 // the server always uses the same server-key in all communications
198 // across the network. All other servers must remember the server key
199 // of servers in the network, e.g.:
201 // ServerA: key=5555555555
202 // ServerB: key=6666666666
203 // I am ServerC: key=77777777777
205 // If ServerC sees a packet from ServerA, and the key stored for ServerA
206 // is 0, then cache the key as the servers key.
207 // after this point, any packet from ServerA which does not contain its key,
208 // 555555555, will be silently dropped.
209 // This should prevent blind spoofing, as to fake a server you must know its
210 // assigned key, and to do that you must receive messages that are origintated
211 // from it or hack the running executable.
213 // During the AUTH phase (when server passwords are checked, the key in any
214 // packet MUST be 0). Only the initial SERVER/PASS packets may have a key
215 // of 0 (and any ACK responses to them).
218 long connection::GenKey()
221 return (random()*time(NULL));
224 // host: in dot notation a.b.c.d
225 // port: host byte order
226 bool connection::RecvPacket(char *message, char* host, int &prt, long &theirkey)
228 // returns false if no packet waiting for receive, e.g. EAGAIN or ECONNRESET
229 sockaddr_in host_address;
230 socklen_t host_address_size;
233 memset((void*)&host_address, 0, sizeof(host_address));
235 host_address.sin_family=AF_INET;
236 host_address_size=sizeof(host_address);
238 if (recvfrom(fd,&p,sizeof(p),0,(sockaddr*)&host_address,&host_address_size)<0)
243 log(DEBUG,"connection::RecvPacket(): received packet type %d '%s'",p.type,p.data);
245 if (p.type == PT_SYN_ONLY)
247 strcpy(message,p.data);
248 strcpy(host,inet_ntoa(host_address.sin_addr));
249 prt = ntohs(host_address.sin_port);
250 SendACK(host,this->port,p.id);
254 if (p.type == PT_ACK_ONLY)
256 strcpy(message,p.data);
257 strcpy(host,inet_ntoa(host_address.sin_addr));
258 prt = ntohs(host_address.sin_port);
262 if (p.type == PT_SYN_WITH_DATA)
264 strcpy(message,p.data);
265 strcpy(host,inet_ntoa(host_address.sin_addr));
267 prt = ntohs(host_address.sin_port);
268 SendACK(host,this->port,p.id);
272 log(DEBUG,"connection::RecvPacket(): Invalid packet type %d (protocol error)",p.type);