/* * ---------------------------------------------------------------- * ircproxy - Connection Functions * ---------------------------------------------------------------- * Copyright (C) 1997-2009 Jonas Kvinge * * This file is part of ircproxy. * * ircproxy is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * ircproxy is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with ircproxy. If not, see . * * Additional permission under GNU GPL version 3 section 7 * * If you modify ircproxy, or any covered work, by linking or * combining it with openssl (or a modified version of that library), * containing parts covered by the terms of the OpenSSL License and the * SSLeay License, the licensors of ircproxy grant you additional * permission to convey the resulting work. * * $Id: conn.c 54 2009-03-18 18:23:29Z jonasio $ * */ #define CONN_C #define NEED_SYS_TYPES_H 1 /* Extra types */ #define NEED_SYS_PARAM_H 1 /* Some systems need this */ #define NEED_LIMITS_H 0 /* Kernel limits */ #define NEED_STDARG_H 1 /* va_list, etc */ #define NEED_ERRNO_H 1 /* errno */ #define NEED_CTYPE_H 1 /* isdigit(), etc */ #define NEED_NETINET_IN_H 1 /* in_addr, sockaddr_in, etc */ #define NEED_ARPA_INET_H 1 /* inet_ntoa(), inet_aton(), etc */ #define NEED_STDIO_H 1 /* Standard C UNIX functions */ #define NEED_STDLIB_H 1 /* malloc(), exit(), atoi(), etc */ #define NEED_TIME_H 1 /* time(), etc */ #define NEED_SYSCTL_H 0 /* sysctl(), etc */ #define NEED_SYS_STAT_H 0 /* chmod(), mkdir(), etc */ #define NEED_SYS_UIO_H 0 /* iovec, etc */ #define NEED_FCNTL_H 1 /* open(), creat(), fcntl(), etc */ #define NEED_SYS_IOCTL_H 1 /* ioctl(), etc */ #define NEED_SYS_FILIO_H 1 /* Solaris need this for ioctl(), etc */ #define NEED_UNISTD_H 1 /* Unix standard functions */ #define NEED_STRING_H 1 /* C string functions */ #define NEED_SIGNAL_H 0 /* Signal functions */ #define NEED_SYS_SOCKET_H 1 /* Socket functions */ #define NEED_NETDB_H 1 /* Network database functions */ #define NEED_ARPA_NAMESER_H 0 /* Nameserver definitions */ #define NEED_GETUSERPW_HEADERS 0 /* Functions to retrive system passwords */ #define NEED_ARES 0 /* Functions needed for ares */ #define NEED_SSL 1 /* Needed for SSL support */ #include "includes.h" #include "irc.h" #include "conf.h" #include "access_conf.h" #include "conn_conf.h" #include "conn.h" #include "conn_io.h" #include "conn_connection.h" #include "conn_sendq.h" #include "conn_ignore.h" #include "conn_log.h" #include "chan.h" #include "chan_user.h" #include "client.h" #include "client_handle.h" #include "client_notice.h" /* VARIABLES - JONAS (31.07.2001) */ struct Conn_Struct *Conn_Head = NULL; struct Conn_Struct *Conn_Tail = NULL; unsigned long int G_Conns = 0; extern struct Client_Struct *Client_Head; /* CONN_ADD FUNCTION - JONAS (22.07.2001) */ struct Conn_Struct *conn_add(struct ConnConf_Struct *ConnConf) { struct Conn_Struct *ConnS = NULL; struct Conn_Struct *ConnS_NEW = NULL; assert(ConnConf != NULL); ConnS = conn_get(ConnConf->Name); if (ConnS != NULL) { aerrno = AEEXISTS; return(ConnS); } ConnS_NEW = malloc(sizeof(struct Conn_Struct)); if (ConnS_NEW == NULL) { aerrno = AEMALLOC; return(NULL); } memset(ConnS_NEW, 0, sizeof(struct Conn_Struct)); ConnS_NEW->Name = strdup(ConnConf->Name); ConnS_NEW->Nick = strdup(ConnConf->Nick); ConnS_NEW->AwayNick = strdup(ConnConf->AwayNick); ConnS_NEW->User = strdup(ConnConf->User); ConnS_NEW->Host = strdup(ConnConf->Host); ConnS_NEW->Mode = strdup(ConnConf->Mode); ConnS_NEW->Info = strdup(ConnConf->Info); ConnS_NEW->Chans = strdup(ConnConf->Chans); ConnS_NEW->AwayMsg = strdup(ConnConf->AwayMsg); ConnS_NEW->PublicDetachMsg = strdup(ConnConf->PublicDetachMsg); ConnS_NEW->PublicAttachMsg = strdup(ConnConf->PublicAttachMsg); ConnS_NEW->NickServNUH = strdup(ConnConf->NickServNUH); ConnS_NEW->NickServPass = strdup(ConnConf->NickServPass); ConnS_NEW->NickServText = strdup(ConnConf->NickServText); if ( (ConnS_NEW->Name == NULL) || (ConnS_NEW->Nick == NULL) || (ConnS_NEW->AwayNick == NULL) || (ConnS_NEW->User == NULL) || (ConnS_NEW->Host == NULL) || (ConnS_NEW->Mode == NULL) || (ConnS_NEW->Info == NULL) || (ConnS_NEW->Chans == NULL) || (ConnS_NEW->AwayMsg == NULL) || (ConnS_NEW->PublicDetachMsg == NULL) || (ConnS_NEW->PublicAttachMsg == NULL) || (ConnS_NEW->NickServNUH == NULL) || (ConnS_NEW->NickServPass == NULL) || (ConnS_NEW->NickServText == NULL) ) { free(ConnS_NEW->Name); free(ConnS_NEW->Nick); free(ConnS_NEW->AwayNick); free(ConnS_NEW->User); free(ConnS_NEW->Host); free(ConnS_NEW->Mode); free(ConnS_NEW->Info); free(ConnS_NEW->Chans); free(ConnS_NEW->AwayMsg); free(ConnS_NEW->PublicDetachMsg); free(ConnS_NEW->PublicAttachMsg); free(ConnS_NEW->NickServNUH); free(ConnS_NEW->NickServPass); free(ConnS_NEW->NickServText); free(ConnS_NEW); aerrno = AEMALLOC; return(NULL); } ConnS_NEW->ConfFlags = ConnConf->ConfFlags; ConnS_NEW->MaxClients = ConnConf->MaxClients; ConnS_NEW->SendMaxLines = ConnConf->SendMaxLines; ConnS_NEW->SendLineTime = ConnConf->SendLineTime; ConnS_NEW->SendMaxBuffer = ConnConf->SendMaxBuffer; ConnS_NEW->SendBufferTime = ConnConf->SendBufferTime; ConnS_NEW->ChanLogFlags = ConnConf->ChanLogFlags; conn_initconnection(ConnS_NEW); if (Conn_Head == NULL) { Conn_Head = ConnS_NEW; Conn_Tail = ConnS_NEW; } else { ConnS = Conn_Tail; ConnS->Next = ConnS_NEW; ConnS_NEW->Prev = ConnS; Conn_Tail = ConnS_NEW; } G_Conns++; aerrno = AESUCCESS; return(ConnS_NEW); } /* CONN_REM FUNCTION - JONAS (01.08.2001) */ void conn_rem(struct Conn_Struct *ConnS) { struct Client_Struct *ClientS = NULL; assert(ConnS != NULL); if (ConnS->Prev == NULL) { Conn_Head = ConnS->Next; } else { ConnS->Prev->Next = ConnS->Next; } if (ConnS->Next == NULL) { Conn_Tail = ConnS->Prev; } else { ConnS->Next->Prev = ConnS->Prev; } for (ClientS = Client_Head ; ClientS != NULL ; ClientS = ClientS->Next) { if (ClientS->ConnS == ConnS) { if (!Client_IsSentError(ClientS)) { client_notice(ClientS, "You are automatically detached from connection %s: Connection removed.", ConnS->Name); } client_detach(ClientS); } } conn_destroyignores(ConnS); conn_initconnection(ConnS); free(ConnS->Name); free(ConnS->Nick); free(ConnS->AwayNick); free(ConnS->User); free(ConnS->Host); free(ConnS->Mode); free(ConnS->Info); free(ConnS->Chans); free(ConnS->AwayMsg); free(ConnS->PublicDetachMsg); free(ConnS->PublicAttachMsg); free(ConnS->NickServNUH); free(ConnS->NickServPass); free(ConnS->NickServText); conn_destroyservers(ConnS); free(ConnS); G_Conns--; } /* CONN_GET - JONAS (06.10.2000) */ struct Conn_Struct *conn_get(const char *const NamePT) { struct Conn_Struct *ConnS = NULL; assert(NamePT != NULL); for (ConnS = Conn_Head ; ConnS != NULL ; ConnS = ConnS->Next) { if (strwm(NamePT, ConnS->Name) == TRUE) { aerrno = AESUCCESS; return(ConnS); } } aerrno = AENOMATCH; return(NULL); } /* CONN_ADDSERVER - JONAS (31.07.2001) */ struct ConnServer_Struct *conn_addserver(struct Conn_Struct *ConnS, const char *const HostPT, const unsigned long int Port, const char *const PassPT) { struct ConnServer_Struct *ConnServer = NULL; struct ConnServer_Struct *ConnServer_NEW = NULL; assert(ConnS != NULL); assert(HostPT != NULL); assert(PassPT != NULL); ConnServer = conn_getserver(ConnS, HostPT); if (ConnServer != NULL) { aerrno = AEEXISTS; return(ConnServer); } ConnServer_NEW = malloc(sizeof(struct ConnServer_Struct)); if (ConnServer_NEW == NULL) { aerrno = AEMALLOC; return(NULL); } memset(ConnServer_NEW, 0, sizeof(struct ConnServer_Struct)); ConnServer_NEW->Host = strdup(HostPT); ConnServer_NEW->Port = Port; if (ConnServer_NEW->Host == NULL) { free(ConnServer_NEW->Host); free(ConnServer_NEW); aerrno = AEMALLOC; return(NULL); } if (ConnS->Server_Head == NULL) { ConnS->Server_Head = ConnServer_NEW; ConnS->Server_Tail = ConnServer_NEW; } else { ConnServer = ConnS->Server_Tail; ConnServer->Next = ConnServer_NEW; ConnServer_NEW->Prev = ConnServer; ConnS->Server_Tail = ConnServer_NEW; } ConnS->NumServers++; aerrno = AESUCCESS; return(ConnServer_NEW); } /* CONN_REMSERVER FUNCTION - JONAS (31.07.2001) */ void conn_remserver(struct Conn_Struct *ConnS, struct ConnServer_Struct *ConnServer) { assert(ConnS != NULL); assert(ConnServer != NULL); if (ConnServer->Prev == NULL) { ConnS->Server_Head = ConnServer->Next; } else { ConnServer->Prev->Next = ConnServer->Next; } if (ConnServer->Next == NULL) { ConnS->Server_Tail = ConnServer->Prev; } else { ConnServer->Next->Prev = ConnServer->Prev; } free(ConnServer->Host); free(ConnServer); if (ConnS->ConnServerTry == ConnServer) { ConnS->ConnServerTry = NULL; } ConnS->NumServers--; } /* CONN_GETSERVER FUNCTION - JONAS (31.07.2001) */ struct ConnServer_Struct *conn_getserver(struct Conn_Struct *ConnS, const char *const HostPT) { struct ConnServer_Struct *ConnServer = NULL; assert(ConnS != NULL); assert(HostPT != NULL); for (ConnServer = ConnS->Server_Head ; ConnServer != NULL ; ConnServer = ConnServer->Next) { if (strcasecmp(ConnServer->Host, HostPT) == FALSE) { aerrno = AESUCCESS; return(ConnServer); } } aerrno = AENOMATCH; return(NULL); } /* CONN_REMSERVERS FUNCTION - JONAS (31.07.2001) */ void conn_destroyservers(struct Conn_Struct *ConnS) { while (ConnS->Server_Head != NULL) { conn_remserver(ConnS, ConnS->Server_Head); } } /* CONN_INITCONNECTION FUNCTION - JONAS (01.08.2001) */ void conn_initconnection(struct Conn_Struct *ConnS) { unsigned short int Index = 0; assert(ConnS != NULL); DEBUGPRINT(BITMASK_DEBUG_CONN, "conn_initconnection(%s)", ConnS->Name); ConnS->ResolveFlags = 0; FREE(ConnS->HostName); FREE(ConnS->HostIPS); memset(&ConnS->INAddr, 0, sizeof(ConnS->INAddr)); #if IPV6_SUPPORT memset(&ConnS->INAddr6, 0, sizeof(ConnS->INAddr6)); #endif ConnS->PortH = 0; ConnS->PortN = 0; ConnS->ServerResolveFlags = 0; FREE(ConnS->ServerHostName); FREE(ConnS->ServerHostIPS); memset(&ConnS->ServerINAddr, 0, sizeof(ConnS->ServerINAddr)); #if IPV6_SUPPORT memset(&ConnS->ServerINAddr6, 0, sizeof(ConnS->ServerINAddr6)); #endif ConnS->ServerPortH = 0; ConnS->ServerPortN = 0; FREE(ConnS->ServerPass); ConnS->ConnectionFlags = 0; ConnS->FD = FD_NONE; FREE(ConnS->ServerName); FREE(ConnS->IRCNick); for (Index = 0 ; Index <= 4 ; ++Index) { FREE(ConnS->Welcome[Index]); } for (Index = 0 ; Index < ConnS->ISupportLines ; ++Index) { free(ConnS->ISupport_String[Index]); } FREE(ConnS->ISupport_String); for (Index = 0 ; Index < ConnS->ISuppChanModes ; ++Index) { FREE(ConnS->ISuppChanMode); } for (Index = 0 ; Index < ConnS->ISuppChanUserModes ; ++Index) { FREE(ConnS->ISuppChanUserMode); } for (Index = 0 ; Index < ConnS->MOTDLines ; ++Index) { free(ConnS->MOTD_Line[Index]); } FREE(ConnS->MOTD_Line); ConnS->ISupportLines = 0; ConnS->ISuppChanUserModes = 0; ConnS->MOTDLines = 0; ConnS->UserModeFlags = 0; ConnS->ChanModeFlags = 0; ConnS->ChanListModeFlags = 0; ConnS->ChanUserModeFlags = 0; conn_initsendq(ConnS); FREE(ConnS->RecvBuffer); FREE(ConnS->SendBuffer); ConnS->NicksIndex = 0; chan_destroy(ConnS); FREE(ConnS->ISupport.Network); FREE(ConnS->ISupport.ChanTypes); FREE(ConnS->ISupport.ChanModes); FREE(ConnS->ISupport.Prefix); ConnS->ISupport.Networks = 0; ConnS->ISupport.MaxModes = IRC_MAXMODES; ConnS->ISupport.MaxChans = IRC_MAXCHANS; ConnS->ISupport.MaxBans = IRC_CHANMAXBANS; ConnS->ISupport.NickLen = IRC_NICKLEN_DEFAULT; ConnS->ISupport.AwayMsgLen = IRC_AWAYMSGLEN; ConnS->ISupport.TopicLen = IRC_CHANTOPICLEN; ConnS->ISupport.KickMsgLen = IRC_CHANKICKMSGLEN; #if 0 for (Index = 0 ; Index < ConnS->Logs ; ++Index) { free(ConnS->LogFile[Index]); } FREE(ConnS->LogFile); #endif FREE(ConnS->RawLogFile); FREE(ConnS->PrivLogFile); if (ConnS->RawLogFileFP != NULL) { fclose(ConnS->RawLogFileFP); ConnS->RawLogFileFP = NULL; } if (ConnS->PrivLogFileFP != NULL) { fclose(ConnS->PrivLogFileFP); ConnS->PrivLogFileFP = NULL; } conn_destroylogs(ConnS); }