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