]> git.netwichtig.de Git - user/henk/code/inspircd.git/blob - src/connection.cpp
1d79a00a13b841a7dbb9d5c2a2029bfef7af2935
[user/henk/code/inspircd.git] / src / connection.cpp
1 #include <connection.h>
2 #include <unistd.h>
3 #include <fcntl.h>
4 #include <sys/errno.h>
5 #include <sys/ioctl.h>
6 #include <sys/utsname.h>
7 #include "inspircd.h"
8
9 packet::packet()
10 {
11         srand(time(NULL));
12         id = random();
13 }
14
15 packet::~packet()
16 {
17 }
18
19 connection::connection()
20 {
21         key = GenKey();
22         fd = 0;
23 }
24
25
26 bool connection::CreateListener(char* host, int port)
27 {
28         sockaddr_in host_address;
29         int flags;
30         in_addr addy;
31         
32         fd = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP);
33         if (fd <= 0)
34         {
35                 return false;
36         }
37
38         memset((void*)&host_address, 0, sizeof(host_address));
39
40         host_address.sin_family = AF_INET;
41
42         if (!strcmp(host,""))
43         {
44                 host_address.sin_addr.s_addr = htonl(INADDR_ANY);
45         }
46         else
47         {
48                 inet_aton(host,&addy);
49                 host_address.sin_addr = addy;
50         }
51
52         host_address.sin_port = htons(port);
53
54         if (bind(fd, (sockaddr*)&host_address, sizeof(host_address))<0)
55         {
56                 return false;
57         }
58
59         // make the socket non-blocking
60         flags = fcntl(fd, F_GETFL, 0);
61         fcntl(fd, F_SETFL, flags | O_NONBLOCK);
62
63         return true;
64 }
65
66 bool connection::BeginLink(char* targethost, int port, char* password)
67 {
68         char connect[MAXBUF];
69         
70         if (this->fd)
71         {
72                 sprintf(connect,"S %s %s :%s",getservername().c_str(),password,getserverdesc().c_str());
73                 this->haspassed = false;
74                 this->SendPacket(connect, targethost, port);
75                 return true;
76         }
77         return false;
78 }
79
80 // targethost: in dot notation a.b.c.d
81 void connection::TerminateLink(char* targethost)
82 {
83 }
84
85 // host: in dot notation a.b.c.d
86 // port: host byte order
87 bool connection::SendPacket(char *message, char* host, int port)
88 {
89         sockaddr_in host_address;
90         in_addr addy;
91         packet p;
92
93         memset((void*)&host_address, 0, sizeof(host_address));
94
95         host_address.sin_family = AF_INET;
96         inet_aton(host,&addy);
97         host_address.sin_addr = addy;
98
99         host_address.sin_port = htons(port);
100
101         strcpy(p.data,message);
102         p.type = PT_SYN_WITH_DATA;
103         p.key = key;
104
105         // returns false if the packet could not be sent (e.g. target host down)
106         if (sendto(fd,&p,sizeof(p),0,(sockaddr*)&host_address,sizeof(host_address))<0)
107         {
108                 return false;
109         }
110         return true;
111
112 }
113
114 bool connection::SendSYN(char* host, int port)
115 {
116         sockaddr_in host_address;
117         in_addr addy;
118         packet p;
119
120         memset((void*)&host_address, 0, sizeof(host_address));
121
122         host_address.sin_family = AF_INET;
123         inet_aton(host,&addy);
124         host_address.sin_addr = addy;
125
126         host_address.sin_port = htons(port);
127
128         p.type = PT_SYN_ONLY;
129         p.key = key;
130         strcpy(p.data,"");
131
132         if (sendto(fd,&p,sizeof(p),0,(sockaddr*)&host_address,sizeof(host_address))<0)
133         {
134                 return false;
135         }
136         return true;
137
138 }
139
140 bool connection::SendACK(char* host, int port, int reply_id)
141 {
142         sockaddr_in host_address;
143         in_addr addy;
144         packet p;
145
146         memset((void*)&host_address, 0, sizeof(host_address));
147
148         host_address.sin_family = AF_INET;
149         inet_aton(host,&addy);
150         host_address.sin_addr = addy;
151
152         host_address.sin_port = htons(port);
153
154         p.type = PT_ACK_ONLY;
155         p.key = key;
156         p.id = reply_id;
157         strcpy(p.data,"");
158
159         if (sendto(fd,&p,sizeof(p),0,(sockaddr*)&host_address,sizeof(host_address))<0)
160         {
161                 return false;
162         }
163         return true;
164
165 }
166
167
168 // Generates a server key. This is pseudo-random.
169 // the server always uses the same server-key in all communications
170 // across the network. All other servers must remember the server key
171 // of servers in the network, e.g.:
172 //
173 // ServerA:  key=5555555555
174 // ServerB:  key=6666666666
175 // I am ServerC: key=77777777777
176 //
177 // If ServerC sees a packet from ServerA, and the key stored for ServerA
178 // is 0, then cache the key as the servers key.
179 // after this point, any packet from ServerA which does not contain its key,
180 // 555555555, will be silently dropped.
181 // This should prevent blind spoofing, as to fake a server you must know its
182 // assigned key, and to do that you must receive messages that are origintated
183 // from it or hack the running executable.
184 //
185 // During the AUTH phase (when server passwords are checked, the key in any
186 // packet MUST be 0). Only the initial SERVER/PASS packets may have a key
187 // of 0 (and any ACK responses to them).
188 //
189
190 long connection::GenKey()
191 {
192         srand(time(NULL));
193         return (random()*time(NULL));
194 }
195
196 // host: in dot notation a.b.c.d
197 // port: host byte order
198 bool connection::RecvPacket(char *message, char* host, int &port)
199 {
200         // returns false if no packet waiting for receive, e.g. EAGAIN or ECONNRESET
201         sockaddr_in host_address;
202         socklen_t host_address_size;
203         packet p;
204         
205         memset((void*)&host_address, 0, sizeof(host_address));
206
207         host_address.sin_family=AF_INET;
208         host_address_size=sizeof(host_address);
209
210         if (recvfrom(fd,&p,sizeof(p),0,(sockaddr*)&host_address,&host_address_size)<0)
211         {
212                 return false;
213         }
214
215         if (p.type == PT_SYN_ONLY)
216         {
217                 strcpy(message,p.data);
218                 strcpy(host,inet_ntoa(host_address.sin_addr));
219                 port = ntohs(host_address.sin_port);
220                 SendACK(host,port,p.id);
221                 return false;
222         }
223
224         if (p.type == PT_ACK_ONLY)
225         {
226                 strcpy(message,p.data);
227                 strcpy(host,inet_ntoa(host_address.sin_addr));
228                 port = ntohs(host_address.sin_port);
229                 SendACK(host,port,p.id);
230                 return false;
231         }
232
233         if (p.type == PT_SYN_WITH_DATA)
234         {
235                 strcpy(message,p.data);
236                 strcpy(host,inet_ntoa(host_address.sin_addr));
237                 port = ntohs(host_address.sin_port);
238                 SendACK(host,port,p.id);
239         }
240
241         return true;
242 }
243