add unlimited flood priv
[ircu2.10.12-pk.git] / ircd / ircd_parser.y
index dc815f937cfee5cf0e3cb35cc41c1a479ee6b877..ae9bfdb146de53beba86fd606a0b28978567233d 100644 (file)
@@ -60,8 +60,8 @@
 #include <arpa/inet.h>
 
 #define MAX_STRINGS 80 /* Maximum number of feature params. */
-#define USE_IPV4 (1 << 0)
-#define USE_IPV6 (1 << 1)
+#define USE_IPV4 (1 << 16)
+#define USE_IPV6 (1 << 17)
 
   extern struct LocalConf   localConf;
   extern struct DenyConf*   denyConfList;
@@ -181,9 +181,9 @@ static void free_slist(struct SLink **link) {
 %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 TPRIV_APASS_OPMODE
-%token TPRIV_LIST_CHAN
+%token TPRIV_UNLIMIT_QUERY TPRIV_UNLIMIT_FLOOD TPRIV_DISPLAY TPRIV_SEE_OPERS
+%token TPRIV_WIDE_GLINE TPRIV_FORCE_OPMODE TPRIV_FORCE_LOCAL_OPMODE
+%token TPRIV_APASS_OPMODE TPRIV_LIST_CHAN
 /* and some types... */
 %type <num> sizespec
 %type <num> timespec timefactor factoredtimes factoredtime
@@ -463,7 +463,6 @@ classusermode: USERMODE '=' QSTRING ';'
 
 connectblock: CONNECT
 {
- maxlinks = 65535;
  flags = CONF_AUTOCONNECT;
 } '{' connectitems '}' ';'
 {
@@ -488,7 +487,10 @@ connectblock: CONNECT
    aconf->conn_class = c_class;
    aconf->address.port = port;
    aconf->host = host;
-   aconf->maximum = maxlinks;
+   /* If the user specified a hub allowance, but not maximum links,
+    * allow an effectively unlimited number of hops.
+    */
+   aconf->maximum = (hub_limit != NULL && maxlinks == 0) ? 65535 : maxlinks;
    aconf->hub_limit = hub_limit;
    aconf->flags = flags;
    lookup_confhost(aconf);
@@ -502,7 +504,7 @@ connectblock: CONNECT
  }
  name = pass = host = origin = hub_limit = NULL;
  c_class = NULL;
- port = flags = 0;
+ port = flags = maxlinks = 0;
 };
 connectitems: connectitem connectitems | connectitem;
 connectitem: connectname | connectpass | connectclass | connecthost
@@ -672,6 +674,7 @@ privtype: TPRIV_CHAN_LIMIT { $$ = PRIV_CHAN_LIMIT; } |
           TPRIV_SHOW_ALL_INVIS { $$ = PRIV_SHOW_ALL_INVIS; } |
           TPRIV_PROPAGATE { $$ = PRIV_PROPAGATE; } |
           TPRIV_UNLIMIT_QUERY { $$ = PRIV_UNLIMIT_QUERY; } |
+          TPRIV_UNLIMIT_FLOOD { $$ = PRIV_UNLIMIT_FLOOD; } |
           TPRIV_DISPLAY { $$ = PRIV_DISPLAY; } |
           TPRIV_SEE_OPERS { $$ = PRIV_SEE_OPERS; } |
           TPRIV_WIDE_GLINE { $$ = PRIV_WIDE_GLINE; } |
@@ -695,45 +698,76 @@ address_family:
     ;
 
 /* The port block... */
