Add autoconnect option for Connect block.
[ircu2.10.12-pk.git] / ircd / ircd_parser.y
index e2717a74a5d50b071b782adc86a6c6ed4272c9ea..c7d726dca9747375740641dfbd9d6b9c8b4c458f 100644 (file)
@@ -68,7 +68,7 @@
 
   int yylex(void);
   /* Now all the globals we need :/... */
-  int tping, tconn, maxlinks, sendq, port, invert, stringno;
+  int tping, tconn, maxlinks, sendq, port, invert, stringno, flags;
   char *name, *pass, *host, *ip, *username, *origin, *hub_limit;
   char *stringlist[MAX_STRINGS];
   struct ConnectionClass *c_class;
@@ -155,6 +155,7 @@ static void parse_error(char *pattern,...) {
 %token IAUTH
 %token TIMEOUT
 %token FAST
+%token AUTOCONNECT
 /* 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
@@ -395,12 +396,22 @@ classusermode: USERMODE '=' QSTRING ';'
 connectblock: CONNECT
 {
  maxlinks = 65535;
+ flags = CONF_AUTOCONNECT;
 } '{' connectitems '}'
 {
- if (name != NULL && pass != NULL && host != NULL && c_class != NULL
-     && !strchr(host, '*') && !strchr(host, '?'))
- {
-   struct ConfItem *aconf = make_conf(CONF_SERVER);
+ struct ConfItem *aconf = NULL;
+ if (name == NULL)
+  parse_error("Missing name in connect block");
+ else if (pass == NULL)
+  parse_error("Missing password in connect block");
+ else if (host == NULL)
+  parse_error("Missing host in connect block");
+ else if (strchr(host, '*') || strchr(host, '?'))
+  parse_error("Invalid host '%s' in connect block", host);
+ else if (c_class == NULL)
+  parse_error("Missing class in connect block");
+ else {
+   aconf = make_conf(CONF_SERVER);
    aconf->name = name;
    aconf->origin_name = origin;
    aconf->passwd = pass;
@@ -409,25 +420,24 @@ connectblock: CONNECT
    aconf->host = host;
    aconf->maximum = maxlinks;
    aconf->hub_limit = hub_limit;
+   aconf->flags = flags;
    lookup_confhost(aconf);
  }
- else
- {
+ if (!aconf) {
    MyFree(name);
    MyFree(pass);
    MyFree(host);
    MyFree(origin);
    MyFree(hub_limit);
-   parse_error("Bad connect block");
  }
  name = pass = host = origin = hub_limit = NULL;
  c_class = NULL;
- port = 0;
+ port = flags = 0;
 }';';
 connectitems: connectitem connectitems | connectitem;
 connectitem: connectname | connectpass | connectclass | connecthost
               | connectport | connectvhost | connectleaf | connecthub
-              | connecthublimit | connectmaxhops | error;
+              | connecthublimit | connectmaxhops | connectauto | error;
 connectname: NAME '=' QSTRING ';'
 {
  MyFree(name);
@@ -441,6 +451,7 @@ connectpass: PASS '=' QSTRING ';'
 connectclass: CLASS '=' QSTRING ';'
 {
  c_class = find_class($3);
+ MyFree($3);
 };
 connecthost: HOST '=' QSTRING ';'
 {
@@ -474,6 +485,8 @@ connectmaxhops: MAXHOPS '=' expr ';'
 {
   maxlinks = $3;
 };
+connectauto: AUTOCONNECT '=' YES ';' { flags |= CONF_AUTOCONNECT; }
+ | AUTOCONNECT '=' NO ';' { flags &= ~CONF_AUTOCONNECT; };
 
 uworldblock: UWORLD '{' uworlditems '}' ';';
 uworlditems: uworlditem uworlditems | uworlditem;
@@ -485,9 +498,17 @@ uworldname: NAME '=' QSTRING ';'
 
 operblock: OPER '{' operitems '}' ';'
 {
-  if (name && pass && host && c_class)
-  {
-    struct ConfItem *aconf = make_conf(CONF_OPERATOR);
+  struct ConfItem *aconf = NULL;
+  if (name == NULL)
+    parse_error("Missing name in operator block");
+  else if (pass == NULL)
+    parse_error("Missing password in operator block");
+  else if (host == NULL)
+    parse_error("Missing host in operator block");
+  else if (c_class == NULL)
+    parse_error("Missing class in operator block");
+  else {
+    aconf = make_conf(CONF_OPERATOR);
     aconf->name = name;
     aconf->passwd = pass;
     conf_parse_userhost(aconf, host);
@@ -498,9 +519,7 @@ operblock: OPER '{' operitems '}' ';'
         && !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
-  {
-    parse_error("operator blocks need a name, password, class and host.");
+  if (!aconf) {
     MyFree(name);
     MyFree(pass);
     MyFree(host);
@@ -589,13 +608,9 @@ yesorno: YES { $$ = 1; } | NO { $$ = 0; };
 portblock: PORT '{' portitems '}' ';'
 {
   if (port > 0 && port <= 0xFFFF)
-  {
     add_listener(port, host, pass, tconn, tping);
-  }
   else
-  {
-    parse_error("Bad port block");
-  }
+    parse_error("Port %d is out of range", port);
   MyFree(host);
   MyFree(pass);
   host = pass = NULL;
@@ -646,7 +661,7 @@ clientblock: CLIENT
   unsigned char addrbits = 0;
 
   if (ip && !ipmask_parse(ip, &addr, &addrbits)) {
-    parse_error("Invalid IP address in block");
+    parse_error("Invalid IP address %s in block", ip);
     MyFree(username);
     MyFree(host);
     MyFree(ip);
@@ -736,7 +751,7 @@ killblock: KILL
     MyFree(dconf->realmask);
     MyFree(dconf->message);
     MyFree(dconf);
-    parse_error("Bad kill block");
+    parse_error("Kill block must match on at least one of username, host or realname");
   }
   dconf = NULL;
 } ';';
@@ -792,8 +807,14 @@ cruleblock: CRULE
   tconn = CRULE_AUTO;
 } '{' cruleitems '}' ';'
 {
-  struct CRuleNode *node;
-  if (host != NULL && pass != NULL && (node=crule_parse(pass)) != NULL)
+  struct CRuleNode *node = NULL;
+  if (host == NULL)
+    parse_error("Missing host in crule block");
+  else if (pass == NULL)
+    parse_error("Missing rule in crule block");
+  else if ((node = crule_parse(pass)) == NULL)
+    parse_error("Invalid rule '%s' in crule block", pass);
+  else
   {
     struct CRuleConf *p = (struct CRuleConf*) MyMalloc(sizeof(*p));
     p->hostmask = host;
@@ -803,11 +824,10 @@ cruleblock: CRULE
     p->next = cruleConfList;
     cruleConfList = p;
   }
-  else
+  if (!node)
   {
     MyFree(host);
     MyFree(pass);
-    parse_error("Bad CRule block");
   }
   host = pass = NULL;
   tconn = 0;
@@ -906,12 +926,15 @@ pseudoblock: PSEUDO QSTRING '{'
 }
 pseudoitems '}' ';'
 {
-  if (!smap->name || !smap->services)
-  {
-    parse_error("pseudo commands need a service name and list of target nicks.");
-    return 0;
-  }
-  if (register_mapping(smap))
+  int valid = 0;
+
+  if (!smap->name)
+    parse_error("Missing name in pseudo %s block", smap->command);
+  else if (!smap->services)
+    parse_error("Missing nick in pseudo %s block", smap->command);
+  else
+    valid = 1;
+  if (valid && register_mapping(smap))
   {
     smap->next = GlobalServiceMapList;
     GlobalServiceMapList = smap;
@@ -936,10 +959,12 @@ pseudoitems: pseudoitem pseudoitems | pseudoitem;
 pseudoitem: pseudoname | pseudoprepend | pseudonick | pseudoflags | error;
 pseudoname: NAME '=' QSTRING ';'
 {
+  MyFree(smap->name);
   smap->name = $3;
 };
 pseudoprepend: PREPEND '=' QSTRING ';'
 {
+  MyFree(smap->prepend);
   smap->prepend = $3;
 };
 pseudonick: NICK '=' QSTRING ';'
@@ -967,11 +992,12 @@ iauthblock: IAUTH '{'
   tping = 60;
 } iauthitems '}' ';'
 {
-  if (!host || !port) {
-    parse_error("IAuth block needs a server name and port.");
-    return 0;
-  }
-  iauth_connect(host, port, pass, tconn, tping);
+  if (!host)
+    parse_error("Missing host in iauth block");
+  else if (!port)
+    parse_error("Missing port in iauth block");
+  else
+    iauth_connect(host, port, pass, tconn, tping);
   MyFree(pass);
   MyFree(host);
   pass = host = NULL;