1 /*
2 * ----------------------------------------------------------------
3 * ircproxy - Connection Functions
4 * ----------------------------------------------------------------
5 * Copyright (C) 1997-2009 Jonas Kvinge
6 *
7 * This file is part of ircproxy.
8 *
9 * ircproxy is free software: you can redistribute it and/or modify
10 * it under the terms of the GNU General Public License as published by
11 * the Free Software Foundation, either version 3 of the License, or
12 * (at your option) any later version.
13 *
14 * ircproxy is distributed in the hope that it will be useful,
15 * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 * GNU General Public License for more details.
18 *
19 * You should have received a copy of the GNU General Public License
20 * along with ircproxy. If not, see <http://www.gnu.org/licenses/>.
21 *
22 * Additional permission under GNU GPL version 3 section 7
23 *
24 * If you modify ircproxy, or any covered work, by linking or
25 * combining it with openssl (or a modified version of that library),
26 * containing parts covered by the terms of the OpenSSL License and the
27 * SSLeay License, the licensors of ircproxy grant you additional
28 * permission to convey the resulting work.
29 *
30 * $Id: conn.c 54 2009-03-18 18:23:29Z jonasio $
31 *
32 */
33
34 #define CONN_C
35
36 #define NEED_SYS_TYPES_H 1 /* Extra types */
37 #define NEED_SYS_PARAM_H 1 /* Some systems need this */
38 #define NEED_LIMITS_H 0 /* Kernel limits */
39 #define NEED_STDARG_H 1 /* va_list, etc */
40 #define NEED_ERRNO_H 1 /* errno */
41 #define NEED_CTYPE_H 1 /* isdigit(), etc */
42 #define NEED_NETINET_IN_H 1 /* in_addr, sockaddr_in, etc */
43 #define NEED_ARPA_INET_H 1 /* inet_ntoa(), inet_aton(), etc */
44 #define NEED_STDIO_H 1 /* Standard C UNIX functions */
45 #define NEED_STDLIB_H 1 /* malloc(), exit(), atoi(), etc */
46 #define NEED_TIME_H 1 /* time(), etc */
47 #define NEED_SYSCTL_H 0 /* sysctl(), etc */
48 #define NEED_SYS_STAT_H 0 /* chmod(), mkdir(), etc */
49 #define NEED_SYS_UIO_H 0 /* iovec, etc */
50 #define NEED_FCNTL_H 1 /* open(), creat(), fcntl(), etc */
51 #define NEED_SYS_IOCTL_H 1 /* ioctl(), etc */
52 #define NEED_SYS_FILIO_H 1 /* Solaris need this for ioctl(), etc */
53 #define NEED_UNISTD_H 1 /* Unix standard functions */
54 #define NEED_STRING_H 1 /* C string functions */
55 #define NEED_SIGNAL_H 0 /* Signal functions */
56 #define NEED_SYS_SOCKET_H 1 /* Socket functions */
57 #define NEED_NETDB_H 1 /* Network database functions */
58 #define NEED_ARPA_NAMESER_H 0 /* Nameserver definitions */
59 #define NEED_GETUSERPW_HEADERS 0 /* Functions to retrive system passwords */
60 #define NEED_ARES 0 /* Functions needed for ares */
61 #define NEED_SSL 1 /* Needed for SSL support */
62
63 #include "includes.h"
64 #include "irc.h"
65
66 #include "conf.h"
67 #include "access_conf.h"
68 #include "conn_conf.h"
69
70 #include "conn.h"
71 #include "conn_io.h"
72 #include "conn_connection.h"
73 #include "conn_sendq.h"
74 #include "conn_ignore.h"
75 #include "conn_log.h"
76
77 #include "chan.h"
78 #include "chan_user.h"
79
80 #include "client.h"
81 #include "client_handle.h"
82 #include "client_notice.h"
83
84 /* VARIABLES - JONAS (31.07.2001) */
85
86 struct Conn_Struct *Conn_Head = NULL;
87 struct Conn_Struct *Conn_Tail = NULL;
88 unsigned long int G_Conns = 0;
89
90 extern struct Client_Struct *Client_Head;
91
92 /* CONN_ADD FUNCTION - JONAS (22.07.2001) */
93
conn_add(struct ConnConf_Struct * ConnConf)94 struct Conn_Struct *conn_add(struct ConnConf_Struct *ConnConf) {
95
96 struct Conn_Struct *ConnS = NULL;
97 struct Conn_Struct *ConnS_NEW = NULL;
98
99 assert(ConnConf != NULL);
100
101 ConnS = conn_get(ConnConf->Name);
102 if (ConnS != NULL) {
103 aerrno = AEEXISTS;
104 return(ConnS);
105 }
106
107 ConnS_NEW = malloc(sizeof(struct Conn_Struct));
108 if (ConnS_NEW == NULL) {
109 aerrno = AEMALLOC;
110 return(NULL);
111 }
112 memset(ConnS_NEW, 0, sizeof(struct Conn_Struct));
113
114 ConnS_NEW->Name = strdup(ConnConf->Name);
115 ConnS_NEW->Nick = strdup(ConnConf->Nick);
116 ConnS_NEW->AwayNick = strdup(ConnConf->AwayNick);
117 ConnS_NEW->User = strdup(ConnConf->User);
118 ConnS_NEW->Host = strdup(ConnConf->Host);
119 ConnS_NEW->Mode = strdup(ConnConf->Mode);
120 ConnS_NEW->Info = strdup(ConnConf->Info);
121 ConnS_NEW->Chans = strdup(ConnConf->Chans);
122 ConnS_NEW->AwayMsg = strdup(ConnConf->AwayMsg);
123 ConnS_NEW->PublicDetachMsg = strdup(ConnConf->PublicDetachMsg);
124 ConnS_NEW->PublicAttachMsg = strdup(ConnConf->PublicAttachMsg);
125 ConnS_NEW->NickServNUH = strdup(ConnConf->NickServNUH);
126 ConnS_NEW->NickServPass = strdup(ConnConf->NickServPass);
127 ConnS_NEW->NickServText = strdup(ConnConf->NickServText);
128
129 if (
130 (ConnS_NEW->Name == NULL) ||
131 (ConnS_NEW->Nick == NULL) ||
132 (ConnS_NEW->AwayNick == NULL) ||
133 (ConnS_NEW->User == NULL) ||
134 (ConnS_NEW->Host == NULL) ||
135 (ConnS_NEW->Mode == NULL) ||
136 (ConnS_NEW->Info == NULL) ||
137 (ConnS_NEW->Chans == NULL) ||
138 (ConnS_NEW->AwayMsg == NULL) ||
139 (ConnS_NEW->PublicDetachMsg == NULL) ||
140 (ConnS_NEW->PublicAttachMsg == NULL) ||
141 (ConnS_NEW->NickServNUH == NULL) ||
142 (ConnS_NEW->NickServPass == NULL) ||
143 (ConnS_NEW->NickServText == NULL)
144 ) {
145 free(ConnS_NEW->Name);
146 free(ConnS_NEW->Nick);
147 free(ConnS_NEW->AwayNick);
148 free(ConnS_NEW->User);
149 free(ConnS_NEW->Host);
150 free(ConnS_NEW->Mode);
151 free(ConnS_NEW->Info);
152 free(ConnS_NEW->Chans);
153 free(ConnS_NEW->AwayMsg);
154 free(ConnS_NEW->PublicDetachMsg);
155 free(ConnS_NEW->PublicAttachMsg);
156 free(ConnS_NEW->NickServNUH);
157 free(ConnS_NEW->NickServPass);
158 free(ConnS_NEW->NickServText);
159 free(ConnS_NEW);
160 aerrno = AEMALLOC;
161 return(NULL);
162 }
163
164 ConnS_NEW->ConfFlags = ConnConf->ConfFlags;
165 ConnS_NEW->MaxClients = ConnConf->MaxClients;
166 ConnS_NEW->SendMaxLines = ConnConf->SendMaxLines;
167 ConnS_NEW->SendLineTime = ConnConf->SendLineTime;
168 ConnS_NEW->SendMaxBuffer = ConnConf->SendMaxBuffer;
169 ConnS_NEW->SendBufferTime = ConnConf->SendBufferTime;
170 ConnS_NEW->ChanLogFlags = ConnConf->ChanLogFlags;
171
172 conn_initconnection(ConnS_NEW);
173
174 if (Conn_Head == NULL) {
175 Conn_Head = ConnS_NEW;
176 Conn_Tail = ConnS_NEW;
177 }
178 else {
179 ConnS = Conn_Tail;
180 ConnS->Next = ConnS_NEW;
181 ConnS_NEW->Prev = ConnS;
182 Conn_Tail = ConnS_NEW;
183 }
184
185 G_Conns++;
186
187 aerrno = AESUCCESS;
188 return(ConnS_NEW);
189
190 }
191
192 /* CONN_REM FUNCTION - JONAS (01.08.2001) */
193
conn_rem(struct Conn_Struct * ConnS)194 void conn_rem(struct Conn_Struct *ConnS) {
195
196 struct Client_Struct *ClientS = NULL;
197
198 assert(ConnS != NULL);
199
200 if (ConnS->Prev == NULL) { Conn_Head = ConnS->Next; }
201 else { ConnS->Prev->Next = ConnS->Next; }
202
203 if (ConnS->Next == NULL) { Conn_Tail = ConnS->Prev; }
204 else { ConnS->Next->Prev = ConnS->Prev; }
205
206 for (ClientS = Client_Head ; ClientS != NULL ; ClientS = ClientS->Next) {
207 if (ClientS->ConnS == ConnS) {
208 if (!Client_IsSentError(ClientS)) { client_notice(ClientS, "You are automatically detached from connection %s: Connection removed.", ConnS->Name); }
209 client_detach(ClientS);
210 }
211 }
212
213 conn_destroyignores(ConnS);
214 conn_initconnection(ConnS);
215
216 free(ConnS->Name);
217 free(ConnS->Nick);
218 free(ConnS->AwayNick);
219 free(ConnS->User);
220 free(ConnS->Host);
221 free(ConnS->Mode);
222 free(ConnS->Info);
223 free(ConnS->Chans);
224 free(ConnS->AwayMsg);
225 free(ConnS->PublicDetachMsg);
226 free(ConnS->PublicAttachMsg);
227 free(ConnS->NickServNUH);
228 free(ConnS->NickServPass);
229 free(ConnS->NickServText);
230 conn_destroyservers(ConnS);
231 free(ConnS);
232
233 G_Conns--;
234
235 }
236
237 /* CONN_GET - JONAS (06.10.2000) */
238
conn_get(const char * const NamePT)239 struct Conn_Struct *conn_get(const char *const NamePT) {
240
241 struct Conn_Struct *ConnS = NULL;
242
243 assert(NamePT != NULL);
244
245 for (ConnS = Conn_Head ; ConnS != NULL ; ConnS = ConnS->Next) {
246 if (strwm(NamePT, ConnS->Name) == TRUE) {
247 aerrno = AESUCCESS;
248 return(ConnS);
249 }
250 }
251 aerrno = AENOMATCH;
252 return(NULL);
253
254 }
255
256 /* CONN_ADDSERVER - JONAS (31.07.2001) */
257
conn_addserver(struct Conn_Struct * ConnS,const char * const HostPT,const unsigned long int Port,const char * const PassPT)258 struct ConnServer_Struct *conn_addserver(struct Conn_Struct *ConnS, const char *const HostPT, const unsigned long int Port, const char *const PassPT) {
259
260 struct ConnServer_Struct *ConnServer = NULL;
261 struct ConnServer_Struct *ConnServer_NEW = NULL;
262
263 assert(ConnS != NULL);
264 assert(HostPT != NULL);
265 assert(PassPT != NULL);
266
267 ConnServer = conn_getserver(ConnS, HostPT);
268 if (ConnServer != NULL) {
269 aerrno = AEEXISTS;
270 return(ConnServer);
271 }
272
273 ConnServer_NEW = malloc(sizeof(struct ConnServer_Struct));
274 if (ConnServer_NEW == NULL) {
275 aerrno = AEMALLOC;
276 return(NULL);
277 }
278 memset(ConnServer_NEW, 0, sizeof(struct ConnServer_Struct));
279
280 ConnServer_NEW->Host = strdup(HostPT);
281 ConnServer_NEW->Port = Port;
282
283 if (ConnServer_NEW->Host == NULL) {
284 free(ConnServer_NEW->Host);
285 free(ConnServer_NEW);
286 aerrno = AEMALLOC;
287 return(NULL);
288 }
289
290 if (ConnS->Server_Head == NULL) {
291 ConnS->Server_Head = ConnServer_NEW;
292 ConnS->Server_Tail = ConnServer_NEW;
293 }
294 else {
295 ConnServer = ConnS->Server_Tail;
296 ConnServer->Next = ConnServer_NEW;
297 ConnServer_NEW->Prev = ConnServer;
298 ConnS->Server_Tail = ConnServer_NEW;
299 }
300
301 ConnS->NumServers++;
302
303 aerrno = AESUCCESS;
304 return(ConnServer_NEW);
305
306 }
307
308 /* CONN_REMSERVER FUNCTION - JONAS (31.07.2001) */
309
conn_remserver(struct Conn_Struct * ConnS,struct ConnServer_Struct * ConnServer)310 void conn_remserver(struct Conn_Struct *ConnS, struct ConnServer_Struct *ConnServer) {
311
312 assert(ConnS != NULL);
313 assert(ConnServer != NULL);
314
315 if (ConnServer->Prev == NULL) { ConnS->Server_Head = ConnServer->Next; }
316 else { ConnServer->Prev->Next = ConnServer->Next; }
317
318 if (ConnServer->Next == NULL) { ConnS->Server_Tail = ConnServer->Prev; }
319 else { ConnServer->Next->Prev = ConnServer->Prev; }
320
321 free(ConnServer->Host);
322 free(ConnServer);
323
324 if (ConnS->ConnServerTry == ConnServer) { ConnS->ConnServerTry = NULL; }
325
326 ConnS->NumServers--;
327
328 }
329
330 /* CONN_GETSERVER FUNCTION - JONAS (31.07.2001) */
331
conn_getserver(struct Conn_Struct * ConnS,const char * const HostPT)332 struct ConnServer_Struct *conn_getserver(struct Conn_Struct *ConnS, const char *const HostPT) {
333
334 struct ConnServer_Struct *ConnServer = NULL;
335
336 assert(ConnS != NULL);
337 assert(HostPT != NULL);
338
339 for (ConnServer = ConnS->Server_Head ; ConnServer != NULL ; ConnServer = ConnServer->Next) {
340 if (strcasecmp(ConnServer->Host, HostPT) == FALSE) {
341 aerrno = AESUCCESS;
342 return(ConnServer);
343 }
344 }
345 aerrno = AENOMATCH;
346 return(NULL);
347
348 }
349
350 /* CONN_REMSERVERS FUNCTION - JONAS (31.07.2001) */
351
conn_destroyservers(struct Conn_Struct * ConnS)352 void conn_destroyservers(struct Conn_Struct *ConnS) {
353
354 while (ConnS->Server_Head != NULL) { conn_remserver(ConnS, ConnS->Server_Head); }
355
356 }
357
358 /* CONN_INITCONNECTION FUNCTION - JONAS (01.08.2001) */
359
conn_initconnection(struct Conn_Struct * ConnS)360 void conn_initconnection(struct Conn_Struct *ConnS) {
361
362 unsigned short int Index = 0;
363
364 assert(ConnS != NULL);
365
366 DEBUGPRINT(BITMASK_DEBUG_CONN, "conn_initconnection(%s)", ConnS->Name);
367
368 ConnS->ResolveFlags = 0;
369 FREE(ConnS->HostName);
370 FREE(ConnS->HostIPS);
371 memset(&ConnS->INAddr, 0, sizeof(ConnS->INAddr));
372 #if IPV6_SUPPORT
373 memset(&ConnS->INAddr6, 0, sizeof(ConnS->INAddr6));
374 #endif
375 ConnS->PortH = 0;
376 ConnS->PortN = 0;
377
378 ConnS->ServerResolveFlags = 0;
379 FREE(ConnS->ServerHostName);
380 FREE(ConnS->ServerHostIPS);
381 memset(&ConnS->ServerINAddr, 0, sizeof(ConnS->ServerINAddr));
382 #if IPV6_SUPPORT
383 memset(&ConnS->ServerINAddr6, 0, sizeof(ConnS->ServerINAddr6));
384 #endif
385 ConnS->ServerPortH = 0;
386 ConnS->ServerPortN = 0;
387 FREE(ConnS->ServerPass);
388
389 ConnS->ConnectionFlags = 0;
390 ConnS->FD = FD_NONE;
391 FREE(ConnS->ServerName);
392 FREE(ConnS->IRCNick);
393 for (Index = 0 ; Index <= 4 ; ++Index) { FREE(ConnS->Welcome[Index]); }
394 for (Index = 0 ; Index < ConnS->ISupportLines ; ++Index) { free(ConnS->ISupport_String[Index]); }
395 FREE(ConnS->ISupport_String);
396 for (Index = 0 ; Index < ConnS->ISuppChanModes ; ++Index) { FREE(ConnS->ISuppChanMode); }
397 for (Index = 0 ; Index < ConnS->ISuppChanUserModes ; ++Index) { FREE(ConnS->ISuppChanUserMode); }
398 for (Index = 0 ; Index < ConnS->MOTDLines ; ++Index) { free(ConnS->MOTD_Line[Index]); }
399 FREE(ConnS->MOTD_Line);
400 ConnS->ISupportLines = 0;
401 ConnS->ISuppChanUserModes = 0;
402 ConnS->MOTDLines = 0;
403 ConnS->UserModeFlags = 0;
404 ConnS->ChanModeFlags = 0;
405 ConnS->ChanListModeFlags = 0;
406 ConnS->ChanUserModeFlags = 0;
407 conn_initsendq(ConnS);
408 FREE(ConnS->RecvBuffer);
409 FREE(ConnS->SendBuffer);
410 ConnS->NicksIndex = 0;
411 chan_destroy(ConnS);
412
413 FREE(ConnS->ISupport.Network);
414 FREE(ConnS->ISupport.ChanTypes);
415 FREE(ConnS->ISupport.ChanModes);
416 FREE(ConnS->ISupport.Prefix);
417 ConnS->ISupport.Networks = 0;
418 ConnS->ISupport.MaxModes = IRC_MAXMODES;
419 ConnS->ISupport.MaxChans = IRC_MAXCHANS;
420 ConnS->ISupport.MaxBans = IRC_CHANMAXBANS;
421 ConnS->ISupport.NickLen = IRC_NICKLEN_DEFAULT;
422 ConnS->ISupport.AwayMsgLen = IRC_AWAYMSGLEN;
423 ConnS->ISupport.TopicLen = IRC_CHANTOPICLEN;
424 ConnS->ISupport.KickMsgLen = IRC_CHANKICKMSGLEN;
425
426 #if 0
427 for (Index = 0 ; Index < ConnS->Logs ; ++Index) { free(ConnS->LogFile[Index]); }
428 FREE(ConnS->LogFile);
429 #endif
430
431 FREE(ConnS->RawLogFile);
432 FREE(ConnS->PrivLogFile);
433 if (ConnS->RawLogFileFP != NULL) { fclose(ConnS->RawLogFileFP); ConnS->RawLogFileFP = NULL; }
434 if (ConnS->PrivLogFileFP != NULL) { fclose(ConnS->PrivLogFileFP); ConnS->PrivLogFileFP = NULL; }
435
436 conn_destroylogs(ConnS);
437
438 }
439