1 #include <connection.h>
6 #include <sys/utsname.h>
12 extern std::vector<Module*> modules;
13 extern std::vector<ircd_module*> factory;
18 #define STATE_WAIT_FOR_ACK 2
30 connection::connection()
39 bool connection::CreateListener(char* host, int p)
41 sockaddr_in host_address;
45 struct linger linger = { 0 };
47 fd = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP);
53 memset((void*)&host_address, 0, sizeof(host_address));
55 host_address.sin_family = AF_INET;
59 host_address.sin_addr.s_addr = htonl(INADDR_ANY);
63 inet_aton(host,&addy);
64 host_address.sin_addr = addy;
67 host_address.sin_port = htons(p);
69 if (bind(fd,(sockaddr*)&host_address,sizeof(host_address))<0)
74 // make the socket non-blocking
75 flags = fcntl(fd, F_GETFL, 0);
76 fcntl(fd, F_SETFL, flags | O_NONBLOCK);
80 setsockopt(fd,SOL_SOCKET,SO_REUSEADDR,(const char*)&on,sizeof(on));
83 setsockopt(fd,SOL_SOCKET,SO_LINGER,(const char*)&linger,sizeof(linger));
90 bool connection::BeginLink(char* targethost, int port, char* password)
96 sprintf(connect,"S %s %s :%s",getservername().c_str(),password,getserverdesc().c_str());
97 this->haspassed = false;
98 return this->SendPacket(connect, targethost, port, 0);
103 // targethost: in dot notation a.b.c.d
104 void connection::TerminateLink(char* targethost)
108 // host: in dot notation a.b.c.d
109 // port: host byte order
110 bool connection::SendPacket(char *message, char* host, int port, long ourkey)
112 sockaddr_in host_address;
116 memset((void*)&host_address, 0, sizeof(host_address));
118 host_address.sin_family = AF_INET;
119 inet_aton(host,&addy);
120 host_address.sin_addr = addy;
122 host_address.sin_port = htons(port);
124 strcpy(p.data,message);
125 p.type = PT_SYN_WITH_DATA;
129 FOREACH_MOD OnPacketTransmit(p.data);
131 log(DEBUG,"main: Connection::SendPacket() sent '%s' to %s:%d",p.data,host,port);
133 // returns false if the packet could not be sent (e.g. target host down)
134 if (sendto(this->fd,&p,sizeof(p),0,(sockaddr*)&host_address,sizeof(host_address))<0)
136 log(DEBUG,"sendto() failed for Connection::SendPacket() with a packet of size %d: %s",sizeof(p),strerror(errno));
140 this->state = STATE_CLEAR;
146 bool connection::SendSYN(char* host, int port)
148 sockaddr_in host_address;
152 memset((void*)&host_address, 0, sizeof(host_address));
154 host_address.sin_family = AF_INET;
155 inet_aton(host,&addy);
156 host_address.sin_addr = addy;
158 host_address.sin_port = htons(port);
160 p.type = PT_SYN_ONLY;
164 if (sendto(fd,&p,sizeof(p),0,(sockaddr*)&host_address,sizeof(host_address))<0)
172 bool connection::SendACK(char* host, int port, int reply_id)
174 sockaddr_in host_address;
178 memset((void*)&host_address, 0, sizeof(host_address));
180 host_address.sin_family = AF_INET;
181 inet_aton(host,&addy);
182 host_address.sin_addr = addy;
184 host_address.sin_port = htons(port);
186 p.type = PT_ACK_ONLY;
191 if (sendto(fd,&p,sizeof(p),0,(sockaddr*)&host_address,sizeof(host_address))<0)
199 // Generates a server key. This is pseudo-random.
200 // the server always uses the same server-key in all communications
201 // across the network. All other servers must remember the server key
202 // of servers in the network, e.g.:
204 // ServerA: key=5555555555
205 // ServerB: key=6666666666
206 // I am ServerC: key=77777777777
208 // If ServerC sees a packet from ServerA, and the key stored for ServerA
209 // is 0, then cache the key as the servers key.
210 // after this point, any packet from ServerA which does not contain its key,
211 // 555555555, will be silently dropped.
212 // This should prevent blind spoofing, as to fake a server you must know its
213 // assigned key, and to do that you must receive messages that are origintated
214 // from it or hack the running executable.
216 // During the AUTH phase (when server passwords are checked, the key in any
217 // packet MUST be 0). Only the initial SERVER/PASS packets may have a key
218 // of 0 (and any ACK responses to them).
221 long connection::GenKey()
224 return (random()*time(NULL));
227 // host: in dot notation a.b.c.d
228 // port: host byte order
229 bool connection::RecvPacket(char *message, char* host, int &prt, long &theirkey)
231 // returns false if no packet waiting for receive, e.g. EAGAIN or ECONNRESET
232 sockaddr_in host_address;
233 socklen_t host_address_size;
236 memset((void*)&host_address, 0, sizeof(host_address));
238 host_address.sin_family=AF_INET;
239 host_address_size=sizeof(host_address);
241 //int recvfrom(int s, void *buf, size_t len, int flags, struct sockaddr *from, socklen_t *fromlen);
242 if (recvfrom(fd,&p,sizeof(p),0,(sockaddr*)&host_address,&host_address_size)<0)
247 log(DEBUG,"connection::RecvPacket(): received packet type %d '%s' from '%s'",p.type,p.data,inet_ntoa(host_address.sin_addr));
249 if (p.type == PT_SYN_ONLY)
251 strcpy(message,p.data);
252 strcpy(host,inet_ntoa(host_address.sin_addr));
253 prt = ntohs(host_address.sin_port);
254 SendACK(host,this->port,p.id);
258 if (p.type == PT_ACK_ONLY)
260 strcpy(message,p.data);
261 strcpy(host,inet_ntoa(host_address.sin_addr));
262 prt = ntohs(host_address.sin_port);
263 this->state = STATE_CLEAR;
267 if (p.type == PT_SYN_WITH_DATA)
269 strcpy(message,p.data);
270 strcpy(host,inet_ntoa(host_address.sin_addr));
272 prt = ntohs(host_address.sin_port); // the port we received it on
273 SendACK(host,prt,p.id);
277 log(DEBUG,"connection::RecvPacket(): Invalid packet type %d (protocol error)",p.type);