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));
81 bool connection::BeginLink(char* targethost, int port, char* password)
87 sprintf(connect,"S %s %s :%s",getservername().c_str(),password,getserverdesc().c_str());
88 this->haspassed = false;
89 return this->SendPacket(connect, targethost, port, 0);
94 // targethost: in dot notation a.b.c.d
95 void connection::TerminateLink(char* targethost)
99 // host: in dot notation a.b.c.d
100 // port: host byte order
101 bool connection::SendPacket(char *message, char* host, int port, long ourkey)
103 sockaddr_in host_address;
107 memset((void*)&host_address, 0, sizeof(host_address));
109 host_address.sin_family = AF_INET;
110 inet_aton(host,&addy);
111 host_address.sin_addr = addy;
113 host_address.sin_port = htons(port);
115 strcpy(p.data,message);
116 p.type = PT_SYN_WITH_DATA;
120 FOREACH_MOD OnPacketTransmit(p.data);
122 log(DEBUG,"main: Connection::SendPacket() sent '%s' to %s:%d",p.data,host,port);
124 // returns false if the packet could not be sent (e.g. target host down)
125 if (sendto(this->fd,&p,sizeof(p),0,(sockaddr*)&host_address,sizeof(host_address))<0)
127 log(DEBUG,"sendto() failed for Connection::SendPacket() with a packet of size %d",sizeof(p));
134 bool connection::SendSYN(char* host, int port)
136 sockaddr_in host_address;
140 memset((void*)&host_address, 0, sizeof(host_address));
142 host_address.sin_family = AF_INET;
143 inet_aton(host,&addy);
144 host_address.sin_addr = addy;
146 host_address.sin_port = htons(port);
148 p.type = PT_SYN_ONLY;
152 if (sendto(fd,&p,sizeof(p),0,(sockaddr*)&host_address,sizeof(host_address))<0)
160 bool connection::SendACK(char* host, int port, int reply_id)
162 sockaddr_in host_address;
166 memset((void*)&host_address, 0, sizeof(host_address));
168 host_address.sin_family = AF_INET;
169 inet_aton(host,&addy);
170 host_address.sin_addr = addy;
172 host_address.sin_port = htons(port);
174 p.type = PT_ACK_ONLY;
179 if (sendto(fd,&p,sizeof(p),0,(sockaddr*)&host_address,sizeof(host_address))<0)
188 // Generates a server key. This is pseudo-random.
189 // the server always uses the same server-key in all communications
190 // across the network. All other servers must remember the server key
191 // of servers in the network, e.g.:
193 // ServerA: key=5555555555
194 // ServerB: key=6666666666
195 // I am ServerC: key=77777777777
197 // If ServerC sees a packet from ServerA, and the key stored for ServerA
198 // is 0, then cache the key as the servers key.
199 // after this point, any packet from ServerA which does not contain its key,
200 // 555555555, will be silently dropped.
201 // This should prevent blind spoofing, as to fake a server you must know its
202 // assigned key, and to do that you must receive messages that are origintated
203 // from it or hack the running executable.
205 // During the AUTH phase (when server passwords are checked, the key in any
206 // packet MUST be 0). Only the initial SERVER/PASS packets may have a key
207 // of 0 (and any ACK responses to them).
210 long connection::GenKey()
213 return (random()*time(NULL));
216 // host: in dot notation a.b.c.d
217 // port: host byte order
218 bool connection::RecvPacket(char *message, char* host, int &prt, long &theirkey)
220 // returns false if no packet waiting for receive, e.g. EAGAIN or ECONNRESET
221 sockaddr_in host_address;
222 socklen_t host_address_size;
225 memset((void*)&host_address, 0, sizeof(host_address));
227 host_address.sin_family=AF_INET;
228 host_address_size=sizeof(host_address);
230 if (recvfrom(fd,&p,sizeof(p),0,(sockaddr*)&host_address,&host_address_size)<0)
235 log(DEBUG,"connection::RecvPacket(): received packet type %d '%s'",p.type,p.data);
237 if (p.type == PT_SYN_ONLY)
239 strcpy(message,p.data);
240 strcpy(host,inet_ntoa(host_address.sin_addr));
241 prt = ntohs(host_address.sin_port);
242 SendACK(host,this->port,p.id);
246 if (p.type == PT_ACK_ONLY)
248 strcpy(message,p.data);
249 strcpy(host,inet_ntoa(host_address.sin_addr));
250 prt = ntohs(host_address.sin_port);
254 if (p.type == PT_SYN_WITH_DATA)
256 strcpy(message,p.data);
257 strcpy(host,inet_ntoa(host_address.sin_addr));
259 prt = ntohs(host_address.sin_port);
260 SendACK(host,this->port,p.id);
264 log(DEBUG,"connection::RecvPacket(): Invalid packet type %d (protocol error)",p.type);