ViewVC Help
View File | Revision Log | Show Annotations | View Changeset | Root Listing
root/svn/ircd-hybrid/trunk/src/conf_parser.y
(Generate patch)

Comparing:
ircd-hybrid-8/src/conf_parser.y (file contents), Revision 1490 by michael, Sat Jul 28 19:33:23 2012 UTC vs.
ircd-hybrid/trunk/src/conf_parser.y (file contents), Revision 1745 by michael, Mon Jan 14 20:31:55 2013 UTC

# Line 33 | Line 33
33   #include "ircd.h"
34   #include "list.h"
35   #include "conf.h"
36 + #include "conf_class.h"
37   #include "event.h"
38   #include "log.h"
39   #include "client.h"     /* for UMODE_ALL only */
# Line 57 | Line 58
58  
59   int yylex(void);
60  
61 < static char *class_name = NULL;
62 < static struct ConfItem *yy_conf = NULL;
63 < static struct AccessItem *yy_aconf = NULL;
64 < static struct MatchItem *yy_match_item = NULL;
65 < static struct ClassItem *yy_class = NULL;
66 < static char *yy_class_name = NULL;
67 <
68 < static dlink_list col_conf_list  = { NULL, NULL, 0 };
69 < static unsigned int listener_flags = 0;
70 < static unsigned int regex_ban = 0;
71 < static char userbuf[IRCD_BUFSIZE];
72 < static char hostbuf[IRCD_BUFSIZE];
73 < static char reasonbuf[REASONLEN + 1];
74 < static char gecos_name[REALLEN * 4];
75 < static char lfile[IRCD_BUFSIZE];
76 < static unsigned int ltype = 0;
77 < static unsigned int lsize = 0;
78 < static char *resv_reason = NULL;
79 < static char *listener_address = NULL;
80 <
81 < struct CollectItem
82 < {
83 <  dlink_node node;
84 <  char *name;
85 <  char *user;
86 <  char *host;
87 <  char *passwd;
88 <  int  port;
89 <  int  flags;
90 < #ifdef HAVE_LIBCRYPTO
91 <  char *rsa_public_key_file;
92 <  RSA *rsa_public_key;
93 < #endif
94 < };
61 > static struct
62 > {
63 >  struct {
64 >    dlink_list list;
65 >  } mask,
66 >    leaf,
67 >    hub;
68 >
69 >  struct {
70 >    char buf[IRCD_BUFSIZE];
71 >  } name,
72 >    user,
73 >    host,
74 >    addr,
75 >    bind,
76 >    file,
77 >    ciph,
78 >    rpass,
79 >    spass,
80 >    class;
81 >
82 >  struct {
83 >    unsigned int value;
84 >  } flags,
85 >    modes,
86 >    size,
87 >    type,
88 >    port,
89 >    aftype,
90 >    ping_freq,
91 >    max_perip,
92 >    con_freq,
93 >    max_total,
94 >    max_global,
95 >    max_local,
96 >    max_ident,
97 >    max_sendq,
98 >    max_recvq,
99 >    cidr_bitlen_ipv4,
100 >    cidr_bitlen_ipv6,
101 >    number_per_cidr;
102 > } block_state;
103  
104   static void
105 < free_collect_item(struct CollectItem *item)
105 > reset_block_state(void)
106   {
107 <  MyFree(item->name);
108 <  MyFree(item->user);
109 <  MyFree(item->host);
110 <  MyFree(item->passwd);
111 < #ifdef HAVE_LIBCRYPTO
112 <  MyFree(item->rsa_public_key_file);
113 < #endif
114 <  MyFree(item);
107 >  dlink_node *ptr = NULL, *ptr_next = NULL;
108 >
109 >  DLINK_FOREACH_SAFE(ptr, ptr_next, block_state.mask.list.head)
110 >  {
111 >    MyFree(ptr->data);
112 >    dlinkDelete(ptr, &block_state.mask.list);
113 >    free_dlink_node(ptr);
114 >  }
115 >
116 >  DLINK_FOREACH_SAFE(ptr, ptr_next, block_state.leaf.list.head)
117 >  {
118 >    MyFree(ptr->data);
119 >    dlinkDelete(ptr, &block_state.leaf.list);
120 >    free_dlink_node(ptr);
121 >  }
122 >
123 >  DLINK_FOREACH_SAFE(ptr, ptr_next, block_state.hub.list.head)
124 >  {
125 >    MyFree(ptr->data);
126 >    dlinkDelete(ptr, &block_state.hub.list);
127 >    free_dlink_node(ptr);
128 >  }
129 >
130 >  memset(&block_state, 0, sizeof(block_state));
131   }
132  
133   %}
# Line 113 | Line 138 | free_collect_item(struct CollectItem *it
138   }
139  
140   %token  ACCEPT_PASSWORD
116 %token  ACTION
141   %token  ADMIN
142   %token  AFTYPE
119 %token  T_ALLOW
143   %token  ANTI_NICK_FLOOD
144   %token  ANTI_SPAM_EXIT_MESSAGE_TIME
145   %token  AUTOCONN
146 < %token  T_BLOCK
124 < %token  BURST_AWAY
125 < %token  BYTES KBYTES MBYTES GBYTES TBYTES
146 > %token  BYTES KBYTES MBYTES
147   %token  CALLER_ID_WAIT
148   %token  CAN_FLOOD
149   %token  CHANNEL
# Line 141 | Line 162 | free_collect_item(struct CollectItem *it
162   %token  DISABLE_FAKE_CHANNELS
163   %token  DISABLE_REMOTE_COMMANDS
164   %token  DOTS_IN_IDENT
144 %token  DURATION
165   %token  EGDPOOL_PATH
166   %token  EMAIL
147 %token  ENABLE
167   %token  ENCRYPTED
168   %token  EXCEED_LIMIT
169   %token  EXEMPT
# Line 157 | Line 176 | free_collect_item(struct CollectItem *it
176   %token  GLINE_DURATION
177   %token  GLINE_ENABLE
178   %token  GLINE_EXEMPT
160 %token  GLINE_TIME
179   %token  GLINE_REQUEST_DURATION
180   %token  GLINE_MIN_CIDR
181   %token  GLINE_MIN_CIDR6
# Line 180 | Line 198 | free_collect_item(struct CollectItem *it
198   %token  KILL_CHASE_TIME_LIMIT
199   %token  KLINE
200   %token  KLINE_EXEMPT
183 %token  KLINE_REASON
184 %token  KLINE_WITH_REASON
201   %token  KNOCK_DELAY
202   %token  KNOCK_DELAY_CHANNEL
203   %token  LEAF_MASK
# Line 216 | Line 232 | free_collect_item(struct CollectItem *it
232   %token  NO_OPER_FLOOD
233   %token  NO_TILDE
234   %token  NUMBER
219 %token  NUMBER_PER_IDENT
235   %token  NUMBER_PER_CIDR
236   %token  NUMBER_PER_IP
222 %token  NUMBER_PER_IP_GLOBAL
237   %token  OPERATOR
238   %token  OPERS_BYPASS_CALLERID
239   %token  OPER_ONLY_UMODES
# Line 234 | Line 248 | free_collect_item(struct CollectItem *it
248   %token  PATH
249   %token  PING_COOKIE
250   %token  PING_TIME
237 %token  PING_WARNING
251   %token  PORT
252   %token  QSTRING
253   %token  QUIET_ON_BAN
# Line 243 | Line 256 | free_collect_item(struct CollectItem *it
256   %token  REDIRSERV
257   %token  REGEX_T
258   %token  REHASH
246 %token  TREJECT_HOLD_TIME
259   %token  REMOTE
260   %token  REMOTEBAN
261   %token  RESTRICT_CHANNELS
250 %token  RESTRICTED
262   %token  RSA_PRIVATE_KEY_FILE
263   %token  RSA_PUBLIC_KEY_FILE
264   %token  SSL_CERTIFICATE_FILE
# Line 269 | Line 280 | free_collect_item(struct CollectItem *it
280   %token  T_CLUSTER
281   %token  TYPE
282   %token  SHORT_MOTD
272 %token  SILENT
283   %token  SPOOF
284   %token  SPOOF_NOTICE
285   %token  STATS_E_DISABLED
# Line 279 | Line 289 | free_collect_item(struct CollectItem *it
289   %token  STATS_P_OPER_ONLY
290   %token  TBOOL
291   %token  TMASKED
282 %token  T_REJECT
292   %token  TS_MAX_DELTA
293   %token  TS_WARN_DELTA
294   %token  TWODOTS
# Line 290 | Line 299 | free_collect_item(struct CollectItem *it
299   %token  T_CCONN
300   %token  T_CCONN_FULL
301   %token  T_SSL_CIPHER_LIST
293 %token  T_CLIENT_FLOOD
302   %token  T_DEAF
303   %token  T_DEBUG
304   %token  T_DLINE
297 %token  T_DRONE
305   %token  T_EXTERNAL
306   %token  T_FULL
307   %token  T_INVISIBLE
# Line 304 | Line 311 | free_collect_item(struct CollectItem *it
311   %token  T_MAX_CLIENTS
312   %token  T_NCHANGE
313   %token  T_OPERWALL
314 + %token  T_RECVQ
315   %token  T_REJ
316   %token  T_SERVER
317   %token  T_SERVNOTICE
# Line 319 | Line 327 | free_collect_item(struct CollectItem *it
327   %token  T_UNXLINE
328   %token  T_GLOBOPS
329   %token  T_WALLOP
330 + %token  T_WEBIRC
331   %token  T_RESTART
332   %token  T_SERVICE
333   %token  T_SERVICES_NAME
334   %token  THROTTLE_TIME
326 %token  TOPICBURST
335   %token  TRUE_NO_OPER_FLOOD
328 %token  TKLINE
329 %token  TXLINE
330 %token  TRESV
336   %token  UNKLINE
337   %token  USER
338   %token  USE_EGD
334 %token  USE_EXCEPT
335 %token  USE_INVEX
336 %token  USE_KNOCK
339   %token  USE_LOGGING
338 %token  USE_WHOIS_ACTUALLY
340   %token  VHOST
341   %token  VHOST6
342   %token  XLINE
342 %token  WARN
343   %token  WARN_NO_NLINE
344   %token  T_SIZE
345   %token  T_FILE
# Line 543 | Line 543 | serverinfo_rsa_private_key_file: RSA_PRI
543        ServerInfo.rsa_private_key_file = NULL;
544      }
545  
546 <    DupString(ServerInfo.rsa_private_key_file, yylval.string);
546 >    ServerInfo.rsa_private_key_file = xstrdup(yylval.string);
547  
548      if ((file = BIO_new_file(yylval.string, "r")) == NULL)
549      {
# Line 625 | Line 625 | serverinfo_name: NAME '=' QSTRING ';'
625    if (conf_parser_ctx.pass == 2 && !ServerInfo.name)
626    {
627      if (valid_servname(yylval.string))
628 <      DupString(ServerInfo.name, yylval.string);
628 >      ServerInfo.name = xstrdup(yylval.string);
629      else
630      {
631        ilog(LOG_TYPE_IRCD, "Ignoring serverinfo::name -- invalid name. Aborting.");
# Line 640 | Line 640 | serverinfo_sid: IRCD_SID '=' QSTRING ';'
640    if (conf_parser_ctx.pass == 2 && !ServerInfo.sid)
641    {
642      if (valid_sid(yylval.string))
643 <      DupString(ServerInfo.sid, yylval.string);
643 >      ServerInfo.sid = xstrdup(yylval.string);
644      else
645      {
646        ilog(LOG_TYPE_IRCD, "Ignoring serverinfo::sid -- invalid SID. Aborting.");
# Line 654 | Line 654 | serverinfo_description: DESCRIPTION '='
654    if (conf_parser_ctx.pass == 2)
655    {
656      MyFree(ServerInfo.description);
657 <    DupString(ServerInfo.description,yylval.string);
657 >    ServerInfo.description = xstrdup(yylval.string);
658    }
659   };
660  
# Line 668 | Line 668 | serverinfo_network_name: NETWORK_NAME '=
668        p = '\0';
669  
670      MyFree(ServerInfo.network_name);
671 <    DupString(ServerInfo.network_name, yylval.string);
671 >    ServerInfo.network_name = xstrdup(yylval.string);
672    }
673   };
674  
# Line 677 | Line 677 | serverinfo_network_desc: NETWORK_DESC '=
677    if (conf_parser_ctx.pass == 2)
678    {
679      MyFree(ServerInfo.network_desc);
680 <    DupString(ServerInfo.network_desc, yylval.string);
680 >    ServerInfo.network_desc = xstrdup(yylval.string);
681    }
682   };
683  
# Line 741 | Line 741 | serverinfo_vhost6: VHOST6 '=' QSTRING ';
741  
742   serverinfo_max_clients: T_MAX_CLIENTS '=' NUMBER ';'
743   {
744 <  if (conf_parser_ctx.pass == 2)
744 >  if (conf_parser_ctx.pass != 2)
745 >    break;
746 >
747 >  if ($3 < MAXCLIENTS_MIN)
748    {
749 <    recalc_fdlimit(NULL);
749 >    char buf[IRCD_BUFSIZE];
750  
751 <    if ($3 < MAXCLIENTS_MIN)
752 <    {
753 <      char buf[IRCD_BUFSIZE];
754 <      ircsprintf(buf, "MAXCLIENTS too low, setting to %d", MAXCLIENTS_MIN);
755 <      yyerror(buf);
756 <    }
757 <    else if ($3 > MAXCLIENTS_MAX)
758 <    {
759 <      char buf[IRCD_BUFSIZE];
760 <      ircsprintf(buf, "MAXCLIENTS too high, setting to %d", MAXCLIENTS_MAX);
761 <      yyerror(buf);
759 <    }
760 <    else
761 <      ServerInfo.max_clients = $3;
751 >    snprintf(buf, sizeof(buf), "MAXCLIENTS too low, setting to %d", MAXCLIENTS_MIN);
752 >    yyerror(buf);
753 >    ServerInfo.max_clients = MAXCLIENTS_MIN;
754 >  }
755 >  else if ($3 > MAXCLIENTS_MAX)
756 >  {
757 >    char buf[IRCD_BUFSIZE];
758 >
759 >    snprintf(buf, sizeof(buf), "MAXCLIENTS too high, setting to %d", MAXCLIENTS_MAX);
760 >    yyerror(buf);
761 >    ServerInfo.max_clients = MAXCLIENTS_MAX;
762    }
763 +  else
764 +    ServerInfo.max_clients = $3;
765   };
766  
767   serverinfo_hub: HUB '=' TBOOL ';'
# Line 782 | Line 784 | admin_name: NAME '=' QSTRING ';'
784    if (conf_parser_ctx.pass == 2)
785    {
786      MyFree(AdminInfo.name);
787 <    DupString(AdminInfo.name, yylval.string);
787 >    AdminInfo.name = xstrdup(yylval.string);
788    }
789   };
790  
# Line 791 | Line 793 | admin_email: EMAIL '=' QSTRING ';'
793    if (conf_parser_ctx.pass == 2)
794    {
795      MyFree(AdminInfo.email);
796 <    DupString(AdminInfo.email, yylval.string);
796 >    AdminInfo.email = xstrdup(yylval.string);
797    }
798   };
799  
# Line 800 | Line 802 | admin_description: DESCRIPTION '=' QSTRI
802    if (conf_parser_ctx.pass == 2)
803    {
804      MyFree(AdminInfo.description);
805 <    DupString(AdminInfo.description, yylval.string);
805 >    AdminInfo.description = xstrdup(yylval.string);
806    }
807   };
808  
# Line 821 | Line 823 | logging_use_logging: USE_LOGGING '=' TBO
823  
824   logging_file_entry:
825   {
826 <  lfile[0] = '\0';
827 <  ltype = 0;
826 <  lsize = 0;
826 >  if (conf_parser_ctx.pass == 2)
827 >    reset_block_state();
828   } T_FILE  '{' logging_file_items '}' ';'
829   {
830 <  if (conf_parser_ctx.pass == 2 && ltype > 0)
831 <    log_add_file(ltype, lsize, lfile);
830 >  if (conf_parser_ctx.pass != 2)
831 >    break;
832 >
833 >  if (block_state.type.value && block_state.file.buf[0])
834 >    log_add_file(block_state.type.value, block_state.size.value,
835 >                 block_state.file.buf);
836   };
837  
838   logging_file_items: logging_file_items logging_file_item |
# Line 838 | Line 843 | logging_file_item:  logging_file_name |
843  
844   logging_file_name: NAME '=' QSTRING ';'
845   {
846 <  strlcpy(lfile, yylval.string, sizeof(lfile));
846 >  if (conf_parser_ctx.pass != 2)
847 >    break;
848 >
849 >  strlcpy(block_state.file.buf, yylval.string, sizeof(block_state.file.buf));
850   }
851  
852   logging_file_size: T_SIZE '=' sizespec ';'
853   {
854 <  lsize = $3;
854 >  block_state.size.value = $3;
855   } | T_SIZE '=' T_UNLIMITED ';'
856   {
857 <  lsize = 0;
857 >  block_state.size.value = 0;
858   };
859  
860   logging_file_type: TYPE
861   {
862    if (conf_parser_ctx.pass == 2)
863 <    ltype = 0;
863 >    block_state.type.value = 0;
864   } '='  logging_file_type_items ';' ;
865  
866   logging_file_type_items: logging_file_type_items ',' logging_file_type_item | logging_file_type_item;
867   logging_file_type_item:  USER
868   {
869    if (conf_parser_ctx.pass == 2)
870 <    ltype = LOG_TYPE_USER;
870 >    block_state.type.value = LOG_TYPE_USER;
871   } | OPERATOR
872   {
873    if (conf_parser_ctx.pass == 2)
874 <    ltype = LOG_TYPE_OPER;
874 >    block_state.type.value = LOG_TYPE_OPER;
875   } | GLINE
876   {
877    if (conf_parser_ctx.pass == 2)
878 <    ltype = LOG_TYPE_GLINE;
878 >    block_state.type.value = LOG_TYPE_GLINE;
879   } | T_DLINE
880   {
881    if (conf_parser_ctx.pass == 2)
882 <    ltype = LOG_TYPE_DLINE;
882 >    block_state.type.value = LOG_TYPE_DLINE;
883   } | KLINE
884   {
885    if (conf_parser_ctx.pass == 2)
886 <    ltype = LOG_TYPE_KLINE;
886 >    block_state.type.value = LOG_TYPE_KLINE;
887   } | KILL
888   {
889    if (conf_parser_ctx.pass == 2)
890 <    ltype = LOG_TYPE_KILL;
890 >    block_state.type.value = LOG_TYPE_KILL;
891   } | T_DEBUG
892   {
893    if (conf_parser_ctx.pass == 2)
894 <    ltype = LOG_TYPE_DEBUG;
894 >    block_state.type.value = LOG_TYPE_DEBUG;
895   };
896  
897  
# Line 892 | Line 900 | logging_file_type_item:  USER
900   ***************************************************************************/
901   oper_entry: OPERATOR
902   {
903 <  if (conf_parser_ctx.pass == 2)
904 <  {
905 <    yy_conf = make_conf_item(OPER_TYPE);
906 <    yy_aconf = map_to_conf(yy_conf);
907 <    SetConfEncrypted(yy_aconf); /* Yes, the default is encrypted */
900 <  }
901 <  else
902 <  {
903 <    MyFree(class_name);
904 <    class_name = NULL;
905 <  }
903 >  if (conf_parser_ctx.pass != 2)
904 >    break;
905 >
906 >  reset_block_state();
907 >  block_state.flags.value |= CONF_FLAGS_ENCRYPTED;
908   } '{' oper_items '}' ';'
909   {
910 <  if (conf_parser_ctx.pass == 2)
911 <  {
912 <    struct CollectItem *yy_tmp;
913 <    dlink_node *ptr;
912 <    dlink_node *next_ptr;
913 <
914 <    conf_add_class_to_conf(yy_conf, class_name);
915 <
916 <    /* Now, make sure there is a copy of the "base" given oper
917 <     * block in each of the collected copies
918 <     */
919 <
920 <    DLINK_FOREACH_SAFE(ptr, next_ptr, col_conf_list.head)
921 <    {
922 <      struct AccessItem *new_aconf;
923 <      struct ConfItem *new_conf;
924 <      yy_tmp = ptr->data;
925 <
926 <      new_conf = make_conf_item(OPER_TYPE);
927 <      new_aconf = (struct AccessItem *)map_to_conf(new_conf);
928 <
929 <      new_aconf->flags = yy_aconf->flags;
930 <
931 <      if (yy_conf->name != NULL)
932 <        DupString(new_conf->name, yy_conf->name);
933 <      if (yy_tmp->user != NULL)
934 <        DupString(new_aconf->user, yy_tmp->user);
935 <      else
936 <        DupString(new_aconf->user, "*");
937 <      if (yy_tmp->host != NULL)
938 <        DupString(new_aconf->host, yy_tmp->host);
939 <      else
940 <        DupString(new_aconf->host, "*");
941 <
942 <      new_aconf->type = parse_netmask(new_aconf->host, &new_aconf->addr,
943 <                                     &new_aconf->bits);
944 <
945 <      conf_add_class_to_conf(new_conf, class_name);
946 <      if (yy_aconf->passwd != NULL)
947 <        DupString(new_aconf->passwd, yy_aconf->passwd);
910 >  dlink_node *ptr = NULL;
911 >
912 >  if (conf_parser_ctx.pass != 2)
913 >    break;
914  
915 <      new_aconf->port = yy_aconf->port;
915 >  if (!block_state.name.buf[0])
916 >    break;
917   #ifdef HAVE_LIBCRYPTO
918 <      if (yy_aconf->rsa_public_key_file != NULL)
919 <      {
920 <        BIO *file;
918 >  if (!(block_state.file.buf[0] ||
919 >        block_state.rpass.buf[0]))
920 >    break;
921 > #else
922 >  if (!block_state.rpass.buf[0])
923 >    break;
924 > #endif
925  
926 <        DupString(new_aconf->rsa_public_key_file,
927 <                  yy_aconf->rsa_public_key_file);
926 >  DLINK_FOREACH(ptr, block_state.mask.list.head)
927 >  {
928 >    struct MaskItem *conf = NULL;
929 >    struct split_nuh_item nuh;
930  
931 <        file = BIO_new_file(yy_aconf->rsa_public_key_file, "r");
932 <        new_aconf->rsa_public_key = (RSA *)PEM_read_bio_RSA_PUBKEY(file,
933 <                                                           NULL, 0, NULL);
934 <        BIO_set_close(file, BIO_CLOSE);
935 <        BIO_free(file);
936 <      }
937 < #endif
931 >    nuh.nuhmask  = ptr->data;
932 >    nuh.nickptr  = NULL;
933 >    nuh.userptr  = block_state.user.buf;
934 >    nuh.hostptr  = block_state.host.buf;
935 >    nuh.nicksize = 0;
936 >    nuh.usersize = sizeof(block_state.user.buf);
937 >    nuh.hostsize = sizeof(block_state.host.buf);
938 >    split_nuh(&nuh);
939 >
940 >    conf        = conf_make(CONF_OPER);
941 >    conf->name  = xstrdup(block_state.name.buf);
942 >    conf->user  = xstrdup(block_state.user.buf);
943 >    conf->host  = xstrdup(block_state.host.buf);
944 >
945 >    if (block_state.rpass.buf[0])
946 >      conf->passwd = xstrdup(block_state.rpass.buf);
947 >
948 >    conf->flags = block_state.flags.value;
949 >    conf->modes = block_state.modes.value;
950 >    conf->port  = block_state.port.value;
951 >    conf->htype = parse_netmask(conf->host, &conf->addr, &conf->bits);
952 >
953 >    conf_add_class_to_conf(conf, block_state.class.buf);
954  
955   #ifdef HAVE_LIBCRYPTO
956 <      if (yy_tmp->name && (yy_tmp->passwd || yy_aconf->rsa_public_key)
957 <          && yy_tmp->host)
958 < #else
959 <      if (yy_tmp->name && yy_tmp->passwd && yy_tmp->host)
960 < #endif
956 >    if (block_state.file.buf[0])
957 >    {
958 >      BIO *file = NULL;
959 >      RSA *pkey = NULL;
960 >
961 >      if ((file = BIO_new_file(block_state.file.buf, "r")) == NULL)
962        {
963 <        conf_add_class_to_conf(new_conf, class_name);
964 <        if (yy_tmp->name != NULL)
975 <          DupString(new_conf->name, yy_tmp->name);
963 >        yyerror("Ignoring rsa_public_key_file -- file doesn't exist");
964 >        break;
965        }
966  
967 <      dlinkDelete(&yy_tmp->node, &col_conf_list);
968 <      free_collect_item(yy_tmp);
980 <    }
981 <
982 <    yy_conf = NULL;
983 <    yy_aconf = NULL;
984 <
967 >      if ((pkey = PEM_read_bio_RSA_PUBKEY(file, NULL, 0, NULL)) == NULL)
968 >        yyerror("Ignoring rsa_public_key_file -- Key invalid; check key syntax.");
969  
970 <    MyFree(class_name);
971 <    class_name = NULL;
970 >      conf->rsa_public_key = pkey;
971 >      BIO_set_close(file, BIO_CLOSE);
972 >      BIO_free(file);
973 >    }
974 > #endif /* HAVE_LIBCRYPTO */
975    }
976 < };
976 > };
977  
978   oper_items:     oper_items oper_item | oper_item;
979   oper_item:      oper_name | oper_user | oper_password |
# Line 996 | Line 983 | oper_item:      oper_name | oper_user |
983   oper_name: NAME '=' QSTRING ';'
984   {
985    if (conf_parser_ctx.pass == 2)
986 <  {
1000 <    MyFree(yy_conf->name);
1001 <    DupString(yy_conf->name, yylval.string);
1002 <  }
986 >    strlcpy(block_state.name.buf, yylval.string, sizeof(block_state.name.buf));
987   };
988  
989   oper_user: USER '=' QSTRING ';'
990   {
991    if (conf_parser_ctx.pass == 2)
992 <  {
1009 <    struct split_nuh_item nuh;
1010 <
1011 <    nuh.nuhmask  = yylval.string;
1012 <    nuh.nickptr  = NULL;
1013 <    nuh.userptr  = userbuf;
1014 <    nuh.hostptr  = hostbuf;
1015 <
1016 <    nuh.nicksize = 0;
1017 <    nuh.usersize = sizeof(userbuf);
1018 <    nuh.hostsize = sizeof(hostbuf);
1019 <
1020 <    split_nuh(&nuh);
1021 <
1022 <    if (yy_aconf->user == NULL)
1023 <    {
1024 <      DupString(yy_aconf->user, userbuf);
1025 <      DupString(yy_aconf->host, hostbuf);
1026 <
1027 <      yy_aconf->type = parse_netmask(yy_aconf->host, &yy_aconf->addr,
1028 <                                    &yy_aconf->bits);
1029 <    }
1030 <    else
1031 <    {
1032 <      struct CollectItem *yy_tmp = MyMalloc(sizeof(struct CollectItem));
1033 <
1034 <      DupString(yy_tmp->user, userbuf);
1035 <      DupString(yy_tmp->host, hostbuf);
1036 <
1037 <      dlinkAdd(yy_tmp, &yy_tmp->node, &col_conf_list);
1038 <    }
1039 <  }
992 >    dlinkAdd(xstrdup(yylval.string), make_dlink_node(), &block_state.mask.list);
993   };
994  
995   oper_password: PASSWORD '=' QSTRING ';'
996   {
997    if (conf_parser_ctx.pass == 2)
998 <  {
1046 <    if (yy_aconf->passwd != NULL)
1047 <      memset(yy_aconf->passwd, 0, strlen(yy_aconf->passwd));
1048 <
1049 <    MyFree(yy_aconf->passwd);
1050 <    DupString(yy_aconf->passwd, yylval.string);
1051 <  }
998 >    strlcpy(block_state.rpass.buf, yylval.string, sizeof(block_state.rpass.buf));
999   };
1000  
1001   oper_encrypted: ENCRYPTED '=' TBOOL ';'
# Line 1056 | Line 1003 | oper_encrypted: ENCRYPTED '=' TBOOL ';'
1003    if (conf_parser_ctx.pass == 2)
1004    {
1005      if (yylval.number)
1006 <      SetConfEncrypted(yy_aconf);
1006 >      block_state.flags.value |= CONF_FLAGS_ENCRYPTED;
1007      else
1008 <      ClearConfEncrypted(yy_aconf);
1008 >      block_state.flags.value &= ~CONF_FLAGS_ENCRYPTED;
1009    }
1010   };
1011  
1012   oper_rsa_public_key_file: RSA_PUBLIC_KEY_FILE '=' QSTRING ';'
1013   {
1067 #ifdef HAVE_LIBCRYPTO
1014    if (conf_parser_ctx.pass == 2)
1015 <  {
1070 <    BIO *file;
1071 <
1072 <    if (yy_aconf->rsa_public_key != NULL)
1073 <    {
1074 <      RSA_free(yy_aconf->rsa_public_key);
1075 <      yy_aconf->rsa_public_key = NULL;
1076 <    }
1077 <
1078 <    if (yy_aconf->rsa_public_key_file != NULL)
1079 <    {
1080 <      MyFree(yy_aconf->rsa_public_key_file);
1081 <      yy_aconf->rsa_public_key_file = NULL;
1082 <    }
1083 <
1084 <    DupString(yy_aconf->rsa_public_key_file, yylval.string);
1085 <    file = BIO_new_file(yylval.string, "r");
1086 <
1087 <    if (file == NULL)
1088 <    {
1089 <      yyerror("Ignoring rsa_public_key_file -- file doesn't exist");
1090 <      break;
1091 <    }
1092 <
1093 <    yy_aconf->rsa_public_key = (RSA *)PEM_read_bio_RSA_PUBKEY(file, NULL, 0, NULL);
1094 <
1095 <    if (yy_aconf->rsa_public_key == NULL)
1096 <    {
1097 <      yyerror("Ignoring rsa_public_key_file -- Key invalid; check key syntax.");
1098 <      break;
1099 <    }
1100 <
1101 <    BIO_set_close(file, BIO_CLOSE);
1102 <    BIO_free(file);
1103 <  }
1104 < #endif /* HAVE_LIBCRYPTO */
1015 >    strlcpy(block_state.file.buf, yylval.string, sizeof(block_state.file.buf));
1016   };
1017  
1018   oper_class: CLASS '=' QSTRING ';'
1019   {
1020    if (conf_parser_ctx.pass == 2)
1021 <  {
1111 <    MyFree(class_name);
1112 <    DupString(class_name, yylval.string);
1113 <  }
1021 >    strlcpy(block_state.class.buf, yylval.string, sizeof(block_state.class.buf));
1022   };
1023  
1024   oper_umodes: T_UMODES
1025   {
1026    if (conf_parser_ctx.pass == 2)
1027 <    yy_aconf->modes = 0;
1027 >    block_state.modes.value = 0;
1028   } '='  oper_umodes_items ';' ;
1029  
1030   oper_umodes_items: oper_umodes_items ',' oper_umodes_item | oper_umodes_item;
1031   oper_umodes_item:  T_BOTS
1032   {
1033    if (conf_parser_ctx.pass == 2)
1034 <    yy_aconf->modes |= UMODE_BOTS;
1034 >    block_state.modes.value |= UMODE_BOTS;
1035   } | T_CCONN
1036   {
1037    if (conf_parser_ctx.pass == 2)
1038 <    yy_aconf->modes |= UMODE_CCONN;
1038 >    block_state.modes.value |= UMODE_CCONN;
1039   } | T_CCONN_FULL
1040   {
1041    if (conf_parser_ctx.pass == 2)
1042 <    yy_aconf->modes |= UMODE_CCONN_FULL;
1042 >    block_state.modes.value |= UMODE_CCONN_FULL;
1043   } | T_DEAF
1044   {
1045    if (conf_parser_ctx.pass == 2)
1046 <    yy_aconf->modes |= UMODE_DEAF;
1046 >    block_state.modes.value |= UMODE_DEAF;
1047   } | T_DEBUG
1048   {
1049    if (conf_parser_ctx.pass == 2)
1050 <    yy_aconf->modes |= UMODE_DEBUG;
1050 >    block_state.modes.value |= UMODE_DEBUG;
1051   } | T_FULL
1052   {
1053    if (conf_parser_ctx.pass == 2)
1054 <    yy_aconf->modes |= UMODE_FULL;
1054 >    block_state.modes.value |= UMODE_FULL;
1055   } | HIDDEN
1056   {
1057    if (conf_parser_ctx.pass == 2)
1058 <    yy_aconf->modes |= UMODE_HIDDEN;
1058 >    block_state.modes.value |= UMODE_HIDDEN;
1059   } | T_SKILL
1060   {
1061    if (conf_parser_ctx.pass == 2)
1062 <    yy_aconf->modes |= UMODE_SKILL;
1062 >    block_state.modes.value |= UMODE_SKILL;
1063   } | T_NCHANGE
1064   {
1065    if (conf_parser_ctx.pass == 2)
1066 <    yy_aconf->modes |= UMODE_NCHANGE;
1066 >    block_state.modes.value |= UMODE_NCHANGE;
1067   } | T_REJ
1068   {
1069    if (conf_parser_ctx.pass == 2)
1070 <    yy_aconf->modes |= UMODE_REJ;
1070 >    block_state.modes.value |= UMODE_REJ;
1071   } | T_UNAUTH
1072   {
1073    if (conf_parser_ctx.pass == 2)
1074 <    yy_aconf->modes |= UMODE_UNAUTH;
1074 >    block_state.modes.value |= UMODE_UNAUTH;
1075   } | T_SPY
1076   {
1077    if (conf_parser_ctx.pass == 2)
1078 <    yy_aconf->modes |= UMODE_SPY;
1078 >    block_state.modes.value |= UMODE_SPY;
1079   } | T_EXTERNAL
1080   {
1081    if (conf_parser_ctx.pass == 2)
1082 <    yy_aconf->modes |= UMODE_EXTERNAL;
1082 >    block_state.modes.value |= UMODE_EXTERNAL;
1083   } | T_OPERWALL
1084   {
1085    if (conf_parser_ctx.pass == 2)
1086 <    yy_aconf->modes |= UMODE_OPERWALL;
1086 >    block_state.modes.value |= UMODE_OPERWALL;
1087   } | T_SERVNOTICE
1088   {
1089    if (conf_parser_ctx.pass == 2)
1090 <    yy_aconf->modes |= UMODE_SERVNOTICE;
1090 >    block_state.modes.value |= UMODE_SERVNOTICE;
1091   } | T_INVISIBLE
1092   {
1093    if (conf_parser_ctx.pass == 2)
1094 <    yy_aconf->modes |= UMODE_INVISIBLE;
1094 >    block_state.modes.value |= UMODE_INVISIBLE;
1095   } | T_WALLOP
1096   {
1097    if (conf_parser_ctx.pass == 2)
1098 <    yy_aconf->modes |= UMODE_WALLOP;
1098 >    block_state.modes.value |= UMODE_WALLOP;
1099   } | T_SOFTCALLERID
1100   {
1101    if (conf_parser_ctx.pass == 2)
1102 <    yy_aconf->modes |= UMODE_SOFTCALLERID;
1102 >    block_state.modes.value |= UMODE_SOFTCALLERID;
1103   } | T_CALLERID
1104   {
1105    if (conf_parser_ctx.pass == 2)
1106 <    yy_aconf->modes |= UMODE_CALLERID;
1106 >    block_state.modes.value |= UMODE_CALLERID;
1107   } | T_LOCOPS
1108   {
1109    if (conf_parser_ctx.pass == 2)
1110 <    yy_aconf->modes |= UMODE_LOCOPS;
1110 >    block_state.modes.value |= UMODE_LOCOPS;
1111   };
1112  
1113   oper_flags: IRCD_FLAGS
1114   {
1115    if (conf_parser_ctx.pass == 2)
1116 <    yy_aconf->port = 0;
1116 >    block_state.port.value = 0;
1117   } '='  oper_flags_items ';';
1118  
1119   oper_flags_items: oper_flags_items ',' oper_flags_item | oper_flags_item;
1120   oper_flags_item: GLOBAL_KILL
1121   {
1122    if (conf_parser_ctx.pass == 2)
1123 <    yy_aconf->port |= OPER_FLAG_GLOBAL_KILL;
1123 >    block_state.port.value |= OPER_FLAG_GLOBAL_KILL;
1124   } | REMOTE
1125   {
1126    if (conf_parser_ctx.pass == 2)
1127 <    yy_aconf->port |= OPER_FLAG_REMOTE;
1127 >    block_state.port.value |= OPER_FLAG_REMOTE;
1128   } | KLINE
1129   {
1130    if (conf_parser_ctx.pass == 2)
1131 <    yy_aconf->port |= OPER_FLAG_K;
1131 >    block_state.port.value |= OPER_FLAG_K;
1132   } | UNKLINE
1133   {
1134    if (conf_parser_ctx.pass == 2)
1135 <    yy_aconf->port |= OPER_FLAG_UNKLINE;
1135 >    block_state.port.value |= OPER_FLAG_UNKLINE;
1136   } | T_DLINE
1137   {
1138    if (conf_parser_ctx.pass == 2)
1139 <    yy_aconf->port |= OPER_FLAG_DLINE;
1139 >    block_state.port.value |= OPER_FLAG_DLINE;
1140   } | T_UNDLINE
1141   {
1142    if (conf_parser_ctx.pass == 2)
1143 <    yy_aconf->port |= OPER_FLAG_UNDLINE;
1143 >    block_state.port.value |= OPER_FLAG_UNDLINE;
1144   } | XLINE
1145   {
1146    if (conf_parser_ctx.pass == 2)
1147 <    yy_aconf->port |= OPER_FLAG_X;
1147 >    block_state.port.value |= OPER_FLAG_X;
1148   } | GLINE
1149   {
1150    if (conf_parser_ctx.pass == 2)
1151 <    yy_aconf->port |= OPER_FLAG_GLINE;
1151 >    block_state.port.value |= OPER_FLAG_GLINE;
1152   } | DIE
1153   {
1154    if (conf_parser_ctx.pass == 2)
1155 <    yy_aconf->port |= OPER_FLAG_DIE;
1155 >    block_state.port.value |= OPER_FLAG_DIE;
1156   } | T_RESTART
1157   {
1158    if (conf_parser_ctx.pass == 2)
1159 <    yy_aconf->port |= OPER_FLAG_RESTART;
1159 >    block_state.port.value |= OPER_FLAG_RESTART;
1160   } | REHASH
1161   {
1162    if (conf_parser_ctx.pass == 2)
1163 <    yy_aconf->port |= OPER_FLAG_REHASH;
1163 >    block_state.port.value |= OPER_FLAG_REHASH;
1164   } | ADMIN
1165   {
1166    if (conf_parser_ctx.pass == 2)
1167 <    yy_aconf->port |= OPER_FLAG_ADMIN;
1167 >    block_state.port.value |= OPER_FLAG_ADMIN;
1168   } | NICK_CHANGES
1169   {
1170    if (conf_parser_ctx.pass == 2)
1171 <    yy_aconf->port |= OPER_FLAG_N;
1171 >    block_state.port.value |= OPER_FLAG_N;
1172   } | T_OPERWALL
1173   {
1174    if (conf_parser_ctx.pass == 2)
1175 <    yy_aconf->port |= OPER_FLAG_OPERWALL;
1175 >    block_state.port.value |= OPER_FLAG_OPERWALL;
1176   } | T_GLOBOPS
1177   {
1178    if (conf_parser_ctx.pass == 2)
1179 <    yy_aconf->port |= OPER_FLAG_GLOBOPS;
1179 >    block_state.port.value |= OPER_FLAG_GLOBOPS;
1180   } | OPER_SPY_T
1181   {
1182    if (conf_parser_ctx.pass == 2)
1183 <    yy_aconf->port |= OPER_FLAG_OPER_SPY;
1183 >    block_state.port.value |= OPER_FLAG_OPER_SPY;
1184   } | REMOTEBAN
1185   {
1186    if (conf_parser_ctx.pass == 2)
1187 <    yy_aconf->port |= OPER_FLAG_REMOTEBAN;
1187 >    block_state.port.value |= OPER_FLAG_REMOTEBAN;
1188   } | T_SET
1189   {
1190    if (conf_parser_ctx.pass == 2)
1191 <    yy_aconf->port |= OPER_FLAG_SET;
1191 >    block_state.port.value |= OPER_FLAG_SET;
1192   } | MODULE
1193   {
1194    if (conf_parser_ctx.pass == 2)
1195 <    yy_aconf->port |= OPER_FLAG_MODULE;
1195 >    block_state.port.value |= OPER_FLAG_MODULE;
1196   };
1197  
1198  
# Line 1293 | Line 1201 | oper_flags_item: GLOBAL_KILL
1201   ***************************************************************************/
1202   class_entry: CLASS
1203   {
1204 <  if (conf_parser_ctx.pass == 1)
1205 <  {
1298 <    yy_conf = make_conf_item(CLASS_TYPE);
1299 <    yy_class = map_to_conf(yy_conf);
1300 <  }
1301 < } '{' class_items '}' ';'
1302 < {
1303 <  if (conf_parser_ctx.pass == 1)
1304 <  {
1305 <    struct ConfItem *cconf = NULL;
1306 <    struct ClassItem *class = NULL;
1204 >  if (conf_parser_ctx.pass != 1)
1205 >    break;
1206  
1207 <    if (yy_class_name == NULL)
1309 <      delete_conf_item(yy_conf);
1310 <    else
1311 <    {
1312 <      cconf = find_exact_name_conf(CLASS_TYPE, NULL, yy_class_name, NULL, NULL);
1313 <
1314 <      if (cconf != NULL)                /* The class existed already */
1315 <      {
1316 <        int user_count = 0;
1207 >  reset_block_state();
1208  
1209 <        rebuild_cidr_class(cconf, yy_class);
1209 >  block_state.ping_freq.value = DEFAULT_PINGFREQUENCY;
1210 >  block_state.con_freq.value  = DEFAULT_CONNECTFREQUENCY;
1211 >  block_state.max_total.value = MAXIMUM_LINKS_DEFAULT;
1212 >  block_state.max_sendq.value = DEFAULT_SENDQ;
1213 >  block_state.max_recvq.value = DEFAULT_RECVQ;
1214  
1215 <        class = map_to_conf(cconf);
1215 > } '{' class_items '}' ';'
1216 > {
1217 >  struct ClassItem *class = NULL;
1218  
1219 <        user_count = class->curr_user_count;
1220 <        memcpy(class, yy_class, sizeof(*class));
1324 <        class->curr_user_count = user_count;
1325 <        class->active = 1;
1219 >  if (conf_parser_ctx.pass != 1)
1220 >    break;
1221  
1222 <        delete_conf_item(yy_conf);
1222 >  if (!block_state.class.buf[0])
1223 >    break;
1224  
1225 <        MyFree(cconf->name);            /* Allows case change of class name */
1226 <        cconf->name = yy_class_name;
1227 <      }
1228 <      else      /* Brand new class */
1229 <      {
1230 <        MyFree(yy_conf->name);          /* just in case it was allocated */
1231 <        yy_conf->name = yy_class_name;
1232 <        yy_class->active = 1;
1233 <      }
1234 <    }
1235 <
1236 <    yy_class_name = NULL;
1237 <  }
1225 >  if (!(class = class_find(block_state.class.buf, 0)))
1226 >    class = class_make();
1227 >
1228 >  class->active = 1;
1229 >  MyFree(class->name);
1230 >  class->name = xstrdup(block_state.class.buf);
1231 >  class->ping_freq = block_state.ping_freq.value;
1232 >  class->max_perip = block_state.max_perip.value;
1233 >  class->con_freq = block_state.con_freq.value;
1234 >  class->max_total = block_state.max_total.value;
1235 >  class->max_global = block_state.max_global.value;
1236 >  class->max_local = block_state.max_local.value;
1237 >  class->max_ident = block_state.max_ident.value;
1238 >  class->max_sendq = block_state.max_sendq.value;
1239 >  class->max_recvq = block_state.max_recvq.value;
1240 >
1241 >  if (class->number_per_cidr && block_state.number_per_cidr.value)
1242 >    if ((class->cidr_bitlen_ipv4 && block_state.cidr_bitlen_ipv4.value) ||
1243 >        (class->cidr_bitlen_ipv6 && block_state.cidr_bitlen_ipv6.value))
1244 >      if ((class->cidr_bitlen_ipv4 != block_state.cidr_bitlen_ipv4.value) ||
1245 >          (class->cidr_bitlen_ipv6 != block_state.cidr_bitlen_ipv6.value))
1246 >        rebuild_cidr_list(class);
1247 >
1248 >  class->cidr_bitlen_ipv4 = block_state.cidr_bitlen_ipv4.value;
1249 >  class->cidr_bitlen_ipv6 = block_state.cidr_bitlen_ipv6.value;
1250 >  class->number_per_cidr = block_state.number_per_cidr.value;
1251   };
1252  
1253   class_items:    class_items class_item | class_item;
1254   class_item:     class_name |
1255                  class_cidr_bitlen_ipv4 | class_cidr_bitlen_ipv6 |
1256                  class_ping_time |
1348                class_ping_warning |
1257                  class_number_per_cidr |
1258                  class_number_per_ip |
1259                  class_connectfreq |
# Line 1353 | Line 1261 | class_item:     class_name |
1261                  class_max_global |
1262                  class_max_local |
1263                  class_max_ident |
1264 <                class_sendq |
1264 >                class_sendq | class_recvq |
1265                  error ';' ;
1266  
1267   class_name: NAME '=' QSTRING ';'
1268   {
1269    if (conf_parser_ctx.pass == 1)
1270 <  {
1363 <    MyFree(yy_class_name);
1364 <    DupString(yy_class_name, yylval.string);
1365 <  }
1270 >    strlcpy(block_state.class.buf, yylval.string, sizeof(block_state.class.buf));
1271   };
1272  
1273   class_ping_time: PING_TIME '=' timespec ';'
1274   {
1275    if (conf_parser_ctx.pass == 1)
1276 <    yy_class->ping_freq = $3;
1372 < };
1373 <
1374 < class_ping_warning: PING_WARNING '=' timespec ';'
1375 < {
1376 <  if (conf_parser_ctx.pass == 1)
1377 <    yy_class->ping_warning = $3;
1276 >    block_state.ping_freq.value = $3;
1277   };
1278  
1279   class_number_per_ip: NUMBER_PER_IP '=' NUMBER ';'
1280   {
1281    if (conf_parser_ctx.pass == 1)
1282 <    yy_class->max_perip = $3;
1282 >    block_state.max_perip.value = $3;
1283   };
1284  
1285   class_connectfreq: CONNECTFREQ '=' timespec ';'
1286   {
1287    if (conf_parser_ctx.pass == 1)
1288 <    yy_class->con_freq = $3;
1288 >    block_state.con_freq.value = $3;
1289   };
1290  
1291   class_max_number: MAX_NUMBER '=' NUMBER ';'
1292   {
1293    if (conf_parser_ctx.pass == 1)
1294 <    yy_class->max_total = $3;
1294 >    block_state.max_total.value = $3;
1295   };
1296  
1297   class_max_global: MAX_GLOBAL '=' NUMBER ';'
1298   {
1299    if (conf_parser_ctx.pass == 1)
1300 <    yy_class->max_global = $3;
1300 >    block_state.max_global.value = $3;
1301   };
1302  
1303   class_max_local: MAX_LOCAL '=' NUMBER ';'
1304   {
1305    if (conf_parser_ctx.pass == 1)
1306 <    yy_class->max_local = $3;
1306 >    block_state.max_local.value = $3;
1307   };
1308  
1309   class_max_ident: MAX_IDENT '=' NUMBER ';'
1310   {
1311    if (conf_parser_ctx.pass == 1)
1312 <    yy_class->max_ident = $3;
1312 >    block_state.max_ident.value = $3;
1313   };
1314  
1315   class_sendq: SENDQ '=' sizespec ';'
1316   {
1317    if (conf_parser_ctx.pass == 1)
1318 <    yy_class->max_sendq = $3;
1318 >    block_state.max_sendq.value = $3;
1319 > };
1320 >
1321 > class_recvq: T_RECVQ '=' sizespec ';'
1322 > {
1323 >  if (conf_parser_ctx.pass == 1)
1324 >    if ($3 >= CLIENT_FLOOD_MIN && $3 <= CLIENT_FLOOD_MAX)
1325 >      block_state.max_recvq.value = $3;
1326   };
1327  
1328   class_cidr_bitlen_ipv4: CIDR_BITLEN_IPV4 '=' NUMBER ';'
1329   {
1330    if (conf_parser_ctx.pass == 1)
1331 <    yy_class->cidr_bitlen_ipv4 = $3 > 32 ? 32 : $3;
1331 >    block_state.cidr_bitlen_ipv4.value = $3 > 32 ? 32 : $3;
1332   };
1333  
1334   class_cidr_bitlen_ipv6: CIDR_BITLEN_IPV6 '=' NUMBER ';'
1335   {
1336    if (conf_parser_ctx.pass == 1)
1337 <    yy_class->cidr_bitlen_ipv6 = $3 > 128 ? 128 : $3;
1337 >    block_state.cidr_bitlen_ipv6.value = $3 > 128 ? 128 : $3;
1338   };
1339  
1340   class_number_per_cidr: NUMBER_PER_CIDR '=' NUMBER ';'
1341   {
1342    if (conf_parser_ctx.pass == 1)
1343 <    yy_class->number_per_cidr = $3;
1343 >    block_state.number_per_cidr.value = $3;
1344   };
1345  
1346   /***************************************************************************
# Line 1443 | Line 1349 | class_number_per_cidr: NUMBER_PER_CIDR '
1349   listen_entry: LISTEN
1350   {
1351    if (conf_parser_ctx.pass == 2)
1352 <  {
1353 <    listener_address = NULL;
1448 <    listener_flags = 0;
1449 <  }
1450 < } '{' listen_items '}' ';'
1451 < {
1452 <  if (conf_parser_ctx.pass == 2)
1453 <  {
1454 <    MyFree(listener_address);
1455 <    listener_address = NULL;
1456 <  }
1457 < };
1352 >    reset_block_state();
1353 > } '{' listen_items '}' ';';
1354  
1355   listen_flags: IRCD_FLAGS
1356   {
1357 <  listener_flags = 0;
1357 >  block_state.flags.value = 0;
1358   } '='  listen_flags_items ';';
1359  
1360   listen_flags_items: listen_flags_items ',' listen_flags_item | listen_flags_item;
1361   listen_flags_item: T_SSL
1362   {
1363    if (conf_parser_ctx.pass == 2)
1364 <    listener_flags |= LISTENER_SSL;
1364 >    block_state.flags.value |= LISTENER_SSL;
1365   } | HIDDEN
1366   {
1367    if (conf_parser_ctx.pass == 2)
1368 <    listener_flags |= LISTENER_HIDDEN;
1368 >    block_state.flags.value |= LISTENER_HIDDEN;
1369   } | T_SERVER
1370   {
1371    if (conf_parser_ctx.pass == 2)
1372 <    listener_flags |= LISTENER_SERVER;
1372 >   block_state.flags.value |= LISTENER_SERVER;
1373   };
1374  
1479
1480
1375   listen_items:   listen_items listen_item | listen_item;
1376   listen_item:    listen_port | listen_flags | listen_address | listen_host | error ';';
1377  
1378 < listen_port: PORT '=' port_items { listener_flags = 0; } ';';
1378 > listen_port: PORT '=' port_items { block_state.flags.value = 0; } ';';
1379  
1380   port_items: port_items ',' port_item | port_item;
1381  
# Line 1489 | Line 1383 | port_item: NUMBER
1383   {
1384    if (conf_parser_ctx.pass == 2)
1385    {
1386 <    if ((listener_flags & LISTENER_SSL))
1386 >    if (block_state.flags.value & LISTENER_SSL)
1387   #ifdef HAVE_LIBCRYPTO
1388        if (!ServerInfo.server_ctx)
1389   #endif
# Line 1497 | Line 1391 | port_item: NUMBER
1391          yyerror("SSL not available - port closed");
1392          break;
1393        }
1394 <    add_listener($1, listener_address, listener_flags);
1394 >    add_listener($1, block_state.addr.buf, block_state.flags.value);
1395    }
1396   } | NUMBER TWODOTS NUMBER
1397   {
# Line 1505 | Line 1399 | port_item: NUMBER
1399    {
1400      int i;
1401  
1402 <    if ((listener_flags & LISTENER_SSL))
1402 >    if (block_state.flags.value & LISTENER_SSL)
1403   #ifdef HAVE_LIBCRYPTO
1404        if (!ServerInfo.server_ctx)
1405   #endif
# Line 1515 | Line 1409 | port_item: NUMBER
1409        }
1410  
1411      for (i = $1; i <= $3; ++i)
1412 <      add_listener(i, listener_address, listener_flags);
1412 >      add_listener(i, block_state.addr.buf, block_state.flags.value);
1413    }
1414   };
1415  
1416   listen_address: IP '=' QSTRING ';'
1417   {
1418    if (conf_parser_ctx.pass == 2)
1419 <  {
1526 <    MyFree(listener_address);
1527 <    DupString(listener_address, yylval.string);
1528 <  }
1419 >    strlcpy(block_state.addr.buf, yylval.string, sizeof(block_state.addr.buf));
1420   };
1421  
1422   listen_host: HOST '=' QSTRING ';'
1423   {
1424    if (conf_parser_ctx.pass == 2)
1425 <  {
1535 <    MyFree(listener_address);
1536 <    DupString(listener_address, yylval.string);
1537 <  }
1425 >    strlcpy(block_state.addr.buf, yylval.string, sizeof(block_state.addr.buf));
1426   };
1427  
1428   /***************************************************************************
# Line 1543 | Line 1431 | listen_host: HOST '=' QSTRING ';'
1431   auth_entry: IRCD_AUTH
1432   {
1433    if (conf_parser_ctx.pass == 2)
1434 <  {
1547 <    yy_conf = make_conf_item(CLIENT_TYPE);
1548 <    yy_aconf = map_to_conf(yy_conf);
1549 <  }
1550 <  else
1551 <  {
1552 <    MyFree(class_name);
1553 <    class_name = NULL;
1554 <  }
1434 >    reset_block_state();
1435   } '{' auth_items '}' ';'
1436   {
1437 <  if (conf_parser_ctx.pass == 2)
1558 <  {
1559 <    struct CollectItem *yy_tmp = NULL;
1560 <    dlink_node *ptr = NULL, *next_ptr = NULL;
1561 <
1562 <    if (yy_aconf->user && yy_aconf->host)
1563 <    {
1564 <      conf_add_class_to_conf(yy_conf, class_name);
1565 <      add_conf_by_address(CONF_CLIENT, yy_aconf);
1566 <    }
1567 <    else
1568 <      delete_conf_item(yy_conf);
1569 <
1570 <    /* copy over settings from first struct */
1571 <    DLINK_FOREACH_SAFE(ptr, next_ptr, col_conf_list.head)
1572 <    {
1573 <      struct AccessItem *new_aconf;
1574 <      struct ConfItem *new_conf;
1575 <
1576 <      new_conf = make_conf_item(CLIENT_TYPE);
1577 <      new_aconf = map_to_conf(new_conf);
1437 >  dlink_node *ptr = NULL;
1438  
1439 <      yy_tmp = ptr->data;
1439 >  if (conf_parser_ctx.pass != 2)
1440 >    break;
1441  
1442 <      assert(yy_tmp->user && yy_tmp->host);
1443 <
1444 <      if (yy_aconf->passwd != NULL)
1445 <        DupString(new_aconf->passwd, yy_aconf->passwd);
1585 <      if (yy_conf->name != NULL)
1586 <        DupString(new_conf->name, yy_conf->name);
1587 <      if (yy_aconf->passwd != NULL)
1588 <        DupString(new_aconf->passwd, yy_aconf->passwd);
1442 >  DLINK_FOREACH(ptr, block_state.mask.list.head)
1443 >  {
1444 >    struct MaskItem *conf = NULL;
1445 >    struct split_nuh_item nuh;
1446  
1447 <      new_aconf->flags = yy_aconf->flags;
1448 <      new_aconf->port  = yy_aconf->port;
1447 >    nuh.nuhmask  = ptr->data;
1448 >    nuh.nickptr  = NULL;
1449 >    nuh.userptr  = block_state.user.buf;
1450 >    nuh.hostptr  = block_state.host.buf;
1451 >    nuh.nicksize = 0;
1452 >    nuh.usersize = sizeof(block_state.user.buf);
1453 >    nuh.hostsize = sizeof(block_state.host.buf);
1454 >    split_nuh(&nuh);
1455  
1456 <      DupString(new_aconf->user, yy_tmp->user);
1457 <      collapse(new_aconf->user);
1456 >    conf        = conf_make(CONF_CLIENT);
1457 >    conf->user  = xstrdup(collapse(block_state.user.buf));
1458 >    conf->host  = xstrdup(collapse(block_state.host.buf));
1459 >
1460 >    if (block_state.rpass.buf[0])
1461 >      conf->passwd = xstrdup(block_state.rpass.buf);
1462 >    if (block_state.name.buf[0])
1463 >      conf->passwd = xstrdup(block_state.name.buf);
1464  
1465 <      DupString(new_aconf->host, yy_tmp->host);
1466 <      collapse(new_aconf->host);
1465 >    conf->flags = block_state.flags.value;
1466 >    conf->port  = block_state.port.value;
1467  
1468 <      conf_add_class_to_conf(new_conf, class_name);
1469 <      add_conf_by_address(CONF_CLIENT, new_aconf);
1601 <      dlinkDelete(&yy_tmp->node, &col_conf_list);
1602 <      free_collect_item(yy_tmp);
1603 <    }
1604 <
1605 <    MyFree(class_name);
1606 <    class_name = NULL;
1607 <    yy_conf = NULL;
1608 <    yy_aconf = NULL;
1468 >    conf_add_class_to_conf(conf, block_state.class.buf);
1469 >    add_conf_by_address(CONF_CLIENT, conf);
1470    }
1471   };
1472  
# Line 1617 | Line 1478 | auth_item:      auth_user | auth_passwd
1478   auth_user: USER '=' QSTRING ';'
1479   {
1480    if (conf_parser_ctx.pass == 2)
1481 <  {
1621 <    struct CollectItem *yy_tmp = NULL;
1622 <    struct split_nuh_item nuh;
1623 <
1624 <    nuh.nuhmask  = yylval.string;
1625 <    nuh.nickptr  = NULL;
1626 <    nuh.userptr  = userbuf;
1627 <    nuh.hostptr  = hostbuf;
1628 <
1629 <    nuh.nicksize = 0;
1630 <    nuh.usersize = sizeof(userbuf);
1631 <    nuh.hostsize = sizeof(hostbuf);
1632 <
1633 <    split_nuh(&nuh);
1634 <
1635 <    if (yy_aconf->user == NULL)
1636 <    {
1637 <      DupString(yy_aconf->user, userbuf);
1638 <      DupString(yy_aconf->host, hostbuf);
1639 <    }
1640 <    else
1641 <    {
1642 <      yy_tmp = MyMalloc(sizeof(struct CollectItem));
1643 <
1644 <      DupString(yy_tmp->user, userbuf);
1645 <      DupString(yy_tmp->host, hostbuf);
1646 <
1647 <      dlinkAdd(yy_tmp, &yy_tmp->node, &col_conf_list);
1648 <    }
1649 <  }
1481 >    dlinkAdd(xstrdup(yylval.string), make_dlink_node(), &block_state.mask.list);
1482   };
1483  
1484   auth_passwd: PASSWORD '=' QSTRING ';'
1485   {
1486    if (conf_parser_ctx.pass == 2)
1487 <  {
1656 <    /* be paranoid */
1657 <    if (yy_aconf->passwd != NULL)
1658 <      memset(yy_aconf->passwd, 0, strlen(yy_aconf->passwd));
1659 <
1660 <    MyFree(yy_aconf->passwd);
1661 <    DupString(yy_aconf->passwd, yylval.string);
1662 <  }
1487 >    strlcpy(block_state.rpass.buf, yylval.string, sizeof(block_state.rpass.buf));
1488   };
1489  
1490   auth_class: CLASS '=' QSTRING ';'
1491   {
1492    if (conf_parser_ctx.pass == 2)
1493 <  {
1669 <    MyFree(class_name);
1670 <    DupString(class_name, yylval.string);
1671 <  }
1493 >    strlcpy(block_state.class.buf, yylval.string, sizeof(block_state.class.buf));
1494   };
1495  
1496   auth_encrypted: ENCRYPTED '=' TBOOL ';'
# Line 1676 | Line 1498 | auth_encrypted: ENCRYPTED '=' TBOOL ';'
1498    if (conf_parser_ctx.pass == 2)
1499    {
1500      if (yylval.number)
1501 <      SetConfEncrypted(yy_aconf);
1501 >      block_state.flags.value |= CONF_FLAGS_ENCRYPTED;
1502      else
1503 <      ClearConfEncrypted(yy_aconf);
1503 >      block_state.flags.value &= ~CONF_FLAGS_ENCRYPTED;
1504    }
1505   };
1506  
1507   auth_flags: IRCD_FLAGS
1508   {
1509 +  if (conf_parser_ctx.pass == 2)
1510 +    block_state.flags.value &= CONF_FLAGS_ENCRYPTED;
1511   } '='  auth_flags_items ';';
1512  
1513   auth_flags_items: auth_flags_items ',' auth_flags_item | auth_flags_item;
1514   auth_flags_item: SPOOF_NOTICE
1515   {
1516    if (conf_parser_ctx.pass == 2)
1517 <    yy_aconf->flags |= CONF_FLAGS_SPOOF_NOTICE;
1517 >    block_state.flags.value |= CONF_FLAGS_SPOOF_NOTICE;
1518   } | EXCEED_LIMIT
1519   {
1520    if (conf_parser_ctx.pass == 2)
1521 <    yy_aconf->flags |= CONF_FLAGS_NOLIMIT;
1521 >    block_state.flags.value |= CONF_FLAGS_NOLIMIT;
1522   } | KLINE_EXEMPT
1523   {
1524    if (conf_parser_ctx.pass == 2)
1525 <    yy_aconf->flags |= CONF_FLAGS_EXEMPTKLINE;
1525 >    block_state.flags.value |= CONF_FLAGS_EXEMPTKLINE;
1526   } | NEED_IDENT
1527   {
1528    if (conf_parser_ctx.pass == 2)
1529 <    yy_aconf->flags |= CONF_FLAGS_NEED_IDENTD;
1529 >    block_state.flags.value |= CONF_FLAGS_NEED_IDENTD;
1530   } | CAN_FLOOD
1531   {
1532    if (conf_parser_ctx.pass == 2)
1533 <    yy_aconf->flags |= CONF_FLAGS_CAN_FLOOD;
1533 >    block_state.flags.value |= CONF_FLAGS_CAN_FLOOD;
1534   } | NO_TILDE
1535   {
1536    if (conf_parser_ctx.pass == 2)
1537 <    yy_aconf->flags |= CONF_FLAGS_NO_TILDE;
1537 >    block_state.flags.value |= CONF_FLAGS_NO_TILDE;
1538   } | GLINE_EXEMPT
1539   {
1540    if (conf_parser_ctx.pass == 2)
1541 <    yy_aconf->flags |= CONF_FLAGS_EXEMPTGLINE;
1541 >    block_state.flags.value |= CONF_FLAGS_EXEMPTGLINE;
1542   } | RESV_EXEMPT
1543   {
1544    if (conf_parser_ctx.pass == 2)
1545 <    yy_aconf->flags |= CONF_FLAGS_EXEMPTRESV;
1545 >    block_state.flags.value |= CONF_FLAGS_EXEMPTRESV;
1546 > } | T_WEBIRC
1547 > {
1548 >  if (conf_parser_ctx.pass == 2)
1549 >    block_state.flags.value |= CONF_FLAGS_WEBIRC;
1550   } | NEED_PASSWORD
1551   {
1552    if (conf_parser_ctx.pass == 2)
1553 <    yy_aconf->flags |= CONF_FLAGS_NEED_PASSWORD;
1553 >    block_state.flags.value |= CONF_FLAGS_NEED_PASSWORD;
1554   };
1555  
1728 /* XXX - need check for illegal hostnames here */
1556   auth_spoof: SPOOF '=' QSTRING ';'
1557   {
1558 <  if (conf_parser_ctx.pass == 2)
1559 <  {
1733 <    MyFree(yy_conf->name);
1558 >  if (conf_parser_ctx.pass != 2)
1559 >    break;
1560  
1561 <    if (strlen(yylval.string) < HOSTLEN)
1562 <    {    
1563 <      DupString(yy_conf->name, yylval.string);
1564 <      yy_aconf->flags |= CONF_FLAGS_SPOOF_IP;
1739 <    }
1740 <    else
1741 <    {
1742 <      ilog(LOG_TYPE_IRCD, "Spoofs must be less than %d..ignoring it", HOSTLEN);
1743 <      yy_conf->name = NULL;
1744 <    }
1561 >  if (strlen(yylval.string) <= HOSTLEN && valid_hostname(yylval.string))
1562 >  {
1563 >    strlcpy(block_state.name.buf, yylval.string, sizeof(block_state.name.buf));
1564 >    block_state.flags.value |= CONF_FLAGS_SPOOF_IP;
1565    }
1566 +  else
1567 +    ilog(LOG_TYPE_IRCD, "Spoof either is too long or contains invalid characters. Ignoring it.");
1568   };
1569  
1570   auth_redir_serv: REDIRSERV '=' QSTRING ';'
1571   {
1572 <  if (conf_parser_ctx.pass == 2)
1573 <  {
1574 <    yy_aconf->flags |= CONF_FLAGS_REDIR;
1575 <    MyFree(yy_conf->name);
1576 <    DupString(yy_conf->name, yylval.string);
1755 <  }
1572 >  if (conf_parser_ctx.pass != 2)
1573 >    break;
1574 >
1575 >  strlcpy(block_state.name.buf, yylval.string, sizeof(block_state.name.buf));
1576 >  block_state.flags.value |= CONF_FLAGS_REDIR;
1577   };
1578  
1579   auth_redir_port: REDIRPORT '=' NUMBER ';'
1580   {
1581 <  if (conf_parser_ctx.pass == 2)
1582 <  {
1583 <    yy_aconf->flags |= CONF_FLAGS_REDIR;
1584 <    yy_aconf->port = $3;
1585 <  }
1581 >  if (conf_parser_ctx.pass != 2)
1582 >    break;
1583 >
1584 >  block_state.flags.value |= CONF_FLAGS_REDIR;
1585 >  block_state.port.value = $3;
1586   };
1587  
1588  
# Line 1770 | Line 1591 | auth_redir_port: REDIRPORT '=' NUMBER ';
1591   ***************************************************************************/
1592   resv_entry: RESV
1593   {
1594 <  if (conf_parser_ctx.pass == 2)
1595 <  {
1596 <    MyFree(resv_reason);
1597 <    resv_reason = NULL;
1598 <  }
1599 < } '{' resv_items '}' ';'
1779 < {
1780 <  if (conf_parser_ctx.pass == 2)
1781 <  {
1782 <    MyFree(resv_reason);
1783 <    resv_reason = NULL;
1784 <  }
1785 < };
1594 >  if (conf_parser_ctx.pass != 2)
1595 >    break;
1596 >
1597 >  reset_block_state();
1598 >  strlcpy(block_state.rpass.buf, CONF_NOREASON, sizeof(block_state.rpass.buf));
1599 > } '{' resv_items '}' ';';
1600  
1601   resv_items:     resv_items resv_item | resv_item;
1602   resv_item:      resv_creason | resv_channel | resv_nick | error ';' ;
# Line 1790 | Line 1604 | resv_item:     resv_creason | resv_channel |
1604   resv_creason: REASON '=' QSTRING ';'
1605   {
1606    if (conf_parser_ctx.pass == 2)
1607 <  {
1794 <    MyFree(resv_reason);
1795 <    DupString(resv_reason, yylval.string);
1796 <  }
1607 >    strlcpy(block_state.rpass.buf, yylval.string, sizeof(block_state.rpass.buf));
1608   };
1609  
1610   resv_channel: CHANNEL '=' QSTRING ';'
1611   {
1612 <  if (conf_parser_ctx.pass == 2)
1613 <  {
1803 <    if (IsChanPrefix(*yylval.string))
1804 <    {
1805 <      char def_reason[] = "No reason";
1612 >  if (conf_parser_ctx.pass != 2)
1613 >    break;
1614  
1615 <      create_channel_resv(yylval.string, resv_reason != NULL ? resv_reason : def_reason, 1);
1616 <    }
1809 <  }
1810 <  /* ignore it for now.. but we really should make a warning if
1811 <   * its an erroneous name --fl_ */
1615 >  if (IsChanPrefix(*yylval.string))
1616 >    create_channel_resv(yylval.string, block_state.rpass.buf, 1);
1617   };
1618  
1619   resv_nick: NICK '=' QSTRING ';'
1620   {
1621    if (conf_parser_ctx.pass == 2)
1622 <  {
1818 <    char def_reason[] = "No reason";
1819 <
1820 <    create_nick_resv(yylval.string, resv_reason != NULL ? resv_reason : def_reason, 1);
1821 <  }
1622 >    create_nick_resv(yylval.string, block_state.rpass.buf, 1);
1623   };
1624  
1625   /***************************************************************************
# Line 1835 | Line 1636 | service_name: NAME '=' QSTRING ';'
1636    {
1637      if (valid_servname(yylval.string))
1638      {
1639 <      yy_conf = make_conf_item(SERVICE_TYPE);
1640 <      DupString(yy_conf->name, yylval.string);
1639 >      struct MaskItem *conf = conf_make(CONF_SERVICE);
1640 >      conf->name = xstrdup(yylval.string);
1641      }
1642    }
1643   };
# Line 1846 | Line 1647 | service_name: NAME '=' QSTRING ';'
1647   ***************************************************************************/
1648   shared_entry: T_SHARED
1649   {
1650 <  if (conf_parser_ctx.pass == 2)
1651 <  {
1652 <    yy_conf = make_conf_item(ULINE_TYPE);
1653 <    yy_match_item = map_to_conf(yy_conf);
1654 <    yy_match_item->action = SHARED_ALL;
1655 <  }
1650 >  if (conf_parser_ctx.pass != 2)
1651 >    break;
1652 >
1653 >  reset_block_state();
1654 >
1655 >  strlcpy(block_state.name.buf, "*", sizeof(block_state.name.buf));
1656 >  strlcpy(block_state.user.buf, "*", sizeof(block_state.user.buf));
1657 >  strlcpy(block_state.host.buf, "*", sizeof(block_state.host.buf));
1658 >  block_state.flags.value = SHARED_ALL;
1659   } '{' shared_items '}' ';'
1660   {
1661 <  if (conf_parser_ctx.pass == 2)
1662 <  {
1663 <    yy_conf = NULL;
1664 <  }
1661 >  struct MaskItem *conf = NULL;
1662 >
1663 >  if (conf_parser_ctx.pass != 2)
1664 >    break;
1665 >
1666 >  conf = conf_make(CONF_ULINE);
1667 >  conf->flags = block_state.flags.value;
1668 >  conf->name = xstrdup(block_state.name.buf);
1669 >  conf->user = xstrdup(block_state.user.buf);
1670 >  conf->user = xstrdup(block_state.host.buf);
1671   };
1672  
1673   shared_items: shared_items shared_item | shared_item;
# Line 1866 | Line 1676 | shared_item:  shared_name | shared_user
1676   shared_name: NAME '=' QSTRING ';'
1677   {
1678    if (conf_parser_ctx.pass == 2)
1679 <  {
1870 <    MyFree(yy_conf->name);
1871 <    DupString(yy_conf->name, yylval.string);
1872 <  }
1679 >    strlcpy(block_state.name.buf, yylval.string, sizeof(block_state.name.buf));
1680   };
1681  
1682   shared_user: USER '=' QSTRING ';'
# Line 1880 | Line 1687 | shared_user: USER '=' QSTRING ';'
1687  
1688      nuh.nuhmask  = yylval.string;
1689      nuh.nickptr  = NULL;
1690 <    nuh.userptr  = userbuf;
1691 <    nuh.hostptr  = hostbuf;
1690 >    nuh.userptr  = block_state.user.buf;
1691 >    nuh.hostptr  = block_state.host.buf;
1692  
1693      nuh.nicksize = 0;
1694 <    nuh.usersize = sizeof(userbuf);
1695 <    nuh.hostsize = sizeof(hostbuf);
1694 >    nuh.usersize = sizeof(block_state.user.buf);
1695 >    nuh.hostsize = sizeof(block_state.host.buf);
1696  
1697      split_nuh(&nuh);
1891
1892    DupString(yy_match_item->user, userbuf);
1893    DupString(yy_match_item->host, hostbuf);
1698    }
1699   };
1700  
1701   shared_type: TYPE
1702   {
1703    if (conf_parser_ctx.pass == 2)
1704 <    yy_match_item->action = 0;
1704 >    block_state.flags.value = 0;
1705   } '=' shared_types ';' ;
1706  
1707   shared_types: shared_types ',' shared_type_item | shared_type_item;
1708   shared_type_item: KLINE
1709   {
1710    if (conf_parser_ctx.pass == 2)
1711 <    yy_match_item->action |= SHARED_KLINE;
1711 >    block_state.flags.value |= SHARED_KLINE;
1712   } | UNKLINE
1713   {
1714    if (conf_parser_ctx.pass == 2)
1715 <    yy_match_item->action |= SHARED_UNKLINE;
1715 >    block_state.flags.value |= SHARED_UNKLINE;
1716   } | T_DLINE
1717   {
1718    if (conf_parser_ctx.pass == 2)
1719 <    yy_match_item->action |= SHARED_DLINE;
1719 >    block_state.flags.value |= SHARED_DLINE;
1720   } | T_UNDLINE
1721   {
1722    if (conf_parser_ctx.pass == 2)
1723 <    yy_match_item->action |= SHARED_UNDLINE;
1723 >    block_state.flags.value |= SHARED_UNDLINE;
1724   } | XLINE
1725   {
1726    if (conf_parser_ctx.pass == 2)
1727 <    yy_match_item->action |= SHARED_XLINE;
1727 >    block_state.flags.value |= SHARED_XLINE;
1728   } | T_UNXLINE
1729   {
1730    if (conf_parser_ctx.pass == 2)
1731 <    yy_match_item->action |= SHARED_UNXLINE;
1731 >    block_state.flags.value |= SHARED_UNXLINE;
1732   } | RESV
1733   {
1734    if (conf_parser_ctx.pass == 2)
1735 <    yy_match_item->action |= SHARED_RESV;
1735 >    block_state.flags.value |= SHARED_RESV;
1736   } | T_UNRESV
1737   {
1738    if (conf_parser_ctx.pass == 2)
1739 <    yy_match_item->action |= SHARED_UNRESV;
1739 >    block_state.flags.value |= SHARED_UNRESV;
1740   } | T_LOCOPS
1741   {
1742    if (conf_parser_ctx.pass == 2)
1743 <    yy_match_item->action |= SHARED_LOCOPS;
1743 >    block_state.flags.value |= SHARED_LOCOPS;
1744   } | T_ALL
1745   {
1746    if (conf_parser_ctx.pass == 2)
1747 <    yy_match_item->action = SHARED_ALL;
1747 >    block_state.flags.value = SHARED_ALL;
1748   };
1749  
1750   /***************************************************************************
# Line 1948 | Line 1752 | shared_type_item: KLINE
1752   ***************************************************************************/
1753   cluster_entry: T_CLUSTER
1754   {
1755 <  if (conf_parser_ctx.pass == 2)
1756 <  {
1757 <    yy_conf = make_conf_item(CLUSTER_TYPE);
1758 <    yy_conf->flags = SHARED_ALL;
1759 <  }
1755 >  if (conf_parser_ctx.pass != 2)
1756 >    break;
1757 >
1758 >  reset_block_state();
1759 >
1760 >  strlcpy(block_state.name.buf, "*", sizeof(block_state.name.buf));
1761 >  block_state.flags.value = SHARED_ALL;
1762   } '{' cluster_items '}' ';'
1763   {
1764 <  if (conf_parser_ctx.pass == 2)
1765 <  {
1766 <    if (yy_conf->name == NULL)
1767 <      DupString(yy_conf->name, "*");
1768 <    yy_conf = NULL;
1769 <  }
1764 >  struct MaskItem *conf = NULL;
1765 >
1766 >  if (conf_parser_ctx.pass != 2)
1767 >    break;
1768 >
1769 >  conf = conf_make(CONF_CLUSTER);
1770 >  conf->flags = block_state.flags.value;
1771 >  conf->name = xstrdup(block_state.name.buf);
1772   };
1773  
1774   cluster_items:  cluster_items cluster_item | cluster_item;
# Line 1969 | Line 1777 | cluster_item:  cluster_name | cluster_typ
1777   cluster_name: NAME '=' QSTRING ';'
1778   {
1779    if (conf_parser_ctx.pass == 2)
1780 <    DupString(yy_conf->name, yylval.string);
1780 >    strlcpy(block_state.name.buf, yylval.string, sizeof(block_state.name.buf));
1781   };
1782  
1783   cluster_type: TYPE
1784   {
1785    if (conf_parser_ctx.pass == 2)
1786 <    yy_conf->flags = 0;
1786 >    block_state.flags.value = 0;
1787   } '=' cluster_types ';' ;
1788  
1789   cluster_types:  cluster_types ',' cluster_type_item | cluster_type_item;
1790   cluster_type_item: KLINE
1791   {
1792    if (conf_parser_ctx.pass == 2)
1793 <    yy_conf->flags |= SHARED_KLINE;
1793 >    block_state.flags.value |= SHARED_KLINE;
1794   } | UNKLINE
1795   {
1796    if (conf_parser_ctx.pass == 2)
1797 <    yy_conf->flags |= SHARED_UNKLINE;
1797 >    block_state.flags.value |= SHARED_UNKLINE;
1798   } | T_DLINE
1799   {
1800    if (conf_parser_ctx.pass == 2)
1801 <    yy_conf->flags |= SHARED_DLINE;
1801 >    block_state.flags.value |= SHARED_DLINE;
1802   } | T_UNDLINE
1803   {
1804    if (conf_parser_ctx.pass == 2)
1805 <    yy_conf->flags |= SHARED_UNDLINE;
1805 >    block_state.flags.value |= SHARED_UNDLINE;
1806   } | XLINE
1807   {
1808    if (conf_parser_ctx.pass == 2)
1809 <    yy_conf->flags |= SHARED_XLINE;
1809 >    block_state.flags.value |= SHARED_XLINE;
1810   } | T_UNXLINE
1811   {
1812    if (conf_parser_ctx.pass == 2)
1813 <    yy_conf->flags |= SHARED_UNXLINE;
1813 >    block_state.flags.value |= SHARED_UNXLINE;
1814   } | RESV
1815   {
1816    if (conf_parser_ctx.pass == 2)
1817 <    yy_conf->flags |= SHARED_RESV;
1817 >    block_state.flags.value |= SHARED_RESV;
1818   } | T_UNRESV
1819   {
1820    if (conf_parser_ctx.pass == 2)
1821 <    yy_conf->flags |= SHARED_UNRESV;
1821 >    block_state.flags.value |= SHARED_UNRESV;
1822   } | T_LOCOPS
1823   {
1824    if (conf_parser_ctx.pass == 2)
1825 <    yy_conf->flags |= SHARED_LOCOPS;
1825 >    block_state.flags.value |= SHARED_LOCOPS;
1826   } | T_ALL
1827   {
1828    if (conf_parser_ctx.pass == 2)
1829 <    yy_conf->flags = SHARED_ALL;
1829 >    block_state.flags.value = SHARED_ALL;
1830   };
1831  
1832   /***************************************************************************
# Line 2026 | Line 1834 | cluster_type_item: KLINE
1834   ***************************************************************************/
1835   connect_entry: CONNECT  
1836   {
2029  if (conf_parser_ctx.pass == 2)
2030  {
2031    yy_conf = make_conf_item(SERVER_TYPE);
2032    yy_aconf = map_to_conf(yy_conf);
1837  
1838 <    /* defaults */
1839 <    yy_aconf->port = PORTNUM;
1840 <  }
1841 <  else
1842 <  {
2039 <    MyFree(class_name);
2040 <    class_name = NULL;
2041 <  }
1838 >  if (conf_parser_ctx.pass != 2)
1839 >    break;
1840 >
1841 >  reset_block_state();
1842 >  block_state.port.value = PORTNUM;
1843   } '{' connect_items '}' ';'
1844   {
1845 <  if (conf_parser_ctx.pass == 2)
1845 >  struct MaskItem *conf = NULL;
1846 >  struct addrinfo hints, *res;
1847 >
1848 >  if (conf_parser_ctx.pass != 2)
1849 >    break;
1850 >
1851 >  if (!block_state.name.buf[0] ||
1852 >      !block_state.host.buf[0])
1853 >    break;
1854 >
1855 >  if (!(block_state.rpass.buf[0] ||
1856 >        block_state.spass.buf[0]))
1857 >    break;
1858 >
1859 >  if (has_wildcards(block_state.name.buf) ||
1860 >      has_wildcards(block_state.host.buf))
1861 >    break;
1862 >
1863 >  conf = conf_make(CONF_SERVER);
1864 >  conf->port = block_state.port.value;
1865 >  conf->flags = block_state.flags.value;
1866 >  conf->aftype = block_state.aftype.value;
1867 >  conf->host = xstrdup(block_state.host.buf);
1868 >  conf->name = xstrdup(block_state.name.buf);
1869 >  conf->passwd = xstrdup(block_state.rpass.buf);
1870 >  conf->spasswd = xstrdup(block_state.spass.buf);
1871 >  conf->cipher_list = xstrdup(block_state.ciph.buf);
1872 >
1873 >  dlinkMoveList(&block_state.leaf.list, &conf->leaf_list);
1874 >  dlinkMoveList(&block_state.hub.list, &conf->hub_list);
1875 >
1876 >  if (block_state.bind.buf[0])
1877    {
1878 <    if (yy_aconf->host && yy_aconf->passwd && yy_aconf->spasswd)
1879 <    {
1880 <      if (conf_add_server(yy_conf, class_name) == -1)
1881 <        delete_conf_item(yy_conf);
1882 <    }
1878 >    memset(&hints, 0, sizeof(hints));
1879 >
1880 >    hints.ai_family   = AF_UNSPEC;
1881 >    hints.ai_socktype = SOCK_STREAM;
1882 >    hints.ai_flags    = AI_PASSIVE | AI_NUMERICHOST;
1883 >
1884 >    if (getaddrinfo(block_state.bind.buf, NULL, &hints, &res))
1885 >      ilog(LOG_TYPE_IRCD, "Invalid netmask for server vhost(%s)", block_state.bind.buf);
1886      else
1887      {
1888 <      if (yy_conf->name != NULL)
2054 <      {
2055 <        if (yy_aconf->host == NULL)
2056 <          yyerror("Ignoring connect block -- missing host");
2057 <        else if (!yy_aconf->passwd || !yy_aconf->spasswd)
2058 <          yyerror("Ignoring connect block -- missing password");
2059 <      }
1888 >      assert(res != NULL);
1889  
1890 <      /* XXX
1891 <       * This fixes a try_connections() core (caused by invalid class_ptr
1892 <       * pointers) reported by metalrock. That's an ugly fix, but there
1893 <       * is currently no better way. The entire config subsystem needs an
2065 <       * rewrite ASAP. make_conf_item() shouldn't really add things onto
2066 <       * a doubly linked list immediately without any sanity checks!  -Michael
2067 <       */
2068 <      delete_conf_item(yy_conf);
1890 >      memcpy(&conf->bind, res->ai_addr, res->ai_addrlen);
1891 >      conf->bind.ss.ss_family = res->ai_family;
1892 >      conf->bind.ss_len = res->ai_addrlen;
1893 >      freeaddrinfo(res);
1894      }
2070
2071    MyFree(class_name);
2072    class_name = NULL;
2073    yy_conf = NULL;
2074    yy_aconf = NULL;
1895    }
1896 +
1897 +  conf_add_class_to_conf(conf, block_state.class.buf);
1898 +  lookup_confhost(conf);
1899   };
1900  
1901   connect_items:  connect_items connect_item | connect_item;
# Line 2086 | Line 1909 | connect_item:   connect_name | connect_h
1909   connect_name: NAME '=' QSTRING ';'
1910   {
1911    if (conf_parser_ctx.pass == 2)
1912 <  {
2090 <    MyFree(yy_conf->name);
2091 <    DupString(yy_conf->name, yylval.string);
2092 <  }
1912 >    strlcpy(block_state.name.buf, yylval.string, sizeof(block_state.name.buf));
1913   };
1914  
1915   connect_host: HOST '=' QSTRING ';'
1916   {
1917    if (conf_parser_ctx.pass == 2)
1918 <  {
2099 <    MyFree(yy_aconf->host);
2100 <    DupString(yy_aconf->host, yylval.string);
2101 <  }
1918 >    strlcpy(block_state.host.buf, yylval.string, sizeof(block_state.host.buf));
1919   };
1920  
1921   connect_vhost: VHOST '=' QSTRING ';'
1922   {
1923    if (conf_parser_ctx.pass == 2)
1924 <  {
2108 <    struct addrinfo hints, *res;
2109 <
2110 <    memset(&hints, 0, sizeof(hints));
2111 <
2112 <    hints.ai_family   = AF_UNSPEC;
2113 <    hints.ai_socktype = SOCK_STREAM;
2114 <    hints.ai_flags    = AI_PASSIVE | AI_NUMERICHOST;
2115 <
2116 <    if (getaddrinfo(yylval.string, NULL, &hints, &res))
2117 <      ilog(LOG_TYPE_IRCD, "Invalid netmask for server vhost(%s)", yylval.string);
2118 <    else
2119 <    {
2120 <      assert(res != NULL);
2121 <
2122 <      memcpy(&yy_aconf->bind, res->ai_addr, res->ai_addrlen);
2123 <      yy_aconf->bind.ss.ss_family = res->ai_family;
2124 <      yy_aconf->bind.ss_len = res->ai_addrlen;
2125 <      freeaddrinfo(res);
2126 <    }
2127 <  }
1924 >    strlcpy(block_state.bind.buf, yylval.string, sizeof(block_state.bind.buf));
1925   };
1926  
1927   connect_send_password: SEND_PASSWORD '=' QSTRING ';'
1928   {
1929 <  if (conf_parser_ctx.pass == 2)
1930 <  {
2134 <    if ($3[0] == ':')
2135 <      yyerror("Server passwords cannot begin with a colon");
2136 <    else if (strchr($3, ' ') != NULL)
2137 <      yyerror("Server passwords cannot contain spaces");
2138 <    else {
2139 <      if (yy_aconf->spasswd != NULL)
2140 <        memset(yy_aconf->spasswd, 0, strlen(yy_aconf->spasswd));
1929 >  if (conf_parser_ctx.pass != 2)
1930 >    break;
1931  
1932 <      MyFree(yy_aconf->spasswd);
1933 <      DupString(yy_aconf->spasswd, yylval.string);
1934 <    }
1935 <  }
1932 >  if ($3[0] == ':')
1933 >    yyerror("Server passwords cannot begin with a colon");
1934 >  else if (strchr($3, ' ') != NULL)
1935 >    yyerror("Server passwords cannot contain spaces");
1936 >  else
1937 >    strlcpy(block_state.spass.buf, yylval.string, sizeof(block_state.spass.buf));
1938   };
1939  
1940   connect_accept_password: ACCEPT_PASSWORD '=' QSTRING ';'
1941   {
1942 <  if (conf_parser_ctx.pass == 2)
1943 <  {
2152 <    if ($3[0] == ':')
2153 <      yyerror("Server passwords cannot begin with a colon");
2154 <    else if (strchr($3, ' ') != NULL)
2155 <      yyerror("Server passwords cannot contain spaces");
2156 <    else {
2157 <      if (yy_aconf->passwd != NULL)
2158 <        memset(yy_aconf->passwd, 0, strlen(yy_aconf->passwd));
1942 >  if (conf_parser_ctx.pass != 2)
1943 >    break;
1944  
1945 <      MyFree(yy_aconf->passwd);
1946 <      DupString(yy_aconf->passwd, yylval.string);
1947 <    }
1948 <  }
1945 >  if ($3[0] == ':')
1946 >    yyerror("Server passwords cannot begin with a colon");
1947 >  else if (strchr($3, ' ') != NULL)
1948 >    yyerror("Server passwords cannot contain spaces");
1949 >  else
1950 >    strlcpy(block_state.rpass.buf, yylval.string, sizeof(block_state.rpass.buf));
1951   };
1952  
1953   connect_port: PORT '=' NUMBER ';'
1954   {
1955    if (conf_parser_ctx.pass == 2)
1956 <    yy_aconf->port = $3;
1956 >    block_state.port.value = $3;
1957   };
1958  
1959   connect_aftype: AFTYPE '=' T_IPV4 ';'
1960   {
1961    if (conf_parser_ctx.pass == 2)
1962 <    yy_aconf->aftype = AF_INET;
1962 >    block_state.aftype.value = AF_INET;
1963   } | AFTYPE '=' T_IPV6 ';'
1964   {
1965   #ifdef IPV6
1966    if (conf_parser_ctx.pass == 2)
1967 <    yy_aconf->aftype = AF_INET6;
1967 >    block_state.aftype.value = AF_INET6;
1968   #endif
1969   };
1970  
1971   connect_flags: IRCD_FLAGS
1972   {
1973 +  block_state.flags.value &= CONF_FLAGS_ENCRYPTED;
1974   } '='  connect_flags_items ';';
1975  
1976   connect_flags_items: connect_flags_items ',' connect_flags_item | connect_flags_item;
1977   connect_flags_item: AUTOCONN
1978   {
1979    if (conf_parser_ctx.pass == 2)
1980 <    SetConfAllowAutoConn(yy_aconf);
2193 < } | BURST_AWAY
2194 < {
2195 <  if (conf_parser_ctx.pass == 2)
2196 <    SetConfAwayBurst(yy_aconf);
2197 < } | TOPICBURST
2198 < {
2199 <  if (conf_parser_ctx.pass == 2)
2200 <    SetConfTopicBurst(yy_aconf);
1980 >    block_state.flags.value |= CONF_FLAGS_ALLOW_AUTO_CONN;
1981   } | T_SSL
1982   {
1983    if (conf_parser_ctx.pass == 2)
1984 <    SetConfSSL(yy_aconf);
1984 >    block_state.flags.value |= CONF_FLAGS_SSL;
1985   };
1986  
1987   connect_encrypted: ENCRYPTED '=' TBOOL ';'
# Line 2209 | Line 1989 | connect_encrypted: ENCRYPTED '=' TBOOL '
1989    if (conf_parser_ctx.pass == 2)
1990    {
1991      if (yylval.number)
1992 <      yy_aconf->flags |= CONF_FLAGS_ENCRYPTED;
1992 >      block_state.flags.value |= CONF_FLAGS_ENCRYPTED;
1993      else
1994 <      yy_aconf->flags &= ~CONF_FLAGS_ENCRYPTED;
1994 >      block_state.flags.value &= ~CONF_FLAGS_ENCRYPTED;
1995    }
1996   };
1997  
1998   connect_hub_mask: HUB_MASK '=' QSTRING ';'
1999   {
2000    if (conf_parser_ctx.pass == 2)
2001 <  {
2222 <    char *mask;
2223 <
2224 <    DupString(mask, yylval.string);
2225 <    dlinkAdd(mask, make_dlink_node(), &yy_aconf->hub_list);
2226 <  }
2001 >    dlinkAdd(xstrdup(yylval.string), make_dlink_node(), &block_state.hub.list);
2002   };
2003  
2004   connect_leaf_mask: LEAF_MASK '=' QSTRING ';'
2005   {
2006    if (conf_parser_ctx.pass == 2)
2007 <  {
2233 <    char *mask;
2234 <
2235 <    DupString(mask, yylval.string);
2236 <    dlinkAdd(mask, make_dlink_node(), &yy_aconf->leaf_list);
2237 <  }
2007 >    dlinkAdd(xstrdup(yylval.string), make_dlink_node(), &block_state.leaf.list);
2008   };
2009  
2010   connect_class: CLASS '=' QSTRING ';'
2011   {
2012    if (conf_parser_ctx.pass == 2)
2013 <  {
2244 <    MyFree(class_name);
2245 <    DupString(class_name, yylval.string);
2246 <  }
2013 >    strlcpy(block_state.class.buf, yylval.string, sizeof(block_state.class.buf));
2014   };
2015  
2016   connect_ssl_cipher_list: T_SSL_CIPHER_LIST '=' QSTRING ';'
2017   {
2018   #ifdef HAVE_LIBCRYPTO
2019    if (conf_parser_ctx.pass == 2)
2020 <  {
2254 <    MyFree(yy_aconf->cipher_list);
2255 <    DupString(yy_aconf->cipher_list, yylval.string);
2256 <  }
2020 >    strlcpy(block_state.ciph.buf, yylval.string, sizeof(block_state.ciph.buf));
2021   #else
2022    if (conf_parser_ctx.pass == 2)
2023      yyerror("Ignoring connect::ciphers -- no OpenSSL support");
# Line 2267 | Line 2031 | connect_ssl_cipher_list: T_SSL_CIPHER_LI
2031   kill_entry: KILL
2032   {
2033    if (conf_parser_ctx.pass == 2)
2034 <  {
2271 <    userbuf[0] = hostbuf[0] = reasonbuf[0] = '\0';
2272 <    regex_ban = 0;
2273 <  }
2034 >    reset_block_state();
2035   } '{' kill_items '}' ';'
2036   {
2037 <  if (conf_parser_ctx.pass == 2)
2037 >  struct MaskItem *conf = NULL;
2038 >
2039 >  if (conf_parser_ctx.pass != 2)
2040 >    break;
2041 >
2042 >  if (!block_state.user.buf[0] ||
2043 >      !block_state.host.buf[0])
2044 >    break;
2045 >
2046 >
2047 >  if (block_state.port.value == 1)
2048    {
2278    if (userbuf[0] && hostbuf[0])
2279    {
2280      if (regex_ban)
2281      {
2049   #ifdef HAVE_LIBPCRE
2050 <        void *exp_user = NULL;
2051 <        void *exp_host = NULL;
2052 <        const char *errptr = NULL;
2053 <
2054 <        if (!(exp_user = ircd_pcre_compile(userbuf, &errptr)) ||
2055 <            !(exp_host = ircd_pcre_compile(hostbuf, &errptr)))
2056 <        {
2057 <          ilog(LOG_TYPE_IRCD, "Failed to add regular expression based K-Line: %s",
2058 <               errptr);
2059 <          break;
2060 <        }
2294 <
2295 <        yy_aconf = map_to_conf(make_conf_item(RKLINE_TYPE));
2296 <        yy_aconf->regexuser = exp_user;
2297 <        yy_aconf->regexhost = exp_host;
2050 >    void *exp_user = NULL;
2051 >    void *exp_host = NULL;
2052 >    const char *errptr = NULL;
2053 >
2054 >    if (!(exp_user = ircd_pcre_compile(block_state.user.buf, &errptr)) ||
2055 >        !(exp_host = ircd_pcre_compile(block_state.host.buf, &errptr)))
2056 >    {
2057 >      ilog(LOG_TYPE_IRCD, "Failed to add regular expression based K-Line: %s",
2058 >           errptr);
2059 >      break;
2060 >    }
2061  
2062 <        DupString(yy_aconf->user, userbuf);
2063 <        DupString(yy_aconf->host, hostbuf);
2062 >    conf = conf_make(CONF_RKLINE);
2063 >    conf->regexuser = exp_user;
2064 >    conf->regexhost = exp_host;
2065  
2066 <        if (reasonbuf[0])
2067 <          DupString(yy_aconf->reason, reasonbuf);
2068 <        else
2069 <          DupString(yy_aconf->reason, "No reason");
2066 >    conf->user = xstrdup(block_state.user.buf);
2067 >    conf->host = xstrdup(block_state.host.buf);
2068 >
2069 >    if (block_state.rpass.buf[0])
2070 >      conf->reason = xstrdup(block_state.rpass.buf);
2071 >    else
2072 >      conf->reason = xstrdup(CONF_NOREASON);
2073   #else
2074 <        ilog(LOG_TYPE_IRCD, "Failed to add regular expression based K-Line: no PCRE support");
2075 <        break;
2074 >    ilog(LOG_TYPE_IRCD, "Failed to add regular expression based K-Line: no PCRE support");
2075 >    break;
2076   #endif
2077 <      }
2078 <      else
2079 <      {
2080 <        find_and_delete_temporary(userbuf, hostbuf, CONF_KLINE);
2314 <
2315 <        yy_aconf = map_to_conf(make_conf_item(KLINE_TYPE));
2077 >  }
2078 >  else
2079 >  {
2080 >    conf = conf_make(CONF_KLINE);
2081  
2082 <        DupString(yy_aconf->user, userbuf);
2083 <        DupString(yy_aconf->host, hostbuf);
2082 >    conf->user = xstrdup(block_state.user.buf);
2083 >    conf->host = xstrdup(block_state.host.buf);
2084  
2085 <        if (reasonbuf[0])
2086 <          DupString(yy_aconf->reason, reasonbuf);
2087 <        else
2088 <          DupString(yy_aconf->reason, "No reason");
2089 <        add_conf_by_address(CONF_KLINE, yy_aconf);
2325 <      }
2326 <    }
2327 <
2328 <    yy_aconf = NULL;
2085 >    if (block_state.rpass.buf[0])
2086 >      conf->reason = xstrdup(block_state.rpass.buf);
2087 >    else
2088 >      conf->reason = xstrdup(CONF_NOREASON);
2089 >    add_conf_by_address(CONF_KLINE, conf);
2090    }
2091   };
2092  
2093   kill_type: TYPE
2094   {
2095 +  if (conf_parser_ctx.pass == 2)
2096 +    block_state.port.value = 0;
2097   } '='  kill_type_items ';';
2098  
2099   kill_type_items: kill_type_items ',' kill_type_item | kill_type_item;
2100   kill_type_item: REGEX_T
2101   {
2102    if (conf_parser_ctx.pass == 2)
2103 <    regex_ban = 1;
2103 >    block_state.port.value = 1;
2104   };
2105  
2106   kill_items:     kill_items kill_item | kill_item;
# Line 2345 | Line 2108 | kill_item:      kill_user | kill_reason
2108  
2109   kill_user: USER '=' QSTRING ';'
2110   {
2111 +
2112    if (conf_parser_ctx.pass == 2)
2113    {
2114      struct split_nuh_item nuh;
2115  
2116      nuh.nuhmask  = yylval.string;
2117      nuh.nickptr  = NULL;
2118 <    nuh.userptr  = userbuf;
2119 <    nuh.hostptr  = hostbuf;
2118 >    nuh.userptr  = block_state.user.buf;
2119 >    nuh.hostptr  = block_state.host.buf;
2120  
2121      nuh.nicksize = 0;
2122 <    nuh.usersize = sizeof(userbuf);
2123 <    nuh.hostsize = sizeof(hostbuf);
2122 >    nuh.usersize = sizeof(block_state.user.buf);
2123 >    nuh.hostsize = sizeof(block_state.host.buf);
2124  
2125      split_nuh(&nuh);
2126    }
# Line 2365 | Line 2129 | kill_user: USER '=' QSTRING ';'
2129   kill_reason: REASON '=' QSTRING ';'
2130   {
2131    if (conf_parser_ctx.pass == 2)
2132 <    strlcpy(reasonbuf, yylval.string, sizeof(reasonbuf));
2132 >    strlcpy(block_state.rpass.buf, yylval.string, sizeof(block_state.rpass.buf));
2133   };
2134  
2135   /***************************************************************************
# Line 2374 | Line 2138 | kill_reason: REASON '=' QSTRING ';'
2138   deny_entry: DENY
2139   {
2140    if (conf_parser_ctx.pass == 2)
2141 <    hostbuf[0] = reasonbuf[0] = '\0';
2141 >    reset_block_state();
2142   } '{' deny_items '}' ';'
2143   {
2144 <  if (conf_parser_ctx.pass == 2)
2381 <  {
2382 <    if (hostbuf[0] && parse_netmask(hostbuf, NULL, NULL) != HM_HOST)
2383 <    {
2384 <      find_and_delete_temporary(NULL, hostbuf, CONF_DLINE);
2144 >  struct MaskItem *conf = NULL;
2145  
2146 <      yy_aconf = map_to_conf(make_conf_item(DLINE_TYPE));
2147 <      DupString(yy_aconf->host, hostbuf);
2146 >  if (conf_parser_ctx.pass != 2)
2147 >    break;
2148  
2149 <      if (reasonbuf[0])
2150 <        DupString(yy_aconf->reason, reasonbuf);
2151 <      else
2152 <        DupString(yy_aconf->reason, "No reason");
2153 <      add_conf_by_address(CONF_DLINE, yy_aconf);
2154 <      yy_aconf = NULL;
2155 <    }
2149 >  if (!block_state.addr.buf[0])
2150 >    break;
2151 >
2152 >  if (parse_netmask(block_state.addr.buf, NULL, NULL) != HM_HOST)
2153 >  {
2154 >    conf = conf_make(CONF_DLINE);
2155 >    conf->host = xstrdup(block_state.addr.buf);
2156 >
2157 >    if (block_state.rpass.buf[0])
2158 >      conf->reason = xstrdup(block_state.rpass.buf);
2159 >    else
2160 >      conf->reason = xstrdup(CONF_NOREASON);
2161 >    add_conf_by_address(CONF_DLINE, conf);
2162    }
2163   };
2164  
# Line 2402 | Line 2168 | deny_item:      deny_ip | deny_reason |
2168   deny_ip: IP '=' QSTRING ';'
2169   {
2170    if (conf_parser_ctx.pass == 2)
2171 <    strlcpy(hostbuf, yylval.string, sizeof(hostbuf));
2171 >    strlcpy(block_state.addr.buf, yylval.string, sizeof(block_state.addr.buf));
2172   };
2173  
2174   deny_reason: REASON '=' QSTRING ';'
2175   {
2176    if (conf_parser_ctx.pass == 2)
2177 <    strlcpy(reasonbuf, yylval.string, sizeof(reasonbuf));
2177 >    strlcpy(block_state.rpass.buf, yylval.string, sizeof(block_state.rpass.buf));
2178   };
2179  
2180   /***************************************************************************
# Line 2425 | Line 2191 | exempt_ip: IP '=' QSTRING ';'
2191    {
2192      if (yylval.string[0] && parse_netmask(yylval.string, NULL, NULL) != HM_HOST)
2193      {
2194 <      yy_aconf = map_to_conf(make_conf_item(EXEMPTDLINE_TYPE));
2195 <      DupString(yy_aconf->host, yylval.string);
2194 >      struct MaskItem *conf = conf_make(CONF_EXEMPT);
2195 >      conf->host = xstrdup(yylval.string);
2196  
2197 <      add_conf_by_address(CONF_EXEMPTDLINE, yy_aconf);
2432 <      yy_aconf = NULL;
2197 >      add_conf_by_address(CONF_EXEMPT, conf);
2198      }
2199    }
2200   };
# Line 2440 | Line 2205 | exempt_ip: IP '=' QSTRING ';'
2205   gecos_entry: GECOS
2206   {
2207    if (conf_parser_ctx.pass == 2)
2208 <  {
2444 <    regex_ban = 0;
2445 <    reasonbuf[0] = gecos_name[0] = '\0';
2446 <  }
2208 >    reset_block_state();
2209   } '{' gecos_items '}' ';'
2210   {
2211 <  if (conf_parser_ctx.pass == 2)
2211 >  struct MaskItem *conf = NULL;
2212 >
2213 >  if (conf_parser_ctx.pass != 2)
2214 >    break;
2215 >
2216 >  if (!block_state.name.buf[0])
2217 >    break;
2218 >
2219 >  if (block_state.port.value == 1)
2220    {
2451    if (gecos_name[0])
2452    {
2453      if (regex_ban)
2454      {
2221   #ifdef HAVE_LIBPCRE
2222 <        void *exp_p = NULL;
2223 <        const char *errptr = NULL;
2222 >    void *exp_p = NULL;
2223 >    const char *errptr = NULL;
2224  
2225 <        if (!(exp_p = ircd_pcre_compile(gecos_name, &errptr)))
2226 <        {
2227 <          ilog(LOG_TYPE_IRCD, "Failed to add regular expression based X-Line: %s",
2228 <               errptr);
2229 <          break;
2230 <        }
2225 >    if (!(exp_p = ircd_pcre_compile(block_state.name.buf, &errptr)))
2226 >    {
2227 >      ilog(LOG_TYPE_IRCD, "Failed to add regular expression based X-Line: %s",
2228 >           errptr);
2229 >      break;
2230 >    }
2231  
2232 <        yy_conf = make_conf_item(RXLINE_TYPE);
2233 <        yy_conf->regexpname = exp_p;
2232 >    conf = conf_make(CONF_RXLINE);
2233 >    conf->regexuser = exp_p;
2234   #else
2235 <        ilog(LOG_TYPE_IRCD, "Failed to add regular expression based X-Line: no PCRE support");
2236 <        break;
2235 >    ilog(LOG_TYPE_IRCD, "Failed to add regular expression based X-Line: no PCRE support");
2236 >    break;
2237   #endif
2238 <      }
2239 <      else
2240 <        yy_conf = make_conf_item(XLINE_TYPE);
2238 >  }
2239 >  else
2240 >    conf = conf_make(CONF_XLINE);
2241  
2242 <      yy_match_item = map_to_conf(yy_conf);
2477 <      DupString(yy_conf->name, gecos_name);
2242 >  conf->name = xstrdup(block_state.name.buf);
2243  
2244 <      if (reasonbuf[0])
2245 <        DupString(yy_match_item->reason, reasonbuf);
2246 <      else
2247 <        DupString(yy_match_item->reason, "No reason");
2483 <    }
2484 <  }
2244 >  if (block_state.rpass.buf[0])
2245 >    conf->reason = xstrdup(block_state.rpass.buf);
2246 >  else
2247 >    conf->reason = xstrdup(CONF_NOREASON);
2248   };
2249  
2250   gecos_flags: TYPE
2251   {
2252 +  if (conf_parser_ctx.pass == 2)
2253 +    block_state.port.value = 0;
2254   } '='  gecos_flags_items ';';
2255  
2256   gecos_flags_items: gecos_flags_items ',' gecos_flags_item | gecos_flags_item;
2257   gecos_flags_item: REGEX_T
2258   {
2259    if (conf_parser_ctx.pass == 2)
2260 <    regex_ban = 1;
2260 >    block_state.port.value = 1;
2261   };
2262  
2263   gecos_items: gecos_items gecos_item | gecos_item;
# Line 2501 | Line 2266 | gecos_item:  gecos_name | gecos_reason |
2266   gecos_name: NAME '=' QSTRING ';'
2267   {
2268    if (conf_parser_ctx.pass == 2)
2269 <    strlcpy(gecos_name, yylval.string, sizeof(gecos_name));
2269 >    strlcpy(block_state.name.buf, yylval.string, sizeof(block_state.name.buf));
2270   };
2271  
2272   gecos_reason: REASON '=' QSTRING ';'
2273   {
2274    if (conf_parser_ctx.pass == 2)
2275 <    strlcpy(reasonbuf, yylval.string, sizeof(reasonbuf));
2275 >    strlcpy(block_state.rpass.buf, yylval.string, sizeof(block_state.rpass.buf));
2276   };
2277  
2278   /***************************************************************************
# Line 2522 | Line 2287 | general_item:       general_hide_spoof_i
2287                      general_max_nick_time | general_max_nick_changes |
2288                      general_max_accept | general_anti_spam_exit_message_time |
2289                      general_ts_warn_delta | general_ts_max_delta |
2290 <                    general_kill_chase_time_limit | general_kline_with_reason |
2291 <                    general_kline_reason | general_invisible_on_connect |
2290 >                    general_kill_chase_time_limit |
2291 >                    general_invisible_on_connect |
2292                      general_warn_no_nline | general_dots_in_ident |
2293                      general_stats_o_oper_only | general_stats_k_oper_only |
2294                      general_pace_wait | general_stats_i_oper_only |
# Line 2537 | Line 2302 | general_item:       general_hide_spoof_i
2302                      general_opers_bypass_callerid | general_default_floodcount |
2303                      general_min_nonwildcard | general_min_nonwildcard_simple |
2304                      general_disable_remote_commands |
2540                    general_client_flood |
2305                      general_throttle_time | general_havent_read_conf |
2306                      general_ping_cookie |
2307                      general_disable_auth |
2308                      general_tkline_expire_notices | general_gline_enable |
2309                      general_gline_duration | general_gline_request_duration |
2310                      general_gline_min_cidr |
2311 <                    general_gline_min_cidr6 | general_use_whois_actually |
2312 <                    general_reject_hold_time | general_stats_e_disabled |
2311 >                    general_gline_min_cidr6 |
2312 >                    general_stats_e_disabled |
2313                      general_max_watch | general_services_name |
2314                      error;
2315  
# Line 2583 | Line 2347 | general_gline_min_cidr6: GLINE_MIN_CIDR6
2347    ConfigFileEntry.gline_min_cidr6 = $3;
2348   };
2349  
2586 general_use_whois_actually: USE_WHOIS_ACTUALLY '=' TBOOL ';'
2587 {
2588  ConfigFileEntry.use_whois_actually = yylval.number;
2589 };
2590
2591 general_reject_hold_time: TREJECT_HOLD_TIME '=' timespec ';'
2592 {
2593  GlobalSetOptions.rejecttime = yylval.number;
2594 };
2595
2350   general_tkline_expire_notices: TKLINE_EXPIRE_NOTICES '=' TBOOL ';'
2351   {
2352    ConfigFileEntry.tkline_expire_notices = yylval.number;
# Line 2670 | Line 2424 | general_havent_read_conf: HAVENT_READ_CO
2424    }
2425   };
2426  
2673 general_kline_with_reason: KLINE_WITH_REASON '=' TBOOL ';'
2674 {
2675  ConfigFileEntry.kline_with_reason = yylval.number;
2676 };
2677
2678 general_kline_reason: KLINE_REASON '=' QSTRING ';'
2679 {
2680  if (conf_parser_ctx.pass == 2)
2681  {
2682    MyFree(ConfigFileEntry.kline_reason);
2683    DupString(ConfigFileEntry.kline_reason, yylval.string);
2684  }
2685 };
2686
2427   general_invisible_on_connect: INVISIBLE_ON_CONNECT '=' TBOOL ';'
2428   {
2429    ConfigFileEntry.invisible_on_connect = yylval.number;
# Line 2796 | Line 2536 | general_egdpool_path: EGDPOOL_PATH '=' Q
2536    if (conf_parser_ctx.pass == 2)
2537    {
2538      MyFree(ConfigFileEntry.egdpool_path);
2539 <    DupString(ConfigFileEntry.egdpool_path, yylval.string);
2539 >    ConfigFileEntry.egdpool_path = xstrdup(yylval.string);
2540    }
2541   };
2542  
# Line 2805 | Line 2545 | general_services_name: T_SERVICES_NAME '
2545    if (conf_parser_ctx.pass == 2 && valid_servname(yylval.string))
2546    {
2547      MyFree(ConfigFileEntry.service_name);
2548 <    DupString(ConfigFileEntry.service_name, yylval.string);
2548 >    ConfigFileEntry.service_name = xstrdup(yylval.string);
2549    }
2550   };
2551  
# Line 2975 | Line 2715 | general_default_floodcount: DEFAULT_FLOO
2715    ConfigFileEntry.default_floodcount = $3;
2716   };
2717  
2978 general_client_flood: T_CLIENT_FLOOD '=' sizespec ';'
2979 {
2980  ConfigFileEntry.client_flood = $3;
2981 };
2982
2718  
2719   /***************************************************************************
2720   *  section channel
# Line 2988 | Line 2723 | channel_entry: CHANNEL
2723    '{' channel_items '}' ';';
2724  
2725   channel_items:      channel_items channel_item | channel_item;
2726 < channel_item:       channel_use_except |
2992 <                    channel_use_invex | channel_use_knock | channel_max_bans |
2726 > channel_item:       channel_max_bans |
2727                      channel_knock_delay | channel_knock_delay_channel |
2728                      channel_max_chans_per_user | channel_max_chans_per_oper |
2729                      channel_quiet_on_ban | channel_default_split_user_count |
# Line 3009 | Line 2743 | channel_restrict_channels: RESTRICT_CHAN
2743    ConfigChannel.restrict_channels = yylval.number;
2744   };
2745  
3012 channel_use_except: USE_EXCEPT '=' TBOOL ';'
3013 {
3014  ConfigChannel.use_except = yylval.number;
3015 };
3016
3017 channel_use_invex: USE_INVEX '=' TBOOL ';'
3018 {
3019  ConfigChannel.use_invex = yylval.number;
3020 };
3021
3022 channel_use_knock: USE_KNOCK '=' TBOOL ';'
3023 {
3024  ConfigChannel.use_knock = yylval.number;
3025 };
3026
2746   channel_knock_delay: KNOCK_DELAY '=' timespec ';'
2747   {
2748    ConfigChannel.knock_delay = $3;
# Line 3114 | Line 2833 | serverhide_hidden_name: HIDDEN_NAME '='
2833    if (conf_parser_ctx.pass == 2)
2834    {
2835      MyFree(ConfigServerHide.hidden_name);
2836 <    DupString(ConfigServerHide.hidden_name, yylval.string);
2836 >    ConfigServerHide.hidden_name = xstrdup(yylval.string);
2837    }
2838   };
2839  

Diff Legend

Removed lines
+ Added lines
< Changed lines (old)
> Changed lines (new)