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;
144 bool connection::SendSYN(char* host, int port)
146 sockaddr_in host_address;
150 memset((void*)&host_address, 0, sizeof(host_address));
152 host_address.sin_family = AF_INET;
153 inet_aton(host,&addy);
154 host_address.sin_addr = addy;
156 host_address.sin_port = htons(port);
158 p.type = PT_SYN_ONLY;
162 if (sendto(fd,&p,sizeof(p),0,(sockaddr*)&host_address,sizeof(host_address))<0)
170 bool connection::SendACK(char* host, int port, int reply_id)
172 sockaddr_in host_address;
176 memset((void*)&host_address, 0, sizeof(host_address));
178 host_address.sin_family = AF_INET;
179 inet_aton(host,&addy);
180 host_address.sin_addr = addy;
182 host_address.sin_port = htons(port);
184 p.type = PT_ACK_ONLY;
189 if (sendto(fd,&p,sizeof(p),0,(sockaddr*)&host_address,sizeof(host_address))<0)
197 // Generates a server key. This is pseudo-random.
198 // the server always uses the same server-key in all communications
199 // across the network. All other servers must remember the server key
200 // of servers in the network, e.g.:
202 // ServerA: key=5555555555
203 // ServerB: key=6666666666
204 // I am ServerC: key=77777777777
206 // If ServerC sees a packet from ServerA, and the key stored for ServerA
207 // is 0, then cache the key as the servers key.
208 // after this point, any packet from ServerA which does not contain its key,
209 // 555555555, will be silently dropped.
210 // This should prevent blind spoofing, as to fake a server you must know its
211 // assigned key, and to do that you must receive messages that are origintated
212 // from it or hack the running executable.
214 // During the AUTH phase (when server passwords are checked, the key in any
215 // packet MUST be 0). Only the initial SERVER/PASS packets may have a key
216 // of 0 (and any ACK responses to them).
219 long connection::GenKey()
222 return (random()*time(NULL));
225 // host: in dot notation a.b.c.d
226 // port: host byte order
227 bool connection::RecvPacket(char *message, char* host, int &prt, long &theirkey)
229 // returns false if no packet waiting for receive, e.g. EAGAIN or ECONNRESET
230 sockaddr_in host_address;
231 socklen_t host_address_size;
234 memset((void*)&host_address, 0, sizeof(host_address));
236 host_address.sin_family=AF_INET;
237 host_address_size=sizeof(host_address);
239 //int recvfrom(int s, void *buf, size_t len, int flags, struct sockaddr *from, socklen_t *fromlen);
240 if (recvfrom(fd,&p,sizeof(p),0,(sockaddr*)&host_address,&host_address_size)<0)
245 log(DEBUG,"connection::RecvPacket(): received packet type %d '%s' from '%s'",p.type,p.data,inet_ntoa(host_address.sin_addr));
247 if (p.type == PT_SYN_ONLY)
249 strcpy(message,p.data);
250 strcpy(host,inet_ntoa(host_address.sin_addr));
251 prt = ntohs(host_address.sin_port);
252 SendACK(host,this->port,p.id);
256 if (p.type == PT_ACK_ONLY)
258 strcpy(message,p.data);
259 strcpy(host,inet_ntoa(host_address.sin_addr));
260 prt = ntohs(host_address.sin_port);
261 this->state = STATE_CLEAR;
265 if (p.type == PT_SYN_WITH_DATA)
267 strcpy(message,p.data);
268 strcpy(host,inet_ntoa(host_address.sin_addr));
270 prt = ntohs(host_address.sin_port); // the port we received it on
271 SendACK(host,prt,p.id);
275 log(DEBUG,"connection::RecvPacket(): Invalid packet type %d (protocol error)",p.type);