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 1549 by michael, Mon Oct 1 18:11:11 2012 UTC vs.
ircd-hybrid/trunk/src/conf_parser.y (file contents), Revision 1783 by michael, Thu Jan 24 19:26:51 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 55 | Line 56
56   #include <openssl/dh.h>
57   #endif
58  
59 + #include "rsa.h"
60 +
61   int yylex(void);
62  
63 < static char *class_name = NULL;
64 < static struct ConfItem *yy_conf = NULL;
65 < static struct AccessItem *yy_aconf = NULL;
66 < static struct MatchItem *yy_match_item = NULL;
67 < static struct ClassItem *yy_class = NULL;
68 < static char *yy_class_name = NULL;
69 <
70 < static dlink_list col_conf_list  = { NULL, NULL, 0 };
71 < static unsigned int listener_flags = 0;
72 < static unsigned int regex_ban = 0;
73 < static char userbuf[IRCD_BUFSIZE];
74 < static char hostbuf[IRCD_BUFSIZE];
75 < static char reasonbuf[REASONLEN + 1];
76 < static char gecos_name[REALLEN * 4];
77 < static char lfile[IRCD_BUFSIZE];
78 < static unsigned int ltype = 0;
79 < static unsigned int lsize = 0;
80 < static char *resv_reason = NULL;
81 < static char *listener_address = NULL;
82 <
83 < struct CollectItem
84 < {
85 <  dlink_node node;
86 <  char *name;
87 <  char *user;
88 <  char *host;
89 <  char *passwd;
90 <  int  port;
91 <  int  flags;
92 < #ifdef HAVE_LIBCRYPTO
93 <  char *rsa_public_key_file;
94 <  RSA *rsa_public_key;
95 < #endif
96 < };
63 > static struct
64 > {
65 >  struct {
66 >    dlink_list list;
67 >  } mask,
68 >    leaf,
69 >    hub;
70 >
71 >  struct {
72 >    char buf[IRCD_BUFSIZE];
73 >  } name,
74 >    user,
75 >    host,
76 >    addr,
77 >    bind,
78 >    file,
79 >    ciph,
80 >    rpass,
81 >    spass,
82 >    class;
83 >
84 >  struct {
85 >    unsigned int value;
86 >  } flags,
87 >    modes,
88 >    size,
89 >    type,
90 >    port,
91 >    aftype,
92 >    ping_freq,
93 >    max_perip,
94 >    con_freq,
95 >    min_idle,
96 >    max_idle,
97 >    max_total,
98 >    max_global,
99 >    max_local,
100 >    max_ident,
101 >    max_sendq,
102 >    max_recvq,
103 >    cidr_bitlen_ipv4,
104 >    cidr_bitlen_ipv6,
105 >    number_per_cidr;
106 > } block_state;
107  
108   static void
109 < free_collect_item(struct CollectItem *item)
109 > reset_block_state(void)
110   {
111 <  MyFree(item->name);
112 <  MyFree(item->user);
113 <  MyFree(item->host);
114 <  MyFree(item->passwd);
115 < #ifdef HAVE_LIBCRYPTO
116 <  MyFree(item->rsa_public_key_file);
117 < #endif
118 <  MyFree(item);
111 >  dlink_node *ptr = NULL, *ptr_next = NULL;
112 >
113 >  DLINK_FOREACH_SAFE(ptr, ptr_next, block_state.mask.list.head)
114 >  {
115 >    MyFree(ptr->data);
116 >    dlinkDelete(ptr, &block_state.mask.list);
117 >    free_dlink_node(ptr);
118 >  }
119 >
120 >  DLINK_FOREACH_SAFE(ptr, ptr_next, block_state.leaf.list.head)
121 >  {
122 >    MyFree(ptr->data);
123 >    dlinkDelete(ptr, &block_state.leaf.list);
124 >    free_dlink_node(ptr);
125 >  }
126 >
127 >  DLINK_FOREACH_SAFE(ptr, ptr_next, block_state.hub.list.head)
128 >  {
129 >    MyFree(ptr->data);
130 >    dlinkDelete(ptr, &block_state.hub.list);
131 >    free_dlink_node(ptr);
132 >  }
133 >
134 >  memset(&block_state, 0, sizeof(block_state));
135   }
136  
137   %}
# Line 187 | Line 216 | free_collect_item(struct CollectItem *it
216   %token  MAX_IDENT
217   %token  MAX_LOCAL
218   %token  MAX_NICK_CHANGES
219 + %token  MAX_NICK_LENGTH
220   %token  MAX_NICK_TIME
221   %token  MAX_NUMBER
222   %token  MAX_TARGETS
223 + %token  MAX_TOPIC_LENGTH
224   %token  MAX_WATCH
225   %token  MESSAGE_LOCALE
226   %token  MIN_NONWILDCARD
227   %token  MIN_NONWILDCARD_SIMPLE
228 + %token  MIN_IDLE
229 + %token  MAX_IDLE
230 + %token  RANDOM_IDLE
231 + %token  HIDE_IDLE_FROM_OPERS
232   %token  MODULE
233   %token  MODULES
234   %token  NAME
# Line 223 | Line 258 | free_collect_item(struct CollectItem *it
258   %token  PATH
259   %token  PING_COOKIE
260   %token  PING_TIME
226 %token  PING_WARNING
261   %token  PORT
262   %token  QSTRING
263   %token  QUIET_ON_BAN
# Line 245 | Line 279 | free_collect_item(struct CollectItem *it
279   %token  T_TLSV1
280   %token  RESV
281   %token  RESV_EXEMPT
282 < %token  SECONDS MINUTES HOURS DAYS WEEKS
282 > %token  SECONDS MINUTES HOURS DAYS WEEKS MONTHS YEARS
283   %token  SENDQ
284   %token  SEND_PASSWORD
285   %token  SERVERHIDE
# Line 303 | Line 337 | free_collect_item(struct CollectItem *it
337   %token  T_UNXLINE
338   %token  T_GLOBOPS
339   %token  T_WALLOP
340 + %token  T_WEBIRC
341   %token  T_RESTART
342   %token  T_SERVICE
343   %token  T_SERVICES_NAME
# Line 381 | Line 416 | timespec:      NUMBER timespec_
416                  {
417                          $$ = $1 * 60 * 60 * 24 * 7 + $3;
418                  }
419 +                | NUMBER MONTHS timespec_
420 +                {
421 +                        $$ = $1 * 60 * 60 * 24 * 7 * 4 + $3;
422 +                }
423 +                | NUMBER YEARS timespec_
424 +                {
425 +                        $$ = $1 * 60 * 60 * 24 * 365 + $3;
426 +                }
427                  ;
428  
429   sizespec_:      { $$ = 0; } | sizespec;
# Line 419 | Line 462 | serverinfo_items:       serverinfo_items
462   serverinfo_item:        serverinfo_name | serverinfo_vhost |
463                          serverinfo_hub | serverinfo_description |
464                          serverinfo_network_name | serverinfo_network_desc |
465 <                        serverinfo_max_clients | serverinfo_ssl_dh_param_file |
465 >                        serverinfo_max_clients | serverinfo_max_nick_length |
466 >                        serverinfo_max_topic_length | serverinfo_ssl_dh_param_file |
467                          serverinfo_rsa_private_key_file | serverinfo_vhost6 |
468                          serverinfo_sid | serverinfo_ssl_certificate_file |
469                          serverinfo_ssl_client_method | serverinfo_ssl_server_method |
# Line 467 | Line 511 | serverinfo_ssl_certificate_file: SSL_CER
511    {
512      if (!ServerInfo.rsa_private_key_file)
513      {
514 <      yyerror("No rsa_private_key_file specified, SSL disabled");
514 >      conf_error_report("No rsa_private_key_file specified, SSL disabled");
515        break;
516      }
517  
# Line 476 | Line 520 | serverinfo_ssl_certificate_file: SSL_CER
520          SSL_CTX_use_certificate_file(ServerInfo.client_ctx, yylval.string,
521                                       SSL_FILETYPE_PEM) <= 0)
522      {
523 <      yyerror(ERR_lib_error_string(ERR_get_error()));
523 >      report_crypto_errors();
524 >      conf_error_report("Could not open/read certificate file");
525        break;
526      }
527  
# Line 485 | Line 530 | serverinfo_ssl_certificate_file: SSL_CER
530          SSL_CTX_use_PrivateKey_file(ServerInfo.client_ctx, ServerInfo.rsa_private_key_file,
531                                      SSL_FILETYPE_PEM) <= 0)
532      {
533 <      yyerror(ERR_lib_error_string(ERR_get_error()));
533 >      report_crypto_errors();
534 >      conf_error_report("Could not read RSA private key");
535        break;
536      }
537  
538      if (!SSL_CTX_check_private_key(ServerInfo.server_ctx) ||
539          !SSL_CTX_check_private_key(ServerInfo.client_ctx))
540      {
541 <      yyerror(ERR_lib_error_string(ERR_get_error()));
541 >      report_crypto_errors();
542 >      conf_error_report("Could not read RSA private key");
543        break;
544      }
545    }
# Line 518 | Line 565 | serverinfo_rsa_private_key_file: RSA_PRI
565        ServerInfo.rsa_private_key_file = NULL;
566      }
567  
568 <    DupString(ServerInfo.rsa_private_key_file, yylval.string);
568 >    ServerInfo.rsa_private_key_file = xstrdup(yylval.string);
569  
570      if ((file = BIO_new_file(yylval.string, "r")) == NULL)
571      {
572 <      yyerror("File open failed, ignoring");
572 >      conf_error_report("File open failed, ignoring");
573        break;
574      }
575  
# Line 533 | Line 580 | serverinfo_rsa_private_key_file: RSA_PRI
580  
581      if (ServerInfo.rsa_private_key == NULL)
582      {
583 <      yyerror("Couldn't extract key, ignoring");
583 >      conf_error_report("Couldn't extract key, ignoring");
584        break;
585      }
586  
# Line 542 | Line 589 | serverinfo_rsa_private_key_file: RSA_PRI
589        RSA_free(ServerInfo.rsa_private_key);
590        ServerInfo.rsa_private_key = NULL;
591  
592 <      yyerror("Invalid key, ignoring");
592 >      conf_error_report("Invalid key, ignoring");
593        break;
594      }
595  
# Line 552 | Line 599 | serverinfo_rsa_private_key_file: RSA_PRI
599        RSA_free(ServerInfo.rsa_private_key);
600        ServerInfo.rsa_private_key = NULL;
601  
602 <      yyerror("Not a 2048 bit key, ignoring");
602 >      conf_error_report("Not a 2048 bit key, ignoring");
603      }
604    }
605   #endif
# Line 575 | Line 622 | serverinfo_ssl_dh_param_file: SSL_DH_PAR
622        if (dh)
623        {
624          if (DH_size(dh) < 128)
625 <          ilog(LOG_TYPE_IRCD, "Ignoring serverinfo::ssl_dh_param_file -- need at least a 1024 bit DH prime size");
625 >          conf_error_report("Ignoring serverinfo::ssl_dh_param_file -- need at least a 1024 bit DH prime size");
626          else
627            SSL_CTX_set_tmp_dh(ServerInfo.server_ctx, dh);
628  
# Line 600 | Line 647 | serverinfo_name: NAME '=' QSTRING ';'
647    if (conf_parser_ctx.pass == 2 && !ServerInfo.name)
648    {
649      if (valid_servname(yylval.string))
650 <      DupString(ServerInfo.name, yylval.string);
650 >      ServerInfo.name = xstrdup(yylval.string);
651      else
652      {
653 <      ilog(LOG_TYPE_IRCD, "Ignoring serverinfo::name -- invalid name. Aborting.");
653 >      conf_error_report("Ignoring serverinfo::name -- invalid name. Aborting.");
654        exit(0);
655      }
656    }
# Line 615 | Line 662 | serverinfo_sid: IRCD_SID '=' QSTRING ';'
662    if (conf_parser_ctx.pass == 2 && !ServerInfo.sid)
663    {
664      if (valid_sid(yylval.string))
665 <      DupString(ServerInfo.sid, yylval.string);
665 >      ServerInfo.sid = xstrdup(yylval.string);
666      else
667      {
668 <      ilog(LOG_TYPE_IRCD, "Ignoring serverinfo::sid -- invalid SID. Aborting.");
668 >      conf_error_report("Ignoring serverinfo::sid -- invalid SID. Aborting.");
669        exit(0);
670      }
671    }
# Line 629 | Line 676 | serverinfo_description: DESCRIPTION '='
676    if (conf_parser_ctx.pass == 2)
677    {
678      MyFree(ServerInfo.description);
679 <    DupString(ServerInfo.description,yylval.string);
679 >    ServerInfo.description = xstrdup(yylval.string);
680    }
681   };
682  
# Line 643 | Line 690 | serverinfo_network_name: NETWORK_NAME '=
690        p = '\0';
691  
692      MyFree(ServerInfo.network_name);
693 <    DupString(ServerInfo.network_name, yylval.string);
693 >    ServerInfo.network_name = xstrdup(yylval.string);
694    }
695   };
696  
# Line 652 | Line 699 | serverinfo_network_desc: NETWORK_DESC '=
699    if (conf_parser_ctx.pass == 2)
700    {
701      MyFree(ServerInfo.network_desc);
702 <    DupString(ServerInfo.network_desc, yylval.string);
702 >    ServerInfo.network_desc = xstrdup(yylval.string);
703    }
704   };
705  
# Line 716 | Line 763 | serverinfo_vhost6: VHOST6 '=' QSTRING ';
763  
764   serverinfo_max_clients: T_MAX_CLIENTS '=' NUMBER ';'
765   {
766 <  if (conf_parser_ctx.pass == 2)
766 >  if (conf_parser_ctx.pass != 2)
767 >    break;
768 >
769 >  if ($3 < MAXCLIENTS_MIN)
770    {
771 <    recalc_fdlimit(NULL);
771 >    char buf[IRCD_BUFSIZE];
772  
773 <    if ($3 < MAXCLIENTS_MIN)
774 <    {
775 <      char buf[IRCD_BUFSIZE];
776 <      ircsprintf(buf, "MAXCLIENTS too low, setting to %d", MAXCLIENTS_MIN);
777 <      yyerror(buf);
778 <    }
779 <    else if ($3 > MAXCLIENTS_MAX)
780 <    {
781 <      char buf[IRCD_BUFSIZE];
782 <      ircsprintf(buf, "MAXCLIENTS too high, setting to %d", MAXCLIENTS_MAX);
783 <      yyerror(buf);
734 <    }
735 <    else
736 <      ServerInfo.max_clients = $3;
773 >    snprintf(buf, sizeof(buf), "MAXCLIENTS too low, setting to %d", MAXCLIENTS_MIN);
774 >    conf_error_report(buf);
775 >    ServerInfo.max_clients = MAXCLIENTS_MIN;
776 >  }
777 >  else if ($3 > MAXCLIENTS_MAX)
778 >  {
779 >    char buf[IRCD_BUFSIZE];
780 >
781 >    snprintf(buf, sizeof(buf), "MAXCLIENTS too high, setting to %d", MAXCLIENTS_MAX);
782 >    conf_error_report(buf);
783 >    ServerInfo.max_clients = MAXCLIENTS_MAX;
784    }
785 +  else
786 +    ServerInfo.max_clients = $3;
787 + };
788 +
789 + serverinfo_max_nick_length: MAX_NICK_LENGTH '=' NUMBER ';'
790 + {
791 +  if (conf_parser_ctx.pass != 2)
792 +    break;
793 +
794 +  if ($3 < 9)
795 +  {
796 +    conf_error_report("max_nick_length too low, setting to 9");
797 +    ServerInfo.max_nick_length = 9;
798 +  }
799 +  else if ($3 > NICKLEN)
800 +  {
801 +    char buf[IRCD_BUFSIZE];
802 +
803 +    snprintf(buf, sizeof(buf), "max_nick_length too high, setting to %d", NICKLEN);
804 +    conf_error_report(buf);
805 +    ServerInfo.max_nick_length = NICKLEN;
806 +  }
807 +  else
808 +    ServerInfo.max_nick_length = $3;
809 + };
810 +
811 + serverinfo_max_topic_length: MAX_TOPIC_LENGTH '=' NUMBER ';'
812 + {
813 +  if (conf_parser_ctx.pass != 2)
814 +    break;
815 +
816 +  if ($3 < 80)
817 +  {
818 +    conf_error_report("max_topic_length too low, setting to 80");
819 +    ServerInfo.max_topic_length = 80;
820 +  }
821 +  else if ($3 > TOPICLEN)
822 +  {
823 +    char buf[IRCD_BUFSIZE];
824 +
825 +    snprintf(buf, sizeof(buf), "max_topic_length too high, setting to %d", TOPICLEN);
826 +    conf_error_report(buf);
827 +    ServerInfo.max_topic_length = TOPICLEN;
828 +  }
829 +  else
830 +    ServerInfo.max_topic_length = $3;
831   };
832  
833   serverinfo_hub: HUB '=' TBOOL ';'
# Line 757 | Line 850 | admin_name: NAME '=' QSTRING ';'
850    if (conf_parser_ctx.pass == 2)
851    {
852      MyFree(AdminInfo.name);
853 <    DupString(AdminInfo.name, yylval.string);
853 >    AdminInfo.name = xstrdup(yylval.string);
854    }
855   };
856  
# Line 766 | Line 859 | admin_email: EMAIL '=' QSTRING ';'
859    if (conf_parser_ctx.pass == 2)
860    {
861      MyFree(AdminInfo.email);
862 <    DupString(AdminInfo.email, yylval.string);
862 >    AdminInfo.email = xstrdup(yylval.string);
863    }
864   };
865  
# Line 775 | Line 868 | admin_description: DESCRIPTION '=' QSTRI
868    if (conf_parser_ctx.pass == 2)
869    {
870      MyFree(AdminInfo.description);
871 <    DupString(AdminInfo.description, yylval.string);
871 >    AdminInfo.description = xstrdup(yylval.string);
872    }
873   };
874  
# Line 796 | Line 889 | logging_use_logging: USE_LOGGING '=' TBO
889  
890   logging_file_entry:
891   {
892 <  lfile[0] = '\0';
893 <  ltype = 0;
801 <  lsize = 0;
892 >  if (conf_parser_ctx.pass == 2)
893 >    reset_block_state();
894   } T_FILE  '{' logging_file_items '}' ';'
895   {
896 <  if (conf_parser_ctx.pass == 2 && ltype > 0)
897 <    log_add_file(ltype, lsize, lfile);
896 >  if (conf_parser_ctx.pass != 2)
897 >    break;
898 >
899 >  if (block_state.type.value && block_state.file.buf[0])
900 >    log_add_file(block_state.type.value, block_state.size.value,
901 >                 block_state.file.buf);
902   };
903  
904   logging_file_items: logging_file_items logging_file_item |
# Line 813 | Line 909 | logging_file_item:  logging_file_name |
909  
910   logging_file_name: NAME '=' QSTRING ';'
911   {
912 <  strlcpy(lfile, yylval.string, sizeof(lfile));
912 >  if (conf_parser_ctx.pass != 2)
913 >    break;
914 >
915 >  strlcpy(block_state.file.buf, yylval.string, sizeof(block_state.file.buf));
916   }
917  
918   logging_file_size: T_SIZE '=' sizespec ';'
919   {
920 <  lsize = $3;
920 >  block_state.size.value = $3;
921   } | T_SIZE '=' T_UNLIMITED ';'
922   {
923 <  lsize = 0;
923 >  block_state.size.value = 0;
924   };
925  
926   logging_file_type: TYPE
927   {
928    if (conf_parser_ctx.pass == 2)
929 <    ltype = 0;
929 >    block_state.type.value = 0;
930   } '='  logging_file_type_items ';' ;
931  
932   logging_file_type_items: logging_file_type_items ',' logging_file_type_item | logging_file_type_item;
933   logging_file_type_item:  USER
934   {
935    if (conf_parser_ctx.pass == 2)
936 <    ltype = LOG_TYPE_USER;
936 >    block_state.type.value = LOG_TYPE_USER;
937   } | OPERATOR
938   {
939    if (conf_parser_ctx.pass == 2)
940 <    ltype = LOG_TYPE_OPER;
940 >    block_state.type.value = LOG_TYPE_OPER;
941   } | GLINE
942   {
943    if (conf_parser_ctx.pass == 2)
944 <    ltype = LOG_TYPE_GLINE;
944 >    block_state.type.value = LOG_TYPE_GLINE;
945   } | T_DLINE
946   {
947    if (conf_parser_ctx.pass == 2)
948 <    ltype = LOG_TYPE_DLINE;
948 >    block_state.type.value = LOG_TYPE_DLINE;
949   } | KLINE
950   {
951    if (conf_parser_ctx.pass == 2)
952 <    ltype = LOG_TYPE_KLINE;
952 >    block_state.type.value = LOG_TYPE_KLINE;
953   } | KILL
954   {
955    if (conf_parser_ctx.pass == 2)
956 <    ltype = LOG_TYPE_KILL;
956 >    block_state.type.value = LOG_TYPE_KILL;
957   } | T_DEBUG
958   {
959    if (conf_parser_ctx.pass == 2)
960 <    ltype = LOG_TYPE_DEBUG;
960 >    block_state.type.value = LOG_TYPE_DEBUG;
961   };
962  
963  
# Line 867 | Line 966 | logging_file_type_item:  USER
966   ***************************************************************************/
967   oper_entry: OPERATOR
968   {
969 <  if (conf_parser_ctx.pass == 2)
970 <  {
971 <    yy_conf = make_conf_item(OPER_TYPE);
972 <    yy_aconf = map_to_conf(yy_conf);
973 <    SetConfEncrypted(yy_aconf); /* Yes, the default is encrypted */
875 <  }
876 <  else
877 <  {
878 <    MyFree(class_name);
879 <    class_name = NULL;
880 <  }
969 >  if (conf_parser_ctx.pass != 2)
970 >    break;
971 >
972 >  reset_block_state();
973 >  block_state.flags.value |= CONF_FLAGS_ENCRYPTED;
974   } '{' oper_items '}' ';'
975   {
976 <  if (conf_parser_ctx.pass == 2)
884 <  {
885 <    struct CollectItem *yy_tmp;
886 <    dlink_node *ptr;
887 <    dlink_node *next_ptr;
888 <
889 <    conf_add_class_to_conf(yy_conf, class_name);
890 <
891 <    /* Now, make sure there is a copy of the "base" given oper
892 <     * block in each of the collected copies
893 <     */
894 <
895 <    DLINK_FOREACH_SAFE(ptr, next_ptr, col_conf_list.head)
896 <    {
897 <      struct AccessItem *new_aconf;
898 <      struct ConfItem *new_conf;
899 <      yy_tmp = ptr->data;
900 <
901 <      new_conf = make_conf_item(OPER_TYPE);
902 <      new_aconf = (struct AccessItem *)map_to_conf(new_conf);
903 <
904 <      new_aconf->flags = yy_aconf->flags;
905 <
906 <      if (yy_conf->name != NULL)
907 <        DupString(new_conf->name, yy_conf->name);
908 <      if (yy_tmp->user != NULL)
909 <        DupString(new_aconf->user, yy_tmp->user);
910 <      else
911 <        DupString(new_aconf->user, "*");
912 <      if (yy_tmp->host != NULL)
913 <        DupString(new_aconf->host, yy_tmp->host);
914 <      else
915 <        DupString(new_aconf->host, "*");
916 <
917 <      new_aconf->type = parse_netmask(new_aconf->host, &new_aconf->addr,
918 <                                     &new_aconf->bits);
919 <
920 <      conf_add_class_to_conf(new_conf, class_name);
921 <      if (yy_aconf->passwd != NULL)
922 <        DupString(new_aconf->passwd, yy_aconf->passwd);
976 >  dlink_node *ptr = NULL;
977  
978 <      new_aconf->port = yy_aconf->port;
978 >  if (conf_parser_ctx.pass != 2)
979 >    break;
980 >
981 >  if (!block_state.name.buf[0])
982 >    break;
983   #ifdef HAVE_LIBCRYPTO
984 <      if (yy_aconf->rsa_public_key_file != NULL)
985 <      {
986 <        BIO *file;
984 >  if (!(block_state.file.buf[0] ||
985 >        block_state.rpass.buf[0]))
986 >    break;
987 > #else
988 >  if (!block_state.rpass.buf[0])
989 >    break;
990 > #endif
991  
992 <        DupString(new_aconf->rsa_public_key_file,
993 <                  yy_aconf->rsa_public_key_file);
992 >  DLINK_FOREACH(ptr, block_state.mask.list.head)
993 >  {
994 >    struct MaskItem *conf = NULL;
995 >    struct split_nuh_item nuh;
996  
997 <        file = BIO_new_file(yy_aconf->rsa_public_key_file, "r");
998 <        new_aconf->rsa_public_key = PEM_read_bio_RSA_PUBKEY(file,
999 <                                                           NULL, 0, NULL);
1000 <        BIO_set_close(file, BIO_CLOSE);
1001 <        BIO_free(file);
1002 <      }
1003 < #endif
997 >    nuh.nuhmask  = ptr->data;
998 >    nuh.nickptr  = NULL;
999 >    nuh.userptr  = block_state.user.buf;
1000 >    nuh.hostptr  = block_state.host.buf;
1001 >    nuh.nicksize = 0;
1002 >    nuh.usersize = sizeof(block_state.user.buf);
1003 >    nuh.hostsize = sizeof(block_state.host.buf);
1004 >    split_nuh(&nuh);
1005 >
1006 >    conf        = conf_make(CONF_OPER);
1007 >    conf->name  = xstrdup(block_state.name.buf);
1008 >    conf->user  = xstrdup(block_state.user.buf);
1009 >    conf->host  = xstrdup(block_state.host.buf);
1010 >
1011 >    if (block_state.rpass.buf[0])
1012 >      conf->passwd = xstrdup(block_state.rpass.buf);
1013 >
1014 >    conf->flags = block_state.flags.value;
1015 >    conf->modes = block_state.modes.value;
1016 >    conf->port  = block_state.port.value;
1017 >    conf->htype = parse_netmask(conf->host, &conf->addr, &conf->bits);
1018 >
1019 >    conf_add_class_to_conf(conf, block_state.class.buf);
1020  
1021   #ifdef HAVE_LIBCRYPTO
1022 <      if (yy_tmp->name && (yy_tmp->passwd || yy_aconf->rsa_public_key)
1023 <          && yy_tmp->host)
1024 < #else
1025 <      if (yy_tmp->name && yy_tmp->passwd && yy_tmp->host)
1026 < #endif
1022 >    if (block_state.file.buf[0])
1023 >    {
1024 >      BIO *file = NULL;
1025 >      RSA *pkey = NULL;
1026 >
1027 >      if ((file = BIO_new_file(block_state.file.buf, "r")) == NULL)
1028        {
1029 <        conf_add_class_to_conf(new_conf, class_name);
1030 <        if (yy_tmp->name != NULL)
950 <          DupString(new_conf->name, yy_tmp->name);
1029 >        conf_error_report("Ignoring rsa_public_key_file -- file doesn't exist");
1030 >        break;
1031        }
1032  
1033 <      dlinkDelete(&yy_tmp->node, &col_conf_list);
1034 <      free_collect_item(yy_tmp);
955 <    }
956 <
957 <    yy_conf = NULL;
958 <    yy_aconf = NULL;
1033 >      if ((pkey = PEM_read_bio_RSA_PUBKEY(file, NULL, 0, NULL)) == NULL)
1034 >        conf_error_report("Ignoring rsa_public_key_file -- Key invalid; check key syntax.");
1035  
1036 <
1037 <    MyFree(class_name);
1038 <    class_name = NULL;
1036 >      conf->rsa_public_key = pkey;
1037 >      BIO_set_close(file, BIO_CLOSE);
1038 >      BIO_free(file);
1039 >    }
1040 > #endif /* HAVE_LIBCRYPTO */
1041    }
1042 < };
1042 > };
1043  
1044   oper_items:     oper_items oper_item | oper_item;
1045   oper_item:      oper_name | oper_user | oper_password |
# Line 971 | Line 1049 | oper_item:      oper_name | oper_user |
1049   oper_name: NAME '=' QSTRING ';'
1050   {
1051    if (conf_parser_ctx.pass == 2)
1052 <  {
975 <    MyFree(yy_conf->name);
976 <    DupString(yy_conf->name, yylval.string);
977 <  }
1052 >    strlcpy(block_state.name.buf, yylval.string, sizeof(block_state.name.buf));
1053   };
1054  
1055   oper_user: USER '=' QSTRING ';'
1056   {
1057    if (conf_parser_ctx.pass == 2)
1058 <  {
984 <    struct split_nuh_item nuh;
985 <
986 <    nuh.nuhmask  = yylval.string;
987 <    nuh.nickptr  = NULL;
988 <    nuh.userptr  = userbuf;
989 <    nuh.hostptr  = hostbuf;
990 <
991 <    nuh.nicksize = 0;
992 <    nuh.usersize = sizeof(userbuf);
993 <    nuh.hostsize = sizeof(hostbuf);
994 <
995 <    split_nuh(&nuh);
996 <
997 <    if (yy_aconf->user == NULL)
998 <    {
999 <      DupString(yy_aconf->user, userbuf);
1000 <      DupString(yy_aconf->host, hostbuf);
1001 <
1002 <      yy_aconf->type = parse_netmask(yy_aconf->host, &yy_aconf->addr,
1003 <                                    &yy_aconf->bits);
1004 <    }
1005 <    else
1006 <    {
1007 <      struct CollectItem *yy_tmp = MyMalloc(sizeof(struct CollectItem));
1008 <
1009 <      DupString(yy_tmp->user, userbuf);
1010 <      DupString(yy_tmp->host, hostbuf);
1011 <
1012 <      dlinkAdd(yy_tmp, &yy_tmp->node, &col_conf_list);
1013 <    }
1014 <  }
1058 >    dlinkAdd(xstrdup(yylval.string), make_dlink_node(), &block_state.mask.list);
1059   };
1060  
1061   oper_password: PASSWORD '=' QSTRING ';'
1062   {
1063    if (conf_parser_ctx.pass == 2)
1064 <  {
1021 <    if (yy_aconf->passwd != NULL)
1022 <      memset(yy_aconf->passwd, 0, strlen(yy_aconf->passwd));
1023 <
1024 <    MyFree(yy_aconf->passwd);
1025 <    DupString(yy_aconf->passwd, yylval.string);
1026 <  }
1064 >    strlcpy(block_state.rpass.buf, yylval.string, sizeof(block_state.rpass.buf));
1065   };
1066  
1067   oper_encrypted: ENCRYPTED '=' TBOOL ';'
# Line 1031 | Line 1069 | oper_encrypted: ENCRYPTED '=' TBOOL ';'
1069    if (conf_parser_ctx.pass == 2)
1070    {
1071      if (yylval.number)
1072 <      SetConfEncrypted(yy_aconf);
1072 >      block_state.flags.value |= CONF_FLAGS_ENCRYPTED;
1073      else
1074 <      ClearConfEncrypted(yy_aconf);
1074 >      block_state.flags.value &= ~CONF_FLAGS_ENCRYPTED;
1075    }
1076   };
1077  
1078   oper_rsa_public_key_file: RSA_PUBLIC_KEY_FILE '=' QSTRING ';'
1079   {
1042 #ifdef HAVE_LIBCRYPTO
1080    if (conf_parser_ctx.pass == 2)
1081 <  {
1045 <    BIO *file;
1046 <
1047 <    if (yy_aconf->rsa_public_key != NULL)
1048 <    {
1049 <      RSA_free(yy_aconf->rsa_public_key);
1050 <      yy_aconf->rsa_public_key = NULL;
1051 <    }
1052 <
1053 <    if (yy_aconf->rsa_public_key_file != NULL)
1054 <    {
1055 <      MyFree(yy_aconf->rsa_public_key_file);
1056 <      yy_aconf->rsa_public_key_file = NULL;
1057 <    }
1058 <
1059 <    DupString(yy_aconf->rsa_public_key_file, yylval.string);
1060 <    file = BIO_new_file(yylval.string, "r");
1061 <
1062 <    if (file == NULL)
1063 <    {
1064 <      yyerror("Ignoring rsa_public_key_file -- file doesn't exist");
1065 <      break;
1066 <    }
1067 <
1068 <    yy_aconf->rsa_public_key = PEM_read_bio_RSA_PUBKEY(file, NULL, 0, NULL);
1069 <
1070 <    if (yy_aconf->rsa_public_key == NULL)
1071 <    {
1072 <      yyerror("Ignoring rsa_public_key_file -- Key invalid; check key syntax.");
1073 <      break;
1074 <    }
1075 <
1076 <    BIO_set_close(file, BIO_CLOSE);
1077 <    BIO_free(file);
1078 <  }
1079 < #endif /* HAVE_LIBCRYPTO */
1081 >    strlcpy(block_state.file.buf, yylval.string, sizeof(block_state.file.buf));
1082   };
1083  
1084   oper_class: CLASS '=' QSTRING ';'
1085   {
1086    if (conf_parser_ctx.pass == 2)
1087 <  {
1086 <    MyFree(class_name);
1087 <    DupString(class_name, yylval.string);
1088 <  }
1087 >    strlcpy(block_state.class.buf, yylval.string, sizeof(block_state.class.buf));
1088   };
1089  
1090   oper_umodes: T_UMODES
1091   {
1092    if (conf_parser_ctx.pass == 2)
1093 <    yy_aconf->modes = 0;
1093 >    block_state.modes.value = 0;
1094   } '='  oper_umodes_items ';' ;
1095  
1096   oper_umodes_items: oper_umodes_items ',' oper_umodes_item | oper_umodes_item;
1097   oper_umodes_item:  T_BOTS
1098   {
1099    if (conf_parser_ctx.pass == 2)
1100 <    yy_aconf->modes |= UMODE_BOTS;
1100 >    block_state.modes.value |= UMODE_BOTS;
1101   } | T_CCONN
1102   {
1103    if (conf_parser_ctx.pass == 2)
1104 <    yy_aconf->modes |= UMODE_CCONN;
1104 >    block_state.modes.value |= UMODE_CCONN;
1105   } | T_CCONN_FULL
1106   {
1107    if (conf_parser_ctx.pass == 2)
1108 <    yy_aconf->modes |= UMODE_CCONN_FULL;
1108 >    block_state.modes.value |= UMODE_CCONN_FULL;
1109   } | T_DEAF
1110   {
1111    if (conf_parser_ctx.pass == 2)
1112 <    yy_aconf->modes |= UMODE_DEAF;
1112 >    block_state.modes.value |= UMODE_DEAF;
1113   } | T_DEBUG
1114   {
1115    if (conf_parser_ctx.pass == 2)
1116 <    yy_aconf->modes |= UMODE_DEBUG;
1116 >    block_state.modes.value |= UMODE_DEBUG;
1117   } | T_FULL
1118   {
1119    if (conf_parser_ctx.pass == 2)
1120 <    yy_aconf->modes |= UMODE_FULL;
1120 >    block_state.modes.value |= UMODE_FULL;
1121   } | HIDDEN
1122   {
1123    if (conf_parser_ctx.pass == 2)
1124 <    yy_aconf->modes |= UMODE_HIDDEN;
1124 >    block_state.modes.value |= UMODE_HIDDEN;
1125   } | T_SKILL
1126   {
1127    if (conf_parser_ctx.pass == 2)
1128 <    yy_aconf->modes |= UMODE_SKILL;
1128 >    block_state.modes.value |= UMODE_SKILL;
1129   } | T_NCHANGE
1130   {
1131    if (conf_parser_ctx.pass == 2)
1132 <    yy_aconf->modes |= UMODE_NCHANGE;
1132 >    block_state.modes.value |= UMODE_NCHANGE;
1133   } | T_REJ
1134   {
1135    if (conf_parser_ctx.pass == 2)
1136 <    yy_aconf->modes |= UMODE_REJ;
1136 >    block_state.modes.value |= UMODE_REJ;
1137   } | T_UNAUTH
1138   {
1139    if (conf_parser_ctx.pass == 2)
1140 <    yy_aconf->modes |= UMODE_UNAUTH;
1140 >    block_state.modes.value |= UMODE_UNAUTH;
1141   } | T_SPY
1142   {
1143    if (conf_parser_ctx.pass == 2)
1144 <    yy_aconf->modes |= UMODE_SPY;
1144 >    block_state.modes.value |= UMODE_SPY;
1145   } | T_EXTERNAL
1146   {
1147    if (conf_parser_ctx.pass == 2)
1148 <    yy_aconf->modes |= UMODE_EXTERNAL;
1148 >    block_state.modes.value |= UMODE_EXTERNAL;
1149   } | T_OPERWALL
1150   {
1151    if (conf_parser_ctx.pass == 2)
1152 <    yy_aconf->modes |= UMODE_OPERWALL;
1152 >    block_state.modes.value |= UMODE_OPERWALL;
1153   } | T_SERVNOTICE
1154   {
1155    if (conf_parser_ctx.pass == 2)
1156 <    yy_aconf->modes |= UMODE_SERVNOTICE;
1156 >    block_state.modes.value |= UMODE_SERVNOTICE;
1157   } | T_INVISIBLE
1158   {
1159    if (conf_parser_ctx.pass == 2)
1160 <    yy_aconf->modes |= UMODE_INVISIBLE;
1160 >    block_state.modes.value |= UMODE_INVISIBLE;
1161   } | T_WALLOP
1162   {
1163    if (conf_parser_ctx.pass == 2)
1164 <    yy_aconf->modes |= UMODE_WALLOP;
1164 >    block_state.modes.value |= UMODE_WALLOP;
1165   } | T_SOFTCALLERID
1166   {
1167    if (conf_parser_ctx.pass == 2)
1168 <    yy_aconf->modes |= UMODE_SOFTCALLERID;
1168 >    block_state.modes.value |= UMODE_SOFTCALLERID;
1169   } | T_CALLERID
1170   {
1171    if (conf_parser_ctx.pass == 2)
1172 <    yy_aconf->modes |= UMODE_CALLERID;
1172 >    block_state.modes.value |= UMODE_CALLERID;
1173   } | T_LOCOPS
1174   {
1175    if (conf_parser_ctx.pass == 2)
1176 <    yy_aconf->modes |= UMODE_LOCOPS;
1176 >    block_state.modes.value |= UMODE_LOCOPS;
1177   };
1178  
1179   oper_flags: IRCD_FLAGS
1180   {
1181    if (conf_parser_ctx.pass == 2)
1182 <    yy_aconf->port = 0;
1182 >    block_state.port.value = 0;
1183   } '='  oper_flags_items ';';
1184  
1185   oper_flags_items: oper_flags_items ',' oper_flags_item | oper_flags_item;
1186   oper_flags_item: GLOBAL_KILL
1187   {
1188    if (conf_parser_ctx.pass == 2)
1189 <    yy_aconf->port |= OPER_FLAG_GLOBAL_KILL;
1189 >    block_state.port.value |= OPER_FLAG_GLOBAL_KILL;
1190   } | REMOTE
1191   {
1192    if (conf_parser_ctx.pass == 2)
1193 <    yy_aconf->port |= OPER_FLAG_REMOTE;
1193 >    block_state.port.value |= OPER_FLAG_REMOTE;
1194   } | KLINE
1195   {
1196    if (conf_parser_ctx.pass == 2)
1197 <    yy_aconf->port |= OPER_FLAG_K;
1197 >    block_state.port.value |= OPER_FLAG_K;
1198   } | UNKLINE
1199   {
1200    if (conf_parser_ctx.pass == 2)
1201 <    yy_aconf->port |= OPER_FLAG_UNKLINE;
1201 >    block_state.port.value |= OPER_FLAG_UNKLINE;
1202   } | T_DLINE
1203   {
1204    if (conf_parser_ctx.pass == 2)
1205 <    yy_aconf->port |= OPER_FLAG_DLINE;
1205 >    block_state.port.value |= OPER_FLAG_DLINE;
1206   } | T_UNDLINE
1207   {
1208    if (conf_parser_ctx.pass == 2)
1209 <    yy_aconf->port |= OPER_FLAG_UNDLINE;
1209 >    block_state.port.value |= OPER_FLAG_UNDLINE;
1210   } | XLINE
1211   {
1212    if (conf_parser_ctx.pass == 2)
1213 <    yy_aconf->port |= OPER_FLAG_X;
1213 >    block_state.port.value |= OPER_FLAG_X;
1214   } | GLINE
1215   {
1216    if (conf_parser_ctx.pass == 2)
1217 <    yy_aconf->port |= OPER_FLAG_GLINE;
1217 >    block_state.port.value |= OPER_FLAG_GLINE;
1218   } | DIE
1219   {
1220    if (conf_parser_ctx.pass == 2)
1221 <    yy_aconf->port |= OPER_FLAG_DIE;
1221 >    block_state.port.value |= OPER_FLAG_DIE;
1222   } | T_RESTART
1223   {
1224    if (conf_parser_ctx.pass == 2)
1225 <    yy_aconf->port |= OPER_FLAG_RESTART;
1225 >    block_state.port.value |= OPER_FLAG_RESTART;
1226   } | REHASH
1227   {
1228    if (conf_parser_ctx.pass == 2)
1229 <    yy_aconf->port |= OPER_FLAG_REHASH;
1229 >    block_state.port.value |= OPER_FLAG_REHASH;
1230   } | ADMIN
1231   {
1232    if (conf_parser_ctx.pass == 2)
1233 <    yy_aconf->port |= OPER_FLAG_ADMIN;
1233 >    block_state.port.value |= OPER_FLAG_ADMIN;
1234   } | NICK_CHANGES
1235   {
1236    if (conf_parser_ctx.pass == 2)
1237 <    yy_aconf->port |= OPER_FLAG_N;
1237 >    block_state.port.value |= OPER_FLAG_N;
1238   } | T_OPERWALL
1239   {
1240    if (conf_parser_ctx.pass == 2)
1241 <    yy_aconf->port |= OPER_FLAG_OPERWALL;
1241 >    block_state.port.value |= OPER_FLAG_OPERWALL;
1242   } | T_GLOBOPS
1243   {
1244    if (conf_parser_ctx.pass == 2)
1245 <    yy_aconf->port |= OPER_FLAG_GLOBOPS;
1245 >    block_state.port.value |= OPER_FLAG_GLOBOPS;
1246   } | OPER_SPY_T
1247   {
1248    if (conf_parser_ctx.pass == 2)
1249 <    yy_aconf->port |= OPER_FLAG_OPER_SPY;
1249 >    block_state.port.value |= OPER_FLAG_OPER_SPY;
1250   } | REMOTEBAN
1251   {
1252    if (conf_parser_ctx.pass == 2)
1253 <    yy_aconf->port |= OPER_FLAG_REMOTEBAN;
1253 >    block_state.port.value |= OPER_FLAG_REMOTEBAN;
1254   } | T_SET
1255   {
1256    if (conf_parser_ctx.pass == 2)
1257 <    yy_aconf->port |= OPER_FLAG_SET;
1257 >    block_state.port.value |= OPER_FLAG_SET;
1258   } | MODULE
1259   {
1260    if (conf_parser_ctx.pass == 2)
1261 <    yy_aconf->port |= OPER_FLAG_MODULE;
1261 >    block_state.port.value |= OPER_FLAG_MODULE;
1262   };
1263  
1264  
# Line 1268 | Line 1267 | oper_flags_item: GLOBAL_KILL
1267   ***************************************************************************/
1268   class_entry: CLASS
1269   {
1270 <  if (conf_parser_ctx.pass == 1)
1271 <  {
1273 <    yy_conf = make_conf_item(CLASS_TYPE);
1274 <    yy_class = map_to_conf(yy_conf);
1275 <  }
1276 < } '{' class_items '}' ';'
1277 < {
1278 <  if (conf_parser_ctx.pass == 1)
1279 <  {
1280 <    struct ConfItem *cconf = NULL;
1281 <    struct ClassItem *class = NULL;
1282 <
1283 <    if (yy_class_name == NULL)
1284 <      delete_conf_item(yy_conf);
1285 <    else
1286 <    {
1287 <      cconf = find_exact_name_conf(CLASS_TYPE, NULL, yy_class_name, NULL, NULL);
1270 >  if (conf_parser_ctx.pass != 1)
1271 >    break;
1272  
1273 <      if (cconf != NULL)                /* The class existed already */
1290 <      {
1291 <        int user_count = 0;
1292 <
1293 <        rebuild_cidr_class(cconf, yy_class);
1273 >  reset_block_state();
1274  
1275 <        class = map_to_conf(cconf);
1275 >  block_state.ping_freq.value = DEFAULT_PINGFREQUENCY;
1276 >  block_state.con_freq.value  = DEFAULT_CONNECTFREQUENCY;
1277 >  block_state.max_total.value = MAXIMUM_LINKS_DEFAULT;
1278 >  block_state.max_sendq.value = DEFAULT_SENDQ;
1279 >  block_state.max_recvq.value = DEFAULT_RECVQ;
1280 > } '{' class_items '}' ';'
1281 > {
1282 >  struct ClassItem *class = NULL;
1283  
1284 <        user_count = class->curr_user_count;
1285 <        memcpy(class, yy_class, sizeof(*class));
1299 <        class->curr_user_count = user_count;
1300 <        class->active = 1;
1284 >  if (conf_parser_ctx.pass != 1)
1285 >    break;
1286  
1287 <        delete_conf_item(yy_conf);
1287 >  if (!block_state.class.buf[0])
1288 >    break;
1289  
1290 <        MyFree(cconf->name);            /* Allows case change of class name */
1291 <        cconf->name = yy_class_name;
1292 <      }
1293 <      else      /* Brand new class */
1294 <      {
1295 <        MyFree(yy_conf->name);          /* just in case it was allocated */
1296 <        yy_conf->name = yy_class_name;
1297 <        yy_class->active = 1;
1298 <      }
1299 <    }
1300 <
1301 <    yy_class_name = NULL;
1302 <  }
1290 >  if (!(class = class_find(block_state.class.buf, 0)))
1291 >    class = class_make();
1292 >
1293 >  class->active = 1;
1294 >  MyFree(class->name);
1295 >  class->name = xstrdup(block_state.class.buf);
1296 >  class->flags = block_state.flags.value;
1297 >  class->ping_freq = block_state.ping_freq.value;
1298 >  class->max_perip = block_state.max_perip.value;
1299 >  class->con_freq = block_state.con_freq.value;
1300 >  class->min_idle = block_state.min_idle.value;
1301 >  class->max_idle = block_state.max_idle.value;
1302 >  class->max_total = block_state.max_total.value;
1303 >  class->max_global = block_state.max_global.value;
1304 >  class->max_local = block_state.max_local.value;
1305 >  class->max_ident = block_state.max_ident.value;
1306 >  class->max_sendq = block_state.max_sendq.value;
1307 >  class->max_recvq = block_state.max_recvq.value;
1308 >
1309 >  if (class->number_per_cidr && block_state.number_per_cidr.value)
1310 >    if ((class->cidr_bitlen_ipv4 && block_state.cidr_bitlen_ipv4.value) ||
1311 >        (class->cidr_bitlen_ipv6 && block_state.cidr_bitlen_ipv6.value))
1312 >      if ((class->cidr_bitlen_ipv4 != block_state.cidr_bitlen_ipv4.value) ||
1313 >          (class->cidr_bitlen_ipv6 != block_state.cidr_bitlen_ipv6.value))
1314 >        rebuild_cidr_list(class);
1315 >
1316 >  class->cidr_bitlen_ipv4 = block_state.cidr_bitlen_ipv4.value;
1317 >  class->cidr_bitlen_ipv6 = block_state.cidr_bitlen_ipv6.value;
1318 >  class->number_per_cidr = block_state.number_per_cidr.value;
1319   };
1320  
1321   class_items:    class_items class_item | class_item;
1322   class_item:     class_name |
1323                  class_cidr_bitlen_ipv4 | class_cidr_bitlen_ipv6 |
1324                  class_ping_time |
1323                class_ping_warning |
1325                  class_number_per_cidr |
1326                  class_number_per_ip |
1327                  class_connectfreq |
# Line 1329 | Line 1330 | class_item:     class_name |
1330                  class_max_local |
1331                  class_max_ident |
1332                  class_sendq | class_recvq |
1333 +                class_min_idle |
1334 +                class_max_idle |
1335 +                class_flags |
1336                  error ';' ;
1337  
1338   class_name: NAME '=' QSTRING ';'
1339   {
1340    if (conf_parser_ctx.pass == 1)
1341 <  {
1338 <    MyFree(yy_class_name);
1339 <    DupString(yy_class_name, yylval.string);
1340 <  }
1341 >    strlcpy(block_state.class.buf, yylval.string, sizeof(block_state.class.buf));
1342   };
1343  
1344   class_ping_time: PING_TIME '=' timespec ';'
1345   {
1346    if (conf_parser_ctx.pass == 1)
1347 <    yy_class->ping_freq = $3;
1347 < };
1348 <
1349 < class_ping_warning: PING_WARNING '=' timespec ';'
1350 < {
1351 <  if (conf_parser_ctx.pass == 1)
1352 <    yy_class->ping_warning = $3;
1347 >    block_state.ping_freq.value = $3;
1348   };
1349  
1350   class_number_per_ip: NUMBER_PER_IP '=' NUMBER ';'
1351   {
1352    if (conf_parser_ctx.pass == 1)
1353 <    yy_class->max_perip = $3;
1353 >    block_state.max_perip.value = $3;
1354   };
1355  
1356   class_connectfreq: CONNECTFREQ '=' timespec ';'
1357   {
1358    if (conf_parser_ctx.pass == 1)
1359 <    yy_class->con_freq = $3;
1359 >    block_state.con_freq.value = $3;
1360   };
1361  
1362   class_max_number: MAX_NUMBER '=' NUMBER ';'
1363   {
1364    if (conf_parser_ctx.pass == 1)
1365 <    yy_class->max_total = $3;
1365 >    block_state.max_total.value = $3;
1366   };
1367  
1368   class_max_global: MAX_GLOBAL '=' NUMBER ';'
1369   {
1370    if (conf_parser_ctx.pass == 1)
1371 <    yy_class->max_global = $3;
1371 >    block_state.max_global.value = $3;
1372   };
1373  
1374   class_max_local: MAX_LOCAL '=' NUMBER ';'
1375   {
1376    if (conf_parser_ctx.pass == 1)
1377 <    yy_class->max_local = $3;
1377 >    block_state.max_local.value = $3;
1378   };
1379  
1380   class_max_ident: MAX_IDENT '=' NUMBER ';'
1381   {
1382    if (conf_parser_ctx.pass == 1)
1383 <    yy_class->max_ident = $3;
1383 >    block_state.max_ident.value = $3;
1384   };
1385  
1386   class_sendq: SENDQ '=' sizespec ';'
1387   {
1388    if (conf_parser_ctx.pass == 1)
1389 <    yy_class->max_sendq = $3;
1389 >    block_state.max_sendq.value = $3;
1390   };
1391  
1392   class_recvq: T_RECVQ '=' sizespec ';'
1393   {
1394    if (conf_parser_ctx.pass == 1)
1395      if ($3 >= CLIENT_FLOOD_MIN && $3 <= CLIENT_FLOOD_MAX)
1396 <      yy_class->max_recvq = $3;
1396 >      block_state.max_recvq.value = $3;
1397   };
1398  
1399   class_cidr_bitlen_ipv4: CIDR_BITLEN_IPV4 '=' NUMBER ';'
1400   {
1401    if (conf_parser_ctx.pass == 1)
1402 <    yy_class->cidr_bitlen_ipv4 = $3 > 32 ? 32 : $3;
1402 >    block_state.cidr_bitlen_ipv4.value = $3 > 32 ? 32 : $3;
1403   };
1404  
1405   class_cidr_bitlen_ipv6: CIDR_BITLEN_IPV6 '=' NUMBER ';'
1406   {
1407    if (conf_parser_ctx.pass == 1)
1408 <    yy_class->cidr_bitlen_ipv6 = $3 > 128 ? 128 : $3;
1408 >    block_state.cidr_bitlen_ipv6.value = $3 > 128 ? 128 : $3;
1409   };
1410  
1411   class_number_per_cidr: NUMBER_PER_CIDR '=' NUMBER ';'
1412   {
1413    if (conf_parser_ctx.pass == 1)
1414 <    yy_class->number_per_cidr = $3;
1414 >    block_state.number_per_cidr.value = $3;
1415 > };
1416 >
1417 > class_min_idle: MIN_IDLE '=' timespec ';'
1418 > {
1419 >  if (conf_parser_ctx.pass == 1)
1420 >    block_state.min_idle.value = $3;
1421   };
1422  
1423 + class_max_idle: MAX_IDLE '=' timespec ';'
1424 + {
1425 +  if (conf_parser_ctx.pass == 1)
1426 +    block_state.max_idle.value = $3;
1427 + };
1428 +
1429 + class_flags: IRCD_FLAGS
1430 + {
1431 +  if (conf_parser_ctx.pass == 1)
1432 +    block_state.flags.value = 0;
1433 + } '='  class_flags_items ';';
1434 +
1435 + class_flags_items: class_flags_items ',' class_flags_item | class_flags_item;
1436 + class_flags_item: RANDOM_IDLE
1437 + {
1438 +  if (conf_parser_ctx.pass == 1)
1439 +    block_state.flags.value |= CLASS_FLAGS_RANDOM_IDLE;
1440 + } | HIDE_IDLE_FROM_OPERS
1441 + {
1442 +  if (conf_parser_ctx.pass == 1)
1443 +    block_state.flags.value |= CLASS_FLAGS_HIDE_IDLE_FROM_OPERS;
1444 + };
1445 +
1446 +
1447   /***************************************************************************
1448   *  section listen
1449   ***************************************************************************/
1450   listen_entry: LISTEN
1451   {
1452    if (conf_parser_ctx.pass == 2)
1453 <  {
1454 <    listener_address = NULL;
1430 <    listener_flags = 0;
1431 <  }
1432 < } '{' listen_items '}' ';'
1433 < {
1434 <  if (conf_parser_ctx.pass == 2)
1435 <  {
1436 <    MyFree(listener_address);
1437 <    listener_address = NULL;
1438 <  }
1439 < };
1453 >    reset_block_state();
1454 > } '{' listen_items '}' ';';
1455  
1456   listen_flags: IRCD_FLAGS
1457   {
1458 <  listener_flags = 0;
1458 >  block_state.flags.value = 0;
1459   } '='  listen_flags_items ';';
1460  
1461   listen_flags_items: listen_flags_items ',' listen_flags_item | listen_flags_item;
1462   listen_flags_item: T_SSL
1463   {
1464    if (conf_parser_ctx.pass == 2)
1465 <    listener_flags |= LISTENER_SSL;
1465 >    block_state.flags.value |= LISTENER_SSL;
1466   } | HIDDEN
1467   {
1468    if (conf_parser_ctx.pass == 2)
1469 <    listener_flags |= LISTENER_HIDDEN;
1469 >    block_state.flags.value |= LISTENER_HIDDEN;
1470   } | T_SERVER
1471   {
1472    if (conf_parser_ctx.pass == 2)
1473 <    listener_flags |= LISTENER_SERVER;
1473 >   block_state.flags.value |= LISTENER_SERVER;
1474   };
1475  
1461
1462
1476   listen_items:   listen_items listen_item | listen_item;
1477   listen_item:    listen_port | listen_flags | listen_address | listen_host | error ';';
1478  
1479 < listen_port: PORT '=' port_items { listener_flags = 0; } ';';
1479 > listen_port: PORT '=' port_items { block_state.flags.value = 0; } ';';
1480  
1481   port_items: port_items ',' port_item | port_item;
1482  
# Line 1471 | Line 1484 | port_item: NUMBER
1484   {
1485    if (conf_parser_ctx.pass == 2)
1486    {
1487 <    if ((listener_flags & LISTENER_SSL))
1487 >    if (block_state.flags.value & LISTENER_SSL)
1488   #ifdef HAVE_LIBCRYPTO
1489        if (!ServerInfo.server_ctx)
1490   #endif
1491        {
1492 <        yyerror("SSL not available - port closed");
1492 >        conf_error_report("SSL not available - port closed");
1493          break;
1494        }
1495 <    add_listener($1, listener_address, listener_flags);
1495 >    add_listener($1, block_state.addr.buf, block_state.flags.value);
1496    }
1497   } | NUMBER TWODOTS NUMBER
1498   {
# Line 1487 | Line 1500 | port_item: NUMBER
1500    {
1501      int i;
1502  
1503 <    if ((listener_flags & LISTENER_SSL))
1503 >    if (block_state.flags.value & LISTENER_SSL)
1504   #ifdef HAVE_LIBCRYPTO
1505        if (!ServerInfo.server_ctx)
1506   #endif
1507        {
1508 <        yyerror("SSL not available - port closed");
1508 >        conf_error_report("SSL not available - port closed");
1509          break;
1510        }
1511  
1512      for (i = $1; i <= $3; ++i)
1513 <      add_listener(i, listener_address, listener_flags);
1513 >      add_listener(i, block_state.addr.buf, block_state.flags.value);
1514    }
1515   };
1516  
1517   listen_address: IP '=' QSTRING ';'
1518   {
1519    if (conf_parser_ctx.pass == 2)
1520 <  {
1508 <    MyFree(listener_address);
1509 <    DupString(listener_address, yylval.string);
1510 <  }
1520 >    strlcpy(block_state.addr.buf, yylval.string, sizeof(block_state.addr.buf));
1521   };
1522  
1523   listen_host: HOST '=' QSTRING ';'
1524   {
1525    if (conf_parser_ctx.pass == 2)
1526 <  {
1517 <    MyFree(listener_address);
1518 <    DupString(listener_address, yylval.string);
1519 <  }
1526 >    strlcpy(block_state.addr.buf, yylval.string, sizeof(block_state.addr.buf));
1527   };
1528  
1529   /***************************************************************************
# Line 1525 | Line 1532 | listen_host: HOST '=' QSTRING ';'
1532   auth_entry: IRCD_AUTH
1533   {
1534    if (conf_parser_ctx.pass == 2)
1535 <  {
1529 <    yy_conf = make_conf_item(CLIENT_TYPE);
1530 <    yy_aconf = map_to_conf(yy_conf);
1531 <  }
1532 <  else
1533 <  {
1534 <    MyFree(class_name);
1535 <    class_name = NULL;
1536 <  }
1535 >    reset_block_state();
1536   } '{' auth_items '}' ';'
1537   {
1538 <  if (conf_parser_ctx.pass == 2)
1540 <  {
1541 <    struct CollectItem *yy_tmp = NULL;
1542 <    dlink_node *ptr = NULL, *next_ptr = NULL;
1543 <
1544 <    if (yy_aconf->user && yy_aconf->host)
1545 <    {
1546 <      conf_add_class_to_conf(yy_conf, class_name);
1547 <      add_conf_by_address(CONF_CLIENT, yy_aconf);
1548 <    }
1549 <    else
1550 <      delete_conf_item(yy_conf);
1551 <
1552 <    /* copy over settings from first struct */
1553 <    DLINK_FOREACH_SAFE(ptr, next_ptr, col_conf_list.head)
1554 <    {
1555 <      struct AccessItem *new_aconf;
1556 <      struct ConfItem *new_conf;
1538 >  dlink_node *ptr = NULL;
1539  
1540 <      new_conf = make_conf_item(CLIENT_TYPE);
1541 <      new_aconf = map_to_conf(new_conf);
1540 >  if (conf_parser_ctx.pass != 2)
1541 >    break;
1542  
1543 <      yy_tmp = ptr->data;
1544 <
1545 <      assert(yy_tmp->user && yy_tmp->host);
1546 <
1565 <      if (yy_aconf->passwd != NULL)
1566 <        DupString(new_aconf->passwd, yy_aconf->passwd);
1567 <      if (yy_conf->name != NULL)
1568 <        DupString(new_conf->name, yy_conf->name);
1569 <      if (yy_aconf->passwd != NULL)
1570 <        DupString(new_aconf->passwd, yy_aconf->passwd);
1571 <
1572 <      new_aconf->flags = yy_aconf->flags;
1573 <      new_aconf->port  = yy_aconf->port;
1543 >  DLINK_FOREACH(ptr, block_state.mask.list.head)
1544 >  {
1545 >    struct MaskItem *conf = NULL;
1546 >    struct split_nuh_item nuh;
1547  
1548 <      DupString(new_aconf->user, yy_tmp->user);
1549 <      collapse(new_aconf->user);
1548 >    nuh.nuhmask  = ptr->data;
1549 >    nuh.nickptr  = NULL;
1550 >    nuh.userptr  = block_state.user.buf;
1551 >    nuh.hostptr  = block_state.host.buf;
1552 >    nuh.nicksize = 0;
1553 >    nuh.usersize = sizeof(block_state.user.buf);
1554 >    nuh.hostsize = sizeof(block_state.host.buf);
1555 >    split_nuh(&nuh);
1556  
1557 <      DupString(new_aconf->host, yy_tmp->host);
1558 <      collapse(new_aconf->host);
1557 >    conf        = conf_make(CONF_CLIENT);
1558 >    conf->user  = xstrdup(collapse(block_state.user.buf));
1559 >    conf->host  = xstrdup(collapse(block_state.host.buf));
1560 >
1561 >    if (block_state.rpass.buf[0])
1562 >      conf->passwd = xstrdup(block_state.rpass.buf);
1563 >    if (block_state.name.buf[0])
1564 >      conf->passwd = xstrdup(block_state.name.buf);
1565  
1566 <      conf_add_class_to_conf(new_conf, class_name);
1567 <      add_conf_by_address(CONF_CLIENT, new_aconf);
1583 <      dlinkDelete(&yy_tmp->node, &col_conf_list);
1584 <      free_collect_item(yy_tmp);
1585 <    }
1566 >    conf->flags = block_state.flags.value;
1567 >    conf->port  = block_state.port.value;
1568  
1569 <    MyFree(class_name);
1570 <    class_name = NULL;
1589 <    yy_conf = NULL;
1590 <    yy_aconf = NULL;
1569 >    conf_add_class_to_conf(conf, block_state.class.buf);
1570 >    add_conf_by_address(CONF_CLIENT, conf);
1571    }
1572   };
1573  
# Line 1599 | Line 1579 | auth_item:      auth_user | auth_passwd
1579   auth_user: USER '=' QSTRING ';'
1580   {
1581    if (conf_parser_ctx.pass == 2)
1582 <  {
1603 <    struct CollectItem *yy_tmp = NULL;
1604 <    struct split_nuh_item nuh;
1605 <
1606 <    nuh.nuhmask  = yylval.string;
1607 <    nuh.nickptr  = NULL;
1608 <    nuh.userptr  = userbuf;
1609 <    nuh.hostptr  = hostbuf;
1610 <
1611 <    nuh.nicksize = 0;
1612 <    nuh.usersize = sizeof(userbuf);
1613 <    nuh.hostsize = sizeof(hostbuf);
1614 <
1615 <    split_nuh(&nuh);
1616 <
1617 <    if (yy_aconf->user == NULL)
1618 <    {
1619 <      DupString(yy_aconf->user, userbuf);
1620 <      DupString(yy_aconf->host, hostbuf);
1621 <    }
1622 <    else
1623 <    {
1624 <      yy_tmp = MyMalloc(sizeof(struct CollectItem));
1625 <
1626 <      DupString(yy_tmp->user, userbuf);
1627 <      DupString(yy_tmp->host, hostbuf);
1628 <
1629 <      dlinkAdd(yy_tmp, &yy_tmp->node, &col_conf_list);
1630 <    }
1631 <  }
1582 >    dlinkAdd(xstrdup(yylval.string), make_dlink_node(), &block_state.mask.list);
1583   };
1584  
1585   auth_passwd: PASSWORD '=' QSTRING ';'
1586   {
1587    if (conf_parser_ctx.pass == 2)
1588 <  {
1638 <    /* be paranoid */
1639 <    if (yy_aconf->passwd != NULL)
1640 <      memset(yy_aconf->passwd, 0, strlen(yy_aconf->passwd));
1641 <
1642 <    MyFree(yy_aconf->passwd);
1643 <    DupString(yy_aconf->passwd, yylval.string);
1644 <  }
1588 >    strlcpy(block_state.rpass.buf, yylval.string, sizeof(block_state.rpass.buf));
1589   };
1590  
1591   auth_class: CLASS '=' QSTRING ';'
1592   {
1593    if (conf_parser_ctx.pass == 2)
1594 <  {
1651 <    MyFree(class_name);
1652 <    DupString(class_name, yylval.string);
1653 <  }
1594 >    strlcpy(block_state.class.buf, yylval.string, sizeof(block_state.class.buf));
1595   };
1596  
1597   auth_encrypted: ENCRYPTED '=' TBOOL ';'
# Line 1658 | Line 1599 | auth_encrypted: ENCRYPTED '=' TBOOL ';'
1599    if (conf_parser_ctx.pass == 2)
1600    {
1601      if (yylval.number)
1602 <      SetConfEncrypted(yy_aconf);
1602 >      block_state.flags.value |= CONF_FLAGS_ENCRYPTED;
1603      else
1604 <      ClearConfEncrypted(yy_aconf);
1604 >      block_state.flags.value &= ~CONF_FLAGS_ENCRYPTED;
1605    }
1606   };
1607  
1608   auth_flags: IRCD_FLAGS
1609   {
1610 +  if (conf_parser_ctx.pass == 2)
1611 +    block_state.flags.value &= CONF_FLAGS_ENCRYPTED;
1612   } '='  auth_flags_items ';';
1613  
1614   auth_flags_items: auth_flags_items ',' auth_flags_item | auth_flags_item;
1615   auth_flags_item: SPOOF_NOTICE
1616   {
1617    if (conf_parser_ctx.pass == 2)
1618 <    yy_aconf->flags |= CONF_FLAGS_SPOOF_NOTICE;
1618 >    block_state.flags.value |= CONF_FLAGS_SPOOF_NOTICE;
1619   } | EXCEED_LIMIT
1620   {
1621    if (conf_parser_ctx.pass == 2)
1622 <    yy_aconf->flags |= CONF_FLAGS_NOLIMIT;
1622 >    block_state.flags.value |= CONF_FLAGS_NOLIMIT;
1623   } | KLINE_EXEMPT
1624   {
1625    if (conf_parser_ctx.pass == 2)
1626 <    yy_aconf->flags |= CONF_FLAGS_EXEMPTKLINE;
1626 >    block_state.flags.value |= CONF_FLAGS_EXEMPTKLINE;
1627   } | NEED_IDENT
1628   {
1629    if (conf_parser_ctx.pass == 2)
1630 <    yy_aconf->flags |= CONF_FLAGS_NEED_IDENTD;
1630 >    block_state.flags.value |= CONF_FLAGS_NEED_IDENTD;
1631   } | CAN_FLOOD
1632   {
1633    if (conf_parser_ctx.pass == 2)
1634 <    yy_aconf->flags |= CONF_FLAGS_CAN_FLOOD;
1634 >    block_state.flags.value |= CONF_FLAGS_CAN_FLOOD;
1635   } | NO_TILDE
1636   {
1637    if (conf_parser_ctx.pass == 2)
1638 <    yy_aconf->flags |= CONF_FLAGS_NO_TILDE;
1638 >    block_state.flags.value |= CONF_FLAGS_NO_TILDE;
1639   } | GLINE_EXEMPT
1640   {
1641    if (conf_parser_ctx.pass == 2)
1642 <    yy_aconf->flags |= CONF_FLAGS_EXEMPTGLINE;
1642 >    block_state.flags.value |= CONF_FLAGS_EXEMPTGLINE;
1643   } | RESV_EXEMPT
1644   {
1645    if (conf_parser_ctx.pass == 2)
1646 <    yy_aconf->flags |= CONF_FLAGS_EXEMPTRESV;
1646 >    block_state.flags.value |= CONF_FLAGS_EXEMPTRESV;
1647 > } | T_WEBIRC
1648 > {
1649 >  if (conf_parser_ctx.pass == 2)
1650 >    block_state.flags.value |= CONF_FLAGS_WEBIRC;
1651   } | NEED_PASSWORD
1652   {
1653    if (conf_parser_ctx.pass == 2)
1654 <    yy_aconf->flags |= CONF_FLAGS_NEED_PASSWORD;
1654 >    block_state.flags.value |= CONF_FLAGS_NEED_PASSWORD;
1655   };
1656  
1657   auth_spoof: SPOOF '=' QSTRING ';'
1658   {
1659 <  if (conf_parser_ctx.pass == 2)
1660 <  {
1714 <    MyFree(yy_conf->name);
1659 >  if (conf_parser_ctx.pass != 2)
1660 >    break;
1661  
1662 <    if (strlen(yylval.string) <= HOSTLEN && valid_hostname(yylval.string))
1663 <    {    
1664 <      DupString(yy_conf->name, yylval.string);
1665 <      yy_aconf->flags |= CONF_FLAGS_SPOOF_IP;
1720 <    }
1721 <    else
1722 <    {
1723 <      ilog(LOG_TYPE_IRCD, "Spoof either is too long or contains invalid characters. Ignoring it.");
1724 <      yy_conf->name = NULL;
1725 <    }
1662 >  if (strlen(yylval.string) <= HOSTLEN && valid_hostname(yylval.string))
1663 >  {
1664 >    strlcpy(block_state.name.buf, yylval.string, sizeof(block_state.name.buf));
1665 >    block_state.flags.value |= CONF_FLAGS_SPOOF_IP;
1666    }
1667 +  else
1668 +    ilog(LOG_TYPE_IRCD, "Spoof either is too long or contains invalid characters. Ignoring it.");
1669   };
1670  
1671   auth_redir_serv: REDIRSERV '=' QSTRING ';'
1672   {
1673 <  if (conf_parser_ctx.pass == 2)
1674 <  {
1675 <    yy_aconf->flags |= CONF_FLAGS_REDIR;
1676 <    MyFree(yy_conf->name);
1677 <    DupString(yy_conf->name, yylval.string);
1736 <  }
1673 >  if (conf_parser_ctx.pass != 2)
1674 >    break;
1675 >
1676 >  strlcpy(block_state.name.buf, yylval.string, sizeof(block_state.name.buf));
1677 >  block_state.flags.value |= CONF_FLAGS_REDIR;
1678   };
1679  
1680   auth_redir_port: REDIRPORT '=' NUMBER ';'
1681   {
1682 <  if (conf_parser_ctx.pass == 2)
1683 <  {
1684 <    yy_aconf->flags |= CONF_FLAGS_REDIR;
1685 <    yy_aconf->port = $3;
1686 <  }
1682 >  if (conf_parser_ctx.pass != 2)
1683 >    break;
1684 >
1685 >  block_state.flags.value |= CONF_FLAGS_REDIR;
1686 >  block_state.port.value = $3;
1687   };
1688  
1689  
# Line 1751 | Line 1692 | auth_redir_port: REDIRPORT '=' NUMBER ';
1692   ***************************************************************************/
1693   resv_entry: RESV
1694   {
1695 <  if (conf_parser_ctx.pass == 2)
1696 <  {
1697 <    MyFree(resv_reason);
1698 <    resv_reason = NULL;
1699 <  }
1700 < } '{' resv_items '}' ';'
1760 < {
1761 <  if (conf_parser_ctx.pass == 2)
1762 <  {
1763 <    MyFree(resv_reason);
1764 <    resv_reason = NULL;
1765 <  }
1766 < };
1695 >  if (conf_parser_ctx.pass != 2)
1696 >    break;
1697 >
1698 >  reset_block_state();
1699 >  strlcpy(block_state.rpass.buf, CONF_NOREASON, sizeof(block_state.rpass.buf));
1700 > } '{' resv_items '}' ';';
1701  
1702   resv_items:     resv_items resv_item | resv_item;
1703   resv_item:      resv_creason | resv_channel | resv_nick | error ';' ;
# Line 1771 | Line 1705 | resv_item:     resv_creason | resv_channel |
1705   resv_creason: REASON '=' QSTRING ';'
1706   {
1707    if (conf_parser_ctx.pass == 2)
1708 <  {
1775 <    MyFree(resv_reason);
1776 <    DupString(resv_reason, yylval.string);
1777 <  }
1708 >    strlcpy(block_state.rpass.buf, yylval.string, sizeof(block_state.rpass.buf));
1709   };
1710  
1711   resv_channel: CHANNEL '=' QSTRING ';'
1712   {
1713 <  if (conf_parser_ctx.pass == 2)
1714 <  {
1784 <    if (IsChanPrefix(*yylval.string))
1785 <    {
1786 <      char def_reason[] = "No reason";
1713 >  if (conf_parser_ctx.pass != 2)
1714 >    break;
1715  
1716 <      create_channel_resv(yylval.string, resv_reason != NULL ? resv_reason : def_reason, 1);
1717 <    }
1790 <  }
1791 <  /* ignore it for now.. but we really should make a warning if
1792 <   * its an erroneous name --fl_ */
1716 >  if (IsChanPrefix(*yylval.string))
1717 >    create_channel_resv(yylval.string, block_state.rpass.buf, 1);
1718   };
1719  
1720   resv_nick: NICK '=' QSTRING ';'
1721   {
1722    if (conf_parser_ctx.pass == 2)
1723 <  {
1799 <    char def_reason[] = "No reason";
1800 <
1801 <    create_nick_resv(yylval.string, resv_reason != NULL ? resv_reason : def_reason, 1);
1802 <  }
1723 >    create_nick_resv(yylval.string, block_state.rpass.buf, 1);
1724   };
1725  
1726   /***************************************************************************
# Line 1816 | Line 1737 | service_name: NAME '=' QSTRING ';'
1737    {
1738      if (valid_servname(yylval.string))
1739      {
1740 <      yy_conf = make_conf_item(SERVICE_TYPE);
1741 <      DupString(yy_conf->name, yylval.string);
1740 >      struct MaskItem *conf = conf_make(CONF_SERVICE);
1741 >      conf->name = xstrdup(yylval.string);
1742      }
1743    }
1744   };
# Line 1827 | Line 1748 | service_name: NAME '=' QSTRING ';'
1748   ***************************************************************************/
1749   shared_entry: T_SHARED
1750   {
1751 <  if (conf_parser_ctx.pass == 2)
1752 <  {
1753 <    yy_conf = make_conf_item(ULINE_TYPE);
1754 <    yy_match_item = map_to_conf(yy_conf);
1755 <    yy_match_item->action = SHARED_ALL;
1756 <  }
1751 >  if (conf_parser_ctx.pass != 2)
1752 >    break;
1753 >
1754 >  reset_block_state();
1755 >
1756 >  strlcpy(block_state.name.buf, "*", sizeof(block_state.name.buf));
1757 >  strlcpy(block_state.user.buf, "*", sizeof(block_state.user.buf));
1758 >  strlcpy(block_state.host.buf, "*", sizeof(block_state.host.buf));
1759 >  block_state.flags.value = SHARED_ALL;
1760   } '{' shared_items '}' ';'
1761   {
1762 <  if (conf_parser_ctx.pass == 2)
1763 <  {
1764 <    yy_conf = NULL;
1765 <  }
1762 >  struct MaskItem *conf = NULL;
1763 >
1764 >  if (conf_parser_ctx.pass != 2)
1765 >    break;
1766 >
1767 >  conf = conf_make(CONF_ULINE);
1768 >  conf->flags = block_state.flags.value;
1769 >  conf->name = xstrdup(block_state.name.buf);
1770 >  conf->user = xstrdup(block_state.user.buf);
1771 >  conf->user = xstrdup(block_state.host.buf);
1772   };
1773  
1774   shared_items: shared_items shared_item | shared_item;
# Line 1847 | Line 1777 | shared_item:  shared_name | shared_user
1777   shared_name: NAME '=' QSTRING ';'
1778   {
1779    if (conf_parser_ctx.pass == 2)
1780 <  {
1851 <    MyFree(yy_conf->name);
1852 <    DupString(yy_conf->name, yylval.string);
1853 <  }
1780 >    strlcpy(block_state.name.buf, yylval.string, sizeof(block_state.name.buf));
1781   };
1782  
1783   shared_user: USER '=' QSTRING ';'
# Line 1861 | Line 1788 | shared_user: USER '=' QSTRING ';'
1788  
1789      nuh.nuhmask  = yylval.string;
1790      nuh.nickptr  = NULL;
1791 <    nuh.userptr  = userbuf;
1792 <    nuh.hostptr  = hostbuf;
1791 >    nuh.userptr  = block_state.user.buf;
1792 >    nuh.hostptr  = block_state.host.buf;
1793  
1794      nuh.nicksize = 0;
1795 <    nuh.usersize = sizeof(userbuf);
1796 <    nuh.hostsize = sizeof(hostbuf);
1795 >    nuh.usersize = sizeof(block_state.user.buf);
1796 >    nuh.hostsize = sizeof(block_state.host.buf);
1797  
1798      split_nuh(&nuh);
1872
1873    DupString(yy_match_item->user, userbuf);
1874    DupString(yy_match_item->host, hostbuf);
1799    }
1800   };
1801  
1802   shared_type: TYPE
1803   {
1804    if (conf_parser_ctx.pass == 2)
1805 <    yy_match_item->action = 0;
1805 >    block_state.flags.value = 0;
1806   } '=' shared_types ';' ;
1807  
1808   shared_types: shared_types ',' shared_type_item | shared_type_item;
1809   shared_type_item: KLINE
1810   {
1811    if (conf_parser_ctx.pass == 2)
1812 <    yy_match_item->action |= SHARED_KLINE;
1812 >    block_state.flags.value |= SHARED_KLINE;
1813   } | UNKLINE
1814   {
1815    if (conf_parser_ctx.pass == 2)
1816 <    yy_match_item->action |= SHARED_UNKLINE;
1816 >    block_state.flags.value |= SHARED_UNKLINE;
1817   } | T_DLINE
1818   {
1819    if (conf_parser_ctx.pass == 2)
1820 <    yy_match_item->action |= SHARED_DLINE;
1820 >    block_state.flags.value |= SHARED_DLINE;
1821   } | T_UNDLINE
1822   {
1823    if (conf_parser_ctx.pass == 2)
1824 <    yy_match_item->action |= SHARED_UNDLINE;
1824 >    block_state.flags.value |= SHARED_UNDLINE;
1825   } | XLINE
1826   {
1827    if (conf_parser_ctx.pass == 2)
1828 <    yy_match_item->action |= SHARED_XLINE;
1828 >    block_state.flags.value |= SHARED_XLINE;
1829   } | T_UNXLINE
1830   {
1831    if (conf_parser_ctx.pass == 2)
1832 <    yy_match_item->action |= SHARED_UNXLINE;
1832 >    block_state.flags.value |= SHARED_UNXLINE;
1833   } | RESV
1834   {
1835    if (conf_parser_ctx.pass == 2)
1836 <    yy_match_item->action |= SHARED_RESV;
1836 >    block_state.flags.value |= SHARED_RESV;
1837   } | T_UNRESV
1838   {
1839    if (conf_parser_ctx.pass == 2)
1840 <    yy_match_item->action |= SHARED_UNRESV;
1840 >    block_state.flags.value |= SHARED_UNRESV;
1841   } | T_LOCOPS
1842   {
1843    if (conf_parser_ctx.pass == 2)
1844 <    yy_match_item->action |= SHARED_LOCOPS;
1844 >    block_state.flags.value |= SHARED_LOCOPS;
1845   } | T_ALL
1846   {
1847    if (conf_parser_ctx.pass == 2)
1848 <    yy_match_item->action = SHARED_ALL;
1848 >    block_state.flags.value = SHARED_ALL;
1849   };
1850  
1851   /***************************************************************************
# Line 1929 | Line 1853 | shared_type_item: KLINE
1853   ***************************************************************************/
1854   cluster_entry: T_CLUSTER
1855   {
1856 <  if (conf_parser_ctx.pass == 2)
1857 <  {
1858 <    yy_conf = make_conf_item(CLUSTER_TYPE);
1859 <    yy_conf->flags = SHARED_ALL;
1860 <  }
1856 >  if (conf_parser_ctx.pass != 2)
1857 >    break;
1858 >
1859 >  reset_block_state();
1860 >
1861 >  strlcpy(block_state.name.buf, "*", sizeof(block_state.name.buf));
1862 >  block_state.flags.value = SHARED_ALL;
1863   } '{' cluster_items '}' ';'
1864   {
1865 <  if (conf_parser_ctx.pass == 2)
1866 <  {
1867 <    if (yy_conf->name == NULL)
1868 <      DupString(yy_conf->name, "*");
1869 <    yy_conf = NULL;
1870 <  }
1865 >  struct MaskItem *conf = NULL;
1866 >
1867 >  if (conf_parser_ctx.pass != 2)
1868 >    break;
1869 >
1870 >  conf = conf_make(CONF_CLUSTER);
1871 >  conf->flags = block_state.flags.value;
1872 >  conf->name = xstrdup(block_state.name.buf);
1873   };
1874  
1875   cluster_items:  cluster_items cluster_item | cluster_item;
# Line 1950 | Line 1878 | cluster_item:  cluster_name | cluster_typ
1878   cluster_name: NAME '=' QSTRING ';'
1879   {
1880    if (conf_parser_ctx.pass == 2)
1881 <    DupString(yy_conf->name, yylval.string);
1881 >    strlcpy(block_state.name.buf, yylval.string, sizeof(block_state.name.buf));
1882   };
1883  
1884   cluster_type: TYPE
1885   {
1886    if (conf_parser_ctx.pass == 2)
1887 <    yy_conf->flags = 0;
1887 >    block_state.flags.value = 0;
1888   } '=' cluster_types ';' ;
1889  
1890   cluster_types:  cluster_types ',' cluster_type_item | cluster_type_item;
1891   cluster_type_item: KLINE
1892   {
1893    if (conf_parser_ctx.pass == 2)
1894 <    yy_conf->flags |= SHARED_KLINE;
1894 >    block_state.flags.value |= SHARED_KLINE;
1895   } | UNKLINE
1896   {
1897    if (conf_parser_ctx.pass == 2)
1898 <    yy_conf->flags |= SHARED_UNKLINE;
1898 >    block_state.flags.value |= SHARED_UNKLINE;
1899   } | T_DLINE
1900   {
1901    if (conf_parser_ctx.pass == 2)
1902 <    yy_conf->flags |= SHARED_DLINE;
1902 >    block_state.flags.value |= SHARED_DLINE;
1903   } | T_UNDLINE
1904   {
1905    if (conf_parser_ctx.pass == 2)
1906 <    yy_conf->flags |= SHARED_UNDLINE;
1906 >    block_state.flags.value |= SHARED_UNDLINE;
1907   } | XLINE
1908   {
1909    if (conf_parser_ctx.pass == 2)
1910 <    yy_conf->flags |= SHARED_XLINE;
1910 >    block_state.flags.value |= SHARED_XLINE;
1911   } | T_UNXLINE
1912   {
1913    if (conf_parser_ctx.pass == 2)
1914 <    yy_conf->flags |= SHARED_UNXLINE;
1914 >    block_state.flags.value |= SHARED_UNXLINE;
1915   } | RESV
1916   {
1917    if (conf_parser_ctx.pass == 2)
1918 <    yy_conf->flags |= SHARED_RESV;
1918 >    block_state.flags.value |= SHARED_RESV;
1919   } | T_UNRESV
1920   {
1921    if (conf_parser_ctx.pass == 2)
1922 <    yy_conf->flags |= SHARED_UNRESV;
1922 >    block_state.flags.value |= SHARED_UNRESV;
1923   } | T_LOCOPS
1924   {
1925    if (conf_parser_ctx.pass == 2)
1926 <    yy_conf->flags |= SHARED_LOCOPS;
1926 >    block_state.flags.value |= SHARED_LOCOPS;
1927   } | T_ALL
1928   {
1929    if (conf_parser_ctx.pass == 2)
1930 <    yy_conf->flags = SHARED_ALL;
1930 >    block_state.flags.value = SHARED_ALL;
1931   };
1932  
1933   /***************************************************************************
# Line 2007 | Line 1935 | cluster_type_item: KLINE
1935   ***************************************************************************/
1936   connect_entry: CONNECT  
1937   {
2010  if (conf_parser_ctx.pass == 2)
2011  {
2012    yy_conf = make_conf_item(SERVER_TYPE);
2013    yy_aconf = map_to_conf(yy_conf);
1938  
1939 <    /* defaults */
1940 <    yy_aconf->port = PORTNUM;
1941 <  }
1942 <  else
1943 <  {
2020 <    MyFree(class_name);
2021 <    class_name = NULL;
2022 <  }
1939 >  if (conf_parser_ctx.pass != 2)
1940 >    break;
1941 >
1942 >  reset_block_state();
1943 >  block_state.port.value = PORTNUM;
1944   } '{' connect_items '}' ';'
1945   {
1946 <  if (conf_parser_ctx.pass == 2)
1946 >  struct MaskItem *conf = NULL;
1947 >  struct addrinfo hints, *res;
1948 >
1949 >  if (conf_parser_ctx.pass != 2)
1950 >    break;
1951 >
1952 >  if (!block_state.name.buf[0] ||
1953 >      !block_state.host.buf[0])
1954 >    break;
1955 >
1956 >  if (!(block_state.rpass.buf[0] ||
1957 >        block_state.spass.buf[0]))
1958 >    break;
1959 >
1960 >  if (has_wildcards(block_state.name.buf) ||
1961 >      has_wildcards(block_state.host.buf))
1962 >    break;
1963 >
1964 >  conf = conf_make(CONF_SERVER);
1965 >  conf->port = block_state.port.value;
1966 >  conf->flags = block_state.flags.value;
1967 >  conf->aftype = block_state.aftype.value;
1968 >  conf->host = xstrdup(block_state.host.buf);
1969 >  conf->name = xstrdup(block_state.name.buf);
1970 >  conf->passwd = xstrdup(block_state.rpass.buf);
1971 >  conf->spasswd = xstrdup(block_state.spass.buf);
1972 >  conf->cipher_list = xstrdup(block_state.ciph.buf);
1973 >
1974 >  dlinkMoveList(&block_state.leaf.list, &conf->leaf_list);
1975 >  dlinkMoveList(&block_state.hub.list, &conf->hub_list);
1976 >
1977 >  if (block_state.bind.buf[0])
1978    {
1979 <    if (yy_aconf->host && yy_aconf->passwd && yy_aconf->spasswd)
1980 <    {
1981 <      if (conf_add_server(yy_conf, class_name) == -1)
1982 <        delete_conf_item(yy_conf);
1983 <    }
1979 >    memset(&hints, 0, sizeof(hints));
1980 >
1981 >    hints.ai_family   = AF_UNSPEC;
1982 >    hints.ai_socktype = SOCK_STREAM;
1983 >    hints.ai_flags    = AI_PASSIVE | AI_NUMERICHOST;
1984 >
1985 >    if (getaddrinfo(block_state.bind.buf, NULL, &hints, &res))
1986 >      ilog(LOG_TYPE_IRCD, "Invalid netmask for server vhost(%s)", block_state.bind.buf);
1987      else
1988      {
1989 <      if (yy_conf->name != NULL)
2035 <      {
2036 <        if (yy_aconf->host == NULL)
2037 <          yyerror("Ignoring connect block -- missing host");
2038 <        else if (!yy_aconf->passwd || !yy_aconf->spasswd)
2039 <          yyerror("Ignoring connect block -- missing password");
2040 <      }
1989 >      assert(res != NULL);
1990  
1991 <      /* XXX
1992 <       * This fixes a try_connections() core (caused by invalid class_ptr
1993 <       * pointers) reported by metalrock. That's an ugly fix, but there
1994 <       * is currently no better way. The entire config subsystem needs an
2046 <       * rewrite ASAP. make_conf_item() shouldn't really add things onto
2047 <       * a doubly linked list immediately without any sanity checks!  -Michael
2048 <       */
2049 <      delete_conf_item(yy_conf);
1991 >      memcpy(&conf->bind, res->ai_addr, res->ai_addrlen);
1992 >      conf->bind.ss.ss_family = res->ai_family;
1993 >      conf->bind.ss_len = res->ai_addrlen;
1994 >      freeaddrinfo(res);
1995      }
2051
2052    MyFree(class_name);
2053    class_name = NULL;
2054    yy_conf = NULL;
2055    yy_aconf = NULL;
1996    }
1997 +
1998 +  conf_add_class_to_conf(conf, block_state.class.buf);
1999 +  lookup_confhost(conf);
2000   };
2001  
2002   connect_items:  connect_items connect_item | connect_item;
# Line 2067 | Line 2010 | connect_item:   connect_name | connect_h
2010   connect_name: NAME '=' QSTRING ';'
2011   {
2012    if (conf_parser_ctx.pass == 2)
2013 <  {
2071 <    MyFree(yy_conf->name);
2072 <    DupString(yy_conf->name, yylval.string);
2073 <  }
2013 >    strlcpy(block_state.name.buf, yylval.string, sizeof(block_state.name.buf));
2014   };
2015  
2016   connect_host: HOST '=' QSTRING ';'
2017   {
2018    if (conf_parser_ctx.pass == 2)
2019 <  {
2080 <    MyFree(yy_aconf->host);
2081 <    DupString(yy_aconf->host, yylval.string);
2082 <  }
2019 >    strlcpy(block_state.host.buf, yylval.string, sizeof(block_state.host.buf));
2020   };
2021  
2022   connect_vhost: VHOST '=' QSTRING ';'
2023   {
2024    if (conf_parser_ctx.pass == 2)
2025 <  {
2089 <    struct addrinfo hints, *res;
2090 <
2091 <    memset(&hints, 0, sizeof(hints));
2092 <
2093 <    hints.ai_family   = AF_UNSPEC;
2094 <    hints.ai_socktype = SOCK_STREAM;
2095 <    hints.ai_flags    = AI_PASSIVE | AI_NUMERICHOST;
2096 <
2097 <    if (getaddrinfo(yylval.string, NULL, &hints, &res))
2098 <      ilog(LOG_TYPE_IRCD, "Invalid netmask for server vhost(%s)", yylval.string);
2099 <    else
2100 <    {
2101 <      assert(res != NULL);
2102 <
2103 <      memcpy(&yy_aconf->bind, res->ai_addr, res->ai_addrlen);
2104 <      yy_aconf->bind.ss.ss_family = res->ai_family;
2105 <      yy_aconf->bind.ss_len = res->ai_addrlen;
2106 <      freeaddrinfo(res);
2107 <    }
2108 <  }
2025 >    strlcpy(block_state.bind.buf, yylval.string, sizeof(block_state.bind.buf));
2026   };
2027  
2028   connect_send_password: SEND_PASSWORD '=' QSTRING ';'
2029   {
2030 <  if (conf_parser_ctx.pass == 2)
2031 <  {
2115 <    if ($3[0] == ':')
2116 <      yyerror("Server passwords cannot begin with a colon");
2117 <    else if (strchr($3, ' ') != NULL)
2118 <      yyerror("Server passwords cannot contain spaces");
2119 <    else {
2120 <      if (yy_aconf->spasswd != NULL)
2121 <        memset(yy_aconf->spasswd, 0, strlen(yy_aconf->spasswd));
2030 >  if (conf_parser_ctx.pass != 2)
2031 >    break;
2032  
2033 <      MyFree(yy_aconf->spasswd);
2034 <      DupString(yy_aconf->spasswd, yylval.string);
2035 <    }
2036 <  }
2033 >  if ($3[0] == ':')
2034 >    conf_error_report("Server passwords cannot begin with a colon");
2035 >  else if (strchr($3, ' ') != NULL)
2036 >    conf_error_report("Server passwords cannot contain spaces");
2037 >  else
2038 >    strlcpy(block_state.spass.buf, yylval.string, sizeof(block_state.spass.buf));
2039   };
2040  
2041   connect_accept_password: ACCEPT_PASSWORD '=' QSTRING ';'
2042   {
2043 <  if (conf_parser_ctx.pass == 2)
2044 <  {
2133 <    if ($3[0] == ':')
2134 <      yyerror("Server passwords cannot begin with a colon");
2135 <    else if (strchr($3, ' ') != NULL)
2136 <      yyerror("Server passwords cannot contain spaces");
2137 <    else {
2138 <      if (yy_aconf->passwd != NULL)
2139 <        memset(yy_aconf->passwd, 0, strlen(yy_aconf->passwd));
2043 >  if (conf_parser_ctx.pass != 2)
2044 >    break;
2045  
2046 <      MyFree(yy_aconf->passwd);
2047 <      DupString(yy_aconf->passwd, yylval.string);
2048 <    }
2049 <  }
2046 >  if ($3[0] == ':')
2047 >    conf_error_report("Server passwords cannot begin with a colon");
2048 >  else if (strchr($3, ' ') != NULL)
2049 >    conf_error_report("Server passwords cannot contain spaces");
2050 >  else
2051 >    strlcpy(block_state.rpass.buf, yylval.string, sizeof(block_state.rpass.buf));
2052   };
2053  
2054   connect_port: PORT '=' NUMBER ';'
2055   {
2056    if (conf_parser_ctx.pass == 2)
2057 <    yy_aconf->port = $3;
2057 >    block_state.port.value = $3;
2058   };
2059  
2060   connect_aftype: AFTYPE '=' T_IPV4 ';'
2061   {
2062    if (conf_parser_ctx.pass == 2)
2063 <    yy_aconf->aftype = AF_INET;
2063 >    block_state.aftype.value = AF_INET;
2064   } | AFTYPE '=' T_IPV6 ';'
2065   {
2066   #ifdef IPV6
2067    if (conf_parser_ctx.pass == 2)
2068 <    yy_aconf->aftype = AF_INET6;
2068 >    block_state.aftype.value = AF_INET6;
2069   #endif
2070   };
2071  
2072   connect_flags: IRCD_FLAGS
2073   {
2074 +  block_state.flags.value &= CONF_FLAGS_ENCRYPTED;
2075   } '='  connect_flags_items ';';
2076  
2077   connect_flags_items: connect_flags_items ',' connect_flags_item | connect_flags_item;
2078   connect_flags_item: AUTOCONN
2079   {
2080    if (conf_parser_ctx.pass == 2)
2081 <    SetConfAllowAutoConn(yy_aconf);
2081 >    block_state.flags.value |= CONF_FLAGS_ALLOW_AUTO_CONN;
2082   } | T_SSL
2083   {
2084    if (conf_parser_ctx.pass == 2)
2085 <    SetConfSSL(yy_aconf);
2085 >    block_state.flags.value |= CONF_FLAGS_SSL;
2086   };
2087  
2088   connect_encrypted: ENCRYPTED '=' TBOOL ';'
# Line 2182 | Line 2090 | connect_encrypted: ENCRYPTED '=' TBOOL '
2090    if (conf_parser_ctx.pass == 2)
2091    {
2092      if (yylval.number)
2093 <      yy_aconf->flags |= CONF_FLAGS_ENCRYPTED;
2093 >      block_state.flags.value |= CONF_FLAGS_ENCRYPTED;
2094      else
2095 <      yy_aconf->flags &= ~CONF_FLAGS_ENCRYPTED;
2095 >      block_state.flags.value &= ~CONF_FLAGS_ENCRYPTED;
2096    }
2097   };
2098  
2099   connect_hub_mask: HUB_MASK '=' QSTRING ';'
2100   {
2101    if (conf_parser_ctx.pass == 2)
2102 <  {
2195 <    char *mask;
2196 <
2197 <    DupString(mask, yylval.string);
2198 <    dlinkAdd(mask, make_dlink_node(), &yy_aconf->hub_list);
2199 <  }
2102 >    dlinkAdd(xstrdup(yylval.string), make_dlink_node(), &block_state.hub.list);
2103   };
2104  
2105   connect_leaf_mask: LEAF_MASK '=' QSTRING ';'
2106   {
2107    if (conf_parser_ctx.pass == 2)
2108 <  {
2206 <    char *mask;
2207 <
2208 <    DupString(mask, yylval.string);
2209 <    dlinkAdd(mask, make_dlink_node(), &yy_aconf->leaf_list);
2210 <  }
2108 >    dlinkAdd(xstrdup(yylval.string), make_dlink_node(), &block_state.leaf.list);
2109   };
2110  
2111   connect_class: CLASS '=' QSTRING ';'
2112   {
2113    if (conf_parser_ctx.pass == 2)
2114 <  {
2217 <    MyFree(class_name);
2218 <    DupString(class_name, yylval.string);
2219 <  }
2114 >    strlcpy(block_state.class.buf, yylval.string, sizeof(block_state.class.buf));
2115   };
2116  
2117   connect_ssl_cipher_list: T_SSL_CIPHER_LIST '=' QSTRING ';'
2118   {
2119   #ifdef HAVE_LIBCRYPTO
2120    if (conf_parser_ctx.pass == 2)
2121 <  {
2227 <    MyFree(yy_aconf->cipher_list);
2228 <    DupString(yy_aconf->cipher_list, yylval.string);
2229 <  }
2121 >    strlcpy(block_state.ciph.buf, yylval.string, sizeof(block_state.ciph.buf));
2122   #else
2123    if (conf_parser_ctx.pass == 2)
2124 <    yyerror("Ignoring connect::ciphers -- no OpenSSL support");
2124 >    conf_error_report("Ignoring connect::ciphers -- no OpenSSL support");
2125   #endif
2126   };
2127  
# Line 2240 | Line 2132 | connect_ssl_cipher_list: T_SSL_CIPHER_LI
2132   kill_entry: KILL
2133   {
2134    if (conf_parser_ctx.pass == 2)
2135 <  {
2244 <    userbuf[0] = hostbuf[0] = reasonbuf[0] = '\0';
2245 <    regex_ban = 0;
2246 <  }
2135 >    reset_block_state();
2136   } '{' kill_items '}' ';'
2137   {
2138 <  if (conf_parser_ctx.pass == 2)
2138 >  struct MaskItem *conf = NULL;
2139 >
2140 >  if (conf_parser_ctx.pass != 2)
2141 >    break;
2142 >
2143 >  if (!block_state.user.buf[0] ||
2144 >      !block_state.host.buf[0])
2145 >    break;
2146 >
2147 >
2148 >  if (block_state.port.value == 1)
2149    {
2251    if (userbuf[0] && hostbuf[0])
2252    {
2253      if (regex_ban)
2254      {
2150   #ifdef HAVE_LIBPCRE
2151 <        void *exp_user = NULL;
2152 <        void *exp_host = NULL;
2153 <        const char *errptr = NULL;
2154 <
2155 <        if (!(exp_user = ircd_pcre_compile(userbuf, &errptr)) ||
2156 <            !(exp_host = ircd_pcre_compile(hostbuf, &errptr)))
2157 <        {
2158 <          ilog(LOG_TYPE_IRCD, "Failed to add regular expression based K-Line: %s",
2159 <               errptr);
2160 <          break;
2161 <        }
2267 <
2268 <        yy_aconf = map_to_conf(make_conf_item(RKLINE_TYPE));
2269 <        yy_aconf->regexuser = exp_user;
2270 <        yy_aconf->regexhost = exp_host;
2151 >    void *exp_user = NULL;
2152 >    void *exp_host = NULL;
2153 >    const char *errptr = NULL;
2154 >
2155 >    if (!(exp_user = ircd_pcre_compile(block_state.user.buf, &errptr)) ||
2156 >        !(exp_host = ircd_pcre_compile(block_state.host.buf, &errptr)))
2157 >    {
2158 >      ilog(LOG_TYPE_IRCD, "Failed to add regular expression based K-Line: %s",
2159 >           errptr);
2160 >      break;
2161 >    }
2162  
2163 <        DupString(yy_aconf->user, userbuf);
2164 <        DupString(yy_aconf->host, hostbuf);
2163 >    conf = conf_make(CONF_RKLINE);
2164 >    conf->regexuser = exp_user;
2165 >    conf->regexhost = exp_host;
2166  
2167 <        if (reasonbuf[0])
2168 <          DupString(yy_aconf->reason, reasonbuf);
2169 <        else
2170 <          DupString(yy_aconf->reason, "No reason");
2167 >    conf->user = xstrdup(block_state.user.buf);
2168 >    conf->host = xstrdup(block_state.host.buf);
2169 >
2170 >    if (block_state.rpass.buf[0])
2171 >      conf->reason = xstrdup(block_state.rpass.buf);
2172 >    else
2173 >      conf->reason = xstrdup(CONF_NOREASON);
2174   #else
2175 <        ilog(LOG_TYPE_IRCD, "Failed to add regular expression based K-Line: no PCRE support");
2176 <        break;
2175 >    ilog(LOG_TYPE_IRCD, "Failed to add regular expression based K-Line: no PCRE support");
2176 >    break;
2177   #endif
2178 <      }
2179 <      else
2180 <      {
2181 <        find_and_delete_temporary(userbuf, hostbuf, CONF_KLINE);
2287 <
2288 <        yy_aconf = map_to_conf(make_conf_item(KLINE_TYPE));
2178 >  }
2179 >  else
2180 >  {
2181 >    conf = conf_make(CONF_KLINE);
2182  
2183 <        DupString(yy_aconf->user, userbuf);
2184 <        DupString(yy_aconf->host, hostbuf);
2183 >    conf->user = xstrdup(block_state.user.buf);
2184 >    conf->host = xstrdup(block_state.host.buf);
2185  
2186 <        if (reasonbuf[0])
2187 <          DupString(yy_aconf->reason, reasonbuf);
2188 <        else
2189 <          DupString(yy_aconf->reason, "No reason");
2190 <        add_conf_by_address(CONF_KLINE, yy_aconf);
2298 <      }
2299 <    }
2300 <
2301 <    yy_aconf = NULL;
2186 >    if (block_state.rpass.buf[0])
2187 >      conf->reason = xstrdup(block_state.rpass.buf);
2188 >    else
2189 >      conf->reason = xstrdup(CONF_NOREASON);
2190 >    add_conf_by_address(CONF_KLINE, conf);
2191    }
2192   };
2193  
2194   kill_type: TYPE
2195   {
2196 +  if (conf_parser_ctx.pass == 2)
2197 +    block_state.port.value = 0;
2198   } '='  kill_type_items ';';
2199  
2200   kill_type_items: kill_type_items ',' kill_type_item | kill_type_item;
2201   kill_type_item: REGEX_T
2202   {
2203    if (conf_parser_ctx.pass == 2)
2204 <    regex_ban = 1;
2204 >    block_state.port.value = 1;
2205   };
2206  
2207   kill_items:     kill_items kill_item | kill_item;
# Line 2318 | Line 2209 | kill_item:      kill_user | kill_reason
2209  
2210   kill_user: USER '=' QSTRING ';'
2211   {
2212 +
2213    if (conf_parser_ctx.pass == 2)
2214    {
2215      struct split_nuh_item nuh;
2216  
2217      nuh.nuhmask  = yylval.string;
2218      nuh.nickptr  = NULL;
2219 <    nuh.userptr  = userbuf;
2220 <    nuh.hostptr  = hostbuf;
2219 >    nuh.userptr  = block_state.user.buf;
2220 >    nuh.hostptr  = block_state.host.buf;
2221  
2222      nuh.nicksize = 0;
2223 <    nuh.usersize = sizeof(userbuf);
2224 <    nuh.hostsize = sizeof(hostbuf);
2223 >    nuh.usersize = sizeof(block_state.user.buf);
2224 >    nuh.hostsize = sizeof(block_state.host.buf);
2225  
2226      split_nuh(&nuh);
2227    }
# Line 2338 | Line 2230 | kill_user: USER '=' QSTRING ';'
2230   kill_reason: REASON '=' QSTRING ';'
2231   {
2232    if (conf_parser_ctx.pass == 2)
2233 <    strlcpy(reasonbuf, yylval.string, sizeof(reasonbuf));
2233 >    strlcpy(block_state.rpass.buf, yylval.string, sizeof(block_state.rpass.buf));
2234   };
2235  
2236   /***************************************************************************
# Line 2347 | Line 2239 | kill_reason: REASON '=' QSTRING ';'
2239   deny_entry: DENY
2240   {
2241    if (conf_parser_ctx.pass == 2)
2242 <    hostbuf[0] = reasonbuf[0] = '\0';
2242 >    reset_block_state();
2243   } '{' deny_items '}' ';'
2244   {
2245 <  if (conf_parser_ctx.pass == 2)
2354 <  {
2355 <    if (hostbuf[0] && parse_netmask(hostbuf, NULL, NULL) != HM_HOST)
2356 <    {
2357 <      find_and_delete_temporary(NULL, hostbuf, CONF_DLINE);
2245 >  struct MaskItem *conf = NULL;
2246  
2247 <      yy_aconf = map_to_conf(make_conf_item(DLINE_TYPE));
2248 <      DupString(yy_aconf->host, hostbuf);
2247 >  if (conf_parser_ctx.pass != 2)
2248 >    break;
2249  
2250 <      if (reasonbuf[0])
2251 <        DupString(yy_aconf->reason, reasonbuf);
2252 <      else
2253 <        DupString(yy_aconf->reason, "No reason");
2254 <      add_conf_by_address(CONF_DLINE, yy_aconf);
2255 <      yy_aconf = NULL;
2256 <    }
2250 >  if (!block_state.addr.buf[0])
2251 >    break;
2252 >
2253 >  if (parse_netmask(block_state.addr.buf, NULL, NULL) != HM_HOST)
2254 >  {
2255 >    conf = conf_make(CONF_DLINE);
2256 >    conf->host = xstrdup(block_state.addr.buf);
2257 >
2258 >    if (block_state.rpass.buf[0])
2259 >      conf->reason = xstrdup(block_state.rpass.buf);
2260 >    else
2261 >      conf->reason = xstrdup(CONF_NOREASON);
2262 >    add_conf_by_address(CONF_DLINE, conf);
2263    }
2264   };
2265  
# Line 2375 | Line 2269 | deny_item:      deny_ip | deny_reason |
2269   deny_ip: IP '=' QSTRING ';'
2270   {
2271    if (conf_parser_ctx.pass == 2)
2272 <    strlcpy(hostbuf, yylval.string, sizeof(hostbuf));
2272 >    strlcpy(block_state.addr.buf, yylval.string, sizeof(block_state.addr.buf));
2273   };
2274  
2275   deny_reason: REASON '=' QSTRING ';'
2276   {
2277    if (conf_parser_ctx.pass == 2)
2278 <    strlcpy(reasonbuf, yylval.string, sizeof(reasonbuf));
2278 >    strlcpy(block_state.rpass.buf, yylval.string, sizeof(block_state.rpass.buf));
2279   };
2280  
2281   /***************************************************************************
# Line 2398 | Line 2292 | exempt_ip: IP '=' QSTRING ';'
2292    {
2293      if (yylval.string[0] && parse_netmask(yylval.string, NULL, NULL) != HM_HOST)
2294      {
2295 <      yy_aconf = map_to_conf(make_conf_item(EXEMPTDLINE_TYPE));
2296 <      DupString(yy_aconf->host, yylval.string);
2295 >      struct MaskItem *conf = conf_make(CONF_EXEMPT);
2296 >      conf->host = xstrdup(yylval.string);
2297  
2298 <      add_conf_by_address(CONF_EXEMPTDLINE, yy_aconf);
2405 <      yy_aconf = NULL;
2298 >      add_conf_by_address(CONF_EXEMPT, conf);
2299      }
2300    }
2301   };
# Line 2413 | Line 2306 | exempt_ip: IP '=' QSTRING ';'
2306   gecos_entry: GECOS
2307   {
2308    if (conf_parser_ctx.pass == 2)
2309 <  {
2417 <    regex_ban = 0;
2418 <    reasonbuf[0] = gecos_name[0] = '\0';
2419 <  }
2309 >    reset_block_state();
2310   } '{' gecos_items '}' ';'
2311   {
2312 <  if (conf_parser_ctx.pass == 2)
2312 >  struct MaskItem *conf = NULL;
2313 >
2314 >  if (conf_parser_ctx.pass != 2)
2315 >    break;
2316 >
2317 >  if (!block_state.name.buf[0])
2318 >    break;
2319 >
2320 >  if (block_state.port.value == 1)
2321    {
2424    if (gecos_name[0])
2425    {
2426      if (regex_ban)
2427      {
2322   #ifdef HAVE_LIBPCRE
2323 <        void *exp_p = NULL;
2324 <        const char *errptr = NULL;
2323 >    void *exp_p = NULL;
2324 >    const char *errptr = NULL;
2325  
2326 <        if (!(exp_p = ircd_pcre_compile(gecos_name, &errptr)))
2327 <        {
2328 <          ilog(LOG_TYPE_IRCD, "Failed to add regular expression based X-Line: %s",
2329 <               errptr);
2330 <          break;
2331 <        }
2326 >    if (!(exp_p = ircd_pcre_compile(block_state.name.buf, &errptr)))
2327 >    {
2328 >      ilog(LOG_TYPE_IRCD, "Failed to add regular expression based X-Line: %s",
2329 >           errptr);
2330 >      break;
2331 >    }
2332  
2333 <        yy_conf = make_conf_item(RXLINE_TYPE);
2334 <        yy_conf->regexpname = exp_p;
2333 >    conf = conf_make(CONF_RXLINE);
2334 >    conf->regexuser = exp_p;
2335   #else
2336 <        ilog(LOG_TYPE_IRCD, "Failed to add regular expression based X-Line: no PCRE support");
2337 <        break;
2336 >    conf_error_report("Failed to add regular expression based X-Line: no PCRE support");
2337 >    break;
2338   #endif
2339 <      }
2340 <      else
2341 <        yy_conf = make_conf_item(XLINE_TYPE);
2339 >  }
2340 >  else
2341 >    conf = conf_make(CONF_XLINE);
2342  
2343 <      yy_match_item = map_to_conf(yy_conf);
2450 <      DupString(yy_conf->name, gecos_name);
2343 >  conf->name = xstrdup(block_state.name.buf);
2344  
2345 <      if (reasonbuf[0])
2346 <        DupString(yy_match_item->reason, reasonbuf);
2347 <      else
2348 <        DupString(yy_match_item->reason, "No reason");
2456 <    }
2457 <  }
2345 >  if (block_state.rpass.buf[0])
2346 >    conf->reason = xstrdup(block_state.rpass.buf);
2347 >  else
2348 >    conf->reason = xstrdup(CONF_NOREASON);
2349   };
2350  
2351   gecos_flags: TYPE
2352   {
2353 +  if (conf_parser_ctx.pass == 2)
2354 +    block_state.port.value = 0;
2355   } '='  gecos_flags_items ';';
2356  
2357   gecos_flags_items: gecos_flags_items ',' gecos_flags_item | gecos_flags_item;
2358   gecos_flags_item: REGEX_T
2359   {
2360    if (conf_parser_ctx.pass == 2)
2361 <    regex_ban = 1;
2361 >    block_state.port.value = 1;
2362   };
2363  
2364   gecos_items: gecos_items gecos_item | gecos_item;
# Line 2474 | Line 2367 | gecos_item:  gecos_name | gecos_reason |
2367   gecos_name: NAME '=' QSTRING ';'
2368   {
2369    if (conf_parser_ctx.pass == 2)
2370 <    strlcpy(gecos_name, yylval.string, sizeof(gecos_name));
2370 >    strlcpy(block_state.name.buf, yylval.string, sizeof(block_state.name.buf));
2371   };
2372  
2373   gecos_reason: REASON '=' QSTRING ';'
2374   {
2375    if (conf_parser_ctx.pass == 2)
2376 <    strlcpy(reasonbuf, yylval.string, sizeof(reasonbuf));
2376 >    strlcpy(block_state.rpass.buf, yylval.string, sizeof(block_state.rpass.buf));
2377   };
2378  
2379   /***************************************************************************
# Line 2744 | Line 2637 | general_egdpool_path: EGDPOOL_PATH '=' Q
2637    if (conf_parser_ctx.pass == 2)
2638    {
2639      MyFree(ConfigFileEntry.egdpool_path);
2640 <    DupString(ConfigFileEntry.egdpool_path, yylval.string);
2640 >    ConfigFileEntry.egdpool_path = xstrdup(yylval.string);
2641    }
2642   };
2643  
# Line 2753 | Line 2646 | general_services_name: T_SERVICES_NAME '
2646    if (conf_parser_ctx.pass == 2 && valid_servname(yylval.string))
2647    {
2648      MyFree(ConfigFileEntry.service_name);
2649 <    DupString(ConfigFileEntry.service_name, yylval.string);
2649 >    ConfigFileEntry.service_name = xstrdup(yylval.string);
2650    }
2651   };
2652  
# Line 3041 | Line 2934 | serverhide_hidden_name: HIDDEN_NAME '='
2934    if (conf_parser_ctx.pass == 2)
2935    {
2936      MyFree(ConfigServerHide.hidden_name);
2937 <    DupString(ConfigServerHide.hidden_name, yylval.string);
2937 >    ConfigServerHide.hidden_name = xstrdup(yylval.string);
2938    }
2939   };
2940  

Diff Legend

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