+2000-09-16 Thomas Helvey <helveytw@home.com>
+ * ircd/s_conf.c: add code for server struct
+ * ircd/client.c: copy of class.c sort of, new file for client
+ specific operations, will move things here as appropriate,
+ currently only one function is exported from here.
+ * ircd/*.c: general logic cleanups, convert negatives to
+ positives in places.
+
2000-09-16 Thomas Helvey <helveytw@home.com>
* ircd/s_conf.c: add code for new crule data structs, strip quotes
* ircd/crule.c: clean up scary casting a bit, type safety stuff
#
# ChangeLog for ircu2.10.11
#
-# $Id: ChangeLog,v 1.163 2000-09-16 05:35:01 bleep Exp $
+# $Id: ChangeLog,v 1.164 2000-09-17 03:41:37 bleep Exp $
#
# Insert new changes at beginning of the change list.
#
extern void free_class(struct ConfClass * tmp);
extern unsigned int get_con_freq(struct ConfClass * clptr);
extern unsigned int get_client_ping(struct Client *acptr);
-extern unsigned int get_conf_class(struct ConfItem *aconf);
+extern unsigned int get_conf_class(const struct ConfItem *aconf);
extern unsigned int get_client_class(struct Client *acptr);
extern void add_class(unsigned int conclass, unsigned int ping,
unsigned int confreq, unsigned int maxli, unsigned int sendq);
*/
#ifndef INCLUDED_client_h
#define INCLUDED_client_h
+#ifndef INCLUDED_ircd_defs_h
+#include "ircd_defs.h"
+#endif
+#ifndef INCLUDED_dbuf_h
+#include "dbuf.h"
+#endif
+#ifndef INCLUDED_ircd_handler_h
+#include "ircd_handler.h"
+#endif
#ifndef INCLUDED_sys_types_h
#include <sys/types.h> /* time_t, size_t */
#define INCLUDED_sys_types_h
#include <netinet/in.h> /* in_addr */
#define INCLUDED_netinet_in_h
#endif
-#ifndef INCLUDED_dbuf_h
-#include "dbuf.h"
-#endif
-#ifndef INCLUDED_ircd_defs_h
-#include "ircd_defs.h"
-#endif
-#ifndef INCLUDED_ircd_handler_h
-#include "ircd_handler.h"
-#endif
struct ConfItem;
struct Listener;
struct DNSReply* dns_reply; /* DNS reply used during client registration */
struct ListingArgs* listing;
unsigned int max_sendq; /* cached max send queue for client */
+ unsigned int ping_freq; /* cached ping freq from client conf class */
unsigned short lastsq; /* # 2k blocks when sendqueued called last */
unsigned short port; /* and the remote port# too :-) */
unsigned char targets[MAXTARGETS]; /* Hash values of current targets */
} ShowIPType;
extern const char* get_client_name(const struct Client* sptr, int showip);
+extern unsigned int client_get_ping(const struct Client* local_client);
#endif /* INCLUDED_client_h */
* Proto types
*/
-extern void hash_init(void); /* Call me on startup */
+extern void init_hash(void); /* Call me on startup */
extern int hAddClient(struct Client *cptr);
extern int hAddChannel(struct Channel *chptr);
extern int hRemClient(struct Client *cptr);
*/
#define EmptyString(x) (!(x) || !(*x))
+/*
+ * initialize recognizers
+ */
+extern int init_string(void);
+
+extern int string_is_hostname(const char* str);
+extern int string_is_address(const char* str);
+
extern char* ircd_strncpy(char* dest, const char* src, size_t len);
extern int ircd_strcmp(const char *a, const char *b);
extern int ircd_strncmp(const char *a, const char *b, size_t n);
*/
struct ConfItem {
+ struct ConfItem* next;
unsigned int status; /* If CONF_ILLEGAL, delete when no clients */
unsigned int clients; /* Number of *LOCAL* clients using this */
struct in_addr ipnum; /* ip number of host field */
time_t hold; /* Hold until this time (calendar time) */
int dns_pending; /* a dns request is pending */
struct ConfClass* confClass; /* Class of connection */
- struct ConfItem* next;
+};
+
+struct ServerConf {
+ struct ServerConf* next;
+ char* hostname;
+ char* passwd;
+ char* alias;
+ struct in_addr address;
+ int port;
+ int dns_pending;
+ int connected;
+ time_t hold;
+ struct ConfClass* confClass;
};
/*
};
struct MotdConf {
+ struct MotdConf* next;
char* hostmask;
char* path;
- struct MotdConf* next;
};
enum {
struct CRuleNode;
struct CRuleConf {
+ struct CRuleConf* next;
char* hostmask;
char* rule;
int type;
struct CRuleNode* node;
- struct CRuleConf* next;
};
struct TRecord {
+ struct TRecord *next;
char *hostmask;
struct MotdItem *tmotd;
struct tm tmotd_tm;
- struct TRecord *next;
};
enum AuthorizationCheckResult {
extern const char* conf_crule_eval(const char* host, int mask);
-extern struct ConfItem* attach_confs_byhost(struct Client* cptr,
- const char* host, int statmask);
-extern struct ConfItem* find_conf_byhost(struct SLink* lp, const char* host,
- int statmask);
-extern struct ConfItem* find_conf_byname(struct SLink* lp, const char *name,
- int statmask);
+extern struct ConfItem* attach_confs_byhost(struct Client* cptr, const char* host, int statmask);
+extern struct ConfItem* find_conf_byhost(struct SLink* lp, const char* host, int statmask);
+extern struct ConfItem* find_conf_byname(struct SLink* lp, const char *name, int statmask);
extern struct ConfItem* conf_find_server(const char* name);
const char* conf_eval_crule(const char* name, int mask);
extern int detach_conf(struct Client *cptr, struct ConfItem *aconf);
extern enum AuthorizationCheckResult attach_conf(struct Client *cptr, struct ConfItem *aconf);
extern struct ConfItem* find_me(void);
-extern struct ConfItem* find_conf_exact(const char* name,
- const char* user,
+extern struct ConfItem* find_conf_exact(const char* name, const char* user,
const char* host, int statmask);
extern enum AuthorizationCheckResult conf_check_client(struct Client *cptr);
extern int conf_check_server(struct Client *cptr);
extern struct ConfItem* find_conf_name(const char* name, int statmask);
extern int rehash(struct Client *cptr, int sig);
-extern int conf_init(void);
+extern int init_conf(void);
extern void read_tlines(void);
extern int find_kill(struct Client *cptr);
extern int find_restrict(struct Client *cptr);
struct ConfClass *classes;
-unsigned int get_conf_class(struct ConfItem *aconf)
+unsigned int get_conf_class(const struct ConfItem* aconf)
{
if ((aconf) && (aconf->confClass))
return (ConfClass(aconf));
Debug((DEBUG_DEBUG, "No Class For %s", (aconf) ? aconf->name : "*No Conf*"));
return (BAD_CONF_CLASS);
-
}
-static unsigned int get_conf_ping(struct ConfItem *aconf)
+unsigned int get_conf_ping(struct ConfItem *aconf)
{
if ((aconf) && (aconf->confClass))
return (ConfPingFreq(aconf));
--- /dev/null
+/*
+ * IRC - Internet Relay Chat, ircd/client.c
+ * Copyright (C) 1990 Darren Reed
+ *
+ * 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 1, 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., 675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ * $Id$
+ */
+#include "client.h"
+#include "class.h"
+#include "ircd.h"
+#include "ircd_reply.h"
+#include "list.h"
+#include "numeric.h"
+#include "s_conf.h"
+#include "s_debug.h"
+#include "send.h"
+#include "struct.h"
+
+#include <assert.h>
+
+#define BAD_PING ((unsigned int)-2)
+
+unsigned int client_get_ping(const struct Client* acptr)
+{
+ unsigned int ping = 0;
+ unsigned int tmp;
+ struct ConfItem* aconf;
+ struct SLink* link;
+
+ for (link = acptr->confs; link; link = link->next) {
+ aconf = link->value.aconf;
+ if (aconf->status & (CONF_CLIENT | CONF_SERVER)) {
+ tmp = get_conf_ping(aconf);
+ if ((tmp != BAD_PING) && ((ping > tmp) || !ping))
+ ping = tmp;
+ }
+ }
+ if (0 == ping)
+ ping = PINGFREQUENCY;
+
+ Debug((DEBUG_DEBUG, "Client %s Ping %d", acptr->name, ping));
+ return (ping);
+}
+
+#if 0
+#define BAD_CONF_CLASS ((unsigned int)-1)
+#define BAD_CLIENT_CLASS ((unsigned int)-3)
+
+unsigned int get_conf_class(struct ConfItem *aconf)
+{
+ if ((aconf) && (aconf->confClass))
+ return (ConfClass(aconf));
+
+ Debug((DEBUG_DEBUG, "No Class For %s", (aconf) ? aconf->name : "*No Conf*"));
+
+ return (BAD_CONF_CLASS);
+
+}
+
+static unsigned int get_conf_ping(struct ConfItem *aconf)
+{
+ if ((aconf) && (aconf->confClass))
+ return (ConfPingFreq(aconf));
+
+ Debug((DEBUG_DEBUG, "No Ping For %s", (aconf) ? aconf->name : "*No Conf*"));
+
+ return (BAD_PING);
+}
+
+unsigned int get_client_class(struct Client *acptr)
+{
+ struct SLink *tmp;
+ struct ConfClass *cl;
+ unsigned int retc = BAD_CLIENT_CLASS;
+
+ if (acptr && !IsMe(acptr) && (acptr->confs))
+ for (tmp = acptr->confs; tmp; tmp = tmp->next)
+ {
+ if (!tmp->value.aconf || !(cl = tmp->value.aconf->confClass))
+ continue;
+ if (ConClass(cl) > retc || retc == BAD_CLIENT_CLASS)
+ retc = ConClass(cl);
+ }
+
+ Debug((DEBUG_DEBUG, "Returning Class %d For %s", retc, acptr->name));
+
+ return (retc);
+}
+unsigned int get_con_freq(struct ConfClass * clptr)
+{
+ if (clptr)
+ return (ConFreq(clptr));
+ else
+ return (CONNECTFREQUENCY);
+}
+
+/*
+ * When adding a class, check to see if it is already present first.
+ * if so, then update the information for that class, rather than create
+ * a new entry for it and later delete the old entry.
+ * if no present entry is found, then create a new one and add it in
+ * immeadiately after the first one (class 0).
+ */
+void add_class(unsigned int conClass, unsigned int ping, unsigned int confreq,
+ unsigned int maxli, unsigned int sendq)
+{
+ struct ConfClass *t, *p;
+
+ t = find_class(conClass);
+ if ((t == classes) && (conClass != 0))
+ {
+ p = (struct ConfClass *) make_class();
+ NextClass(p) = NextClass(t);
+ NextClass(t) = p;
+ }
+ else
+ p = t;
+ Debug((DEBUG_DEBUG, "Add Class %u: p %p t %p - cf: %u pf: %u ml: %u sq: %d",
+ conClass, p, t, confreq, ping, maxli, sendq));
+ ConClass(p) = conClass;
+ ConFreq(p) = confreq;
+ PingFreq(p) = ping;
+ MaxLinks(p) = maxli;
+ MaxSendq(p) = (sendq > 0) ? sendq : DEFAULTMAXSENDQLENGTH;
+ if (p != t)
+ Links(p) = 0;
+}
+
+struct ConfClass *find_class(unsigned int cclass)
+{
+ struct ConfClass *cltmp;
+
+ for (cltmp = FirstClass(); cltmp; cltmp = NextClass(cltmp))
+ if (ConClass(cltmp) == cclass)
+ return cltmp;
+ return classes;
+}
+
+void check_class(void)
+{
+ struct ConfClass *cltmp, *cltmp2;
+
+ Debug((DEBUG_DEBUG, "Class check:"));
+
+ for (cltmp2 = cltmp = FirstClass(); cltmp; cltmp = NextClass(cltmp2))
+ {
+ Debug((DEBUG_DEBUG,
+ "Class %d : CF: %d PF: %d ML: %d LI: %d SQ: %d",
+ ConClass(cltmp), ConFreq(cltmp), PingFreq(cltmp),
+ MaxLinks(cltmp), Links(cltmp), MaxSendq(cltmp)));
+ if (IsMarkedDelete(cltmp))
+ {
+ NextClass(cltmp2) = NextClass(cltmp);
+ if (Links(cltmp) == 0)
+ free_class(cltmp);
+ }
+ else
+ cltmp2 = cltmp;
+ }
+}
+
+void initclass(void)
+{
+ classes = (struct ConfClass *) make_class();
+
+ ConClass(FirstClass()) = 0;
+ ConFreq(FirstClass()) = CONNECTFREQUENCY;
+ PingFreq(FirstClass()) = PINGFREQUENCY;
+ MaxLinks(FirstClass()) = MAXIMUM_LINKS;
+ MaxSendq(FirstClass()) = DEFAULTMAXSENDQLENGTH;
+ Links(FirstClass()) = 0;
+ NextClass(FirstClass()) = NULL;
+}
+
+void report_classes(struct Client *sptr)
+{
+ struct ConfClass *cltmp;
+
+ for (cltmp = FirstClass(); cltmp; cltmp = NextClass(cltmp))
+ send_reply(sptr, RPL_STATSYLINE, 'Y', ConClass(cltmp), PingFreq(cltmp),
+ ConFreq(cltmp), MaxLinks(cltmp), MaxSendq(cltmp));
+}
+
+unsigned int get_sendq(struct Client *cptr)
+{
+ assert(0 != cptr);
+ assert(0 != cptr->local);
+
+ if (cptr->max_sendq)
+ return cptr->max_sendq;
+
+ else if (cptr->confs) {
+ struct SLink* tmp;
+ struct ConfClass* cl;
+
+ for (tmp = cptr->confs; tmp; tmp = tmp->next) {
+ if (!tmp->value.aconf || !(cl = tmp->value.aconf->confClass))
+ continue;
+ if (ConClass(cl) != BAD_CLIENT_CLASS) {
+ cptr->max_sendq = MaxSendq(cl);
+ return cptr->max_sendq;
+ }
+ }
+ }
+ return DEFAULTMAXSENDQLENGTH;
+}
+#endif
be symmetric, if HASHEQ(a,b) then HASHEQ(b,a), obvious ok but... :) */
#define HASHEQ(x,y) ((ToLower(x)) == (ToLower(y)))
-/* hash_init
+/* init_hash
* Initialize the maps used by hash functions and clear the tables */
-void hash_init(void)
+void init_hash(void)
{
int i;
int j;
continue;
}
- max_ping = IsRegistered(cptr) ? get_client_ping(cptr) : CONNECTTIMEOUT;
+ max_ping = IsRegistered(cptr) ? client_get_ping(cptr) : CONNECTTIMEOUT;
Debug((DEBUG_DEBUG, "check_pings(%s)=status:%s limit: %d current: %d",
cptr->name, (cptr->flags & FLAGS_PINGSENT) ? "[Ping Sent]" : "[]",
#ifdef CHROOTDIR
if (!set_chroot_environment())
- exit(1);
+ return 1;
#endif
#if defined(HAVE_SETRLIMIT) && defined(RLIMIT_CORE)
if (chdir(dpath)) {
fprintf(stderr, "Fail: Cannot chdir(%s): %s, check DPATH\n", dpath, strerror(errno));
- exit(2);
+ return 2;
}
if (!set_userid_if_needed())
- exit(3);
+ return 3;
/* Check paths for accessibility */
if (!check_file_access(SPATH, 'S', X_OK) ||
!check_file_access(configfile, 'C', R_OK) ||
!check_file_access(MPATH, 'M', R_OK) ||
!check_file_access(RPATH, 'R', R_OK))
- exit(4);
+ return 4;
#ifdef DEBUG
if (!check_file_access(LPATH, 'L', W_OK))
- exit(5);
+ return 5;
#endif
debug_init(thisServer.bootopt & BOOT_TTY);
open_log(*argv);
set_nomem_handler(outofmemory);
+
+ if (!init_string()) {
+ ircd_log(L_CRIT, "Failed to initialize string module");
+ return 6;
+ }
initload();
init_list();
- hash_init();
+ init_hash();
initclass();
initwhowas();
initmsgtree();
init_resolver();
- if (!conf_init()) {
+ if (!init_conf()) {
ircd_log(L_CRIT, "Failed to read configuration file %s", configfile);
- exit(6);
+ return 7;
}
if (!init_server_identity()) {
ircd_log(L_CRIT, "Failed to initialize server identity");
- exit(7);
+ return 8;
}
uping_init();
#include "ircd_string.h"
#include "ircd_defs.h"
#include "ircd_chattr.h"
+#include "ircd_log.h"
#include <assert.h>
#include <string.h>
+#include <regex.h>
/*
* include the character attribute tables here
*/
#include "chattr.tab.c"
+
+/*
+ * 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.
+ */
+static const char* hostExpr = "^([-0-9A-Za-z]*[0-9A-Za-z]\\.)+[A-Za-z]+$";
+static regex_t hostRegex;
+
+static const char* addrExpr =
+ "^((25[0-5]|2[0-4][0-9]|1[0-9]{2}|[1-9]?[0-9])\\.){1,3}(25[0-5]|2[0-4][0-9]|1[0-9]{2}|[1-9]?[0-9])$";
+static regex_t addrRegex;
+
+int init_string(void)
+{
+ /*
+ * initialize matching expressions
+ * XXX - expressions MUST be correct, don't change expressions
+ * without testing them. Might be a good idea to exit if these fail,
+ * important code depends on them.
+ * TODO: use regerror for an error message
+ */
+ if (regcomp(&hostRegex, hostExpr, REG_EXTENDED | REG_NOSUB))
+ return 0;
+
+ if (regcomp(&addrRegex, addrExpr, REG_EXTENDED | REG_NOSUB))
+ return 0;
+ return 1;
+}
+
+int string_is_hostname(const char* str)
+{
+ assert(0 != str);
+ return (strlen(str) <= HOSTLEN && 0 == regexec(&hostRegex, str, 0, 0, 0));
+}
+
+int string_is_address(const char* str)
+{
+ assert(0 != str);
+ return (0 == regexec(&addrRegex, str, 0, 0, 0));
+}
+
/*
* strtoken.c
*
int re_unkrep;
} reinfo;
-/*
- * 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.
- */
-static const char* hostExpr = "([-0-9A-Za-z]*[0-9A-Za-z]\\.)+[A-Za-z]+";
-static regex_t hostRegex;
/*
* From bind 8.3, these aren't declared in earlier versions of bind
errno = h_errno = 0;
- if (regcomp(&hostRegex, hostExpr, REG_EXTENDED | REG_NOSUB)) {
- ircd_log(L_CRIT, "Resolver: error compiling host expression %s", hostExpr);
- exit(2);
- }
start_resolver();
Debug((DEBUG_DNS, "Resolver: fd %d errno: %d h_errno: %d: %s",
ResolverFileDescriptor, errno, h_errno,
int i = 0;
assert(0 != hp);
for (name = hp->h_name; name; name = hp->h_aliases[i++]) {
- if (HOSTLEN < strlen(name) || 0 != regexec(&hostRegex, name, 0, 0, 0))
+ if (!string_is_hostname(name))
return 0;
}
return 1;
struct TRecord* tdata = NULL;
struct tm motd_tm;
-static struct LocalConf localConf;
-static struct MotdConf* motdConfList;
-static struct CRuleConf* cruleConfList;
+static struct LocalConf localConf;
+static struct MotdConf* motdConfList;
+static struct CRuleConf* cruleConfList;
+static struct ServerConf* serverConfList;
/*
* output the reason for being k lined from a file - Mmmm
return cruleConfList;
}
+void conf_add_server(const char* const* fields, int count)
+{
+ struct ServerConf* server;
+ struct in_addr addr;
+ assert(0 != fields);
+ /*
+ * missing host, password, or alias?
+ */
+ if (count < 6 || EmptyString(fields[1]) || EmptyString(fields[2]) || EmptyString(fields[3]))
+ return;
+ /*
+ * check the host
+ */
+ if (string_is_hostname(fields[1]))
+ addr.s_addr = INADDR_NONE;
+ else if (INADDR_NONE == (addr.s_addr = inet_addr(fields[1])))
+ return;
+
+ server = (struct ServerConf*) MyMalloc(sizeof(struct ServerConf));
+ assert(0 != server);
+ DupString(server->hostname, fields[1]);
+ DupString(server->passwd, fields[2]);
+ DupString(server->alias, fields[3]);
+ server->address.s_addr = addr.s_addr;
+ server->port = atoi(fields[4]);
+ server->dns_pending = 0;
+ server->connected = 0;
+ server->hold = 0;
+ server->confClass = find_class(atoi(fields[5]));
+
+ server->next = serverConfList;
+ serverConfList = server;
+
+ // if (INADDR_NONE == server->address.s_addr)
+ // lookup_confhost(server);
+}
+
+
/*
* read_configuration_file
*
* that it will be deleted when the last client
* exits...
*/
- if (!(tmp2->status & CONF_CLIENT)) {
+ if (CONF_CLIENT == (tmp2->status & CONF_CLIENT))
+ tmp = &tmp2->next;
+ else {
*tmp = tmp2->next;
tmp2->next = 0;
}
- else
- tmp = &tmp2->next;
tmp2->status |= CONF_ILLEGAL;
}
else {
* Flush out deleted I and P lines although still in use.
*/
for (tmp = &GlobalConfList; (tmp2 = *tmp);) {
- if (!(tmp2->status & CONF_ILLEGAL))
- tmp = &tmp2->next;
- else
- {
+ if (CONF_ILLEGAL == (tmp2->status & CONF_ILLEGAL)) {
*tmp = tmp2->next;
tmp2->next = NULL;
if (!tmp2->clients)
free_conf(tmp2);
}
+ else
+ tmp = &tmp2->next;
}
for (i = 0; i <= HighestFd; i++) {
if ((acptr = LocalClientArray[i])) {
}
/*
- * conf_init
+ * init_conf
*
* Read configuration file.
*
* 1, if file read
*/
-int conf_init(void)
+int init_conf(void)
{
if (read_configuration_file()) {
/*