* 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., 675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ * $Id$
*/
+#include "s_conf.h"
+#include "IPcheck.h"
+#include "class.h"
+#include "client.h"
+#include "crule.h"
+#include "fileio.h"
+#include "gline.h"
+#include "hash.h"
+#include "ircd.h"
+#include "ircd_alloc.h"
+#include "ircd_chattr.h"
+#include "ircd_log.h"
+#include "ircd_reply.h"
+#include "ircd_snprintf.h"
+#include "ircd_string.h"
+#include "list.h"
+#include "listener.h"
+#include "match.h"
+#include "numeric.h"
+#include "numnicks.h"
+#include "opercmds.h"
+#include "parse.h"
+#include "res.h"
+#include "s_bsd.h"
+#include "s_debug.h"
+#include "s_misc.h"
+#include "send.h"
+#include "sprintf_irc.h"
+#include "struct.h"
+#include "support.h"
#include "sys.h"
-#include <sys/socket.h>
-#if HAVE_FCNTL_H
+
+#include <assert.h>
+#include <arpa/inet.h>
+#include <errno.h>
#include <fcntl.h>
-#endif
+#include <netdb.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <sys/stat.h>
+#include <unistd.h>
-#if HAVE_SYS_WAIT_H
-# include <sys/wait.h>
-#endif
-#ifndef WEXITSTATUS
-# define WEXITSTATUS(stat_val) ((unsigned)(stat_val) >> 8)
-#endif
-#ifndef WIFEXITED
-# define WIFEXITED(stat_val) (((stat_val) & 255) == 0)
+#ifndef INADDR_NONE
+#define INADDR_NONE 0xffffffff
#endif
-#include <sys/stat.h>
-#ifdef R_LINES
-#include <signal.h>
-#endif
-#if HAVE_UNISTD_H
-#include <unistd.h>
+struct ConfItem* GlobalConfList = 0;
+int GlobalConfCount = 0;
+struct MotdItem* motd = NULL;
+struct MotdItem* rmotd = NULL;
+struct TRecord* tdata = NULL;
+struct tm motd_tm;
+
+
+/*
+ * output the reason for being k lined from a file - Mmmm
+ * sptr is server
+ * parv is the sender prefix
+ * filename is the file that is to be output to the K lined client
+ */
+static void killcomment(struct Client *sptr, char *parv, char *filename)
+{
+ FBFILE* file = NULL;
+ char line[80];
+ char* tmp = NULL;
+ struct stat sb;
+ struct tm* tm;
+
+ if (NULL == (file = fbopen(filename, "r"))) {
+ send_reply(sptr, ERR_NOMOTD);
+ send_reply(sptr, SND_EXPLICIT | ERR_YOUREBANNEDCREEP,
+ ":Connection from your host is refused on this server.");
+ return;
+ }
+ fbstat(&sb, file);
+ tm = localtime((time_t*) &sb.st_mtime); /* NetBSD needs cast */
+ while (fbgets(line, sizeof(line) - 1, file)) {
+ if ((tmp = strchr(line, '\n')))
+ *tmp = '\0';
+ if ((tmp = strchr(line, '\r')))
+ *tmp = '\0';
+ send_reply(sptr, RPL_MOTD, line);
+ }
+ send_reply(sptr, SND_EXPLICIT | ERR_YOUREBANNEDCREEP,
+ ":Connection from your host is refused on this server.");
+ fbclose(file);
+}
+
+struct ConfItem* make_conf(void)
+{
+ struct ConfItem* aconf;
+
+ aconf = (struct ConfItem*) MyMalloc(sizeof(struct ConfItem));
+ assert(0 != aconf);
+#ifdef DEBUGMODE
+ ++GlobalConfCount;
#endif
-#include <stdlib.h>
-#include <netdb.h>
-#include <netinet/in.h>
-#include <arpa/inet.h>
-#ifdef USE_SYSLOG
-#include <syslog.h>
+ aconf->status = CONF_ILLEGAL;
+ aconf->clients = 0;
+ aconf->ipnum.s_addr = INADDR_NONE;
+ aconf->host = 0;
+ aconf->passwd = 0;
+ aconf->name = 0;
+ aconf->port = 0;
+ aconf->hold = 0;
+ aconf->dns_pending = 0;
+ aconf->confClass = 0;
+ aconf->next = 0;
+ return aconf;
+}
+
+void delist_conf(struct ConfItem *aconf)
+{
+ if (aconf == GlobalConfList)
+ GlobalConfList = GlobalConfList->next;
+ else {
+ struct ConfItem *bconf;
+
+ for (bconf = GlobalConfList; aconf != bconf->next; bconf = bconf->next)
+ ;
+ bconf->next = aconf->next;
+ }
+ aconf->next = NULL;
+}
+
+void free_conf(struct ConfItem *aconf)
+{
+ Debug((DEBUG_DEBUG, "free_conf: %s %s %d",
+ aconf->host ? aconf->host : "*",
+ aconf->name ? aconf->name : "*",
+ aconf->port));
+ if (aconf->dns_pending)
+ delete_resolver_queries(aconf);
+ MyFree(aconf->host);
+ if (aconf->passwd)
+ memset(aconf->passwd, 0, strlen(aconf->passwd));
+ MyFree(aconf->passwd);
+ MyFree(aconf->name);
+ MyFree(aconf);
+#ifdef DEBUGMODE
+ --GlobalConfCount;
#endif
-#include "h.h"
-#include "struct.h"
-#include "s_serv.h"
-#include "opercmds.h"
-#include "numeric.h"
-#include "send.h"
-#include "s_conf.h"
-#include "class.h"
-#include "s_misc.h"
-#include "match.h"
-#include "common.h"
-#include "s_err.h"
-#include "s_bsd.h"
-#include "ircd.h"
-#include "crule.h"
-#include "res.h"
-#include "support.h"
-#include "parse.h"
-#include "numnicks.h"
-#include "sprintf_irc.h"
-#include "IPcheck.h"
-#include "hash.h"
-#include "fileio.h"
+}
+
+/*
+ * conf_dns_callback - called when resolver query finishes
+ * if the query resulted in a successful search, hp will contain
+ * a non-null pointer, otherwise hp will be null.
+ * if successful save hp in the conf item it was called with
+ */
+static void conf_dns_callback(void* vptr, struct DNSReply* reply)
+{
+ struct ConfItem* aconf = (struct ConfItem*) vptr;
+ aconf->dns_pending = 0;
+ if (reply)
+ memcpy(&aconf->ipnum, reply->hp->h_addr, sizeof(struct in_addr));
+}
+
+/*
+ * conf_dns_lookup - do a nameserver lookup of the conf host
+ * if the conf entry is currently doing a ns lookup do nothing, otherwise
+ * if the lookup returns a null pointer, set the conf dns_pending flag
+ */
+static struct DNSReply* conf_dns_lookup(struct ConfItem* aconf)
+{
+ struct DNSReply* dns_reply = 0;
+ if (!aconf->dns_pending) {
+ char buf[HOSTLEN + 1];
+ struct DNSQuery query;
+ query.vptr = aconf;
+ query.callback = conf_dns_callback;
+ host_from_uh(buf, aconf->host, HOSTLEN);
+ buf[HOSTLEN] = '\0';
+
+ if (0 == (dns_reply = gethost_byname(buf, &query)))
+ aconf->dns_pending = 1;
+ }
+ return dns_reply;
+}
+
+
+/*
+ * lookup_confhost
+ *
+ * Do (start) DNS lookups of all hostnames in the conf line and convert
+ * an IP addresses in a.b.c.d number for to IP#s.
+ */
+static void lookup_confhost(struct ConfItem *aconf)
+{
+ struct DNSReply* reply;
+
+ if (EmptyString(aconf->host) || EmptyString(aconf->name)) {
+ Debug((DEBUG_ERROR, "Host/server name error: (%s) (%s)",
+ aconf->host, aconf->name));
+ return;
+ }
+ /*
+ * Do name lookup now on hostnames given and store the
+ * ip numbers in conf structure.
+ */
+ if (IsDigit(*aconf->host)) {
+ /*
+ * rfc 1035 sez host names may not start with a digit
+ * XXX - this has changed code needs to be updated
+ */
+ aconf->ipnum.s_addr = inet_addr(aconf->host);
+ if (INADDR_NONE == aconf->ipnum.s_addr) {
+ Debug((DEBUG_ERROR, "Host/server name error: (%s) (%s)",
+ aconf->host, aconf->name));
+ }
+ }
+ else if ((reply = conf_dns_lookup(aconf)))
+ memcpy(&aconf->ipnum, reply->hp->h_addr, sizeof(struct in_addr));
+}
+
+/*
+ * conf_find_server - find a server by name or hostname
+ * returns a server conf item pointer if found, 0 otherwise
+ *
+ * NOTE: at some point when we don't have to scan the entire
+ * list it may be cheaper to look for server names and host
+ * names in separate loops (original code did it that way)
+ */
+struct ConfItem* conf_find_server(const char* name)
+{
+ struct ConfItem* conf;
+ assert(0 != name);
-RCSTAG_CC("$Id$");
+ for (conf = GlobalConfList; conf; conf = conf->next) {
+ if (CONF_SERVER == conf->status) {
+ /*
+ * Check first servernames, then try hostnames.
+ * XXX - match returns 0 if there _is_ a match... guess they
+ * haven't decided what true is yet
+ */
+ if (0 == match(name, conf->name))
+ return conf;
+ }
+ }
+ return 0;
+}
+
+/*
+ * conf_eval_crule - evaluate connection rules
+ * returns the name of the rule triggered if found, 0 otherwise
+ *
+ * Evaluate connection rules... If no rules found, allow the
+ * connect. Otherwise stop with the first true rule (ie: rules
+ * are ored together. Oper connects are effected only by D
+ * lines (CRULEALL) not d lines (CRULEAUTO).
+ */
+const char* conf_eval_crule(struct ConfItem* conf)
+{
+ struct ConfItem* rule;
+ assert(0 != conf);
-static int check_time_interval(char *, char *);
-static int lookup_confhost(aConfItem *);
-static int is_comment(char *);
-static void killcomment(aClient *sptr, char *parv, char *filename);
+ for (rule = GlobalConfList; rule; rule = rule->next) {
+ if ((CONF_CRULEALL == rule->status) && (0 == match(rule->host, conf->name))) {
+ if (crule_eval(rule->passwd))
+ return rule->name;
+ }
+ }
+ return 0;
+}
-aConfItem *conf = NULL;
-aGline *gline = NULL;
-aGline *badchan = NULL;
-aMotdItem *motd = NULL;
-aMotdItem *rmotd = NULL;
-atrecord *tdata = NULL;
-struct tm motd_tm;
/*
* field breakup for ircd.conf file.
*/
-static char *gfline = NULL;
-char *getfield(char *newline, char fs)
+static char* getfield(char* newline, char fs)
{
- char *end, *field;
+ static char* gfline = NULL;
+ char* end;
+ char* field;
if (newline)
gfline = newline;
end = field = gfline;
- if (fs != ':')
- {
+ if (fs != ':') {
if (*end == fs)
++end;
else
fs = ':';
}
- do
- {
- while (*end != fs)
- {
- if (!*end)
- {
- end = NULL;
- break;
+ do {
+ while (*end != fs) {
+ if (!*end) {
+ end = NULL;
+ break;
}
++end;
}
- }
- while (end && fs != ':' && *++end != ':' && *end != '\n');
+ } while (end && fs != ':' && *++end != ':' && *end != '\n') ;
- if (end == NULL)
- {
+ if (end == NULL) {
gfline = NULL;
if ((end = strchr(field, '\n')) == NULL)
end = field + strlen(field);
* Remove all conf entries from the client except those which match
* the status field mask.
*/
-void det_confs_butmask(aClient *cptr, int mask)
+void det_confs_butmask(struct Client *cptr, int mask)
{
- Reg1 Link *tmp, *tmp2;
+ struct SLink *tmp, *tmp2;
- for (tmp = cptr->confs; tmp; tmp = tmp2)
- {
+ for (tmp = cptr->confs; tmp; tmp = tmp2) {
tmp2 = tmp->next;
if ((tmp->value.aconf->status & mask) == 0)
detach_conf(cptr, tmp->value.aconf);
}
/*
- * Find the first (best) I line to attach.
+ * validate_hostent - make sure hostnames are valid in a hostent struct
+ * XXX - this is terrible, what's worse is it used to be in the inner
+ * loop of scanning all the I:lines --Bleep
*/
-enum AuthorizationCheckResult attach_Iline(aClient *cptr, struct hostent *hp,
- char *sockhost)
+static int validate_hostent(struct hostent* hp)
{
- Reg1 aConfItem *aconf;
- Reg3 const char *hname;
- Reg4 int i;
- static char uhost[HOSTLEN + USERLEN + 3];
- static char fullname[HOSTLEN + 1];
+ char fullname[HOSTLEN + 1];
+ int i = 0;
+ int error = 0;
+ const char* hname;
- for (aconf = conf; aconf; aconf = aconf->next)
- {
+ for (hname = hp->h_name; hname; hname = hp->h_aliases[i++]) {
+ unsigned int fullnamelen = 0;
+ unsigned int label_count = 0;
+
+ ircd_strncpy(fullname, hname, HOSTLEN);
+ fullname[HOSTLEN] = '\0';
+ /*
+ * Disallow a hostname label to contain anything but a [-a-zA-Z0-9].
+ * It may not start or end on a '.'.
+ * A label may not end on a '-', the maximum length of a label is
+ * 63 characters.
+ * On top of that (which seems to be the RFC) we demand that the
+ * top domain does not contain any digits.
+ */
+ error = (*hname == '.') ? 1 : 0; /* May not start with a '.' */
+ if (!error) {
+ char *p;
+ for (p = fullname; *p; ++p, ++fullnamelen) {
+ if (*p == '.') {
+ /* Label may not end on '-' and May not end on a '.' */
+ if (p[-1] == '-' || p[1] == 0) {
+ error = 1;
+ break;
+ }
+ label_count = 0;
+ error = 0; /* Was not top domain */
+ continue;
+ }
+ if (++label_count > 63) {
+ /* Label not longer then 63 */
+ error = 1;
+ break;
+ }
+ if (*p >= '0' && *p <= '9') {
+ /* In case this is top domain */
+ error = 1;
+ continue;
+ }
+ if (!(*p >= 'a' && *p <= 'z')
+ && !(*p >= 'A' && *p <= 'Z') && *p != '-') {
+ error = 1;
+ break;
+ }
+ }
+ }
+ if (error)
+ break;
+ }
+ return (0 == error);
+}
+
+/*
+ * check_limit_and_attach - check client limits and attach I:line
+ *
+ * Made it accept 1 charactor, and 2 charactor limits (0->99 now),
+ * and dislallow more than 255 people here as well as in ipcheck.
+ * removed the old "ONE" scheme too.
+ * -- Isomer 2000-06-22
+ */
+static enum AuthorizationCheckResult
+check_limit_and_attach(struct Client* cptr, struct ConfItem* aconf)
+{
+ int number = 255;
+
+ if (aconf->passwd) {
+ if (IsDigit(*aconf->passwd) && !aconf->passwd[1])
+ number = *aconf->passwd-'0';
+ else if (IsDigit(*aconf->passwd) && IsDigit(aconf->passwd[1]) &&
+ !aconf->passwd[2])
+ number = (*aconf->passwd-'0')*10+(aconf->passwd[1]-'0');
+ }
+ if (ip_registry_count(cptr->ip.s_addr) > number)
+ return ACR_TOO_MANY_FROM_IP;
+ return attach_conf(cptr, aconf);
+}
+
+/*
+ * Find the first (best) I line to attach.
+ */
+enum AuthorizationCheckResult attach_iline(struct Client* cptr)
+{
+ struct ConfItem* aconf;
+ const char* hname;
+ int i;
+ static char uhost[HOSTLEN + USERLEN + 3];
+ static char fullname[HOSTLEN + 1];
+ struct hostent* hp = 0;
+
+ if (cptr->dns_reply) {
+ hp = cptr->dns_reply->hp;
+ if (!validate_hostent(hp))
+ hp = 0;
+ }
+ for (aconf = GlobalConfList; aconf; aconf = aconf->next) {
if (aconf->status != CONF_CLIENT)
continue;
- if (aconf->port && aconf->port != cptr->acpt->port)
+ if (aconf->port && aconf->port != cptr->listener->port)
continue;
if (!aconf->host || !aconf->name)
continue;
- if (hp)
- for (i = 0, hname = hp->h_name; hname; hname = hp->h_aliases[i++])
- {
- size_t fullnamelen = 0;
- size_t label_count = 0;
- int error;
-
- strncpy(fullname, hname, HOSTLEN);
- fullname[HOSTLEN] = 0;
-
- /*
- * Disallow a hostname label to contain anything but a [-a-zA-Z0-9].
- * It may not start or end on a '.'.
- * A label may not end on a '-', the maximum length of a label is
- * 63 characters.
- * On top of that (which seems to be the RFC) we demand that the
- * top domain does not contain any digits.
- */
- error = (*hname == '.') ? 1 : 0; /* May not start with a '.' */
- if (!error)
- {
- char *p;
- for (p = fullname; *p; ++p, ++fullnamelen)
- {
- if (*p == '.')
- {
- if (p[-1] == '-' /* Label may not end on '-' */
- || p[1] == 0) /* May not end on a '.' */
- {
- error = 1;
- break;
- }
- label_count = 0;
- error = 0; /* Was not top domain */
- continue;
- }
- if (++label_count > 63) /* Label not longer then 63 */
- {
- error = 1;
- break;
- }
- if (*p >= '0' && *p <= '9')
- {
- error = 1; /* In case this is top domain */
- continue;
- }
- if (!(*p >= 'a' && *p <= 'z')
- && !(*p >= 'A' && *p <= 'Z') && *p != '-')
- {
- error = 1;
- break;
- }
- }
- }
- if (error)
- {
- hp = NULL;
- break;
- }
-
- add_local_domain(fullname, HOSTLEN - fullnamelen);
- Debug((DEBUG_DNS, "a_il: %s->%s", sockhost, fullname));
- if (strchr(aconf->name, '@'))
- {
- strcpy(uhost, cptr->username);
- strcat(uhost, "@");
- }
- else
- *uhost = '\0';
- strncat(uhost, fullname, sizeof(uhost) - 1 - strlen(uhost));
- uhost[sizeof(uhost) - 1] = 0;
- if (!match(aconf->name, uhost))
- {
- if (strchr(uhost, '@'))
- cptr->flags |= FLAGS_DOID;
- goto attach_iline;
- }
+ if (hp) {
+ for (i = 0, hname = hp->h_name; hname; hname = hp->h_aliases[i++]) {
+ ircd_strncpy(fullname, hname, HOSTLEN);
+ fullname[HOSTLEN] = '\0';
+
+ Debug((DEBUG_DNS, "a_il: %s->%s", cptr->sockhost, fullname));
+
+ if (strchr(aconf->name, '@')) {
+ strcpy(uhost, cptr->username);
+ strcat(uhost, "@");
+ }
+ else
+ *uhost = '\0';
+ strncat(uhost, fullname, sizeof(uhost) - 1 - strlen(uhost));
+ uhost[sizeof(uhost) - 1] = 0;
+ if (0 == match(aconf->name, uhost)) {
+ if (strchr(uhost, '@'))
+ cptr->flags |= FLAGS_DOID;
+ return check_limit_and_attach(cptr, aconf);
+ }
}
-
- if (strchr(aconf->host, '@'))
- {
- strncpy(uhost, cptr->username, sizeof(uhost) - 2);
+ }
+ if (strchr(aconf->host, '@')) {
+ ircd_strncpy(uhost, cptr->username, sizeof(uhost) - 2);
uhost[sizeof(uhost) - 2] = 0;
strcat(uhost, "@");
}
else
*uhost = '\0';
- strncat(uhost, sockhost, sizeof(uhost) - 1 - strlen(uhost));
+ strncat(uhost, cptr->sock_ip, sizeof(uhost) - 1 - strlen(uhost));
uhost[sizeof(uhost) - 1] = 0;
if (match(aconf->host, uhost))
continue;
if (strchr(uhost, '@'))
cptr->flags |= FLAGS_DOID;
- if (hp && hp->h_name)
- {
- strncpy(uhost, hp->h_name, HOSTLEN);
- uhost[HOSTLEN] = 0;
- add_local_domain(uhost, HOSTLEN - strlen(uhost));
- }
- attach_iline:
- get_sockhost(cptr, uhost);
- if (aconf->passwd)
- {
- if (isDigit(*aconf->passwd) && !aconf->passwd[1]) /* Special case: exactly one digit */
- {
- /* Refuse connections when there are already <digit> clients connected with the same IP number */
- unsigned short nr = *aconf->passwd - '0';
- if (IPcheck_nr(cptr) > nr)
- return ACR_TOO_MANY_FROM_IP; /* Already got nr with that ip# */
- }
-#ifdef USEONE
- else if (!strcmp(aconf->passwd, "ONE"))
- {
- for (i = highest_fd; i >= 0; i--)
- if (loc_clients[i] && MyUser(loc_clients[i]) &&
- loc_clients[i]->ip.s_addr == cptr->ip.s_addr)
- return ACR_TOO_MANY_FROM_IP; /* Already got one with that ip# */
- }
-#endif
- }
- return attach_conf(cptr, aconf);
+ return check_limit_and_attach(cptr, aconf);
}
return ACR_NO_AUTHORIZATION;
}
/*
- * Find the single N line and return pointer to it (from list).
- * If more than one then return NULL pointer.
+ * detach_conf - Disassociate configuration from the client.
*/
-aConfItem *count_cnlines(Link *lp)
+int detach_conf(struct Client *cptr, struct ConfItem *aconf)
{
- Reg1 aConfItem *aconf, *cline = NULL, *nline = NULL;
+ struct SLink** lp;
+ struct SLink* tmp;
- for (; lp; lp = lp->next)
- {
- aconf = lp->value.aconf;
- if (!(aconf->status & CONF_SERVER_MASK))
- continue;
- if (aconf->status == CONF_CONNECT_SERVER && !cline)
- cline = aconf;
- else if (aconf->status == CONF_NOCONNECT_SERVER && !nline)
- nline = aconf;
- }
- return nline;
-}
-
-/*
- * detach_conf
- *
- * Disassociate configuration from the client.
- */
-int detach_conf(aClient *cptr, aConfItem *aconf)
-{
- Reg1 Link **lp, *tmp;
+ assert(0 != aconf);
+ assert(0 != cptr);
+ assert(0 < aconf->clients);
lp = &(cptr->confs);
- while (*lp)
- {
- if ((*lp)->value.aconf == aconf)
- {
- if (aconf && (aconf->confClass)
- && (aconf->status & CONF_CLIENT_MASK) && ConfLinks(aconf) > 0)
- --ConfLinks(aconf);
- if (aconf && !--aconf->clients && IsIllegal(aconf))
- free_conf(aconf);
+ while (*lp) {
+ if ((*lp)->value.aconf == aconf) {
+ if (aconf->confClass && (aconf->status & CONF_CLIENT_MASK) &&
+ ConfLinks(aconf) > 0)
+ --ConfLinks(aconf);
+ if (0 == --aconf->clients && IsIllegal(aconf))
+ free_conf(aconf);
tmp = *lp;
*lp = tmp->next;
free_link(tmp);
return -1;
}
-static int is_attached(aConfItem *aconf, aClient *cptr)
+static int is_attached(struct ConfItem *aconf, struct Client *cptr)
{
- Reg1 Link *lp;
+ struct SLink *lp;
for (lp = cptr->confs; lp; lp = lp->next)
if (lp->value.aconf == aconf)
* connection). Note, that this automaticly changes the
* attachment if there was an old one...
*/
-enum AuthorizationCheckResult attach_conf(aClient *cptr, aConfItem *aconf)
+enum AuthorizationCheckResult attach_conf(struct Client *cptr, struct ConfItem *aconf)
{
- Reg1 Link *lp;
+ struct SLink *lp;
if (is_attached(aconf, cptr))
return ACR_ALREADY_AUTHORIZED;
return ACR_NO_AUTHORIZATION;
if ((aconf->status & (CONF_LOCOP | CONF_OPERATOR | CONF_CLIENT)) &&
ConfLinks(aconf) >= ConfMaxLinks(aconf) && ConfMaxLinks(aconf) > 0)
- return ACR_TOO_MANY_IN_CLASS; /* Use this for printing error message */
+ return ACR_TOO_MANY_IN_CLASS; /* Use this for printing error message */
lp = make_link();
lp->next = cptr->confs;
lp->value.aconf = aconf;
cptr->confs = lp;
- aconf->clients++;
+ ++aconf->clients;
if (aconf->status & CONF_CLIENT_MASK)
ConfLinks(aconf)++;
return ACR_OK;
}
-aConfItem *find_admin(void)
+struct ConfItem *find_admin(void)
{
- Reg1 aConfItem *aconf;
+ struct ConfItem *aconf;
- for (aconf = conf; aconf; aconf = aconf->next)
+ for (aconf = GlobalConfList; aconf; aconf = aconf->next) {
if (aconf->status & CONF_ADMIN)
break;
-
- return (aconf);
+ }
+ return aconf;
}
-aConfItem *find_me(void)
+struct ConfItem* find_me(void)
{
- Reg1 aConfItem *aconf;
- for (aconf = conf; aconf; aconf = aconf->next)
+ struct ConfItem* aconf;
+ for (aconf = GlobalConfList; aconf; aconf = aconf->next) {
if (aconf->status & CONF_ME)
break;
-
- return (aconf);
+ }
+ return aconf;
}
/*
- * attach_confs
+ * attach_confs_byname
*
* Attach a CONF line to a client if the name passed matches that for
* the conf file (for non-C/N lines) or is an exact match (C/N lines
* only). The difference in behaviour is to stop C:*::* and N:*::*.
*/
-aConfItem *attach_confs(aClient *cptr, const char *name, int statmask)
+struct ConfItem* attach_confs_byname(struct Client* cptr, const char* name,
+ int statmask)
{
- Reg1 aConfItem *tmp;
- aConfItem *first = NULL;
- int len = strlen(name);
+ struct ConfItem* tmp;
+ struct ConfItem* first = NULL;
- if (!name || len > HOSTLEN)
- return NULL;
- for (tmp = conf; tmp; tmp = tmp->next)
- {
- if ((tmp->status & statmask) && !IsIllegal(tmp) &&
- ((tmp->status & (CONF_SERVER_MASK | CONF_HUB)) == 0) &&
- tmp->name && !match(tmp->name, name))
- {
- if (attach_conf(cptr, tmp) == ACR_OK && !first)
- first = tmp;
- }
- else if ((tmp->status & statmask) && !IsIllegal(tmp) &&
- (tmp->status & (CONF_SERVER_MASK | CONF_HUB)) &&
- tmp->name && !strCasediff(tmp->name, name))
- {
- if (attach_conf(cptr, tmp) == ACR_OK && !first)
- first = tmp;
+ assert(0 != name);
+
+ if (HOSTLEN < strlen(name))
+ return 0;
+
+ for (tmp = GlobalConfList; tmp; tmp = tmp->next) {
+ if (0 != (tmp->status & statmask) && !IsIllegal(tmp)) {
+ assert(0 != tmp->name);
+ if (0 == match(tmp->name, name) || 0 == ircd_strcmp(tmp->name, name)) {
+ if (ACR_OK == attach_conf(cptr, tmp) && !first)
+ first = tmp;
+ }
}
}
- return (first);
+ return first;
}
/*
* Added for new access check meLazy
*/
-aConfItem *attach_confs_host(aClient *cptr, char *host, int statmask)
+struct ConfItem* attach_confs_byhost(struct Client* cptr, const char* host,
+ int statmask)
{
- Reg1 aConfItem *tmp;
- aConfItem *first = NULL;
- int len = strlen(host);
+ struct ConfItem* tmp;
+ struct ConfItem* first = 0;
- if (!host || len > HOSTLEN)
- return NULL;
+ assert(0 != host);
+ if (HOSTLEN < strlen(host))
+ return 0;
- for (tmp = conf; tmp; tmp = tmp->next)
- {
- if ((tmp->status & statmask) && !IsIllegal(tmp) &&
- (tmp->status & CONF_SERVER_MASK) == 0 &&
- (!tmp->host || match(tmp->host, host) == 0))
- {
- if (attach_conf(cptr, tmp) == ACR_OK && !first)
- first = tmp;
- }
- else if ((tmp->status & statmask) && !IsIllegal(tmp) &&
- (tmp->status & CONF_SERVER_MASK) &&
- (tmp->host && strCasediff(tmp->host, host) == 0))
- {
- if (attach_conf(cptr, tmp) == ACR_OK && !first)
- first = tmp;
+ for (tmp = GlobalConfList; tmp; tmp = tmp->next) {
+ if (0 != (tmp->status & statmask) && !IsIllegal(tmp)) {
+ assert(0 != tmp->host);
+ if (0 == match(tmp->host, host) || 0 == ircd_strcmp(tmp->host, host)) {
+ if (ACR_OK == attach_conf(cptr, tmp) && !first)
+ first = tmp;
+ }
}
}
- return (first);
+ return first;
}
/*
* find a conf entry which matches the hostname and has the same name.
*/
-aConfItem *find_conf_exact(char *name, char *user, char *host, int statmask)
+struct ConfItem* find_conf_exact(const char* name, const char* user,
+ const char* host, int statmask)
{
- Reg1 aConfItem *tmp;
+ struct ConfItem *tmp;
char userhost[USERLEN + HOSTLEN + 3];
- sprintf_irc(userhost, "%s@%s", user, host);
+ if (user)
+ ircd_snprintf(0, userhost, sizeof(userhost), "%s@%s", user, host);
+ else
+ ircd_strncpy(userhost, host, sizeof(userhost) - 1);
- for (tmp = conf; tmp; tmp = tmp->next)
- {
+ for (tmp = GlobalConfList; tmp; tmp = tmp->next) {
if (!(tmp->status & statmask) || !tmp->name || !tmp->host ||
- strCasediff(tmp->name, name))
+ 0 != ircd_strcmp(tmp->name, name))
continue;
/*
* Accept if the *real* hostname (usually sockecthost)
*/
if (match(tmp->host, userhost))
continue;
- if (tmp->status & (CONF_OPERATOR | CONF_LOCOP))
- {
+ if (tmp->status & (CONF_OPERATOR | CONF_LOCOP)) {
if (tmp->clients < MaxLinks(tmp->confClass))
- return tmp;
+ return tmp;
else
- continue;
+ continue;
}
else
return tmp;
}
- return NULL;
+ return 0;
}
-aConfItem *find_conf(Link *lp, const char *name, int statmask)
+struct ConfItem* find_conf_byname(struct SLink* lp, const char* name,
+ int statmask)
{
- Reg1 aConfItem *tmp;
- int namelen = name ? strlen(name) : 0;
+ struct ConfItem* tmp;
+ assert(0 != name);
- if (namelen > HOSTLEN)
- return (aConfItem *)0;
+ if (HOSTLEN < strlen(name))
+ return 0;
- for (; lp; lp = lp->next)
- {
+ for (; lp; lp = lp->next) {
tmp = lp->value.aconf;
- if ((tmp->status & statmask) &&
- (((tmp->status & (CONF_SERVER_MASK | CONF_HUB)) &&
- tmp->name && !strCasediff(tmp->name, name)) ||
- ((tmp->status & (CONF_SERVER_MASK | CONF_HUB)) == 0 &&
- tmp->name && !match(tmp->name, name))))
- return tmp;
+ if (0 != (tmp->status & statmask)) {
+ assert(0 != tmp->name);
+ if (0 == ircd_strcmp(tmp->name, name) || 0 == match(tmp->name, name))
+ return tmp;
+ }
}
- return NULL;
+ return 0;
}
/*
* Added for new access check meLazy
*/
-aConfItem *find_conf_host(Link *lp, char *host, int statmask)
+struct ConfItem* find_conf_byhost(struct SLink* lp, const char* host,
+ int statmask)
{
- Reg1 aConfItem *tmp;
- int hostlen = host ? strlen(host) : 0;
+ struct ConfItem* tmp = NULL;
+ assert(0 != host);
- if (hostlen > HOSTLEN || BadPtr(host))
- return (aConfItem *)NULL;
- for (; lp; lp = lp->next)
- {
+ if (HOSTLEN < strlen(host))
+ return 0;
+
+ for (; lp; lp = lp->next) {
tmp = lp->value.aconf;
- if (tmp->status & statmask &&
- (!(tmp->status & CONF_SERVER_MASK || tmp->host) ||
- (tmp->host && !match(tmp->host, host))))
- return tmp;
+ if (0 != (tmp->status & statmask)) {
+ assert(0 != tmp->host);
+ if (0 == match(tmp->host, host))
+ return tmp;
+ }
}
- return NULL;
+ return 0;
}
/*
* Find a conf line using the IP# stored in it to search upon.
* Added 1/8/92 by Avalon.
*/
-aConfItem *find_conf_ip(Link *lp, char *ip, char *user, int statmask)
+struct ConfItem* find_conf_byip(struct SLink* lp, const char* ip,
+ int statmask)
{
- Reg1 aConfItem *tmp;
- Reg2 char *s;
+ struct ConfItem* tmp;
- for (; lp; lp = lp->next)
- {
+ for (; lp; lp = lp->next) {
tmp = lp->value.aconf;
- if (!(tmp->status & statmask))
- continue;
- s = strchr(tmp->host, '@');
- *s = '\0';
- if (match(tmp->host, user))
- {
- *s = '@';
- continue;
+ if (0 != (tmp->status & statmask)) {
+ if (0 == memcmp(&tmp->ipnum, ip, sizeof(struct in_addr)))
+ return tmp;
}
- *s = '@';
- if (!memcmp(&tmp->ipnum, ip, sizeof(struct in_addr)))
- return tmp;
}
- return NULL;
+ return 0;
}
/*
*
* - looks for a match on all given fields.
*/
-static aConfItem *find_conf_entry(aConfItem *aconf, unsigned int mask)
+static struct ConfItem *find_conf_entry(struct ConfItem *aconf,
+ unsigned int mask)
{
- Reg1 aConfItem *bconf;
+ struct ConfItem *bconf;
+ assert(0 != aconf);
- for (bconf = conf, mask &= ~CONF_ILLEGAL; bconf; bconf = bconf->next)
- {
+ mask &= ~CONF_ILLEGAL;
+
+ for (bconf = GlobalConfList; bconf; bconf = bconf->next) {
if (!(bconf->status & mask) || (bconf->port != aconf->port))
continue;
- if ((BadPtr(bconf->host) && !BadPtr(aconf->host)) ||
- (BadPtr(aconf->host) && !BadPtr(bconf->host)))
+ if ((EmptyString(bconf->host) && !EmptyString(aconf->host)) ||
+ (EmptyString(aconf->host) && !EmptyString(bconf->host)))
continue;
- if (!BadPtr(bconf->host) && strCasediff(bconf->host, aconf->host))
+ if (!EmptyString(bconf->host) && 0 != ircd_strcmp(bconf->host, aconf->host))
continue;
- if ((BadPtr(bconf->passwd) && !BadPtr(aconf->passwd)) ||
- (BadPtr(aconf->passwd) && !BadPtr(bconf->passwd)))
+ if ((EmptyString(bconf->passwd) && !EmptyString(aconf->passwd)) ||
+ (EmptyString(aconf->passwd) && !EmptyString(bconf->passwd)))
continue;
- if (!BadPtr(bconf->passwd) && (!isDigit(*bconf->passwd) || bconf->passwd[1])
+ if (!EmptyString(bconf->passwd) && (!IsDigit(*bconf->passwd) || bconf->passwd[1])
#ifdef USEONE
- && strCasediff(bconf->passwd, "ONE")
+ && 0 != ircd_strcmp(bconf->passwd, "ONE")
#endif
- && strCasediff(bconf->passwd, aconf->passwd))
+ && 0 != ircd_strcmp(bconf->passwd, aconf->passwd))
continue;
- if ((BadPtr(bconf->name) && !BadPtr(aconf->name)) ||
- (BadPtr(aconf->name) && !BadPtr(bconf->name)))
+ if ((EmptyString(bconf->name) && !EmptyString(aconf->name)) ||
+ (EmptyString(aconf->name) && !EmptyString(bconf->name)))
continue;
- if (!BadPtr(bconf->name) && strCasediff(bconf->name, aconf->name))
+ if (!EmptyString(bconf->name) && 0 != ircd_strcmp(bconf->name, aconf->name))
continue;
break;
}
* as a result of an operator issuing this command, else assume it has been
* called as a result of the server receiving a HUP signal.
*/
-int rehash(aClient *cptr, int sig)
+int rehash(struct Client *cptr, int sig)
{
- Reg1 aConfItem **tmp = &conf, *tmp2;
- Reg2 aConfClass *cltmp;
- Reg1 aClient *acptr;
- Reg2 aMotdItem *temp;
- Reg2 int i;
- int ret = 0, found_g;
-
- if (sig == 1)
- sendto_ops("Got signal SIGHUP, reloading ircd conf. file");
-
- for (i = 0; i <= highest_fd; i++)
- if ((acptr = loc_clients[i]) && !IsMe(acptr))
- {
- /*
- * Nullify any references from client structures to
- * this host structure which is about to be freed.
- * Could always keep reference counts instead of
- * this....-avalon
- */
- acptr->hostp = NULL;
- }
-
- while ((tmp2 = *tmp))
- if (tmp2->clients || tmp2->status & CONF_LISTEN_PORT)
- {
+ struct ConfItem** tmp = &GlobalConfList;
+ struct ConfItem* tmp2;
+ struct ConfClass* cltmp;
+ struct Client* acptr;
+ struct MotdItem* temp;
+ int i;
+ int ret = 0;
+ int found_g = 0;
+
+ if (1 == sig)
+ sendto_opmask_butone(0, SNO_OLDSNO,
+ "Got signal SIGHUP, reloading ircd conf. file");
+
+ while ((tmp2 = *tmp)) {
+ if (tmp2->clients) {
/*
* Configuration entry is still in use by some
* local clients, cannot delete it--mark it so
* that it will be deleted when the last client
* exits...
*/
- if (!(tmp2->status & (CONF_LISTEN_PORT | CONF_CLIENT)))
- {
- *tmp = tmp2->next;
- tmp2->next = NULL;
+ if (!(tmp2->status & CONF_CLIENT)) {
+ *tmp = tmp2->next;
+ tmp2->next = 0;
}
else
- tmp = &tmp2->next;
+ tmp = &tmp2->next;
tmp2->status |= CONF_ILLEGAL;
}
- else
- {
+ else {
*tmp = tmp2->next;
/* free expression trees of connect rules */
if ((tmp2->status & (CONF_CRULEALL | CONF_CRULEAUTO)) &&
- (tmp2->passwd != NULL))
- crule_free(&(tmp2->passwd));
+ (tmp2->passwd != NULL))
+ crule_free(&(tmp2->passwd));
free_conf(tmp2);
}
+ }
/*
* We don't delete the class table, rather mark all entries
clearNickJupes();
if (sig != 2)
- flush_cache();
- if (initconf(0) == -1) /* This calls check_class(), */
- check_class(); /* unless it fails */
+ flush_resolver_cache();
+
+ mark_listeners_closing();
+
+ if (!conf_init()) /* This calls check_class(), */
+ check_class(); /* unless it fails */
+
+ /*
+ * make sure that the server listener is re-added so it doesn't get
+ * closed
+ */
close_listeners();
/*
* Flush out deleted I and P lines although still in use.
*/
- for (tmp = &conf; (tmp2 = *tmp);)
+ for (tmp = &GlobalConfList; (tmp2 = *tmp);) {
if (!(tmp2->status & CONF_ILLEGAL))
tmp = &tmp2->next;
else
*tmp = tmp2->next;
tmp2->next = NULL;
if (!tmp2->clients)
- free_conf(tmp2);
+ free_conf(tmp2);
}
-
- for (i = 0; i <= highest_fd; i++) {
- if ((acptr = loc_clients[i]) && !IsMe(acptr)) {
+ }
+ for (i = 0; i <= HighestFd; i++) {
+ if ((acptr = LocalClientArray[i])) {
+ assert(!IsMe(acptr));
if (IsServer(acptr)) {
- det_confs_butmask(acptr,
- ~(CONF_HUB | CONF_LEAF | CONF_UWORLD | CONF_ILLEGAL));
- attach_confs(acptr, acptr->name, CONF_HUB | CONF_LEAF | CONF_UWORLD);
+ det_confs_butmask(acptr,
+ ~(CONF_HUB | CONF_LEAF | CONF_UWORLD | CONF_ILLEGAL));
+ attach_confs_byname(acptr, acptr->name,
+ CONF_HUB | CONF_LEAF | CONF_UWORLD);
}
+ /* Because admin's are getting so uppity about people managing to
+ * get past K/G's etc, we'll "fix" the bug by actually explaining
+ * whats going on.
+ */
if ((found_g = find_kill(acptr))) {
- sendto_op_mask(found_g == -2 ? SNO_GLINE : SNO_OPERKILL,
- found_g == -2 ? "G-line active for %s" : "K-line active for %s",
- get_client_name(acptr, FALSE));
- if (exit_client(cptr, acptr, &me, found_g == -2 ? "G-lined" :
- "K-lined") == CPTR_KILLED)
- ret = CPTR_KILLED;
+ sendto_opmask_butone(0, found_g == -2 ? SNO_GLINE : SNO_OPERKILL,
+ found_g == -2 ? "G-line active for %s%s" :
+ "K-line active for %s%s",
+ IsUnknown(acptr) ? "Unregistered Client ":"",
+ get_client_name(acptr, HIDE_IP));
+ if (exit_client(cptr, acptr, &me, found_g == -2 ? "G-lined" :
+ "K-lined") == CPTR_KILLED)
+ ret = CPTR_KILLED;
}
-#if defined(R_LINES) && defined(R_LINES_REHASH) && !defined(R_LINES_OFTEN)
- if (find_restrict(acptr)) {
- sendto_ops("Restricting %s, closing lp", get_client_name(acptr, FALSE));
- if (exit_client(cptr, acptr, &me, "R-lined") == CPTR_KILLED)
- ret = CPTR_KILLED;
- }
-#endif
}
}
-
- /* free old motd structs */
+ /*
+ * free old motd structs
+ */
while (motd) {
temp = motd->next;
- RunFree(motd);
+ MyFree(motd);
motd = temp;
}
while (rmotd) {
temp = rmotd->next;
- RunFree(rmotd);
+ MyFree(rmotd);
rmotd = temp;
}
/* reload motd files */
read_tlines();
rmotd = read_motd(RPATH);
motd = read_motd(MPATH);
-
return ret;
}
/*
- * initconf
+ * conf_init
*
* Read configuration file.
*
- * returns -1, if file cannot be opened
- * 0, if file opened
+ * returns 0, if file cannot be opened
+ * 1, if file read
*/
#define MAXCONFLINKS 150
-unsigned short server_port;
-int initconf(int opt)
+int conf_init(void)
{
static char quotes[9][2] = {
{'b', '\b'},
{'\\', '\\'},
{0, 0}
};
- Reg1 char *tmp, *s;
+ char *tmp, *s;
FBFILE *file;
int i;
char line[512];
- int ccount = 0, ncount = 0;
- aConfItem *aconf = NULL;
+ int ccount = 0;
+ struct ConfItem *aconf = 0;
- Debug((DEBUG_DEBUG, "initconf(): ircd.conf = %s", configfile));
- if (NULL == (file = fbopen(configfile, "r")))
- {
- return -1;
+ Debug((DEBUG_DEBUG, "conf_init: ircd.conf = %s", configfile));
+ if (0 == (file = fbopen(configfile, "r"))) {
+ return 0;
}
- while (fbgets(line, sizeof(line) - 1, file))
- {
+ while (fbgets(line, sizeof(line) - 1, file)) {
if ((tmp = strchr(line, '\n')))
*tmp = '\0';
/*
* Do quoting of characters and # detection.
*/
- for (tmp = line; *tmp; tmp++)
- {
- if (*tmp == '\\')
- {
- for (i = 0; quotes[i][0]; i++)
- if (quotes[i][0] == *(tmp + 1))
- {
- *tmp = quotes[i][1];
- break;
- }
- if (!quotes[i][0])
- *tmp = *(tmp + 1);
- if (!*(tmp + 1))
- break;
- else
- for (s = tmp; (*s = *(s + 1)); s++)
- ;
+ for (tmp = line; *tmp; tmp++) {
+ if (*tmp == '\\') {
+ for (i = 0; quotes[i][0]; i++) {
+ if (quotes[i][0] == *(tmp + 1)) {
+ *tmp = quotes[i][1];
+ break;
+ }
+ }
+ if (!quotes[i][0])
+ *tmp = *(tmp + 1);
+ if (!*(tmp + 1))
+ break;
+ else {
+ for (s = tmp; (*s = *(s + 1)); s++)
+ ;
+ }
}
else if (*tmp == '#')
- *tmp = '\0';
+ *tmp = '\0';
}
if (!*line || line[0] == '#' || line[0] == '\n' ||
- line[0] == ' ' || line[0] == '\t')
+ line[0] == ' ' || line[0] == '\t')
continue;
/* Could we test if it's conf line at all? -Vesa */
- if (line[1] != ':')
- {
+ if (line[1] != ':') {
Debug((DEBUG_ERROR, "Bad config line: %s", line));
+ sendto_op_mask(SNO_OLDSNO,"Bad Config line");
continue;
}
if (aconf)
tmp = getfield(line, ':');
if (!tmp)
continue;
- switch (*tmp)
- {
- case 'A': /* Name, e-mail address of administrator */
- case 'a': /* of this server. */
- aconf->status = CONF_ADMIN;
- break;
- case 'C': /* Server where I should try to connect */
- case 'c': /* in case of lp failures */
- ccount++;
- aconf->status = CONF_CONNECT_SERVER;
- break;
- /* Connect rule */
- case 'D':
- aconf->status = CONF_CRULEALL;
- break;
- /* Connect rule - autos only */
- case 'd':
- aconf->status = CONF_CRULEAUTO;
- break;
- case 'H': /* Hub server line */
- case 'h':
- aconf->status = CONF_HUB;
- break;
- case 'I': /* Just plain normal irc client trying */
- case 'i': /* to connect me */
- aconf->status = CONF_CLIENT;
- break;
- case 'K': /* Kill user line on irc.conf */
- aconf->status = CONF_KILL;
- break;
- case 'k': /* Kill user line based on IP in ircd.conf */
- aconf->status = CONF_IPKILL;
- break;
- /* Operator. Line should contain at least */
- /* password and host where connection is */
- case 'L': /* guaranteed leaf server */
- case 'l':
- aconf->status = CONF_LEAF;
- break;
- /* Me. Host field is name used for this host */
- /* and port number is the number of the port */
- case 'M':
- case 'm':
- aconf->status = CONF_ME;
- break;
- case 'N': /* Server where I should NOT try to */
- case 'n': /* connect in case of lp failures */
- /* but which tries to connect ME */
- ++ncount;
- aconf->status = CONF_NOCONNECT_SERVER;
- break;
- case 'O':
- aconf->status = CONF_OPERATOR;
- break;
- /* Local Operator, (limited privs --SRB) */
- case 'o':
- aconf->status = CONF_LOCOP;
- break;
- case 'P': /* listen port line */
- case 'p':
- aconf->status = CONF_LISTEN_PORT;
- break;
-#ifdef R_LINES
- case 'R': /* extended K line */
- case 'r': /* Offers more options of how to restrict */
- aconf->status = CONF_RESTRICT;
- break;
-#endif
- case 'T': /* print out different motd's */
- case 't': /* based on hostmask */
- aconf->status = CONF_TLINES;
- break;
- case 'U': /* Underworld server, allowed to hack modes */
- case 'u': /* *Every* server on the net must define the same !!! */
- aconf->status = CONF_UWORLD;
- break;
- case 'Y':
- case 'y':
- aconf->status = CONF_CLASS;
- break;
- default:
- Debug((DEBUG_ERROR, "Error in config file: %s", line));
- break;
+ switch (*tmp) {
+ case 'A': /* Name, e-mail address of administrator */
+ case 'a': /* of this server. */
+ aconf->status = CONF_ADMIN;
+ break;
+ case 'C': /* Server where I should try to connect */
+ case 'c': /* in case of lp failures */
+ ++ccount;
+ aconf->status = CONF_SERVER;
+ break;
+ /* Connect rule */
+ case 'D':
+ aconf->status = CONF_CRULEALL;
+ break;
+ /* Connect rule - autos only */
+ case 'd':
+ aconf->status = CONF_CRULEAUTO;
+ break;
+ case 'H': /* Hub server line */
+ case 'h':
+ aconf->status = CONF_HUB;
+ break;
+ case 'I': /* Just plain normal irc client trying */
+ case 'i': /* to connect me */
+ aconf->status = CONF_CLIENT;
+ break;
+ case 'K': /* Kill user line on irc.conf */
+ aconf->status = CONF_KILL;
+ break;
+ case 'k': /* Kill user line based on IP in ircd.conf */
+ aconf->status = CONF_IPKILL;
+ break;
+ /* Operator. Line should contain at least */
+ /* password and host where connection is */
+ case 'L': /* guaranteed leaf server */
+ case 'l':
+ aconf->status = CONF_LEAF;
+ break;
+ /* Me. Host field is name used for this host */
+ /* and port number is the number of the port */
+ case 'M':
+ case 'm':
+ aconf->status = CONF_ME;
+ break;
+ case 'O':
+ aconf->status = CONF_OPERATOR;
+ break;
+ /* Local Operator, (limited privs --SRB) */
+ case 'o':
+ aconf->status = CONF_LOCOP;
+ break;
+ case 'P': /* listen port line */
+ case 'p':
+ aconf->status = CONF_LISTEN_PORT;
+ break;
+ case 'T': /* print out different motd's */
+ case 't': /* based on hostmask */
+ aconf->status = CONF_TLINES;
+ break;
+ case 'U': /* Underworld server, allowed to hack modes */
+ case 'u': /* *Every* server on the net must define the same !!! */
+ aconf->status = CONF_UWORLD;
+ break;
+ case 'Y':
+ case 'y':
+ aconf->status = CONF_CLASS;
+ break;
+ default:
+ Debug((DEBUG_ERROR, "Error in config file: %s", line));
+ sendto_op_mask(SNO_OLDSNO,"Unknown prefix in config file: %c",*tmp);
+ break;
}
if (IsIllegal(aconf))
continue;
- for (;;) /* Fake loop, that I can use break here --msa */
- {
+ for (;;) { /* Fake loop, that I can use break here --msa */
if ((tmp = getfield(NULL, ':')) == NULL)
- break;
+ break;
DupString(aconf->host, tmp);
if ((tmp = getfield(NULL, (aconf->status == CONF_KILL
- || aconf->status == CONF_IPKILL) ? '"' : ':')) == NULL)
- break;
+ || aconf->status == CONF_IPKILL) ? '"' : ':')) == NULL)
+ break;
DupString(aconf->passwd, tmp);
if ((tmp = getfield(NULL, ':')) == NULL)
- break;
+ break;
DupString(aconf->name, tmp);
if ((tmp = getfield(NULL, ':')) == NULL)
- break;
+ break;
aconf->port = atoi(tmp);
tmp = getfield(NULL, ':');
- if (aconf->status & CONF_ME)
- {
- server_port = aconf->port;
- if (!tmp)
- {
- Debug((DEBUG_FATAL, "Your M: line must have the Numeric, "
- "assigned to you by routing-com, behind the port number!\n"));
-#ifdef USE_SYSLOG
- syslog(LOG_WARNING, "Your M: line must have the Numeric, "
- "assigned to you by routing-com, behind the port number!\n");
-#endif
- exit(-1);
- }
- SetYXXServerName(&me, atoi(tmp)); /* Our Numeric Nick */
+ if (aconf->status & CONF_ME) {
+ if (!tmp) {
+ Debug((DEBUG_FATAL, "Your M: line must have the Numeric, "
+ "assigned to you by routing-com!\n"));
+ ircd_log(L_WARNING, "Your M: line must have the Numeric, "
+ "assigned to you by routing-com!\n");
+ exit(-1);
+ }
+ SetYXXServerName(&me, atoi(tmp)); /* Our Numeric Nick */
}
else if (tmp)
- aconf->confClass = find_class(atoi(tmp));
+ aconf->confClass = find_class(atoi(tmp));
break;
}
/*
* If conf line is a class definition, create a class entry
* for it and make the conf_line illegal and delete it.
*/
- if (aconf->status & CONF_CLASS)
- {
+ if (aconf->status & CONF_CLASS) {
add_class(atoi(aconf->host), atoi(aconf->passwd),
- atoi(aconf->name), aconf->port, tmp ? atoi(tmp) : 0);
+ atoi(aconf->name), aconf->port, tmp ? atoi(tmp) : 0);
continue;
}
/*
* Associate each conf line with a class by using a pointer
* to the correct class record. -avalon
*/
- if (aconf->status & (CONF_CLIENT_MASK | CONF_LISTEN_PORT))
- {
+ if (aconf->status & CONF_CLIENT_MASK) {
if (aconf->confClass == 0)
- aconf->confClass = find_class(0);
+ aconf->confClass = find_class(0);
}
- if (aconf->status & (CONF_LISTEN_PORT | CONF_CLIENT))
- {
- aConfItem *bconf;
-
- if ((bconf = find_conf_entry(aconf, aconf->status)))
- {
- delist_conf(bconf);
- bconf->status &= ~CONF_ILLEGAL;
- if (aconf->status == CONF_CLIENT)
- {
- char *passwd = bconf->passwd;
- bconf->passwd = aconf->passwd;
- aconf->passwd = passwd;
- ConfLinks(bconf) -= bconf->clients;
- bconf->confClass = aconf->confClass;
- if (bconf->confClass)
- ConfLinks(bconf) += bconf->clients;
- }
- free_conf(aconf);
- aconf = bconf;
+ if (aconf->status & CONF_LISTEN_PORT) {
+ int is_server = 0;
+ int is_hidden = 0;
+ if (!EmptyString(aconf->name)) {
+ const char* x = aconf->name;
+ if ('S' == ToUpper(*x))
+ is_server = 1;
+ ++x;
+ if ('H' == ToUpper(*x))
+ is_hidden = 1;
+ }
+ add_listener(aconf->port, aconf->passwd, aconf->host,
+ is_server, is_hidden);
+ continue;
+ }
+ if (aconf->status & CONF_CLIENT) {
+ struct ConfItem *bconf;
+
+ if ((bconf = find_conf_entry(aconf, aconf->status))) {
+ delist_conf(bconf);
+ bconf->status &= ~CONF_ILLEGAL;
+ if (aconf->status == CONF_CLIENT) {
+ /*
+ * copy the password field in case it changed
+ */
+ MyFree(bconf->passwd);
+ bconf->passwd = aconf->passwd;
+ aconf->passwd = 0;
+
+ ConfLinks(bconf) -= bconf->clients;
+ bconf->confClass = aconf->confClass;
+ if (bconf->confClass)
+ ConfLinks(bconf) += bconf->clients;
+ }
+ free_conf(aconf);
+ aconf = bconf;
}
- else if (aconf->host && aconf->status == CONF_LISTEN_PORT)
- add_listener(aconf);
}
- if (aconf->status & CONF_SERVER_MASK)
- if (ncount > MAXCONFLINKS || ccount > MAXCONFLINKS ||
- !aconf->host || strchr(aconf->host, '*') ||
- strchr(aconf->host, '?') || !aconf->name)
- continue;
-
- if (aconf->status & (CONF_SERVER_MASK | CONF_LOCOP | CONF_OPERATOR))
- if (!strchr(aconf->host, '@') && *aconf->host != '/')
- {
- char *newhost;
- int len = 3; /* *@\0 = 3 */
-
- len += strlen(aconf->host);
- newhost = (char *)RunMalloc(len);
- sprintf_irc(newhost, "*@%s", aconf->host);
- RunFree(aconf->host);
- aconf->host = newhost;
+ if (aconf->status & CONF_SERVER) {
+ if (ccount > MAXCONFLINKS || !aconf->host || strchr(aconf->host, '*') ||
+ strchr(aconf->host, '?') || !aconf->name)
+ continue;
+ }
+ if (aconf->status & (CONF_LOCOP | CONF_OPERATOR)) {
+ if (!strchr(aconf->host, '@')) {
+ char* newhost;
+ int len = 3; /* *@\0 = 3 */
+
+ len += strlen(aconf->host);
+ newhost = (char*) MyMalloc(len);
+ assert(0 != newhost);
+ ircd_snprintf(0, newhost, len, "*@%s", aconf->host);
+ MyFree(aconf->host);
+ aconf->host = newhost;
}
- if (aconf->status & CONF_SERVER_MASK)
- {
- if (BadPtr(aconf->passwd))
- continue;
- else if (!(opt & BOOT_QUICK))
- lookup_confhost(aconf);
+ }
+ if (aconf->status & CONF_SERVER) {
+ if (EmptyString(aconf->passwd))
+ continue;
+ lookup_confhost(aconf);
}
/* Create expression tree from connect rule...
* If there's a parsing error, nuke the conf structure */
- if (aconf->status & (CONF_CRULEALL | CONF_CRULEAUTO))
- {
- RunFree(aconf->passwd);
- if ((aconf->passwd = (char *)crule_parse(aconf->name)) == NULL)
- {
- free_conf(aconf);
- aconf = NULL;
- continue;
+ if (aconf->status & (CONF_CRULEALL | CONF_CRULEAUTO)) {
+ MyFree(aconf->passwd);
+ if ((aconf->passwd = (char *)crule_parse(aconf->name)) == NULL) {
+ free_conf(aconf);
+ aconf = NULL;
+ continue;
}
}
* if previously defined. Note, that "info"-field can be
* changed by "/rehash".
*/
- if (aconf->status == CONF_ME)
- {
- strncpy(me.info, aconf->name, sizeof(me.info) - 1);
- if (me.name[0] == '\0' && aconf->host[0])
- strncpy(me.name, aconf->host, sizeof(me.name) - 1);
- if (portnum == 0)
- portnum = aconf->port;
+ if (aconf->status == CONF_ME) {
+ ircd_strncpy(me.info, aconf->name, REALLEN);
+ }
+
+ if (aconf->status == CONF_IPKILL) {
+ /*
+ * Here we use the same kludge as in listener.c to parse
+ * a.b.c.d, or a.b.c.*, or a.b.c.d/e.
+ */
+ int class;
+ char ipname[16];
+ int ad[4] = { 0 };
+ int bits2=0;
+ class=sscanf(aconf->host,"%d.%d.%d.%d/%d",
+ &ad[0], &ad[1], &ad[2], &ad[3], &bits2);
+ if (class!=5) {
+ aconf->bits=class*8;
+ }
+ else {
+ aconf->bits=bits2;
+ }
+ sprintf_irc(ipname,"%d.%d.%d.%d",ad[0], ad[1], ad[2], ad[3]);
+
+ /* This ensures endian correctness */
+ aconf->ipnum.s_addr = inet_addr(ipname);
+ Debug((DEBUG_DEBUG,"IPkill: %s = %08x/%i (%08x)",ipname,
+ aconf->ipnum.s_addr,aconf->bits,NETMASK(aconf->bits)));
}
/*
if ((aconf->status == CONF_UWORLD) && (aconf->passwd) && (*aconf->passwd))
addNickJupes(aconf->passwd);
- if (aconf->status & CONF_ADMIN)
- if (!aconf->host || !aconf->passwd || !aconf->name)
- {
- Debug((DEBUG_FATAL, "Your A: line must have 4 fields!\n"));
-#ifdef USE_SYSLOG
- syslog(LOG_WARNING, "Your A: line must have 4 fields!\n");
-#endif
- exit(-1);
+ if (aconf->status & CONF_ADMIN) {
+ if (!aconf->host || !aconf->passwd || !aconf->name) {
+ Debug((DEBUG_FATAL, "Your A: line must have 4 fields!\n"));
+ ircd_log(L_WARNING, "Your A: line must have 4 fields!\n");
+ exit(-1);
}
-
+ }
collapse(aconf->host);
collapse(aconf->name);
Debug((DEBUG_NOTICE,
- "Read Init: (%d) (%s) (%s) (%s) (%u) (%p)",
- aconf->status, aconf->host, aconf->passwd,
- aconf->name, aconf->port, aconf->confClass));
- aconf->next = conf;
- conf = aconf;
+ "Read Init: (%d) (%s) (%s) (%s) (%u) (%p)",
+ aconf->status, aconf->host, aconf->passwd,
+ aconf->name, aconf->port, aconf->confClass));
+ aconf->next = GlobalConfList;
+ GlobalConfList = aconf;
aconf = NULL;
}
if (aconf)
free_conf(aconf);
fbclose(file);
check_class();
- nextping = nextconnect = now;
- return 0;
-}
-
-/*
- * lookup_confhost
- *
- * Do (start) DNS lookups of all hostnames in the conf line and convert
- * an IP addresses in a.b.c.d number for to IP#s.
- */
-static int lookup_confhost(aConfItem *aconf)
-{
- Reg2 char *s;
- Reg3 struct hostent *hp;
- Link ln;
-
- if (BadPtr(aconf->host) || BadPtr(aconf->name))
- goto badlookup;
- if ((s = strchr(aconf->host, '@')))
- s++;
- else
- s = aconf->host;
- /*
- * Do name lookup now on hostnames given and store the
- * ip numbers in conf structure.
- */
- if (!isAlpha(*s) && !isDigit(*s))
- goto badlookup;
-
- /*
- * Prepare structure in case we have to wait for a
- * reply which we get later and store away.
- */
- ln.value.aconf = aconf;
- ln.flags = ASYNC_CONF;
-
- if (isDigit(*s))
- aconf->ipnum.s_addr = inet_addr(s);
- else if ((hp = gethost_byname(s, &ln)))
- memcpy(&(aconf->ipnum), hp->h_addr, sizeof(struct in_addr));
-
- if (aconf->ipnum.s_addr == INADDR_NONE)
- goto badlookup;
- return 0;
-badlookup:
- if (aconf->ipnum.s_addr == INADDR_NONE)
- memset(&aconf->ipnum, 0, sizeof(struct in_addr));
- Debug((DEBUG_ERROR, "Host/server name error: (%s) (%s)",
- aconf->host, aconf->name));
- return -1;
+ nextping = nextconnect = CurrentTime;
+ return 1;
}
/* read_tlines
- * Read info from T:lines into trecords which include the file
+ * Read info from T:lines into TRecords which include the file
* timestamp, the hostmask, and the contents of the motd file
* -Ghostwolf 7sep97
*/
void read_tlines()
{
- aConfItem *tmp;
- atrecord *temp, *last = NULL; /* Init. to avoid compiler warning */
- aMotdItem *amotd;
+ struct ConfItem *tmp;
+ struct TRecord *temp;
+ struct TRecord *last = NULL; /* Init. to avoid compiler warning */
+ struct MotdItem *amotd;
/* Free the old trecords and the associated motd contents first */
while (tdata)
while (tdata->tmotd)
{
amotd = tdata->tmotd->next;
- RunFree(tdata->tmotd);
+ MyFree(tdata->tmotd);
tdata->tmotd = amotd;
}
- RunFree(tdata);
+ MyFree(tdata);
tdata = last;
}
- for (tmp = conf; tmp; tmp = tmp->next)
- if (tmp->status == CONF_TLINES && tmp->host && tmp->passwd)
- {
- temp = (atrecord *) RunMalloc(sizeof(atrecord));
- if (!temp)
- outofmemory();
+ for (tmp = GlobalConfList; tmp; tmp = tmp->next) {
+ if (tmp->status == CONF_TLINES && tmp->host && tmp->passwd) {
+ temp = (struct TRecord*) MyMalloc(sizeof(struct TRecord));
+ assert(0 != temp);
+
temp->hostmask = tmp->host;
temp->tmotd = read_motd(tmp->passwd);
temp->tmotd_tm = motd_tm;
temp->next = NULL;
if (!tdata)
- tdata = temp;
+ tdata = temp;
else
- last->next = temp;
+ last->next = temp;
last = temp;
}
+ }
}
-int find_kill(aClient *cptr)
+/*
+ * find_kill
+ * input:
+ * client pointer
+ * returns:
+ * 0: Client may continue to try and connect
+ * -1: Client was K/k:'d - sideeffect: reason was sent.
+ * -2: Client was G/g:'d - sideeffect: reason was sent.
+ * sideeffects:
+ * Client may have been sent a reason why they are denied, as above.
+ */
+int find_kill(struct Client *cptr)
{
- char reply[256], *host, *name;
- aConfItem *tmp;
- aGline *agline = NULL;
+ const char* host;
+ const char* name;
+ struct ConfItem* tmp;
+ struct Gline* agline = NULL;
+
+ assert(0 != cptr);
if (!cptr->user)
return 0;
host = cptr->sockhost;
name = cptr->user->username;
- if (strlen(host) > (size_t)HOSTLEN ||
- (name ? strlen(name) : 0) > (size_t)HOSTLEN)
- return (0);
-
- reply[0] = '\0';
-
- for (tmp = conf; tmp; tmp = tmp->next)
- /* Added a check against the user's IP address as well.
- * If the line is either CONF_KILL or CONF_IPKILL, check it; if and only
- * if it's CONF_IPKILL, check the IP address as well (the && below will
- * short circuit and the match won't even get run) -Kev
+ assert(strlen(host) <= HOSTLEN);
+ assert((name ? strlen(name) : 0) <= HOSTLEN);
+
+ /* 2000-07-14: Rewrote this loop for massive speed increases.
+ * -- Isomer
+ */
+ for (tmp = GlobalConfList; tmp; tmp = tmp->next) {
+
+ if ((tmp->status & CONF_KLINE) == 0)
+ continue;
+
+ /*
+ * What is this for? You can K: by port?!
+ * -- Isomer
*/
- if ((tmp->status & CONF_KLINE) && tmp->host && tmp->name &&
- (match(tmp->host, host) == 0 ||
- ((tmp->status == CONF_IPKILL) &&
- match(tmp->host, inetntoa(cptr->ip)) == 0)) &&
- (!name || match(tmp->name, name) == 0) &&
- (!tmp->port || (tmp->port == cptr->acpt->port)))
- {
- /*
- * Can short-circuit evaluation - not taking chances
- * because check_time_interval destroys tmp->passwd
- * - Mmmm
- */
- if (BadPtr(tmp->passwd))
- break;
- else if (is_comment(tmp->passwd))
- break;
- else if (check_time_interval(tmp->passwd, reply))
- break;
+ if (tmp->port && tmp->port != cptr->listener->port)
+ continue;
+
+ if (!tmp->name || match(tmp->name, name) != 0)
+ continue;
+
+ if (!tmp->host)
+ break;
+
+ if (tmp->status != CONF_IPKILL) {
+ if (match(tmp->host, host) == 0)
+ break;
}
-
- if (reply[0])
- sendto_one(cptr, reply, me.name, ERR_YOUREBANNEDCREEP, cptr->name);
- else if (tmp)
- {
- if (BadPtr(tmp->passwd))
- sendto_one(cptr,
- ":%s %d %s :Connection from your host is refused on this server.",
- me.name, ERR_YOUREBANNEDCREEP, cptr->name);
- else
- {
- if (*tmp->passwd == '"')
- {
- char *sbuf =
- sprintf_irc(sendbuf, ":%s %d %s :%s", me.name, ERR_YOUREBANNEDCREEP,
- cptr->name, &tmp->passwd[1]);
- sbuf[-1] = '.'; /* Overwrite last quote with a dot */
- sendbufto_one(cptr);
+ else { /* k: by IP */
+ Debug((DEBUG_DEBUG, "ip: %08x network: %08x/%i mask: %08x",
+ cptr->ip.s_addr, tmp->ipnum.s_addr, tmp->bits,
+ NETMASK(tmp->bits)));
+ if ((cptr->ip.s_addr & NETMASK(tmp->bits)) == tmp->ipnum.s_addr)
+ break;
+ }
+ }
+ if (tmp) {
+ if (EmptyString(tmp->passwd))
+ send_reply(cptr, SND_EXPLICIT | ERR_YOUREBANNEDCREEP,
+ ":Connection from your host is refused on this server.");
+ else {
+ if (*tmp->passwd == '"') {
+ send_reply(cptr, SND_EXPLICIT | ERR_YOUREBANNEDCREEP, ":%*s.",
+ strlen(tmp->passwd + 1) - 1, tmp->passwd + 1);
}
else if (*tmp->passwd == '!')
- killcomment(cptr, cptr->name, &tmp->passwd[1]);
+ killcomment(cptr, cptr->name, &tmp->passwd[1]);
else
#ifdef COMMENT_IS_FILE
- killcomment(cptr, cptr->name, tmp->passwd);
+ killcomment(cptr, cptr->name, tmp->passwd);
#else
- sendto_one(cptr, ":%s %d %s :%s.", me.name, ERR_YOUREBANNEDCREEP,
- cptr->name, tmp->passwd);
+ send_reply(cptr, SND_EXPLICIT | ERR_YOUREBANNEDCREEP, ":%s.",
+ tmp->passwd);
#endif
}
}
/* find active glines */
/* added a check against the user's IP address to find_gline() -Kev */
- else if ((agline = find_gline(cptr, NULL)) && GlineIsActive(agline))
- sendto_one(cptr, ":%s %d %s :%s.", me.name, ERR_YOUREBANNEDCREEP,
- cptr->name, agline->reason);
+ else if ((agline = gline_lookup(cptr, 0)) && GlineIsActive(agline))
+ send_reply(cptr, SND_EXPLICIT | ERR_YOUREBANNEDCREEP, ":%s.",
+ GlineReason(agline));
else
- agline = NULL; /* if a gline was found, it was inactive */
-
- return (tmp ? -1 : (agline ? -2 : 0));
-}
-
-#ifdef R_LINES
-/*
- * find_restrict
- *
- * Works against host/name and calls an outside program
- * to determine whether a client is allowed to connect. This allows
- * more freedom to determine who is legal and who isn't, for example
- * machine load considerations. The outside program is expected to
- * return a reply line where the first word is either 'Y' or 'N' meaning
- * "Yes Let them in" or "No don't let them in." If the first word
- * begins with neither 'Y' or 'N' the default is to let the person on.
- * It returns a value of 0 if the user is to be let through -Hoppie
- */
-int find_restrict(aClient *cptr)
-{
- aConfItem *tmp;
- char reply[80], temprpl[80];
- char *rplhold = reply, *host, *name, *s;
- char rplchar = 'Y';
- int pi[2], rc = 0, n;
- FBFILE *file = NULL;
-
- if (!cptr->user)
- return 0;
- name = cptr->user->username;
- host = cptr->sockhost;
- Debug((DEBUG_INFO, "R-line check for %s[%s]", name, host));
-
- for (tmp = conf; tmp; tmp = tmp->next)
- {
- if (tmp->status != CONF_RESTRICT ||
- (tmp->host && host && match(tmp->host, host)) ||
- (tmp->name && name && match(tmp->name, name)))
- continue;
-
- if (BadPtr(tmp->passwd))
- {
- sendto_ops("Program missing on R-line %s/%s, ignoring", name, host);
- continue;
- }
+ agline = NULL; /* if a gline was found, it was inactive */
- if (pipe(pi) == -1)
- {
- report_error("Error creating pipe for R-line %s: %s", &me);
- return 0;
- }
- switch (rc = fork())
- {
- case -1:
- report_error("Error forking for R-line %s: %s", &me);
- return 0;
- case 0:
- {
- Reg1 int i;
-
- close(pi[0]);
- for (i = 2; i < MAXCONNECTIONS; i++)
- if (i != pi[1])
- close(i);
- if (pi[1] != 2)
- dup2(pi[1], 2);
- dup2(2, 1);
- if (pi[1] != 2 && pi[1] != 1)
- close(pi[1]);
- execlp(tmp->passwd, tmp->passwd, name, host, 0);
- exit(-1);
- }
- default:
- close(pi[1]);
- break;
- }
- *reply = '\0';
- file = fdbopen(pi[0], "r");
- while (fbgets(temprpl, sizeof(temprpl) - 1, file))
- {
- if ((s = strchr(temprpl, '\n')))
- *s = '\0';
- if (strlen(temprpl) + strlen(reply) < sizeof(reply) - 2)
- sprintf_irc(rplhold, "%s %s", rplhold, temprpl);
- else
- {
- sendto_ops("R-line %s/%s: reply too long!", name, host);
- break;
- }
- }
- fbclose(file);
- kill(rc, SIGKILL); /* cleanup time */
- wait(0);
-
- rc = 0;
- while (*rplhold == ' ')
- rplhold++;
- rplchar = *rplhold; /* Pull out the yes or no */
- while (*rplhold != ' ')
- rplhold++;
- while (*rplhold == ' ')
- rplhold++;
- strcpy(reply, rplhold);
- rplhold = reply;
-
- if ((rc = (rplchar == 'n' || rplchar == 'N')))
- break;
- }
- if (rc)
- {
- sendto_one(cptr, ":%s %d %s :Restriction: %s",
- me.name, ERR_YOUREBANNEDCREEP, cptr->name, reply);
+ if (tmp)
return -1;
- }
+ if (agline)
+ return -2;
+
return 0;
}
-#endif
-/*
- * output the reason for being k lined from a file - Mmmm
- * sptr is server
- * parv is the sender prefix
- * filename is the file that is to be output to the K lined client
- */
-static void killcomment(aClient *sptr, char *parv, char *filename)
+struct MotdItem* read_motd(const char* motdfile)
{
- FBFILE *file = NULL;
- char line[80];
- Reg1 char *tmp;
- struct stat sb;
- struct tm *tm;
-
- if (NULL == (file = fbopen(filename, "r")))
- {
- sendto_one(sptr, err_str(ERR_NOMOTD), me.name, parv);
- sendto_one(sptr,
- ":%s %d %s :Connection from your host is refused on this server.",
- me.name, ERR_YOUREBANNEDCREEP, parv);
- return;
+ FBFILE* file = NULL;
+ struct MotdItem* temp;
+ struct MotdItem* newmotd;
+ struct MotdItem* last;
+ struct stat sb;
+ char line[80];
+ char* tmp;
+
+ if (NULL == (file = fbopen(motdfile, "r"))) {
+ Debug((DEBUG_ERROR, "Couldn't open \"%s\": %s", motdfile, strerror(errno)));
+ return NULL;
}
- fbstat(&sb, file);
- tm = localtime((time_t *) & sb.st_mtime); /* NetBSD needs cast */
- while (fbgets(line, sizeof(line) - 1, file))
- {
- if ((tmp = strchr(line, '\n')))
+ if (-1 == fbstat(&sb, file)) {
+ fbclose(file);
+ return NULL;
+ }
+ newmotd = last = NULL;
+ motd_tm = *localtime((time_t *) & sb.st_mtime); /* NetBSD needs cast */
+ while (fbgets(line, sizeof(line) - 1, file)) {
+ if ((tmp = (char *)strchr(line, '\n')))
*tmp = '\0';
- if ((tmp = strchr(line, '\r')))
+ if ((tmp = (char *)strchr(line, '\r')))
*tmp = '\0';
- /* sendto_one(sptr,
- * ":%s %d %s : %s.",
- * me.name, ERR_YOUREBANNEDCREEP, parv,line); */
- sendto_one(sptr, rpl_str(RPL_MOTD), me.name, parv, line);
+ temp = (struct MotdItem*) MyMalloc(sizeof(struct MotdItem));
+ assert(0 != temp);
+ strcpy(temp->line, line);
+ temp->next = NULL;
+ if (!newmotd)
+ newmotd = temp;
+ else
+ last->next = temp;
+ last = temp;
}
- sendto_one(sptr,
- ":%s %d %s :Connection from your host is refused on this server.",
- me.name, ERR_YOUREBANNEDCREEP, parv);
fbclose(file);
- return;
+ return newmotd;
}
+
/*
- * is the K line field an interval or a comment? - Mmmm
+ * Ordinary client access check. Look for conf lines which have the same
+ * status as the flags passed.
*/
-static int is_comment(char *comment)
+enum AuthorizationCheckResult conf_check_client(struct Client *cptr)
{
- size_t i;
- for (i = 0; i < strlen(comment); i++)
- if ((comment[i] != ' ') && (comment[i] != '-')
- && (comment[i] != ',') && ((comment[i] < '0') || (comment[i] > '9')))
- return (1);
+ enum AuthorizationCheckResult acr = ACR_OK;
+
+ ClearAccess(cptr);
- return (0);
+ if ((acr = attach_iline(cptr))) {
+ Debug((DEBUG_DNS, "ch_cl: access denied: %s[%s]",
+ cptr->name, cptr->sockhost));
+ return acr;
+ }
+ return ACR_OK;
}
/*
- * check against a set of time intervals
+ * check_server()
+ *
+ * Check access for a server given its name (passed in cptr struct).
+ * Must check for all C/N lines which have a name which matches the
+ * name given and a host which matches. A host alias which is the
+ * same as the server name is also acceptable in the host field of a
+ * C/N line.
+ *
+ * Returns
+ * 0 = Success
+ * -1 = Access denied
+ * -2 = Bad socket.
*/
-static int check_time_interval(char *interval, char *reply)
+int conf_check_server(struct Client *cptr)
{
- struct tm *tptr;
- char *p;
- int perm_min_hours, perm_min_minutes, perm_max_hours, perm_max_minutes;
- int nowm, perm_min, perm_max;
+ struct ConfItem* c_conf = NULL;
+ struct SLink* lp;
- tptr = localtime(&now);
- nowm = tptr->tm_hour * 60 + tptr->tm_min;
+ Debug((DEBUG_DNS, "sv_cl: check access for %s[%s]",
+ cptr->name, cptr->sockhost));
- while (interval)
- {
- p = strchr(interval, ',');
- if (p)
- *p = '\0';
- if (sscanf(interval, "%2d%2d-%2d%2d", &perm_min_hours, &perm_min_minutes,
- &perm_max_hours, &perm_max_minutes) != 4)
- {
- if (p)
- *p = ',';
- return (0);
- }
- if (p)
- *(p++) = ',';
- perm_min = 60 * perm_min_hours + perm_min_minutes;
- perm_max = 60 * perm_max_hours + perm_max_minutes;
- /*
- * The following check allows intervals over midnight ...
- */
- if ((perm_min < perm_max)
- ? (perm_min <= nowm && nowm <= perm_max)
- : (perm_min <= nowm || nowm <= perm_max))
- {
- printf(reply,
- ":%%s %%d %%s :%s %d:%02d to %d:%02d.",
- "You are not allowed to connect from",
- perm_min_hours, perm_min_minutes, perm_max_hours, perm_max_minutes);
- return (ERR_YOUREBANNEDCREEP);
- }
- if ((perm_min < perm_max)
- ? (perm_min <= nowm + 5 && nowm + 5 <= perm_max)
- : (perm_min <= nowm + 5 || nowm + 5 <= perm_max))
- {
- sprintf_irc(reply, ":%%s %%d %%s :%d minute%s%s",
- perm_min - nowm, (perm_min - nowm) > 1 ? "s " : " ",
- "and you will be denied for further access");
- return (ERR_YOUWILLBEBANNED);
+ if (IsUnknown(cptr) && !attach_confs_byname(cptr, cptr->name, CONF_SERVER)) {
+ Debug((DEBUG_DNS, "No C/N lines for %s", cptr->sockhost));
+ return -1;
+ }
+ lp = cptr->confs;
+ /*
+ * We initiated this connection so the client should have a C and N
+ * line already attached after passing through the connect_server()
+ * function earlier.
+ */
+ if (IsConnecting(cptr) || IsHandshake(cptr)) {
+ c_conf = find_conf_byname(lp, cptr->name, CONF_SERVER);
+ if (!c_conf) {
+ sendto_opmask_butone(0, SNO_OLDSNO, "Connect Error: lost C:line for %s",
+ cptr->name);
+ det_confs_butmask(cptr, 0);
+ return -1;
}
- interval = p;
}
- return (0);
-}
-aMotdItem *read_motd(char *motdfile)
-{
- FBFILE *file = NULL;
- register aMotdItem *temp, *newmotd, *last;
- struct stat sb;
- char line[80];
- register char *tmp;
+ ClearAccess(cptr);
- if (NULL == (file = fbopen(motdfile, "r")))
- {
- Debug((DEBUG_ERROR, "Couldn't open \"%s\": %s", motdfile, strerror(errno)));
- return NULL;
- }
- if (-1 == fbstat(&sb, file))
- {
- return NULL;
+ if (!c_conf) {
+ if (cptr->dns_reply) {
+ int i;
+ struct hostent* hp = cptr->dns_reply->hp;
+ const char* name = hp->h_name;
+ /*
+ * If we are missing a C or N line from above, search for
+ * it under all known hostnames we have for this ip#.
+ */
+ for (i = 0; name; name = hp->h_aliases[i++]) {
+ if ((c_conf = find_conf_byhost(lp, name, CONF_SERVER))) {
+ ircd_strncpy(cptr->sockhost, name, HOSTLEN);
+ break;
+ }
+ }
+ if (!c_conf) {
+ for (i = 0; hp->h_addr_list[i]; i++) {
+ if ((c_conf = find_conf_byip(lp, hp->h_addr_list[i], CONF_SERVER)))
+ break;
+ }
+ }
+ }
+ else {
+ /*
+ * Check for C lines with the hostname portion the ip number
+ * of the host the server runs on. This also checks the case where
+ * there is a server connecting from 'localhost'.
+ */
+ c_conf = find_conf_byhost(lp, cptr->sockhost, CONF_SERVER);
+ }
}
- newmotd = last = NULL;
- motd_tm = *localtime((time_t *) & sb.st_mtime); /* NetBSD needs cast */
- while (fbgets(line, sizeof(line) - 1, file))
- {
- if ((tmp = (char *)strchr(line, '\n')))
- *tmp = '\0';
- if ((tmp = (char *)strchr(line, '\r')))
- *tmp = '\0';
- temp = (aMotdItem *) RunMalloc(sizeof(aMotdItem));
- if (!temp)
- outofmemory();
- strcpy(temp->line, line);
- temp->next = NULL;
- if (!newmotd)
- newmotd = temp;
- else
- last->next = temp;
- last = temp;
+ /*
+ * Attach by IP# only if all other checks have failed.
+ * It is quite possible to get here with the strange things that can
+ * happen when using DNS in the way the irc server does. -avalon
+ */
+ if (!c_conf)
+ c_conf = find_conf_byip(lp, (const char*) &cptr->ip, CONF_SERVER);
+ /*
+ * detach all conf lines that got attached by attach_confs()
+ */
+ det_confs_butmask(cptr, 0);
+ /*
+ * if no C or no N lines, then deny access
+ */
+ if (!c_conf) {
+ Debug((DEBUG_DNS, "sv_cl: access denied: %s[%s@%s]",
+ cptr->name, cptr->username, cptr->sockhost));
+ return -1;
}
- fbclose(file);
- return newmotd;
+ ircd_strncpy(cptr->name, c_conf->name, HOSTLEN);
+ /*
+ * attach the C and N lines to the client structure for later use.
+ */
+ attach_conf(cptr, c_conf);
+ attach_confs_byname(cptr, cptr->name, CONF_HUB | CONF_LEAF | CONF_UWORLD);
+
+ if (INADDR_NONE == c_conf->ipnum.s_addr)
+ c_conf->ipnum.s_addr = cptr->ip.s_addr;
+
+ Debug((DEBUG_DNS, "sv_cl: access ok: %s[%s]", cptr->name, cptr->sockhost));
+ return 0;
}
+