-portblock: PORT '{' portitems '}' ';'
-{
-  if (!FlagHas(&listen_flags, LISTEN_IPV4)
-      && !FlagHas(&listen_flags, LISTEN_IPV6))
-  {
-    FlagSet(&listen_flags, LISTEN_IPV4);
-    FlagSet(&listen_flags, LISTEN_IPV6);
+portblock: PORT '{' portitems '}' ';' {
+  struct ListenerFlags flags_here;
+  struct SLink *link;
+  if (hosts == NULL) {
+    struct SLink *link;
+    link = make_link();
+    DupString(link->value.cp, "*");
+    link->flags = 0;
+    link->next = hosts;
+    hosts = link;
   }
-  if (port > 0 && port <= 0xFFFF)
-    add_listener(port, host, pass, &listen_flags);
-  else
-    parse_error("Port %d is out of range", port);
-  MyFree(host);
+  for (link = hosts; link != NULL; link = link->next) {
+    memcpy(&flags_here, &listen_flags, sizeof(flags_here));
+    switch (link->flags & (USE_IPV4 | USE_IPV6)) {
+    case USE_IPV4:
+      FlagSet(&flags_here, LISTEN_IPV4);
+      break;
+    case USE_IPV6:
+      FlagSet(&flags_here, LISTEN_IPV6);
+      break;
+    default: /* 0 or USE_IPV4|USE_IPV6 */
+      FlagSet(&flags_here, LISTEN_IPV4);
+      FlagSet(&flags_here, LISTEN_IPV6);
+      break;
+    }
+    if (link->flags & 65535)
+      port = link->flags & 65535;
+    add_listener(port, link->value.cp, pass, &flags_here);
+  }
+  free_slist(&hosts);
   MyFree(pass);
   memset(&listen_flags, 0, sizeof(listen_flags));
-  host = pass = NULL;
+  pass = NULL;
   port = 0;
 };
 portitems: portitem portitems | portitem;
-portitem: portnumber | portvhost | portmask | portserver | porthidden;
+portitem: portnumber | portvhost | portvhostnumber | portmask | portserver | porthidden;
 portnumber: PORT '=' address_family NUMBER ';'
 {
-  int families = $3;
-  if (families & USE_IPV4)
-    FlagSet(&listen_flags, LISTEN_IPV4);
-  else if (families & USE_IPV6)
-    FlagSet(&listen_flags, LISTEN_IPV6);
-  port = $4;
+  if ($4 < 1 || $4 > 65535) {
+    parse_error("Port %d is out of range", port);
+  } else {
+    port = $3 | $4;
+    if (hosts && (0 == (hosts->flags & 65535)))
+      hosts->flags = (hosts->flags & ~65535) | port;
+  }
 };
 
 portvhost: VHOST '=' address_family QSTRING ';'
 {
-  int families = $3;
-  if (families & USE_IPV4)
-    FlagSet(&listen_flags, LISTEN_IPV4);
-  else if (families & USE_IPV6)
-    FlagSet(&listen_flags, LISTEN_IPV6);
-  MyFree(host);
-  host = $4;
+  struct SLink *link;
+  link = make_link();
+  link->value.cp = $4;
+  link->flags = $3 | port;
+  link->next = hosts;
+  hosts = link;
+};
+
+portvhostnumber: VHOST '=' address_family QSTRING NUMBER ';'
+{
+  if ($5 < 1 || $5 > 65535) {
+    parse_error("Port %d is out of range", port);
+  } else {
+    struct SLink *link;
+    link = make_link();
+    link->value.cp = $4;
+    link->flags = $3 | $5;
+    link->next = hosts;
+    hosts = link;
+  }
 };
 
 portmask: MASK '=' QSTRING ';'
@@ -799,6 +833,7 @@ clientblock: CLIENT
   host = NULL;
   username = NULL;
   c_class = NULL;
+  maxlinks = 0;
   ip = NULL;
   pass = NULL;
   port = 0;
@@ -931,28 +966,30 @@ cruleblock: CRULE
 } '{' cruleitems '}' ';'
 {
   struct CRuleNode *node = NULL;
-  if (host == NULL)
-    parse_error("Missing host in crule block");
+  struct SLink *link;
+
+  if (hosts == NULL)
+    parse_error("Missing server(s) 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
+  else for (link = hosts; link != NULL; link = link->next)
   {
     struct CRuleConf *p = (struct CRuleConf*) MyMalloc(sizeof(*p));
-    p->hostmask = host;
-    p->rule = pass;
+    if (node == NULL)
+      node = crule_parse(pass);
+    DupString(p->hostmask, link->value.cp);
+    DupString(p->rule, pass);
     p->type = tconn;
     p->node = node;
+    node = NULL;
     p->next = cruleConfList;
     cruleConfList = p;
   }
-  if (!node)
-  {
-    MyFree(host);
-    MyFree(pass);
-  }
-  host = pass = NULL;
+  free_slist(&hosts);
+  MyFree(pass);
+  pass = NULL;
   tconn = 0;
 };
 
@@ -961,9 +998,11 @@ cruleitem: cruleserver | crulerule | cruleall;
 
 cruleserver: SERVER '=' QSTRING ';'
 {
-  MyFree(host);
-  collapse($3);
-  host = $3;
+  struct SLink *link;
+  link = make_link();
+  link->value.cp = $3;
+  link->next = hosts;
+  hosts = link;
 };
 
 crulerule: RULE '=' QSTRING ';'
@@ -1055,6 +1094,8 @@ pseudoitems '}' ';'
     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 if (!strIsAlpha(smap->command))
+    parse_error("Pseudo command %s invalid: must all be letters", smap->command);
   else
     valid = 1;
   if (valid && register_mapping(smap))
@@ -1104,7 +1145,10 @@ iauthblock: IAUTH '{' iauthitems '}' ';'
 {
   auth_spawn(stringno, stringlist);
   while (stringno > 0)
-    MyFree(stringlist[--stringno]);
+  {
+    --stringno;
+    MyFree(stringlist[stringno]);
+  }
 };
 
 iauthitems: iauthitem iauthitems | iauthitem;
@@ -1112,5 +1156,8 @@ iauthitem: iauthprogram;
 iauthprogram: PROGRAM '='
 {
   while (stringno > 0)
-    MyFree(stringlist[--stringno]);
+  {
+    --stringno;
+    MyFree(stringlist[stringno]);
+  }
 } stringlist ';';