#include "s_misc.h"
#include "send.h"
#include "struct.h"
-#include "support.h"
#include "sys.h"
#include <stdlib.h>
#include <stdio.h>
extern struct ServerConf* serverConfList;
extern struct s_map* GlobalServiceMapList;
extern struct qline* GlobalQuarantineList;
-
int yylex(void);
/* Now all the globals we need :/... */
- int tping, tconn, maxlinks, sendq, port, invert;
- int stringno;
- char *name, *pass, *host, *origin;
+ int tping, tconn, maxlinks, sendq, port, invert, stringno;
+ char *name, *pass, *host, *ip, *username, *origin, *hub_limit;
char *stringlist[MAX_STRINGS];
struct ConnectionClass *c_class;
- struct ConfItem *aconf;
struct DenyConf *dconf;
struct ServerConf *sconf;
struct qline *qconf = NULL;
%token PINGFREQ
%token CONNECTFREQ
%token MAXLINKS
+%token MAXHOPS
%token SENDQ
%token NAME
%token HOST
+%token IP
+%token USERNAME
%token PASS
%token LOCAL
%token SECONDS
%token TFILE
%token RULE
%token ALL
-%token IP
%token FEATURES
%token QUARANTINE
%token PSEUDO
%token USERMODE
%token IAUTH
%token TIMEOUT
-/* and now a lot of priviledges... */
+/* and now a lot of privileges... */
%token TPRIV_CHAN_LIMIT TPRIV_MODE_LCHAN TPRIV_DEOP_LCHAN TPRIV_WALK_LCHAN
%token TPRIV_LOCAL_KILL TPRIV_REHASH TPRIV_RESTART TPRIV_DIE
%token TPRIV_GLINE TPRIV_LOCAL_GLINE TPRIV_LOCAL_JUPE TPRIV_LOCAL_BADCHAN
%token TPRIV_LOCAL_OPMODE TPRIV_OPMODE TPRIV_SET TPRIV_WHOX TPRIV_BADCHAN
%token TPRIV_SEE_CHAN TPRIV_SHOW_INVIS TPRIV_SHOW_ALL_INVIS TPRIV_PROPAGATE
%token TPRIV_UNLIMIT_QUERY TPRIV_DISPLAY TPRIV_SEE_OPERS TPRIV_WIDE_GLINE
-%token TPRIV_FORCE_OPMODE TPRIV_FORCE_LOCAL_OPMODE
+%token TPRIV_FORCE_OPMODE TPRIV_FORCE_LOCAL_OPMODE TPRIV_APASS_OPMODE
/* and some types... */
%type <num> sizespec
%type <num> timespec timefactor factoredtimes factoredtime
/* Blocks in the config file... */
blocks: blocks block | block;
block: adminblock | generalblock | classblock | connectblock |
- serverblock | operblock | portblock | jupeblock | clientblock |
+ uworldblock | operblock | portblock | jupeblock | clientblock |
killblock | cruleblock | motdblock | featuresblock | quarantineblock |
pseudoblock | iauthblock | error;
}
;
-/* this is an arithmatic expression */
+/* this is an arithmetic expression */
expr: NUMBER
{
$$ = $1;
$$ = $1 / $3;
}
/* leave this out until we find why it makes BSD yacc dump core -larne
- | '-' expr %prec NEG
- = {
+ | '-' expr %prec NEG {
$$ = -$2;
} */
| '(' expr ')' {
addNickJupes($3);
} ';';
-generalblock: GENERAL '{' generalitems '}' ';' ;
+generalblock: GENERAL '{' generalitems '}'
+{
+ if (localConf.name == NULL)
+ parse_error("Your General block must contain a name.");
+ if (localConf.numeric == 0)
+ parse_error("Your General block must contain a numeric (between 1 and 4095).");
+} ';' ;
generalitems: generalitem generalitems | generalitem;
generalitem: generalnumeric | generalname | generalvhost | generaldesc | error;
generalnumeric: NUMERIC '=' NUMBER ';'
generalvhost: VHOST '=' QSTRING ';'
{
- ircd_aton(&localConf.vhost_address, $3);
+ struct irc_in_addr addr;
+ if (!ircd_aton(&addr, $3))
+ parse_error("Invalid virtual host '%s'.", $3);
+ else if (irc_in_addr_is_ipv4(&addr))
+ memcpy(&VirtualHost_v4.addr, &addr, sizeof(addr));
+ else
+ memcpy(&VirtualHost_v6.addr, &addr, sizeof(addr));
};
adminblock: ADMIN '{' adminitems '}'
};
classblock: CLASS {
- name = NULL;
tping = 90;
- tconn = 0;
- maxlinks = 0;
- sendq = 0;
- pass = NULL;
- memset(&privs, 0, sizeof(privs));
- memset(&privs_dirty, 0, sizeof(privs_dirty));
} '{' classitems '}'
{
if (name != NULL)
else {
parse_error("Missing name in class block");
}
+ name = NULL;
pass = NULL;
+ tconn = 0;
+ maxlinks = 0;
+ sendq = 0;
+ memset(&privs, 0, sizeof(privs));
+ memset(&privs_dirty, 0, sizeof(privs_dirty));
} ';';
classitems: classitem classitems | classitem;
classitem: classname | classpingfreq | classconnfreq | classmaxlinks |
};
classusermode: USERMODE '=' QSTRING ';'
{
- if (pass)
- MyFree(pass);
+ MyFree(pass);
DupString(pass, $3);
};
connectblock: CONNECT
{
- name = pass = host = origin = NULL;
- c_class = NULL;
- port = 0;
+ maxlinks = 65535;
} '{' connectitems '}'
{
if (name != NULL && pass != NULL && host != NULL && c_class != NULL
&& !strchr(host, '*') && !strchr(host, '?'))
{
- aconf = make_conf();
- aconf->status = CONF_SERVER;
+ struct ConfItem *aconf = make_conf(CONF_SERVER);
aconf->name = name;
aconf->origin_name = origin;
aconf->passwd = pass;
aconf->conn_class = c_class;
aconf->address.port = port;
- aconf->status = CONF_SERVER;
aconf->host = host;
- aconf->next = GlobalConfList;
+ aconf->maximum = maxlinks;
+ aconf->hub_limit = hub_limit;
lookup_confhost(aconf);
- GlobalConfList = aconf;
}
else
{
MyFree(pass);
MyFree(host);
MyFree(origin);
+ MyFree(hub_limit);
parse_error("Bad connect block");
}
- name = pass = host = origin = NULL;
+ name = pass = host = origin = hub_limit = NULL;
+ c_class = NULL;
+ port = 0;
}';';
connectitems: connectitem connectitems | connectitem;
connectitem: connectname | connectpass | connectclass | connecthost
- | connectport | connectvhost | error;
+ | connectport | connectvhost | connectleaf | connecthub
+ | connecthublimit | connectmaxhops | error;
connectname: NAME '=' QSTRING ';'
{
MyFree(name);
MyFree(origin);
DupString(origin, $3);
};
-
-serverblock: SERVER
+connectleaf: LEAF ';'
+{
+ maxlinks = 0;
+};
+connecthub: HUB ';'
+{
+ MyFree(hub_limit);
+ DupString(hub_limit, "*");
+};
+connecthublimit: HUB '=' QSTRING ';'
{
- aconf = (struct ConfItem*) MyMalloc(sizeof(*aconf));
- memset(aconf, 0, sizeof(*aconf));
- aconf->status = CONF_LEAF;
-} '{' serveritems '}'
+ MyFree(hub_limit);
+ DupString(hub_limit, $3);
+};
+connectmaxhops: MAXHOPS '=' expr ';'
+{
+ maxlinks = $3;
+};
+
+uworldblock: UWORLD '{' uworlditems '}' ';'
{
- if (aconf->status == 0)
+ if (name)
{
- MyFree(aconf->host);
- MyFree(aconf->name);
- MyFree(aconf);
- aconf = NULL;
- parse_error("Bad server block");
+ struct ConfItem *aconf = make_conf(CONF_UWORLD);
+ aconf->host = name;
}
else
{
- aconf->next = GlobalConfList;
- GlobalConfList = aconf;
+ MyFree(name);
+ parse_error("Bad UWorld block");
}
-} ';';
-serveritems: serveritem serveritems | serveritem;
-serveritem: servername | servermask | serverhub | serverleaf |
- serveruworld | error;
-servername: NAME '=' QSTRING
-{
- MyFree(aconf->name);
- DupString(aconf->name, $3);
-} ';' ;
-servermask: MASK '=' QSTRING
-{
- MyFree(aconf->host);
- DupString(aconf->host, $3);
-} ';' ;
-/* XXX - perhaps we should do this the hybrid way in connect blocks
- * instead -A1kmm. */
-serverhub: HUB '=' YES ';'
-{
- aconf->status |= CONF_HUB;
- aconf->status &= ~CONF_LEAF;
-}
-| HUB '=' NO
-{
- aconf->status &= ~CONF_HUB;
-} ';';
-serverleaf: LEAF '=' YES ';'
-{
- if (!(aconf->status & CONF_HUB && aconf->status & CONF_UWORLD))
- aconf->status |= CONF_LEAF;
- else
- parse_error("Server is both leaf and a hub");
-}
-| LEAF '=' NO ';'
-{
- aconf->status &= ~CONF_LEAF;
+ name = NULL;
};
-serveruworld: UWORLD '=' YES ';'
+uworlditems: uworlditem uworlditems | uworlditem;
+uworlditem: uworldname | error;
+uworldname: NAME '=' QSTRING ';'
{
- aconf->status |= CONF_UWORLD;
- aconf->status &= ~CONF_LEAF;
-}
-| UWORLD '=' NO ';'
-{
- aconf->status &= ~CONF_UWORLD;
+ MyFree(name);
+ DupString(name, $3);
};
-operblock: OPER
-{
- aconf = (struct ConfItem*) MyMalloc(sizeof(*aconf));
- memset(aconf, 0, sizeof(*aconf));
- memset(&privs, 0, sizeof(privs));
- memset(&privs_dirty, 0, sizeof(privs_dirty));
- aconf->status = CONF_OPERATOR;
-} '{' operitems '}' ';'
+operblock: OPER '{' operitems '}' ';'
{
- if (aconf->name != NULL && aconf->passwd != NULL && aconf->host != NULL
- && aconf->conn_class != NULL)
+ if (name && pass && host && c_class)
{
+ struct ConfItem *aconf = make_conf(CONF_OPERATOR);
+ aconf->name = name;
+ aconf->passwd = pass;
+ conf_parse_userhost(aconf, host);
+ aconf->conn_class = c_class;
memcpy(&aconf->privs, &privs, sizeof(aconf->privs));
memcpy(&aconf->privs_dirty, &privs_dirty, sizeof(aconf->privs_dirty));
- if (!PrivHas(&privs_dirty, PRIV_PROPAGATE)
- && !PrivHas(&aconf->conn_class->privs_dirty, PRIV_PROPAGATE))
- parse_error("Operator block for %s and class %s have no LOCAL setting", aconf->name, aconf->conn_class->cc_name);
- aconf->next = GlobalConfList;
- GlobalConfList = aconf;
+ if (!FlagHas(&privs_dirty, PRIV_PROPAGATE)
+ && !FlagHas(&c_class->privs_dirty, PRIV_PROPAGATE))
+ parse_error("Operator block for %s and class %s have no LOCAL setting", name, c_class->cc_name);
}
else
{
- log_write(LS_CONFIG, L_ERROR, 0, "operator blocks need a name, password, and host.");
- MyFree(aconf->name);
- MyFree(aconf->passwd);
- MyFree(aconf->host);
- MyFree(aconf);
- aconf = NULL;
+ parse_error("operator blocks need a name, password, class and host.");
+ MyFree(name);
+ MyFree(pass);
+ MyFree(host);
}
+ name = pass = host = NULL;
+ c_class = NULL;
+ memset(&privs, 0, sizeof(privs));
+ memset(&privs_dirty, 0, sizeof(privs_dirty));
};
operitems: operitem | operitems operitem;
operitem: opername | operpass | operhost | operclass | priv | error;
-
opername: NAME '=' QSTRING ';'
{
- MyFree(aconf->name);
- DupString(aconf->name, $3);
+ MyFree(name);
+ DupString(name, $3);
};
-
operpass: PASS '=' QSTRING ';'
{
- MyFree(aconf->passwd);
- DupString(aconf->passwd, $3);
+ MyFree(pass);
+ DupString(pass, $3);
};
-
operhost: HOST '=' QSTRING ';'
{
- MyFree(aconf->host);
+ MyFree(host);
if (!strchr($3, '@'))
{
int uh_len;
char *b = (char*) MyMalloc((uh_len = strlen($3)+3));
ircd_snprintf(0, b, uh_len, "*@%s", $3);
- aconf->host = b;
+ host = b;
}
else
- DupString(aconf->host, $3);
+ DupString(host, $3);
};
-
operclass: CLASS '=' QSTRING ';'
{
- aconf->conn_class = find_class($3);
+ c_class = find_class($3);
};
priv: privtype '=' yesorno ';'
{
- PrivSet(&privs_dirty, $1);
+ FlagSet(&privs_dirty, $1);
if (($3 == 1) ^ invert)
- PrivSet(&privs, $1);
+ FlagSet(&privs, $1);
else
- PrivClr(&privs, $1);
+ FlagClr(&privs, $1);
invert = 0;
};
TPRIV_SET { $$ = PRIV_SET; } |
TPRIV_WHOX { $$ = PRIV_WHOX; } |
TPRIV_BADCHAN { $$ = PRIV_BADCHAN; } |
- TPRIV_LOCAL_BADCHAN { $$ = TPRIV_LOCAL_BADCHAN; } |
+ TPRIV_LOCAL_BADCHAN { $$ = PRIV_LOCAL_BADCHAN; } |
TPRIV_SEE_CHAN { $$ = PRIV_SEE_CHAN; } |
TPRIV_SHOW_INVIS { $$ = PRIV_SHOW_INVIS; } |
TPRIV_SHOW_ALL_INVIS { $$ = PRIV_SHOW_ALL_INVIS; } |
TPRIV_WIDE_GLINE { $$ = PRIV_WIDE_GLINE; } |
LOCAL { $$ = PRIV_PROPAGATE; invert = 1; } |
TPRIV_FORCE_OPMODE { $$ = PRIV_FORCE_OPMODE; } |
- TPRIV_FORCE_LOCAL_OPMODE { $$ = PRIV_FORCE_LOCAL_OPMODE; };
+ TPRIV_FORCE_LOCAL_OPMODE { $$ = PRIV_FORCE_LOCAL_OPMODE; } |
+ TPRIV_APASS_OPMODE { $$ = PRIV_APASS_OPMODE; } ;
yesorno: YES { $$ = 1; } | NO { $$ = 0; };
/* The port block... */
-portblock: PORT {
- port = 0;
- host = NULL;
- /* Hijack these for is_server, is_hidden to cut down on globals... */
- tconn = 0;
- tping = 0;
- /* and this for mask... */
- pass = NULL;
-} '{' portitems '}' ';'
+portblock: PORT '{' portitems '}' ';'
{
if (port > 0 && port <= 0xFFFF)
{
MyFree(host);
MyFree(pass);
host = pass = NULL;
+ port = tconn = tping = 0;
};
portitems: portitem portitems | portitem;
portitem: portnumber | portvhost | portmask | portserver | porthidden | error;
clientblock: CLIENT
{
- aconf = (struct ConfItem*) MyMalloc(sizeof(*aconf));
- memset(aconf, 0, sizeof(*aconf));
- aconf->status = CONF_CLIENT;
-} '{' clientitems '}'
+ maxlinks = 65535;
+}
+'{' clientitems '}' ';'
{
- if ((aconf->host != NULL || aconf->name!=NULL))
- {
- if (aconf->host == NULL)
- DupString(aconf->host, "");
- if (aconf->name == NULL)
- DupString(aconf->name, "");
- if (aconf->conn_class == NULL)
- aconf->conn_class = find_class("default");
- aconf->next = GlobalConfList;
- GlobalConfList = aconf;
- aconf = NULL;
- }
- else
- {
- MyFree(aconf->host);
- MyFree(aconf->passwd);
- MyFree(aconf);
- aconf = NULL;
- parse_error("Bad client block");
+ struct irc_in_addr addr;
+ unsigned char addrbits = 0;
+
+ if (ip && !ipmask_parse(ip, &addr, &addrbits)) {
+ parse_error("Invalid IP address in block");
+ MyFree(username);
+ MyFree(host);
+ MyFree(ip);
+ } else {
+ struct ConfItem *aconf = make_conf(CONF_CLIENT);
+ aconf->username = username;
+ aconf->host = host;
+ if (ip)
+ memcpy(&aconf->address.addr, &addr, sizeof(aconf->address.addr));
+ else
+ memset(&aconf->address.addr, 0, sizeof(aconf->address.addr));
+ aconf->addrbits = addrbits;
+ aconf->name = ip;
+ aconf->conn_class = c_class ? c_class : find_class("default");
+ aconf->maximum = maxlinks;
}
-} ';';
+ host = NULL;
+ username = NULL;
+ c_class = NULL;
+ ip = NULL;
+};
clientitems: clientitem clientitems | clientitem;
-clientitem: clienthost | clientclass | clientpass | clientip | error;
+clientitem: clienthost | clientip | clientusername | clientclass | clientpass | clientmaxlinks | error;
+clienthost: HOST '=' QSTRING ';'
+{
+ char *sep = strchr($3, '@');
+ MyFree(host);
+ if (sep) {
+ *sep++ = '\0';
+ MyFree(username);
+ DupString(username, $3);
+ DupString(host, sep);
+ } else {
+ DupString(host, $3);
+ }
+};
clientip: IP '=' QSTRING ';'
{
- MyFree(aconf->host);
- DupString(aconf->host, $3);
+ char *sep = strchr($3, '@');
+ MyFree(ip);
+ if (sep) {
+ *sep++ = '\0';
+ MyFree(username);
+ DupString(username, $3);
+ DupString(ip, sep);
+ } else {
+ DupString(ip, $3);
+ }
};
-
-clienthost: HOST '=' QSTRING ';'
+clientusername: USERNAME '=' QSTRING ';'
{
- MyFree(aconf->name);
- DupString(aconf->name, $3);
+ MyFree(username);
+ DupString(username, $3);
};
-
clientclass: CLASS '=' QSTRING ';'
{
- aconf->conn_class = find_class($3);
+ c_class = find_class($3);
};
-
clientpass: PASS '=' QSTRING ';'
{
- MyFree(aconf->passwd);
- DupString(aconf->passwd, $3);
+ MyFree(pass);
+ DupString(pass, $3);
+};
+clientmaxlinks: MAXLINKS '=' expr ';'
+{
+ maxlinks = $3;
};
killblock: KILL
{
- dconf = (struct DenyConf*) MyMalloc(sizeof(*dconf));
- memset(dconf, 0, sizeof(*dconf));
+ dconf = (struct DenyConf*) MyCalloc(1, sizeof(*dconf));
} '{' killitems '}'
{
if (dconf->hostmask != NULL)
DupString(dconf->usermask, "*");
dconf->next = denyConfList;
denyConfList = dconf;
- dconf = NULL;
}
else
{
MyFree(dconf->hostmask);
MyFree(dconf->message);
MyFree(dconf);
- dconf = NULL;
parse_error("Bad kill block");
}
+ dconf = NULL;
} ';';
killitems: killitem killitems | killitem;
killitem: killuhost | killreal | killreasonfile | killreason | error;
killreason: REASON '=' QSTRING ';'
{
- dconf->flags &= DENY_FLAGS_FILE;
+ dconf->flags &= ~DENY_FLAGS_FILE;
MyFree(dconf->message);
DupString(dconf->message, $3);
};
cruleblock: CRULE
{
- host = pass = NULL;
tconn = CRULE_AUTO;
-} '{' cruleitems '}'
+} '{' cruleitems '}' ';'
{
struct CRuleNode *node;
if (host != NULL && pass != NULL && (node=crule_parse(pass)) != NULL)
MyFree(pass);
parse_error("Bad CRule block");
}
-} ';';
+ host = pass = NULL;
+ tconn = 0;
+};
cruleitems: cruleitem cruleitems | cruleitem;
cruleitem: cruleserver | crulerule | cruleall | error;
tconn = CRULE_AUTO;
};
-motdblock: MOTD {
- pass = host = NULL;
-} '{' motditems '}'
+motdblock: MOTD '{' motditems '}' ';'
{
if (host != NULL && pass != NULL)
motd_add(host, pass);
MyFree(host);
MyFree(pass);
host = pass = NULL;
-} ';';
+};
motditems: motditem motditems | motditem;
motditem: motdhost | motdfile | error;
quarantineblock: QUARANTINE '{'
{
- if (qconf != NULL)
- qconf = (struct qline*) MyMalloc(sizeof(*qconf));
- else
- {
- if (qconf->chname != NULL)
- MyFree(qconf->chname);
- if (qconf->reason != NULL)
- MyFree(qconf->reason);
- }
- memset(qconf, 0, sizeof(*qconf));
+ qconf = (struct qline*) MyCalloc(1, sizeof(*qconf));
} quarantineitems '}' ';'
{
if (qconf->chname == NULL || qconf->reason == NULL)
{
- log_write(LS_CONFIG, L_ERROR, 0, "quarantine blocks need a channel name "
- "and a reason.");
+ parse_error("quarantine blocks need a channel name and a reason.");
return 0;
}
qconf->next = GlobalQuarantineList;
{
if (!smap->name || !smap->services)
{
- log_write(LS_CONFIG, L_ERROR, 0, "pseudo commands need a service name and list of target nicks.");
+ parse_error("pseudo commands need a service name and list of target nicks.");
return 0;
}
if (register_mapping(smap))
iauthblock: IAUTH '{'
{
- pass = host = NULL;
- port = 0;
tconn = 60;
tping = 60;
} iauthitems '}' ';'
{
- if (!name || !host || !port) {
- log_write(LS_CONFIG, L_ERROR, 0, "IAuth block needs a server name and port.");
+ if (!host || !port) {
+ parse_error("IAuth block needs a server name and port.");
return 0;
}
iauth_connect(host, port, pass, tconn, tping);
MyFree(pass);
MyFree(host);
pass = host = NULL;
+ port = tconn = tping = 0;
};
iauthitems: iauthitem iauthitems | iauthitem;