Allow multiple server entries in a CRule and multiple vhosts in a Port.
authorMichael Poole <mdpoole@troilus.org>
Sun, 18 Mar 2007 02:46:56 +0000 (02:46 +0000)
committerMichael Poole <mdpoole@troilus.org>
Sun, 18 Mar 2007 02:46:56 +0000 (02:46 +0000)
git-svn-id: file:///home/klmitch/undernet-ircu/undernet-ircu-svn/ircu2/branches/u2_10_12_branch@1784 c9e4aea6-c8fd-4c43-8297-357d70d61c8c

ChangeLog
doc/example.conf
ircd/ircd_parser.y

index 1d4f807f8ed3787bebebe492933ca42e8b06377a..0688a24501dcbe6732cfabdbaecac19bad78e6b4 100644 (file)
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,24 @@
+2007-03-17  Michael Poole <mdpoole@troilus.org>
+
+       * doc/example.conf (CRule): Document the support for multiple
+       server masks in a single CRule block.
+       (Port): Document the optional additional field for vhost entries.
+       Document the support for multiple vhost entries in a single Port
+       block.
+
+       * ircd/ircd_parser.y (USE_IPV4): Shift up by 16 bytes.
+       (USE_IPV6): Likewise.
+       (portblock): Iterate over hosts rather than using the single host.
+       (portitem): Add portvhostnumber alternative production.
+       (portnumber): Check port number here.  If valid, combine address
+       family and port number in "port" variable.  If a port-less item
+       exists in "hosts", set its port number.
+       (portvhost): Prepend mask to "hosts" list.
+       (portvhostnumber): New production.
+       (cruleblock): Iterate over hosts rather than using the single
+       host.
+       (cruleserver): Prepend server mask to "hosts" list.
+
 2007-03-17  Michael Poole <mdpoole@troilus.org>
 
        * ircd/listener.c (add_listener): Only try to create IPv6 sockets
index 93ad60ee145e6ec959eb8c988b852aac5770ce53..0a93c2a0be6a7df17110ac2991ed52f959bf6a73 100644 (file)
@@ -570,6 +570,8 @@ Connect {
 #
 # For an advanced, real-time rule-based routing decision making system
 # you can use crule blocks. For more information, see doc/readme.crules.
+# If more than one server mask is present in a single crule, the rule
+# applies to all servers.
 # CRULE
 # {
 #  server = "servermask";
@@ -673,11 +675,14 @@ Operator {
 # IANA says we should use port 194, but that requires us to run as root,
 # so we don't do that.
 #
+#
 # Port {
 #  port = [ipv4] [ipv6] number;
 #  mask = "ipmask";
 #  # Use this to control the interface you bind to.
 #  vhost = [ipv4] [ipv6] "virtualhostip";
+#  # You can specify both virtual host and port number in one entry.
+#  vhost = [ipv4] [ipv6] "virtualhostip" number;
 #  # Setting to yes makes this server only.
 #  server = yes;
 #  # Setting to yes makes the port "hidden" from stats.
@@ -730,6 +735,14 @@ Port {
  port = 7000;
 };
 
+# More than one vhost may be present in a single Port block; in this case,
+# we recommend listing the port number on the vhost line for clarity.
+Port {
+ vhost = "172.16.0.1" 6667;
+ vhost = "172.16.3.1" 6668;
+ hidden = no;
+};
+
 # Quarantine blocks disallow operators from using OPMODE and CLEARMODE
 # on certain channels.  Opers with the force_opmode (for local
 # channels, force_local_opmode) privilege may override the quarantine
index dc815f937cfee5cf0e3cb35cc41c1a479ee6b877..67fddfcc6a43f3c3fedab746193972cac908f7b0 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;
@@ -695,45 +695,68 @@ 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;
+  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);
   }
-  if (port > 0 && port <= 0xFFFF)
-    add_listener(port, host, pass, &listen_flags);
-  else
-    parse_error("Port %d is out of range", port);
-  MyFree(host);
+  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 ';'
@@ -931,28 +954,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 +986,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 ';'