/* * ---------------------------------------------------------------- * Night Light IRC Proxy - Listen Configuration Functions * ---------------------------------------------------------------- * Copyright (C) 1997-2003 Jonas Kvinge * All rights reserved. * * This program 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 2 of the License, or * (at your option) any later version. * * This program 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 this program; if not, write to the Free Software Foundation, Inc., * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * * Last modified by: * Jonas Kvinge (25.06.2001) * */ #define LISTEN_CONF_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 0 /* 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 0 /* ioctl(), etc */ #define NEED_SYS_FILIO_H 0 /* 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 0 /* Socket functions */ #define NEED_NETDB_H 0 /* 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 "conf.h" #include "listen_conf.h" #include "listen.h" /* VARIABLES - JONAS (06.10.2000) */ struct ListenConf_Struct *ListenConf_Head = NULL; struct ListenConf_Struct *ListenConf_Tail = NULL; unsigned long int ListenConfs = 0; extern struct Conf_Struct ConfS; /* LISTEN_CONF_READ FUNCTION - JONAS (01.07.2000) */ signed long int listen_conf_read(void) { char File[FILELEN+1] = ""; FILE *FilePT = NULL; char *TempPT = NULL; char Line[LINELEN+1] = ""; char *LinePT = NULL; unsigned short int Count = 0; char *EntryPT = NULL; char *DataPT = NULL; char *HostPT = NULL; unsigned long int Port = 0; unsigned short int SSL = FALSE; unsigned short int IPv6 = FALSE; DEBUGPRINT(BITMASK_DEBUG_CONF, "Reading listen configuration file."); if (ConfS.ListenConfFile[0] != '/') { strncat(File, ConfS.DataPath, FILELEN); if (ConfS.DataPath[strlen(ConfS.DataPath)] != '/') { strncat(File, "/", (FILELEN - strlen(File))); } } strncat(File, ConfS.ListenConfFile, (FILELEN - strlen(File))); FilePT = fopen(File, "r"); if (FilePT == NULL) { sysprint(BITMASK_ERROR, "Unable to open listen configuration file %s: [%d] %s", File, errno, strerror(errno)); return(ERROR); } listen_conf_destroy(); FOREVERLOOP { memset(&Line, 0, LINELEN+1); TempPT = fgets(Line, LINELEN, FilePT); if (TempPT == NULL) { break; } ++Count; LinePT = Line; while ((TempPT = strchr(LinePT, '\r')) != NULL) { *TempPT = '\0'; } while ((TempPT = strchr(LinePT, '\n')) != NULL) { *TempPT = '\0'; } while ((TempPT = strchr(LinePT, '\t')) != NULL) { *TempPT = ' '; } while ((LinePT[0] == ' ') || (LinePT[0] == '\t')) { ++LinePT; } if ((LinePT[0] == '#') || (LinePT[0] == ';') || (LinePT[0] == '\0')) { continue; } EntryPT = LinePT; StrMovePastToken(LinePT, ' '); DataPT = LinePT; DEBUGPRINT(BITMASK_DEBUG_CONF, "Listen Host: %s Data: %s", EntryPT, DataPT); if (strcasecmp(EntryPT, "LISTEN") == FALSE) { FREE(HostPT); Port = 0; IPv6 = 0; SSL = 0; continue; } if (EntryPT[0] == '}') { if (HostPT == NULL) { continue; } listen_conf_add(HostPT, Port, IPv6, SSL); FREE(HostPT); Port = 0; IPv6 = 0; SSL = 0; continue; } if (DataPT == NULL) { sysprint(BITMASK_ERROR, "Listen configuration error, file %s line %d: Expecting more data for \"%s\" entry.", File, Count, EntryPT); continue; } if (strcasecmp(EntryPT, "HOST") == FALSE) { HostPT = strrealloc(HostPT, DataPT); } else if (strcasecmp(EntryPT, "PORT") == FALSE) { Port = strtoul(DataPT, NULL, 0); } else if (strcasecmp(EntryPT, "IPV6") == FALSE) { if ((strcasecmp(DataPT, "y") == FALSE) || (strcasecmp(DataPT, "yes") == FALSE) || (strcasecmp(DataPT, "1") == FALSE)) { IPv6 = TRUE; } else { IPv6 = FALSE; } } else if (strcasecmp(EntryPT, "SSL") == FALSE) { if ((strcasecmp(DataPT, "y") == FALSE) || (strcasecmp(DataPT, "yes") == FALSE) || (strcasecmp(DataPT, "1") == FALSE)) { SSL = TRUE; } else { SSL = FALSE; } } } fclose(FilePT); free(HostPT); return(ListenConfs); } /* LISTEN_CONF_ADD FUNCTION - JONAS (06.10.2000) */ struct ListenConf_Struct *listen_conf_add(const char *const HostPT, const unsigned long int Port, const unsigned short int IPv6, const unsigned short int SSL) { struct ListenConf_Struct *ListenConf = NULL; struct ListenConf_Struct *ListenConf_NEW = NULL; struct Listen_Struct *ListenS = NULL; assert(HostPT != NULL); DEBUGPRINT(BITMASK_DEBUG_CONF, "Adding listen address: Host: %s - Port: %ld.", HostPT, Port); ListenConf = listen_conf_get(HostPT, Port, IPv6, SSL); if (ListenConf != NULL) { aerrno = AEEXISTS; return(ListenConf); } ListenConf_NEW = malloc(sizeof(struct ListenConf_Struct)); if (ListenConf_NEW == NULL) { aerrno = AEMALLOC; return(NULL); } memset(ListenConf_NEW, 0, sizeof(struct ListenConf_Struct)); ListenConf_NEW->Host = strdup(HostPT); if (ListenConf_NEW->Host == NULL) { free(ListenConf_NEW); aerrno = AEMALLOC; return(NULL); } ListenConf_NEW->Port = Port; ListenConf_NEW->SSL = SSL; ListenConf_NEW->IPv6 = IPv6; if (ListenConf_Head == NULL) { ListenConf_Head = ListenConf_NEW; ListenConf_Tail = ListenConf_NEW; } else { ListenConf = ListenConf_Tail; ListenConf->Next = ListenConf_NEW; ListenConf_NEW->Prev = ListenConf; ListenConf_Tail = ListenConf_NEW; } ListenConfs++; ListenS = listen_add(HostPT, Port); assert(ListenS != NULL); if (SSL == TRUE) { Listen_SetSSL(ListenS); } if (IPv6 == TRUE) { Listen_SetIPv6(ListenS); } #if !SSL_SUPPORT if (SSL == TRUE) { sysprint(BITMASK_ERROR, "Listen configuration error, entry %s:%ld has SSL enabled, but %s was compiled without SSL support! Ignoring entry!", HostPT, Port, PACKAGE); } #endif aerrno = AESUCCESS; return(ListenConf_NEW); } /* LISTEN_CONF_REM - JONAS (06.10.2000) */ void listen_conf_rem(struct ListenConf_Struct *ListenConf) { assert(ListenConf != NULL); if (ListenConf->Prev == NULL) { ListenConf_Head = ListenConf->Next; } else { ListenConf->Prev->Next = ListenConf->Next; } if (ListenConf->Next == NULL) { ListenConf_Tail = ListenConf->Prev; } else { ListenConf->Next->Prev = ListenConf->Prev; } free(ListenConf->Host); free(ListenConf); ListenConfs--; } /* LISTEN_CONF_GET - JONAS (06.10.2000) */ struct ListenConf_Struct *listen_conf_get(const char *const HostPT, const unsigned long int Port, const unsigned short int IPv6, const unsigned short int SSL) { struct ListenConf_Struct *ListenConf = NULL; assert(HostPT != NULL); for (ListenConf = ListenConf_Head ; ListenConf != NULL ; ListenConf = ListenConf->Next) { if ((strcasecmp(ListenConf->Host, HostPT) == FALSE) && (ListenConf->Port == Port) && (ListenConf->IPv6 == IPv6) && (ListenConf->SSL == SSL)) { aerrno = AESUCCESS; return(ListenConf); } } aerrno = AENOMATCH; return(NULL); } /* LISTEN_CONF_DESTROY FUNCTION - JONAS (31.07.2001) */ void listen_conf_destroy(void) { while (ListenConf_Head != NULL) { listen_conf_rem(ListenConf_Head); } }