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 1352 by michael, Fri Apr 13 09:57:08 2012 UTC vs.
ircd-hybrid/trunk/src/conf_parser.y (file contents), Revision 9101 by michael, Wed Jan 1 09:58:45 2020 UTC

# Line 1 | Line 1
1   /*
2 < *  ircd-hybrid: an advanced Internet Relay Chat Daemon(ircd).
3 < *  conf_parser.y: Parses the ircd configuration file.
2 > *  ircd-hybrid: an advanced, lightweight Internet Relay Chat Daemon (ircd)
3   *
4 < *  Copyright (C) 2005 by the past and present ircd coders, and others.
4 > *  Copyright (c) 2000-2020 ircd-hybrid development team
5   *
6   *  This program is free software; you can redistribute it and/or modify
7   *  it under the terms of the GNU General Public License as published by
# Line 16 | Line 15
15   *
16   *  You should have received a copy of the GNU General Public License
17   *  along with this program; if not, write to the Free Software
18 < *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307
18 > *  Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301
19   *  USA
21 *
22 *  $Id$
20   */
21  
22 < %{
22 > /*! \file conf_parser.y
23 > * \brief Parses the ircd configuration file.
24 > * \version $Id$
25 > */
26  
27 < #define YY_NO_UNPUT
28 < #include <sys/types.h>
29 < #include <string.h>
27 >
28 > %{
29  
30   #include "config.h"
31   #include "stdinc.h"
32   #include "ircd.h"
33   #include "list.h"
34 + #include "parse.h"
35   #include "conf.h"
36 + #include "conf_class.h"
37 + #include "conf_cluster.h"
38 + #include "conf_gecos.h"
39 + #include "conf_pseudo.h"
40 + #include "conf_resv.h"
41 + #include "conf_service.h"
42 + #include "conf_shared.h"
43   #include "event.h"
44 + #include "id.h"
45   #include "log.h"
38 #include "client.h"     /* for UMODE_ALL only */
46   #include "irc_string.h"
40 #include "sprintf_irc.h"
47   #include "memory.h"
48   #include "modules.h"
49 < #include "s_serv.h"
49 > #include "server.h"
50   #include "hostmask.h"
45 #include "send.h"
51   #include "listener.h"
52 < #include "resv.h"
53 < #include "numeric.h"
49 < #include "s_user.h"
50 <
51 < #ifdef HAVE_LIBCRYPTO
52 < #include <openssl/rsa.h>
53 < #include <openssl/bio.h>
54 < #include <openssl/pem.h>
55 < #include <openssl/dh.h>
56 < #endif
52 > #include "user.h"
53 > #include "motd.h"
54  
55   int yylex(void);
56  
57 < static char *class_name = NULL;
61 < static struct ConfItem *yy_conf = NULL;
62 < static struct AccessItem *yy_aconf = NULL;
63 < static struct MatchItem *yy_match_item = NULL;
64 < static struct ClassItem *yy_class = NULL;
65 < static char *yy_class_name = NULL;
66 <
67 < static dlink_list col_conf_list  = { NULL, NULL, 0 };
68 < static dlink_list hub_conf_list  = { NULL, NULL, 0 };
69 < static dlink_list leaf_conf_list = { NULL, NULL, 0 };
70 < static unsigned int listener_flags = 0;
71 < static unsigned int regex_ban = 0;
72 < static char userbuf[IRCD_BUFSIZE];
73 < static char hostbuf[IRCD_BUFSIZE];
74 < static char reasonbuf[REASONLEN + 1];
75 < static char gecos_name[REALLEN * 4];
76 < static char lfile[IRCD_BUFSIZE];
77 < static unsigned int ltype = 0;
78 < static unsigned int lsize = 0;
79 < static char *resv_reason = NULL;
80 < static char *listener_address = NULL;
81 <
82 < struct CollectItem
83 < {
84 <  dlink_node node;
85 <  char *name;
86 <  char *user;
87 <  char *host;
88 <  char *passwd;
89 <  int  port;
90 <  int  flags;
91 < #ifdef HAVE_LIBCRYPTO
92 <  char *rsa_public_key_file;
93 <  RSA *rsa_public_key;
94 < #endif
95 < };
96 <
97 < static void
98 < free_collect_item(struct CollectItem *item)
57 > static struct
58   {
59 <  MyFree(item->name);
60 <  MyFree(item->user);
61 <  MyFree(item->host);
62 <  MyFree(item->passwd);
63 < #ifdef HAVE_LIBCRYPTO
64 <  MyFree(item->rsa_public_key_file);
65 < #endif
66 <  MyFree(item);
67 < }
59 >  struct
60 >  {
61 >    dlink_list list;
62 >  } mask,
63 >    leaf,
64 >    hub;
65 >
66 >  struct
67 >  {
68 >    char buf[IRCD_BUFSIZE];
69 >  } name,
70 >    nick,
71 >    user,
72 >    host,
73 >    addr,
74 >    bind,
75 >    file,
76 >    ciph,
77 >    cert,
78 >    rpass,
79 >    spass,
80 >    whois,
81 >    class,
82 >    target,
83 >    prepend,
84 >    command;
85 >
86 >  struct
87 >  {
88 >    unsigned int value;
89 >  } flags,
90 >    modes,
91 >    size,
92 >    type,
93 >    port,
94 >    timeout,
95 >    aftype,
96 >    ping_freq,
97 >    max_perip_local,
98 >    max_perip_global,
99 >    con_freq,
100 >    min_idle,
101 >    max_idle,
102 >    max_total,
103 >    max_sendq,
104 >    max_recvq,
105 >    max_channels,
106 >    cidr_bitlen_ipv4,
107 >    cidr_bitlen_ipv6,
108 >    number_per_cidr;
109 > } block_state;
110  
111   static void
112 < unhook_hub_leaf_confs(void)
112 > reset_block_state(void)
113   {
114 <  dlink_node *ptr;
114 <  dlink_node *next_ptr;
115 <  struct CollectItem *yy_hconf;
116 <  struct CollectItem *yy_lconf;
114 >  dlink_node *node = NULL, *node_next = NULL;
115  
116 <  DLINK_FOREACH_SAFE(ptr, next_ptr, hub_conf_list.head)
116 >  DLINK_FOREACH_SAFE(node, node_next, block_state.mask.list.head)
117    {
118 <    yy_hconf = ptr->data;
119 <    dlinkDelete(&yy_hconf->node, &hub_conf_list);
120 <    free_collect_item(yy_hconf);
118 >    xfree(node->data);
119 >    dlinkDelete(node, &block_state.mask.list);
120 >    free_dlink_node(node);
121    }
122  
123 <  DLINK_FOREACH_SAFE(ptr, next_ptr, leaf_conf_list.head)
123 >  DLINK_FOREACH_SAFE(node, node_next, block_state.leaf.list.head)
124    {
125 <    yy_lconf = ptr->data;
126 <    dlinkDelete(&yy_lconf->node, &leaf_conf_list);
127 <    free_collect_item(yy_lconf);
125 >    xfree(node->data);
126 >    dlinkDelete(node, &block_state.leaf.list);
127 >    free_dlink_node(node);
128    }
129 +
130 +  DLINK_FOREACH_SAFE(node, node_next, block_state.hub.list.head)
131 +  {
132 +    xfree(node->data);
133 +    dlinkDelete(node, &block_state.hub.list);
134 +    free_dlink_node(node);
135 +  }
136 +
137 +  memset(&block_state, 0, sizeof(block_state));
138   }
139  
140   %}
# Line 138 | Line 145 | unhook_hub_leaf_confs(void)
145   }
146  
147   %token  ACCEPT_PASSWORD
141 %token  ACTION
148   %token  ADMIN
149   %token  AFTYPE
144 %token  T_ALLOW
150   %token  ANTI_NICK_FLOOD
151   %token  ANTI_SPAM_EXIT_MESSAGE_TIME
152   %token  AUTOCONN
153 < %token  T_BLOCK
154 < %token  BURST_AWAY
155 < %token  BURST_TOPICWHO
151 < %token  BYTES KBYTES MBYTES GBYTES TBYTES
153 > %token  AWAY_COUNT
154 > %token  AWAY_TIME
155 > %token  BYTES KBYTES MBYTES
156   %token  CALLER_ID_WAIT
157   %token  CAN_FLOOD
158   %token  CHANNEL
159 < %token  CIDR_BITLEN_IPV4
160 < %token  CIDR_BITLEN_IPV6
159 > %token  CIDR_BITLEN_IPV4
160 > %token  CIDR_BITLEN_IPV6
161   %token  CLASS
162 + %token  CLOSE
163   %token  CONNECT
164   %token  CONNECTFREQ
165 + %token  CYCLE_ON_HOST_CHANGE
166   %token  DEFAULT_FLOODCOUNT
167 < %token  DEFAULT_SPLIT_SERVER_COUNT
168 < %token  DEFAULT_SPLIT_USER_COUNT
167 > %token  DEFAULT_FLOODTIME
168 > %token  DEFAULT_JOIN_FLOOD_COUNT
169 > %token  DEFAULT_JOIN_FLOOD_TIME
170 > %token  DEFAULT_MAX_CLIENTS
171   %token  DENY
172   %token  DESCRIPTION
173   %token  DIE
174   %token  DISABLE_AUTH
175   %token  DISABLE_FAKE_CHANNELS
168 %token  DISABLE_HIDDEN
169 %token  DISABLE_LOCAL_CHANNELS
176   %token  DISABLE_REMOTE_COMMANDS
177 + %token  DLINE_MIN_CIDR
178 + %token  DLINE_MIN_CIDR6
179   %token  DOTS_IN_IDENT
172 %token  DURATION
173 %token  EGDPOOL_PATH
180   %token  EMAIL
175 %token  ENABLE
181   %token  ENCRYPTED
182   %token  EXCEED_LIMIT
183   %token  EXEMPT
184 + %token  EXPIRATION
185   %token  FAILED_OPER_NOTICE
180 %token  IRCD_FLAGS
186   %token  FLATTEN_LINKS
187 + %token  FLATTEN_LINKS_DELAY
188 + %token  FLATTEN_LINKS_FILE
189   %token  GECOS
190   %token  GENERAL
184 %token  GLINE
185 %token  GLINES
186 %token  GLINE_EXEMPT
187 %token  GLINE_TIME
188 %token  GLINE_MIN_CIDR
189 %token  GLINE_MIN_CIDR6
190 %token  GLOBAL_KILL
191 %token  IRCD_AUTH
192 %token  NEED_IDENT
193 %token  HAVENT_READ_CONF
191   %token  HIDDEN
192 < %token  HIDDEN_NAME
192 > %token  HIDDEN_NAME
193 > %token  HIDE_CHANS
194 > %token  HIDE_IDLE
195 > %token  HIDE_IDLE_FROM_OPERS
196   %token  HIDE_SERVER_IPS
197   %token  HIDE_SERVERS
198 < %token  HIDE_SPOOF_IPS
198 > %token  HIDE_SERVICES
199   %token  HOST
200   %token  HUB
201   %token  HUB_MASK
202 %token  IGNORE_BOGUS_TS
202   %token  INVISIBLE_ON_CONNECT
203 + %token  INVITE_CLIENT_COUNT
204 + %token  INVITE_CLIENT_TIME
205 + %token  INVITE_DELAY_CHANNEL
206 + %token  INVITE_EXPIRE_TIME
207   %token  IP
208 + %token  IRCD_AUTH
209 + %token  IRCD_FLAGS
210 + %token  IRCD_SID
211 + %token  JOIN
212   %token  KILL
213 < %token  KILL_CHASE_TIME_LIMIT
213 > %token  KILL_CHASE_TIME_LIMIT
214   %token  KLINE
215   %token  KLINE_EXEMPT
216 < %token  KLINE_REASON
217 < %token  KLINE_WITH_REASON
218 < %token  KNOCK_DELAY
216 > %token  KLINE_MIN_CIDR
217 > %token  KLINE_MIN_CIDR6
218 > %token  KNOCK_CLIENT_COUNT
219 > %token  KNOCK_CLIENT_TIME
220   %token  KNOCK_DELAY_CHANNEL
221   %token  LEAF_MASK
214 %token  LINKS_DELAY
222   %token  LISTEN
223 < %token  T_LOG
223 > %token  MASK
224   %token  MAX_ACCEPT
225   %token  MAX_BANS
226 < %token  MAX_CHANS_PER_USER
227 < %token  MAX_GLOBAL
228 < %token  MAX_IDENT
229 < %token  MAX_LOCAL
226 > %token  MAX_BANS_LARGE
227 > %token  MAX_CHANNELS
228 > %token  MAX_IDLE
229 > %token  MAX_INVITES
230   %token  MAX_NICK_CHANGES
231 + %token  MAX_NICK_LENGTH
232   %token  MAX_NICK_TIME
233   %token  MAX_NUMBER
234   %token  MAX_TARGETS
235 + %token  MAX_TOPIC_LENGTH
236   %token  MAX_WATCH
237 < %token  MESSAGE_LOCALE
237 > %token  MIN_IDLE
238   %token  MIN_NONWILDCARD
239   %token  MIN_NONWILDCARD_SIMPLE
240   %token  MODULE
241   %token  MODULES
242 + %token  MOTD
243   %token  NAME
244 + %token  NEED_IDENT
245   %token  NEED_PASSWORD
246   %token  NETWORK_DESC
247   %token  NETWORK_NAME
248   %token  NICK
238 %token  NICK_CHANGES
239 %token  NO_CREATE_ON_SPLIT
240 %token  NO_JOIN_ON_SPLIT
249   %token  NO_OPER_FLOOD
250   %token  NO_TILDE
251   %token  NUMBER
244 %token  NUMBER_PER_IDENT
252   %token  NUMBER_PER_CIDR
246 %token  NUMBER_PER_IP
253   %token  NUMBER_PER_IP_GLOBAL
254 < %token  OPERATOR
249 < %token  OPERS_BYPASS_CALLERID
254 > %token  NUMBER_PER_IP_LOCAL
255   %token  OPER_ONLY_UMODES
251 %token  OPER_PASS_RESV
252 %token  OPER_SPY_T
256   %token  OPER_UMODES
257 < %token  JOIN_FLOOD_COUNT
258 < %token  JOIN_FLOOD_TIME
257 > %token  OPERATOR
258 > %token  OPERS_BYPASS_CALLERID
259   %token  PACE_WAIT
260   %token  PACE_WAIT_SIMPLE
261   %token  PASSWORD
262   %token  PATH
263   %token  PING_COOKIE
264   %token  PING_TIME
262 %token  PING_WARNING
265   %token  PORT
266   %token  QSTRING
267 < %token  QUIET_ON_BAN
267 > %token  RANDOM_IDLE
268   %token  REASON
269   %token  REDIRPORT
270   %token  REDIRSERV
269 %token  REGEX_T
271   %token  REHASH
271 %token  TREJECT_HOLD_TIME
272   %token  REMOTE
273   %token  REMOTEBAN
274 %token  RESTRICT_CHANNELS
275 %token  RESTRICTED
276 %token  RSA_PRIVATE_KEY_FILE
277 %token  RSA_PUBLIC_KEY_FILE
278 %token  SSL_CERTIFICATE_FILE
279 %token  SSL_DH_PARAM_FILE
280 %token  T_SSL_CLIENT_METHOD
281 %token  T_SSL_SERVER_METHOD
282 %token  T_SSLV3
283 %token  T_TLSV1
274   %token  RESV
275   %token  RESV_EXEMPT
276 < %token  SECONDS MINUTES HOURS DAYS WEEKS
277 < %token  SENDQ
276 > %token  RSA_PRIVATE_KEY_FILE
277 > %token  SECONDS MINUTES HOURS DAYS WEEKS MONTHS YEARS
278   %token  SEND_PASSWORD
279 + %token  SENDQ
280   %token  SERVERHIDE
281   %token  SERVERINFO
291 %token  IRCD_SID
292 %token  TKLINE_EXPIRE_NOTICES
293 %token  T_SHARED
294 %token  T_CLUSTER
295 %token  TYPE
282   %token  SHORT_MOTD
297 %token  SILENT
283   %token  SPOOF
284   %token  SPOOF_NOTICE
285 + %token  SQUIT
286 + %token  SSL_CERTIFICATE_FILE
287 + %token  SSL_CERTIFICATE_FINGERPRINT
288 + %token  SSL_CONNECTION_REQUIRED
289 + %token  SSL_DH_ELLIPTIC_CURVE
290 + %token  SSL_DH_PARAM_FILE
291 + %token  SSL_MESSAGE_DIGEST_ALGORITHM
292   %token  STATS_E_DISABLED
293   %token  STATS_I_OPER_ONLY
294   %token  STATS_K_OPER_ONLY
295 + %token  STATS_M_OPER_ONLY
296   %token  STATS_O_OPER_ONLY
297   %token  STATS_P_OPER_ONLY
298 < %token  TBOOL
306 < %token  TMASKED
307 < %token  T_REJECT
308 < %token  TS_MAX_DELTA
309 < %token  TS_WARN_DELTA
310 < %token  TWODOTS
298 > %token  STATS_U_OPER_ONLY
299   %token  T_ALL
300 + %token  T_BIND
301   %token  T_BOTS
313 %token  T_SOFTCALLERID
302   %token  T_CALLERID
303   %token  T_CCONN
304 < %token  T_CCONN_FULL
305 < %token  T_SSL_CIPHER_LIST
318 < %token  T_CLIENT_FLOOD
304 > %token  T_COMMAND
305 > %token  T_CLUSTER
306   %token  T_DEAF
307   %token  T_DEBUG
308   %token  T_DLINE
322 %token  T_DRONE
309   %token  T_EXTERNAL
310 + %token  T_FARCONNECT
311 + %token  T_FILE
312   %token  T_FULL
313 + %token  T_GLOBOPS
314   %token  T_INVISIBLE
315   %token  T_IPV4
316   %token  T_IPV6
317   %token  T_LOCOPS
318 < %token  T_MAX_CLIENTS
318 > %token  T_LOG
319   %token  T_NCHANGE
320 < %token  T_OPERWALL
320 > %token  T_NONONREG
321 > %token  T_OPME
322 > %token  T_PREPEND
323 > %token  T_PSEUDO
324 > %token  T_RECVQ
325   %token  T_REJ
326 + %token  T_RESTART
327   %token  T_SERVER
328 + %token  T_SERVICE
329   %token  T_SERVNOTICE
330 + %token  T_SET
331 + %token  T_SHARED
332 + %token  T_SIZE
333   %token  T_SKILL
334 + %token  T_SOFTCALLERID
335   %token  T_SPY
336   %token  T_SSL
337 + %token  T_SSL_CIPHER_LIST
338 + %token  T_TARGET
339   %token  T_UMODES
340   %token  T_UNAUTH
341   %token  T_UNDLINE
342   %token  T_UNLIMITED
343   %token  T_UNRESV
344   %token  T_UNXLINE
344 %token  T_GLOBOPS
345   %token  T_WALLOP
346 < %token  T_RESTART
347 < %token  T_SERVICE
348 < %token  T_SERVICES_NAME
346 > %token  T_WALLOPS
347 > %token  T_WEBIRC
348 > %token  TBOOL
349 > %token  THROTTLE_COUNT
350   %token  THROTTLE_TIME
351 < %token  TOPICBURST
352 < %token  TRUE_NO_OPER_FLOOD
353 < %token  TKLINE
354 < %token  TXLINE
355 < %token  TRESV
351 > %token  TIMEOUT
352 > %token  TMASKED
353 > %token  TS_MAX_DELTA
354 > %token  TS_WARN_DELTA
355 > %token  TWODOTS
356 > %token  TYPE
357   %token  UNKLINE
356 %token  USER
357 %token  USE_EGD
358 %token  USE_EXCEPT
359 %token  USE_INVEX
360 %token  USE_KNOCK
358   %token  USE_LOGGING
359 < %token  USE_WHOIS_ACTUALLY
359 > %token  USER
360   %token  VHOST
361   %token  VHOST6
362 + %token  WARN_NO_CONNECT_BLOCK
363 + %token  WHOIS
364 + %token  WHOWAS_HISTORY_LENGTH
365   %token  XLINE
366 < %token  WARN
367 < %token  WARN_NO_NLINE
368 < %token  T_SIZE
369 < %token  T_FILE
366 > %token  XLINE_EXEMPT
367  
368 < %type <string> QSTRING
369 < %type <number> NUMBER
370 < %type <number> timespec
371 < %type <number> timespec_
372 < %type <number> sizespec
373 < %type <number> sizespec_
368 > %type  <string> QSTRING
369 > %type  <number> NUMBER
370 > %type  <number> timespec
371 > %type  <number> timespec_
372 > %type  <number> sizespec
373 > %type  <number> sizespec_
374  
375   %%
376 < conf:  
376 > conf:
377          | conf conf_item
378          ;
379  
380   conf_item:        admin_entry
381                  | logging_entry
382                  | oper_entry
383 <                | channel_entry
384 <                | class_entry
383 >                | channel_entry
384 >                | class_entry
385                  | listen_entry
386                  | auth_entry
387                  | serverinfo_entry
388 <                | serverhide_entry
388 >                | serverhide_entry
389                  | resv_entry
390                  | service_entry
391                  | shared_entry
392 <                | cluster_entry
392 >                | cluster_entry
393                  | connect_entry
394                  | kill_entry
395                  | deny_entry
396 <                | exempt_entry
397 <                | general_entry
401 <                | gline_entry
396 >                | exempt_entry
397 >                | general_entry
398                  | gecos_entry
399                  | modules_entry
400 +                | motd_entry
401 +                | pseudo_entry
402                  | error ';'
403                  | error '}'
404          ;
405  
406  
407   timespec_: { $$ = 0; } | timespec;
408 < timespec:       NUMBER timespec_
409 <                {
410 <                        $$ = $1 + $2;
411 <                }
412 <                | NUMBER SECONDS timespec_
413 <                {
414 <                        $$ = $1 + $3;
415 <                }
416 <                | NUMBER MINUTES timespec_
417 <                {
418 <                        $$ = $1 * 60 + $3;
419 <                }
420 <                | NUMBER HOURS timespec_
421 <                {
422 <                        $$ = $1 * 60 * 60 + $3;
423 <                }
426 <                | NUMBER DAYS timespec_
427 <                {
428 <                        $$ = $1 * 60 * 60 * 24 + $3;
429 <                }
430 <                | NUMBER WEEKS timespec_
431 <                {
432 <                        $$ = $1 * 60 * 60 * 24 * 7 + $3;
433 <                }
434 <                ;
435 <
436 < sizespec_:      { $$ = 0; } | sizespec;
437 < sizespec:       NUMBER sizespec_ { $$ = $1 + $2; }
438 <                | NUMBER BYTES sizespec_ { $$ = $1 + $3; }
439 <                | NUMBER KBYTES sizespec_ { $$ = $1 * 1024 + $3; }
440 <                | NUMBER MBYTES sizespec_ { $$ = $1 * 1024 * 1024 + $3; }
441 <                ;
408 > timespec:  NUMBER timespec_         { $$ = $1 + $2; } |
409 >           NUMBER SECONDS timespec_ { $$ = $1 + $3; } |
410 >           NUMBER MINUTES timespec_ { $$ = $1 * 60 + $3; } |
411 >           NUMBER HOURS timespec_   { $$ = $1 * 60 * 60 + $3; } |
412 >           NUMBER DAYS timespec_    { $$ = $1 * 60 * 60 * 24 + $3; } |
413 >           NUMBER WEEKS timespec_   { $$ = $1 * 60 * 60 * 24 * 7 + $3; } |
414 >           NUMBER MONTHS timespec_  { $$ = $1 * 60 * 60 * 24 * 7 * 4 + $3; } |
415 >           NUMBER YEARS timespec_   { $$ = $1 * 60 * 60 * 24 * 365 + $3; }
416 >           ;
417 >
418 > sizespec_:  { $$ = 0; } | sizespec;
419 > sizespec:   NUMBER sizespec_ { $$ = $1 + $2; } |
420 >            NUMBER BYTES sizespec_ { $$ = $1 + $3; } |
421 >            NUMBER KBYTES sizespec_ { $$ = $1 * 1024 + $3; } |
422 >            NUMBER MBYTES sizespec_ { $$ = $1 * 1024 * 1024 + $3; }
423 >            ;
424  
425  
426   /***************************************************************************
427 < *  section modules
427 > * modules {} section
428   ***************************************************************************/
429 < modules_entry: MODULES
448 <  '{' modules_items '}' ';';
429 > modules_entry: MODULES '{' modules_items '}' ';';
430  
431   modules_items:  modules_items modules_item | modules_item;
432   modules_item:   modules_module | modules_path | error ';' ;
# Line 463 | Line 444 | modules_path: PATH '=' QSTRING ';'
444   };
445  
446  
447 + /***************************************************************************
448 + * serverinfo {}  section
449 + ***************************************************************************/
450   serverinfo_entry: SERVERINFO '{' serverinfo_items '}' ';';
451  
452   serverinfo_items:       serverinfo_items serverinfo_item | serverinfo_item ;
453 < serverinfo_item:        serverinfo_name | serverinfo_vhost |
454 <                        serverinfo_hub | serverinfo_description |
455 <                        serverinfo_network_name | serverinfo_network_desc |
456 <                        serverinfo_max_clients | serverinfo_ssl_dh_param_file |
457 <                        serverinfo_rsa_private_key_file | serverinfo_vhost6 |
458 <                        serverinfo_sid | serverinfo_ssl_certificate_file |
459 <                        serverinfo_ssl_client_method | serverinfo_ssl_server_method |
453 > serverinfo_item:        serverinfo_name |
454 >                        serverinfo_hub |
455 >                        serverinfo_description |
456 >                        serverinfo_network_name |
457 >                        serverinfo_network_desc |
458 >                        serverinfo_default_max_clients |
459 >                        serverinfo_max_nick_length |
460 >                        serverinfo_max_topic_length |
461 >                        serverinfo_ssl_dh_param_file |
462 >                        serverinfo_ssl_dh_elliptic_curve |
463 >                        serverinfo_rsa_private_key_file |
464 >                        serverinfo_sid |
465 >                        serverinfo_ssl_certificate_file |
466                          serverinfo_ssl_cipher_list |
467 <                        error ';' ;
468 <
467 >                        serverinfo_ssl_message_digest_algorithm |
468 >                        error ';' ;
469  
480 serverinfo_ssl_client_method: T_SSL_CLIENT_METHOD '=' client_method_types ';' ;
481 serverinfo_ssl_server_method: T_SSL_SERVER_METHOD '=' server_method_types ';' ;
470  
471 < client_method_types: client_method_types ',' client_method_type_item | client_method_type_item;
484 < client_method_type_item: T_SSLV3
485 < {
486 < #ifdef HAVE_LIBCRYPTO
487 <  if (conf_parser_ctx.pass == 2 && ServerInfo.client_ctx)
488 <    SSL_CTX_clear_options(ServerInfo.client_ctx, SSL_OP_NO_SSLv3);
489 < #endif
490 < } | T_TLSV1
471 > serverinfo_ssl_certificate_file: SSL_CERTIFICATE_FILE '=' QSTRING ';'
472   {
473 < #ifdef HAVE_LIBCRYPTO
474 <  if (conf_parser_ctx.pass == 2 && ServerInfo.client_ctx)
475 <    SSL_CTX_clear_options(ServerInfo.client_ctx, SSL_OP_NO_TLSv1);
476 < #endif
473 >  if (conf_parser_ctx.pass == 2)
474 >  {
475 >    xfree(ConfigServerInfo.ssl_certificate_file);
476 >    ConfigServerInfo.ssl_certificate_file = xstrdup(yylval.string);
477 >  }
478   };
479  
480 < server_method_types: server_method_types ',' server_method_type_item | server_method_type_item;
499 < server_method_type_item: T_SSLV3
500 < {
501 < #ifdef HAVE_LIBCRYPTO
502 <  if (conf_parser_ctx.pass == 2 && ServerInfo.server_ctx)
503 <    SSL_CTX_clear_options(ServerInfo.server_ctx, SSL_OP_NO_SSLv3);
504 < #endif
505 < } | T_TLSV1
480 > serverinfo_rsa_private_key_file: RSA_PRIVATE_KEY_FILE '=' QSTRING ';'
481   {
482 < #ifdef HAVE_LIBCRYPTO
483 <  if (conf_parser_ctx.pass == 2 && ServerInfo.server_ctx)
484 <    SSL_CTX_clear_options(ServerInfo.server_ctx, SSL_OP_NO_TLSv1);
485 < #endif
482 >  if (conf_parser_ctx.pass == 2)
483 >  {
484 >    xfree(ConfigServerInfo.rsa_private_key_file);
485 >    ConfigServerInfo.rsa_private_key_file = xstrdup(yylval.string);
486 >  }
487   };
488  
489 < serverinfo_ssl_certificate_file: SSL_CERTIFICATE_FILE '=' QSTRING ';'
489 > serverinfo_ssl_dh_param_file: SSL_DH_PARAM_FILE '=' QSTRING ';'
490   {
491 < #ifdef HAVE_LIBCRYPTO
516 <  if (conf_parser_ctx.pass == 2 && ServerInfo.server_ctx)
491 >  if (conf_parser_ctx.pass == 2)
492    {
493 <    if (!ServerInfo.rsa_private_key_file)
494 <    {
520 <      yyerror("No rsa_private_key_file specified, SSL disabled");
521 <      break;
522 <    }
523 <
524 <    if (SSL_CTX_use_certificate_file(ServerInfo.server_ctx, yylval.string,
525 <                                     SSL_FILETYPE_PEM) <= 0 ||
526 <        SSL_CTX_use_certificate_file(ServerInfo.client_ctx, yylval.string,
527 <                                     SSL_FILETYPE_PEM) <= 0)
528 <    {
529 <      yyerror(ERR_lib_error_string(ERR_get_error()));
530 <      break;
531 <    }
532 <
533 <    if (SSL_CTX_use_PrivateKey_file(ServerInfo.server_ctx, ServerInfo.rsa_private_key_file,
534 <                                    SSL_FILETYPE_PEM) <= 0 ||
535 <        SSL_CTX_use_PrivateKey_file(ServerInfo.client_ctx, ServerInfo.rsa_private_key_file,
536 <                                    SSL_FILETYPE_PEM) <= 0)
537 <    {
538 <      yyerror(ERR_lib_error_string(ERR_get_error()));
539 <      break;
540 <    }
541 <
542 <    if (!SSL_CTX_check_private_key(ServerInfo.server_ctx) ||
543 <        !SSL_CTX_check_private_key(ServerInfo.client_ctx))
544 <    {
545 <      yyerror(ERR_lib_error_string(ERR_get_error()));
546 <      break;
547 <    }
493 >    xfree(ConfigServerInfo.ssl_dh_param_file);
494 >    ConfigServerInfo.ssl_dh_param_file = xstrdup(yylval.string);
495    }
549 #endif
496   };
497  
498 < serverinfo_rsa_private_key_file: RSA_PRIVATE_KEY_FILE '=' QSTRING ';'
498 > serverinfo_ssl_cipher_list: T_SSL_CIPHER_LIST '=' QSTRING ';'
499   {
500 < #ifdef HAVE_LIBCRYPTO
555 <  if (conf_parser_ctx.pass == 1)
500 >  if (conf_parser_ctx.pass == 2)
501    {
502 <    BIO *file;
503 <
559 <    if (ServerInfo.rsa_private_key)
560 <    {
561 <      RSA_free(ServerInfo.rsa_private_key);
562 <      ServerInfo.rsa_private_key = NULL;
563 <    }
564 <
565 <    if (ServerInfo.rsa_private_key_file)
566 <    {
567 <      MyFree(ServerInfo.rsa_private_key_file);
568 <      ServerInfo.rsa_private_key_file = NULL;
569 <    }
570 <
571 <    DupString(ServerInfo.rsa_private_key_file, yylval.string);
572 <
573 <    if ((file = BIO_new_file(yylval.string, "r")) == NULL)
574 <    {
575 <      yyerror("File open failed, ignoring");
576 <      break;
577 <    }
578 <
579 <    ServerInfo.rsa_private_key = PEM_read_bio_RSAPrivateKey(file, NULL, 0, NULL);
580 <
581 <    BIO_set_close(file, BIO_CLOSE);
582 <    BIO_free(file);
583 <
584 <    if (ServerInfo.rsa_private_key == NULL)
585 <    {
586 <      yyerror("Couldn't extract key, ignoring");
587 <      break;
588 <    }
589 <
590 <    if (!RSA_check_key(ServerInfo.rsa_private_key))
591 <    {
592 <      RSA_free(ServerInfo.rsa_private_key);
593 <      ServerInfo.rsa_private_key = NULL;
594 <
595 <      yyerror("Invalid key, ignoring");
596 <      break;
597 <    }
598 <
599 <    /* require 2048 bit (256 byte) key */
600 <    if (RSA_size(ServerInfo.rsa_private_key) != 256)
601 <    {
602 <      RSA_free(ServerInfo.rsa_private_key);
603 <      ServerInfo.rsa_private_key = NULL;
604 <
605 <      yyerror("Not a 2048 bit key, ignoring");
606 <    }
502 >    xfree(ConfigServerInfo.ssl_cipher_list);
503 >    ConfigServerInfo.ssl_cipher_list = xstrdup(yylval.string);
504    }
608 #endif
505   };
506  
507 < serverinfo_ssl_dh_param_file: SSL_DH_PARAM_FILE '=' QSTRING ';'
507 > serverinfo_ssl_message_digest_algorithm: SSL_MESSAGE_DIGEST_ALGORITHM '=' QSTRING ';'
508   {
509 < /* TBD - XXX: error reporting */
614 < #ifdef HAVE_LIBCRYPTO
615 <  if (conf_parser_ctx.pass == 2 && ServerInfo.server_ctx)
509 >  if (conf_parser_ctx.pass == 2)
510    {
511 <    BIO *file = BIO_new_file(yylval.string, "r");
512 <
619 <    if (file)
620 <    {
621 <      DH *dh = PEM_read_bio_DHparams(file, NULL, NULL, NULL);
622 <
623 <      BIO_free(file);
624 <
625 <      if (dh)
626 <      {
627 <        if (DH_size(dh) < 128)
628 <          ilog(LOG_TYPE_IRCD, "Ignoring serverinfo::ssl_dh_param_file -- need at least a 1024 bit DH prime size");
629 <        else
630 <          SSL_CTX_set_tmp_dh(ServerInfo.server_ctx, dh);
631 <
632 <        DH_free(dh);
633 <      }
634 <    }
511 >    xfree(ConfigServerInfo.ssl_message_digest_algorithm);
512 >    ConfigServerInfo.ssl_message_digest_algorithm = xstrdup(yylval.string);
513    }
514 < #endif
637 < };
514 > }
515  
516 < serverinfo_ssl_cipher_list: T_SSL_CIPHER_LIST '=' QSTRING ';'
516 > serverinfo_ssl_dh_elliptic_curve: SSL_DH_ELLIPTIC_CURVE '=' QSTRING ';'
517   {
518 < #ifdef HAVE_LIBCRYPTO
519 <  if (conf_parser_ctx.pass == 2 && ServerInfo.server_ctx)
520 <    SSL_CTX_set_cipher_list(ServerInfo.server_ctx, yylval.string);
521 < #endif
518 >  if (conf_parser_ctx.pass == 2)
519 >  {
520 >    xfree(ConfigServerInfo.ssl_dh_elliptic_curve);
521 >    ConfigServerInfo.ssl_dh_elliptic_curve = xstrdup(yylval.string);
522 >  }
523   };
524  
525 < serverinfo_name: NAME '=' QSTRING ';'
525 > serverinfo_name: NAME '=' QSTRING ';'
526   {
527 <  /* this isn't rehashable */
528 <  if (conf_parser_ctx.pass == 2 && !ServerInfo.name)
527 >  /* This isn't rehashable */
528 >  if (conf_parser_ctx.pass == 2 && ConfigServerInfo.name == NULL)
529    {
530 <    if (valid_servname(yylval.string))
531 <      DupString(ServerInfo.name, yylval.string);
530 >    if (server_valid_name(yylval.string) == true)
531 >      ConfigServerInfo.name = xstrdup(yylval.string);
532      else
533      {
534 <      ilog(LOG_TYPE_IRCD, "Ignoring serverinfo::name -- invalid name. Aborting.");
535 <      exit(0);
534 >      conf_error_report("Ignoring serverinfo::name -- invalid name. Aborting.");
535 >      exit(EXIT_FAILURE);
536      }
537    }
538   };
539  
540 < serverinfo_sid: IRCD_SID '=' QSTRING ';'
540 > serverinfo_sid: IRCD_SID '=' QSTRING ';'
541   {
542 <  /* this isn't rehashable */
543 <  if (conf_parser_ctx.pass == 2 && !ServerInfo.sid)
542 >  /* This isn't rehashable */
543 >  if (conf_parser_ctx.pass == 2 && ConfigServerInfo.sid == NULL)
544    {
545      if (valid_sid(yylval.string))
546 <      DupString(ServerInfo.sid, yylval.string);
546 >      ConfigServerInfo.sid = xstrdup(yylval.string);
547      else
548      {
549 <      ilog(LOG_TYPE_IRCD, "Ignoring serverinfo::sid -- invalid SID. Aborting.");
550 <      exit(0);
549 >      conf_error_report("Ignoring serverinfo::sid -- invalid SID. Aborting.");
550 >      exit(EXIT_FAILURE);
551      }
552    }
553   };
# Line 678 | Line 556 | serverinfo_description: DESCRIPTION '='
556   {
557    if (conf_parser_ctx.pass == 2)
558    {
559 <    MyFree(ServerInfo.description);
560 <    DupString(ServerInfo.description,yylval.string);
559 >    xfree(ConfigServerInfo.description);
560 >    ConfigServerInfo.description = xstrdup(yylval.string);
561 >    strlcpy(me.info, ConfigServerInfo.description, sizeof(me.info));
562    }
563   };
564  
# Line 689 | Line 568 | serverinfo_network_name: NETWORK_NAME '=
568    {
569      char *p;
570  
571 <    if ((p = strchr(yylval.string, ' ')) != NULL)
572 <      p = '\0';
571 >    if ((p = strchr(yylval.string, ' ')))
572 >      *p = '\0';
573  
574 <    MyFree(ServerInfo.network_name);
575 <    DupString(ServerInfo.network_name, yylval.string);
574 >    xfree(ConfigServerInfo.network_name);
575 >    ConfigServerInfo.network_name = xstrdup(yylval.string);
576    }
577   };
578  
579   serverinfo_network_desc: NETWORK_DESC '=' QSTRING ';'
580   {
581 <  if (conf_parser_ctx.pass == 2)
581 >  if (conf_parser_ctx.pass != 2)
582 >    break;
583 >
584 >  xfree(ConfigServerInfo.network_desc);
585 >  ConfigServerInfo.network_desc = xstrdup(yylval.string);
586 > };
587 >
588 > serverinfo_default_max_clients: DEFAULT_MAX_CLIENTS '=' NUMBER ';'
589 > {
590 >  if (conf_parser_ctx.pass != 2)
591 >    break;
592 >
593 >  if ($3 < 1)
594    {
595 <    MyFree(ServerInfo.network_desc);
596 <    DupString(ServerInfo.network_desc, yylval.string);
595 >    conf_error_report("default_max_clients too low, setting to 1");
596 >    ConfigServerInfo.default_max_clients = 1;
597    }
598 +  else if ($3 > MAXCLIENTS_MAX)
599 +  {
600 +    char buf[IRCD_BUFSIZE] = "";
601 +
602 +    snprintf(buf, sizeof(buf), "default_max_clients too high, setting to %d", MAXCLIENTS_MAX);
603 +    conf_error_report(buf);
604 +
605 +    ConfigServerInfo.default_max_clients = MAXCLIENTS_MAX;
606 +  }
607 +  else
608 +    ConfigServerInfo.default_max_clients = $3;
609   };
610  
611 < serverinfo_vhost: VHOST '=' QSTRING ';'
611 > serverinfo_max_nick_length: MAX_NICK_LENGTH '=' NUMBER ';'
612   {
613 <  if (conf_parser_ctx.pass == 2 && *yylval.string != '*')
613 >  if (conf_parser_ctx.pass != 2)
614 >    break;
615 >
616 >  if ($3 < 9)
617    {
618 <    struct addrinfo hints, *res;
618 >    conf_error_report("max_nick_length too low, setting to 9");
619 >    ConfigServerInfo.max_nick_length = 9;
620 >  }
621 >  else if ($3 > NICKLEN)
622 >  {
623 >    char buf[IRCD_BUFSIZE] = "";
624  
625 <    memset(&hints, 0, sizeof(hints));
625 >    snprintf(buf, sizeof(buf), "max_nick_length too high, setting to %d", NICKLEN);
626 >    conf_error_report(buf);
627  
628 <    hints.ai_family   = AF_UNSPEC;
629 <    hints.ai_socktype = SOCK_STREAM;
630 <    hints.ai_flags    = AI_PASSIVE | AI_NUMERICHOST;
628 >    ConfigServerInfo.max_nick_length = NICKLEN;
629 >  }
630 >  else
631 >    ConfigServerInfo.max_nick_length = $3;
632 > };
633  
634 <    if (getaddrinfo(yylval.string, NULL, &hints, &res))
635 <      ilog(LOG_TYPE_IRCD, "Invalid netmask for server vhost(%s)", yylval.string);
636 <    else
637 <    {
725 <      assert(res != NULL);
634 > serverinfo_max_topic_length: MAX_TOPIC_LENGTH '=' NUMBER ';'
635 > {
636 >  if (conf_parser_ctx.pass != 2)
637 >    break;
638  
639 <      memcpy(&ServerInfo.ip, res->ai_addr, res->ai_addrlen);
640 <      ServerInfo.ip.ss.ss_family = res->ai_family;
641 <      ServerInfo.ip.ss_len = res->ai_addrlen;
642 <      freeaddrinfo(res);
639 >  if ($3 < 80)
640 >  {
641 >    conf_error_report("max_topic_length too low, setting to 80");
642 >    ConfigServerInfo.max_topic_length = 80;
643 >  }
644 >  else if ($3 > TOPICLEN)
645 >  {
646 >    char buf[IRCD_BUFSIZE] = "";
647  
648 <      ServerInfo.specific_ipv4_vhost = 1;
649 <    }
648 >    snprintf(buf, sizeof(buf), "max_topic_length too high, setting to %d", TOPICLEN);
649 >    conf_error_report(buf);
650 >
651 >    ConfigServerInfo.max_topic_length = TOPICLEN;
652    }
653 +  else
654 +    ConfigServerInfo.max_topic_length = $3;
655   };
656  
657 < serverinfo_vhost6: VHOST6 '=' QSTRING ';'
657 > serverinfo_hub: HUB '=' TBOOL ';'
658   {
659 < #ifdef IPV6
660 <  if (conf_parser_ctx.pass == 2 && *yylval.string != '*')
661 <  {
742 <    struct addrinfo hints, *res;
659 >  if (conf_parser_ctx.pass == 2)
660 >    ConfigServerInfo.hub = yylval.number;
661 > };
662  
744    memset(&hints, 0, sizeof(hints));
663  
664 <    hints.ai_family   = AF_UNSPEC;
665 <    hints.ai_socktype = SOCK_STREAM;
666 <    hints.ai_flags    = AI_PASSIVE | AI_NUMERICHOST;
664 > /***************************************************************************
665 > * admin {} section
666 > ***************************************************************************/
667 > admin_entry: ADMIN '{' admin_items '}' ';' ;
668  
669 <    if (getaddrinfo(yylval.string, NULL, &hints, &res))
670 <      ilog(LOG_TYPE_IRCD, "Invalid netmask for server vhost6(%s)", yylval.string);
671 <    else
672 <    {
673 <      assert(res != NULL);
669 > admin_items: admin_items admin_item | admin_item;
670 > admin_item:  admin_name |
671 >             admin_description |
672 >             admin_email |
673 >             error ';' ;
674  
675 <      memcpy(&ServerInfo.ip6, res->ai_addr, res->ai_addrlen);
676 <      ServerInfo.ip6.ss.ss_family = res->ai_family;
677 <      ServerInfo.ip6.ss_len = res->ai_addrlen;
678 <      freeaddrinfo(res);
675 > admin_name: NAME '=' QSTRING ';'
676 > {
677 >  if (conf_parser_ctx.pass != 2)
678 >    break;
679  
680 <      ServerInfo.specific_ipv6_vhost = 1;
681 <    }
763 <  }
764 < #endif
680 >  xfree(ConfigAdminInfo.name);
681 >  ConfigAdminInfo.name = xstrdup(yylval.string);
682   };
683  
684 < serverinfo_max_clients: T_MAX_CLIENTS '=' NUMBER ';'
684 > admin_email: EMAIL '=' QSTRING ';'
685 > {
686 >  if (conf_parser_ctx.pass != 2)
687 >    break;
688 >
689 >  xfree(ConfigAdminInfo.email);
690 >  ConfigAdminInfo.email = xstrdup(yylval.string);
691 > };
692 >
693 > admin_description: DESCRIPTION '=' QSTRING ';'
694 > {
695 >  if (conf_parser_ctx.pass != 2)
696 >    break;
697 >
698 >  xfree(ConfigAdminInfo.description);
699 >  ConfigAdminInfo.description = xstrdup(yylval.string);
700 > };
701 >
702 >
703 > /***************************************************************************
704 > * motd {} section
705 > ***************************************************************************/
706 > motd_entry: MOTD
707   {
708    if (conf_parser_ctx.pass == 2)
709 <  {
710 <    recalc_fdlimit(NULL);
709 >    reset_block_state();
710 > } '{' motd_items '}' ';'
711 > {
712 >  dlink_node *node = NULL;
713  
714 <    if ($3 < MAXCLIENTS_MIN)
715 <    {
716 <      char buf[IRCD_BUFSIZE];
717 <      ircsprintf(buf, "MAXCLIENTS too low, setting to %d", MAXCLIENTS_MIN);
718 <      yyerror(buf);
719 <    }
720 <    else if ($3 > MAXCLIENTS_MAX)
721 <    {
781 <      char buf[IRCD_BUFSIZE];
782 <      ircsprintf(buf, "MAXCLIENTS too high, setting to %d", MAXCLIENTS_MAX);
783 <      yyerror(buf);
784 <    }
785 <    else
786 <      ServerInfo.max_clients = $3;
787 <  }
714 >  if (conf_parser_ctx.pass != 2)
715 >    break;
716 >
717 >  if (!block_state.file.buf[0])
718 >    break;
719 >
720 >  DLINK_FOREACH(node, block_state.mask.list.head)
721 >    motd_add(node->data, block_state.file.buf);
722   };
723  
724 < serverinfo_hub: HUB '=' TBOOL ';'
724 > motd_items: motd_items motd_item | motd_item;
725 > motd_item:  motd_mask | motd_file | error ';' ;
726 >
727 > motd_mask: MASK '=' QSTRING ';'
728   {
729    if (conf_parser_ctx.pass == 2)
730 <    ServerInfo.hub = yylval.number;
730 >    dlinkAdd(xstrdup(yylval.string), make_dlink_node(), &block_state.mask.list);
731   };
732  
733 + motd_file: T_FILE '=' QSTRING ';'
734 + {
735 +  if (conf_parser_ctx.pass == 2)
736 +    strlcpy(block_state.file.buf, yylval.string, sizeof(block_state.file.buf));
737 + };
738 +
739 +
740   /***************************************************************************
741 < * admin section
741 > * pseudo {} section
742   ***************************************************************************/
743 < admin_entry: ADMIN  '{' admin_items '}' ';' ;
743 > pseudo_entry: T_PSEUDO
744 > {
745 >  if (conf_parser_ctx.pass == 2)
746 >    reset_block_state();
747 > } '{' pseudo_items '}' ';'
748 > {
749 >  if (conf_parser_ctx.pass != 2)
750 >    break;
751  
752 < admin_items: admin_items admin_item | admin_item;
753 < admin_item:  admin_name | admin_description |
754 <             admin_email | error ';' ;
752 >  if (!block_state.command.buf[0] ||
753 >      !block_state.name.buf[0] ||
754 >      !block_state.nick.buf[0] ||
755 >      !block_state.host.buf[0])
756 >    break;
757  
758 < admin_name: NAME '=' QSTRING ';'
758 >  pseudo_register(block_state.name.buf, block_state.nick.buf, block_state.host.buf,
759 >                  block_state.prepend.buf, block_state.command.buf);
760 > };
761 >
762 > pseudo_items: pseudo_items pseudo_item | pseudo_item;
763 > pseudo_item:  pseudo_command | pseudo_prepend | pseudo_name | pseudo_target | error ';' ;
764 >
765 > pseudo_command: T_COMMAND '=' QSTRING ';'
766   {
767    if (conf_parser_ctx.pass == 2)
768 <  {
809 <    MyFree(AdminInfo.name);
810 <    DupString(AdminInfo.name, yylval.string);
811 <  }
768 >    strlcpy(block_state.command.buf, yylval.string, sizeof(block_state.command.buf));
769   };
770  
771 < admin_email: EMAIL '=' QSTRING ';'
771 > pseudo_name: NAME '=' QSTRING ';'
772   {
773    if (conf_parser_ctx.pass == 2)
774 <  {
818 <    MyFree(AdminInfo.email);
819 <    DupString(AdminInfo.email, yylval.string);
820 <  }
774 >    strlcpy(block_state.name.buf, yylval.string, sizeof(block_state.name.buf));
775   };
776  
777 < admin_description: DESCRIPTION '=' QSTRING ';'
777 > pseudo_prepend: T_PREPEND '=' QSTRING ';'
778 > {
779 >  if (conf_parser_ctx.pass == 2)
780 >    strlcpy(block_state.prepend.buf, yylval.string, sizeof(block_state.prepend.buf));
781 > };
782 >
783 > pseudo_target: T_TARGET '=' QSTRING ';'
784   {
785    if (conf_parser_ctx.pass == 2)
786    {
787 <    MyFree(AdminInfo.description);
788 <    DupString(AdminInfo.description, yylval.string);
787 >    struct split_nuh_item nuh;
788 >
789 >    nuh.nuhmask  = yylval.string;
790 >    nuh.nickptr  = NULL;
791 >    nuh.userptr  = block_state.nick.buf;
792 >    nuh.hostptr  = block_state.host.buf;
793 >    nuh.nicksize = 0;
794 >    nuh.usersize = sizeof(block_state.nick.buf);
795 >    nuh.hostsize = sizeof(block_state.host.buf);
796 >
797 >    split_nuh(&nuh);
798    }
799   };
800  
801 +
802   /***************************************************************************
803 < *  section logging
803 > * log {} section
804   ***************************************************************************/
805   logging_entry:          T_LOG  '{' logging_items '}' ';' ;
806   logging_items:          logging_items logging_item | logging_item ;
807  
808 < logging_item:           logging_use_logging | logging_file_entry |
809 <                        error ';' ;
808 > logging_item:           logging_use_logging | logging_file_entry |
809 >                        error ';' ;
810  
811   logging_use_logging: USE_LOGGING '=' TBOOL ';'
812   {
813    if (conf_parser_ctx.pass == 2)
814 <    ConfigLoggingEntry.use_logging = yylval.number;
814 >    ConfigLog.use_logging = yylval.number;
815   };
816  
817   logging_file_entry:
818   {
819 <  lfile[0] = '\0';
820 <  ltype = 0;
851 <  lsize = 0;
819 >  if (conf_parser_ctx.pass == 2)
820 >    reset_block_state();
821   } T_FILE  '{' logging_file_items '}' ';'
822   {
823 <  if (conf_parser_ctx.pass == 2 && ltype > 0)
824 <    log_add_file(ltype, lsize, lfile);
823 >  if (conf_parser_ctx.pass != 2)
824 >    break;
825 >
826 >  if (block_state.type.value && block_state.file.buf[0])
827 >    log_set_file(block_state.type.value, block_state.size.value,
828 >                 block_state.file.buf);
829   };
830  
831   logging_file_items: logging_file_items logging_file_item |
# Line 863 | Line 836 | logging_file_item:  logging_file_name |
836  
837   logging_file_name: NAME '=' QSTRING ';'
838   {
839 <  strlcpy(lfile, yylval.string, sizeof(lfile));
839 >  if (conf_parser_ctx.pass != 2)
840 >    break;
841 >
842 >  strlcpy(block_state.file.buf, yylval.string, sizeof(block_state.file.buf));
843   }
844  
845   logging_file_size: T_SIZE '=' sizespec ';'
846   {
847 <  lsize = $3;
847 >  block_state.size.value = $3;
848   } | T_SIZE '=' T_UNLIMITED ';'
849   {
850 <  lsize = 0;
850 >  block_state.size.value = 0;
851   };
852  
853   logging_file_type: TYPE
854   {
855    if (conf_parser_ctx.pass == 2)
856 <    ltype = 0;
856 >    block_state.type.value = 0;
857   } '='  logging_file_type_items ';' ;
858  
859   logging_file_type_items: logging_file_type_items ',' logging_file_type_item | logging_file_type_item;
860   logging_file_type_item:  USER
861   {
862    if (conf_parser_ctx.pass == 2)
863 <    ltype = LOG_TYPE_USER;
863 >    block_state.type.value = LOG_TYPE_USER;
864   } | OPERATOR
865   {
866    if (conf_parser_ctx.pass == 2)
867 <    ltype = LOG_TYPE_OPER;
868 < } | GLINE
867 >    block_state.type.value = LOG_TYPE_OPER;
868 > } | XLINE
869 > {
870 >  if (conf_parser_ctx.pass == 2)
871 >    block_state.type.value = LOG_TYPE_XLINE;
872 > } | RESV
873   {
874    if (conf_parser_ctx.pass == 2)
875 <    ltype = LOG_TYPE_GLINE;
875 >    block_state.type.value = LOG_TYPE_RESV;
876   } | T_DLINE
877   {
878    if (conf_parser_ctx.pass == 2)
879 <    ltype = LOG_TYPE_DLINE;
879 >    block_state.type.value = LOG_TYPE_DLINE;
880   } | KLINE
881   {
882    if (conf_parser_ctx.pass == 2)
883 <    ltype = LOG_TYPE_KLINE;
883 >    block_state.type.value = LOG_TYPE_KLINE;
884   } | KILL
885   {
886    if (conf_parser_ctx.pass == 2)
887 <    ltype = LOG_TYPE_KILL;
887 >    block_state.type.value = LOG_TYPE_KILL;
888   } | T_DEBUG
889   {
890    if (conf_parser_ctx.pass == 2)
891 <    ltype = LOG_TYPE_DEBUG;
891 >    block_state.type.value = LOG_TYPE_DEBUG;
892   };
893  
894  
895   /***************************************************************************
896 < * section oper
896 > * operator {} section
897   ***************************************************************************/
898 < oper_entry: OPERATOR
898 > oper_entry: OPERATOR
899   {
900 <  if (conf_parser_ctx.pass == 2)
901 <  {
902 <    yy_conf = make_conf_item(OPER_TYPE);
903 <    yy_aconf = map_to_conf(yy_conf);
904 <    SetConfEncrypted(yy_aconf); /* Yes, the default is encrypted */
925 <  }
926 <  else
927 <  {
928 <    MyFree(class_name);
929 <    class_name = NULL;
930 <  }
900 >  if (conf_parser_ctx.pass != 2)
901 >    break;
902 >
903 >  reset_block_state();
904 >  block_state.flags.value |= CONF_FLAGS_ENCRYPTED;
905   } '{' oper_items '}' ';'
906   {
907 <  if (conf_parser_ctx.pass == 2)
934 <  {
935 <    struct CollectItem *yy_tmp;
936 <    dlink_node *ptr;
937 <    dlink_node *next_ptr;
907 >  dlink_node *node = NULL;
908  
909 <    conf_add_class_to_conf(yy_conf, class_name);
909 >  if (conf_parser_ctx.pass != 2)
910 >    break;
911  
912 <    /* Now, make sure there is a copy of the "base" given oper
913 <     * block in each of the collected copies
943 <     */
912 >  if (!block_state.name.buf[0])
913 >    break;
914  
915 <    DLINK_FOREACH_SAFE(ptr, next_ptr, col_conf_list.head)
916 <    {
947 <      struct AccessItem *new_aconf;
948 <      struct ConfItem *new_conf;
949 <      yy_tmp = ptr->data;
950 <
951 <      new_conf = make_conf_item(OPER_TYPE);
952 <      new_aconf = (struct AccessItem *)map_to_conf(new_conf);
953 <
954 <      new_aconf->flags = yy_aconf->flags;
955 <
956 <      if (yy_conf->name != NULL)
957 <        DupString(new_conf->name, yy_conf->name);
958 <      if (yy_tmp->user != NULL)
959 <        DupString(new_aconf->user, yy_tmp->user);
960 <      else
961 <        DupString(new_aconf->user, "*");
962 <      if (yy_tmp->host != NULL)
963 <        DupString(new_aconf->host, yy_tmp->host);
964 <      else
965 <        DupString(new_aconf->host, "*");
966 <
967 <      new_aconf->type = parse_netmask(new_aconf->host, &new_aconf->ipnum,
968 <                                     &new_aconf->bits);
969 <
970 <      conf_add_class_to_conf(new_conf, class_name);
971 <      if (yy_aconf->passwd != NULL)
972 <        DupString(new_aconf->passwd, yy_aconf->passwd);
973 <
974 <      new_aconf->port = yy_aconf->port;
975 < #ifdef HAVE_LIBCRYPTO
976 <      if (yy_aconf->rsa_public_key_file != NULL)
977 <      {
978 <        BIO *file;
979 <
980 <        DupString(new_aconf->rsa_public_key_file,
981 <                  yy_aconf->rsa_public_key_file);
982 <
983 <        file = BIO_new_file(yy_aconf->rsa_public_key_file, "r");
984 <        new_aconf->rsa_public_key = (RSA *)PEM_read_bio_RSA_PUBKEY(file,
985 <                                                           NULL, 0, NULL);
986 <        BIO_set_close(file, BIO_CLOSE);
987 <        BIO_free(file);
988 <      }
989 < #endif
915 >  if (!block_state.rpass.buf[0])
916 >    break;
917  
918 < #ifdef HAVE_LIBCRYPTO
919 <      if (yy_tmp->name && (yy_tmp->passwd || yy_aconf->rsa_public_key)
920 <          && yy_tmp->host)
921 < #else
995 <      if (yy_tmp->name && yy_tmp->passwd && yy_tmp->host)
996 < #endif
997 <      {
998 <        conf_add_class_to_conf(new_conf, class_name);
999 <        if (yy_tmp->name != NULL)
1000 <          DupString(new_conf->name, yy_tmp->name);
1001 <      }
918 >  DLINK_FOREACH(node, block_state.mask.list.head)
919 >  {
920 >    struct split_nuh_item nuh;
921 >    char *s = node->data;
922  
923 <      dlinkDelete(&yy_tmp->node, &col_conf_list);
924 <      free_collect_item(yy_tmp);
1005 <    }
923 >    if (EmptyString(s))
924 >      continue;
925  
926 <    yy_conf = NULL;
927 <    yy_aconf = NULL;
926 >    nuh.nuhmask  = s;
927 >    nuh.nickptr  = NULL;
928 >    nuh.userptr  = block_state.user.buf;
929 >    nuh.hostptr  = block_state.host.buf;
930  
931 +    nuh.nicksize = 0;
932 +    nuh.usersize = sizeof(block_state.user.buf);
933 +    nuh.hostsize = sizeof(block_state.host.buf);
934 +
935 +    split_nuh(&nuh);
936  
937 <    MyFree(class_name);
938 <    class_name = NULL;
937 >    struct MaskItem *conf = conf_make(CONF_OPER);
938 >    conf->addr = xcalloc(sizeof(*conf->addr));
939 >    conf->name = xstrdup(block_state.name.buf);
940 >    conf->user = xstrdup(block_state.user.buf);
941 >    conf->host = xstrdup(block_state.host.buf);
942 >
943 >    if (block_state.cert.buf[0])
944 >      conf->certfp = xstrdup(block_state.cert.buf);
945 >
946 >    if (block_state.rpass.buf[0])
947 >      conf->passwd = xstrdup(block_state.rpass.buf);
948 >
949 >    if (block_state.whois.buf[0])
950 >      conf->whois = xstrdup(block_state.whois.buf);
951 >
952 >    conf->flags = block_state.flags.value;
953 >    conf->modes = block_state.modes.value;
954 >    conf->port  = block_state.port.value;
955 >    conf->htype = parse_netmask(conf->host, conf->addr, &conf->bits);
956 >
957 >    conf_add_class_to_conf(conf, block_state.class.buf);
958    }
959 < };
959 > };
960  
961   oper_items:     oper_items oper_item | oper_item;
962 < oper_item:      oper_name | oper_user | oper_password |
963 <                oper_umodes | oper_class | oper_encrypted |
964 <                oper_rsa_public_key_file | oper_flags | error ';' ;
962 > oper_item:      oper_name |
963 >                oper_user |
964 >                oper_password |
965 >                oper_whois |
966 >                oper_umodes |
967 >                oper_class |
968 >                oper_encrypted |
969 >                oper_ssl_certificate_fingerprint |
970 >                oper_ssl_connection_required |
971 >                oper_flags |
972 >                error ';' ;
973  
974   oper_name: NAME '=' QSTRING ';'
975   {
976    if (conf_parser_ctx.pass == 2)
977 <  {
1025 <    if (strlen(yylval.string) > OPERNICKLEN)
1026 <      yylval.string[OPERNICKLEN] = '\0';
1027 <
1028 <    MyFree(yy_conf->name);
1029 <    DupString(yy_conf->name, yylval.string);
1030 <  }
977 >    strlcpy(block_state.name.buf, yylval.string, sizeof(block_state.name.buf));
978   };
979  
980   oper_user: USER '=' QSTRING ';'
981   {
982    if (conf_parser_ctx.pass == 2)
983 <  {
1037 <    struct split_nuh_item nuh;
1038 <
1039 <    nuh.nuhmask  = yylval.string;
1040 <    nuh.nickptr  = NULL;
1041 <    nuh.userptr  = userbuf;
1042 <    nuh.hostptr  = hostbuf;
1043 <
1044 <    nuh.nicksize = 0;
1045 <    nuh.usersize = sizeof(userbuf);
1046 <    nuh.hostsize = sizeof(hostbuf);
1047 <
1048 <    split_nuh(&nuh);
1049 <
1050 <    if (yy_aconf->user == NULL)
1051 <    {
1052 <      DupString(yy_aconf->user, userbuf);
1053 <      DupString(yy_aconf->host, hostbuf);
1054 <
1055 <      yy_aconf->type = parse_netmask(yy_aconf->host, &yy_aconf->ipnum,
1056 <                                    &yy_aconf->bits);
1057 <    }
1058 <    else
1059 <    {
1060 <      struct CollectItem *yy_tmp = MyMalloc(sizeof(struct CollectItem));
1061 <
1062 <      DupString(yy_tmp->user, userbuf);
1063 <      DupString(yy_tmp->host, hostbuf);
1064 <
1065 <      dlinkAdd(yy_tmp, &yy_tmp->node, &col_conf_list);
1066 <    }
1067 <  }
983 >    dlinkAdd(xstrdup(yylval.string), make_dlink_node(), &block_state.mask.list);
984   };
985  
986   oper_password: PASSWORD '=' QSTRING ';'
987   {
988    if (conf_parser_ctx.pass == 2)
989 <  {
1074 <    if (yy_aconf->passwd != NULL)
1075 <      memset(yy_aconf->passwd, 0, strlen(yy_aconf->passwd));
1076 <
1077 <    MyFree(yy_aconf->passwd);
1078 <    DupString(yy_aconf->passwd, yylval.string);
1079 <  }
989 >    strlcpy(block_state.rpass.buf, yylval.string, sizeof(block_state.rpass.buf));
990   };
991  
992 < oper_encrypted: ENCRYPTED '=' TBOOL ';'
992 > oper_whois: WHOIS '=' QSTRING ';'
993   {
994    if (conf_parser_ctx.pass == 2)
995 <  {
1086 <    if (yylval.number)
1087 <      SetConfEncrypted(yy_aconf);
1088 <    else
1089 <      ClearConfEncrypted(yy_aconf);
1090 <  }
995 >    strlcpy(block_state.whois.buf, yylval.string, sizeof(block_state.whois.buf));
996   };
997  
998 < oper_rsa_public_key_file: RSA_PUBLIC_KEY_FILE '=' QSTRING ';'
998 > oper_encrypted: ENCRYPTED '=' TBOOL ';'
999   {
1000 < #ifdef HAVE_LIBCRYPTO
1001 <  if (conf_parser_ctx.pass == 2)
1097 <  {
1098 <    BIO *file;
1099 <
1100 <    if (yy_aconf->rsa_public_key != NULL)
1101 <    {
1102 <      RSA_free(yy_aconf->rsa_public_key);
1103 <      yy_aconf->rsa_public_key = NULL;
1104 <    }
1000 >  if (conf_parser_ctx.pass != 2)
1001 >    break;
1002  
1003 <    if (yy_aconf->rsa_public_key_file != NULL)
1004 <    {
1005 <      MyFree(yy_aconf->rsa_public_key_file);
1006 <      yy_aconf->rsa_public_key_file = NULL;
1007 <    }
1111 <
1112 <    DupString(yy_aconf->rsa_public_key_file, yylval.string);
1113 <    file = BIO_new_file(yylval.string, "r");
1114 <
1115 <    if (file == NULL)
1116 <    {
1117 <      yyerror("Ignoring rsa_public_key_file -- file doesn't exist");
1118 <      break;
1119 <    }
1003 >  if (yylval.number)
1004 >    block_state.flags.value |= CONF_FLAGS_ENCRYPTED;
1005 >  else
1006 >    block_state.flags.value &= ~CONF_FLAGS_ENCRYPTED;
1007 > };
1008  
1009 <    yy_aconf->rsa_public_key = (RSA *)PEM_read_bio_RSA_PUBKEY(file, NULL, 0, NULL);
1009 > oper_ssl_certificate_fingerprint: SSL_CERTIFICATE_FINGERPRINT '=' QSTRING ';'
1010 > {
1011 >  if (conf_parser_ctx.pass == 2)
1012 >    strlcpy(block_state.cert.buf, yylval.string, sizeof(block_state.cert.buf));
1013 > };
1014  
1015 <    if (yy_aconf->rsa_public_key == NULL)
1016 <    {
1017 <      yyerror("Ignoring rsa_public_key_file -- Key invalid; check key syntax.");
1018 <      break;
1127 <    }
1015 > oper_ssl_connection_required: SSL_CONNECTION_REQUIRED '=' TBOOL ';'
1016 > {
1017 >  if (conf_parser_ctx.pass != 2)
1018 >    break;
1019  
1020 <    BIO_set_close(file, BIO_CLOSE);
1021 <    BIO_free(file);
1022 <  }
1023 < #endif /* HAVE_LIBCRYPTO */
1020 >  if (yylval.number)
1021 >    block_state.flags.value |= CONF_FLAGS_SSL;
1022 >  else
1023 >    block_state.flags.value &= ~CONF_FLAGS_SSL;
1024   };
1025  
1026   oper_class: CLASS '=' QSTRING ';'
1027   {
1028    if (conf_parser_ctx.pass == 2)
1029 <  {
1139 <    MyFree(class_name);
1140 <    DupString(class_name, yylval.string);
1141 <  }
1029 >    strlcpy(block_state.class.buf, yylval.string, sizeof(block_state.class.buf));
1030   };
1031  
1032   oper_umodes: T_UMODES
1033   {
1034    if (conf_parser_ctx.pass == 2)
1035 <    yy_aconf->modes = 0;
1035 >    block_state.modes.value = 0;
1036   } '='  oper_umodes_items ';' ;
1037  
1038   oper_umodes_items: oper_umodes_items ',' oper_umodes_item | oper_umodes_item;
1039   oper_umodes_item:  T_BOTS
1040   {
1041    if (conf_parser_ctx.pass == 2)
1042 <    yy_aconf->modes |= UMODE_BOTS;
1042 >    block_state.modes.value |= UMODE_BOTS;
1043   } | T_CCONN
1044   {
1045    if (conf_parser_ctx.pass == 2)
1046 <    yy_aconf->modes |= UMODE_CCONN;
1159 < } | T_CCONN_FULL
1160 < {
1161 <  if (conf_parser_ctx.pass == 2)
1162 <    yy_aconf->modes |= UMODE_CCONN_FULL;
1046 >    block_state.modes.value |= UMODE_CCONN;
1047   } | T_DEAF
1048   {
1049    if (conf_parser_ctx.pass == 2)
1050 <    yy_aconf->modes |= UMODE_DEAF;
1050 >    block_state.modes.value |= UMODE_DEAF;
1051   } | T_DEBUG
1052   {
1053    if (conf_parser_ctx.pass == 2)
1054 <    yy_aconf->modes |= UMODE_DEBUG;
1054 >    block_state.modes.value |= UMODE_DEBUG;
1055   } | T_FULL
1056   {
1057    if (conf_parser_ctx.pass == 2)
1058 <    yy_aconf->modes |= UMODE_FULL;
1058 >    block_state.modes.value |= UMODE_FULL;
1059   } | HIDDEN
1060   {
1061    if (conf_parser_ctx.pass == 2)
1062 <    yy_aconf->modes |= UMODE_HIDDEN;
1062 >    block_state.modes.value |= UMODE_HIDDEN;
1063 > } | HIDE_CHANS
1064 > {
1065 >  if (conf_parser_ctx.pass == 2)
1066 >    block_state.modes.value |= UMODE_HIDECHANS;
1067 > } | HIDE_IDLE
1068 > {
1069 >  if (conf_parser_ctx.pass == 2)
1070 >    block_state.modes.value |= UMODE_HIDEIDLE;
1071   } | T_SKILL
1072   {
1073    if (conf_parser_ctx.pass == 2)
1074 <    yy_aconf->modes |= UMODE_SKILL;
1074 >    block_state.modes.value |= UMODE_SKILL;
1075   } | T_NCHANGE
1076   {
1077    if (conf_parser_ctx.pass == 2)
1078 <    yy_aconf->modes |= UMODE_NCHANGE;
1078 >    block_state.modes.value |= UMODE_NCHANGE;
1079   } | T_REJ
1080   {
1081    if (conf_parser_ctx.pass == 2)
1082 <    yy_aconf->modes |= UMODE_REJ;
1082 >    block_state.modes.value |= UMODE_REJ;
1083   } | T_UNAUTH
1084   {
1085    if (conf_parser_ctx.pass == 2)
1086 <    yy_aconf->modes |= UMODE_UNAUTH;
1086 >    block_state.modes.value |= UMODE_UNAUTH;
1087   } | T_SPY
1088   {
1089    if (conf_parser_ctx.pass == 2)
1090 <    yy_aconf->modes |= UMODE_SPY;
1090 >    block_state.modes.value |= UMODE_SPY;
1091   } | T_EXTERNAL
1092   {
1093    if (conf_parser_ctx.pass == 2)
1094 <    yy_aconf->modes |= UMODE_EXTERNAL;
1203 < } | T_OPERWALL
1204 < {
1205 <  if (conf_parser_ctx.pass == 2)
1206 <    yy_aconf->modes |= UMODE_OPERWALL;
1094 >    block_state.modes.value |= UMODE_EXTERNAL;
1095   } | T_SERVNOTICE
1096   {
1097    if (conf_parser_ctx.pass == 2)
1098 <    yy_aconf->modes |= UMODE_SERVNOTICE;
1098 >    block_state.modes.value |= UMODE_SERVNOTICE;
1099   } | T_INVISIBLE
1100   {
1101    if (conf_parser_ctx.pass == 2)
1102 <    yy_aconf->modes |= UMODE_INVISIBLE;
1102 >    block_state.modes.value |= UMODE_INVISIBLE;
1103   } | T_WALLOP
1104   {
1105    if (conf_parser_ctx.pass == 2)
1106 <    yy_aconf->modes |= UMODE_WALLOP;
1106 >    block_state.modes.value |= UMODE_WALLOP;
1107   } | T_SOFTCALLERID
1108   {
1109    if (conf_parser_ctx.pass == 2)
1110 <    yy_aconf->modes |= UMODE_SOFTCALLERID;
1110 >    block_state.modes.value |= UMODE_SOFTCALLERID;
1111   } | T_CALLERID
1112   {
1113    if (conf_parser_ctx.pass == 2)
1114 <    yy_aconf->modes |= UMODE_CALLERID;
1114 >    block_state.modes.value |= UMODE_CALLERID;
1115   } | T_LOCOPS
1116   {
1117    if (conf_parser_ctx.pass == 2)
1118 <    yy_aconf->modes |= UMODE_LOCOPS;
1118 >    block_state.modes.value |= UMODE_LOCOPS;
1119 > } | T_NONONREG
1120 > {
1121 >  if (conf_parser_ctx.pass == 2)
1122 >    block_state.modes.value |= UMODE_REGONLY;
1123 > } | T_FARCONNECT
1124 > {
1125 >  if (conf_parser_ctx.pass == 2)
1126 >    block_state.modes.value |= UMODE_FARCONNECT;
1127 > } | EXPIRATION
1128 > {
1129 >  if (conf_parser_ctx.pass == 2)
1130 >    block_state.modes.value |= UMODE_EXPIRATION;
1131   };
1132  
1133   oper_flags: IRCD_FLAGS
1134   {
1135    if (conf_parser_ctx.pass == 2)
1136 <    yy_aconf->port = 0;
1136 >    block_state.port.value = 0;
1137   } '='  oper_flags_items ';';
1138  
1139   oper_flags_items: oper_flags_items ',' oper_flags_item | oper_flags_item;
1140 < oper_flags_item: GLOBAL_KILL
1140 > oper_flags_item: KILL ':' REMOTE
1141 > {
1142 >  if (conf_parser_ctx.pass == 2)
1143 >    block_state.port.value |= OPER_FLAG_KILL_REMOTE;
1144 > } | KILL
1145 > {
1146 >  if (conf_parser_ctx.pass == 2)
1147 >    block_state.port.value |= OPER_FLAG_KILL;
1148 > } | CONNECT ':' REMOTE
1149 > {
1150 >  if (conf_parser_ctx.pass == 2)
1151 >    block_state.port.value |= OPER_FLAG_CONNECT_REMOTE;
1152 > } | CONNECT
1153   {
1154    if (conf_parser_ctx.pass == 2)
1155 <    yy_aconf->port |= OPER_FLAG_GLOBAL_KILL;
1156 < } | REMOTE
1155 >    block_state.port.value |= OPER_FLAG_CONNECT;
1156 > } | SQUIT ':' REMOTE
1157   {
1158    if (conf_parser_ctx.pass == 2)
1159 <    yy_aconf->port |= OPER_FLAG_REMOTE;
1159 >    block_state.port.value |= OPER_FLAG_SQUIT_REMOTE;
1160 > } | SQUIT
1161 > {
1162 >  if (conf_parser_ctx.pass == 2)
1163 >    block_state.port.value |= OPER_FLAG_SQUIT;
1164   } | KLINE
1165   {
1166    if (conf_parser_ctx.pass == 2)
1167 <    yy_aconf->port |= OPER_FLAG_K;
1167 >    block_state.port.value |= OPER_FLAG_KLINE;
1168   } | UNKLINE
1169   {
1170    if (conf_parser_ctx.pass == 2)
1171 <    yy_aconf->port |= OPER_FLAG_UNKLINE;
1171 >    block_state.port.value |= OPER_FLAG_UNKLINE;
1172   } | T_DLINE
1173   {
1174    if (conf_parser_ctx.pass == 2)
1175 <    yy_aconf->port |= OPER_FLAG_DLINE;
1175 >    block_state.port.value |= OPER_FLAG_DLINE;
1176   } | T_UNDLINE
1177   {
1178    if (conf_parser_ctx.pass == 2)
1179 <    yy_aconf->port |= OPER_FLAG_UNDLINE;
1179 >    block_state.port.value |= OPER_FLAG_UNDLINE;
1180   } | XLINE
1181   {
1182    if (conf_parser_ctx.pass == 2)
1183 <    yy_aconf->port |= OPER_FLAG_X;
1184 < } | GLINE
1183 >    block_state.port.value |= OPER_FLAG_XLINE;
1184 > } | T_UNXLINE
1185   {
1186    if (conf_parser_ctx.pass == 2)
1187 <    yy_aconf->port |= OPER_FLAG_GLINE;
1187 >    block_state.port.value |= OPER_FLAG_UNXLINE;
1188   } | DIE
1189   {
1190    if (conf_parser_ctx.pass == 2)
1191 <    yy_aconf->port |= OPER_FLAG_DIE;
1191 >    block_state.port.value |= OPER_FLAG_DIE;
1192   } | T_RESTART
1193   {
1194    if (conf_parser_ctx.pass == 2)
1195 <    yy_aconf->port |= OPER_FLAG_RESTART;
1195 >    block_state.port.value |= OPER_FLAG_RESTART;
1196 > } | REHASH ':' REMOTE
1197 > {
1198 >  if (conf_parser_ctx.pass == 2)
1199 >    block_state.port.value |= OPER_FLAG_REHASH_REMOTE;
1200   } | REHASH
1201   {
1202    if (conf_parser_ctx.pass == 2)
1203 <    yy_aconf->port |= OPER_FLAG_REHASH;
1203 >    block_state.port.value |= OPER_FLAG_REHASH;
1204   } | ADMIN
1205   {
1206    if (conf_parser_ctx.pass == 2)
1207 <    yy_aconf->port |= OPER_FLAG_ADMIN;
1208 < } | NICK_CHANGES
1207 >    block_state.port.value |= OPER_FLAG_ADMIN;
1208 > } | T_GLOBOPS
1209   {
1210    if (conf_parser_ctx.pass == 2)
1211 <    yy_aconf->port |= OPER_FLAG_N;
1212 < } | T_OPERWALL
1211 >    block_state.port.value |= OPER_FLAG_GLOBOPS;
1212 > } | T_WALLOPS
1213   {
1214    if (conf_parser_ctx.pass == 2)
1215 <    yy_aconf->port |= OPER_FLAG_OPERWALL;
1216 < } | T_GLOBOPS
1215 >    block_state.port.value |= OPER_FLAG_WALLOPS;
1216 > } | T_LOCOPS
1217   {
1218    if (conf_parser_ctx.pass == 2)
1219 <    yy_aconf->port |= OPER_FLAG_GLOBOPS;
1220 < } | OPER_SPY_T
1219 >    block_state.port.value |= OPER_FLAG_LOCOPS;
1220 > } | REMOTEBAN
1221   {
1222    if (conf_parser_ctx.pass == 2)
1223 <    yy_aconf->port |= OPER_FLAG_OPER_SPY;
1224 < } | REMOTEBAN
1223 >    block_state.port.value |= OPER_FLAG_REMOTEBAN;
1224 > } | T_SET
1225   {
1226    if (conf_parser_ctx.pass == 2)
1227 <    yy_aconf->port |= OPER_FLAG_REMOTEBAN;
1227 >    block_state.port.value |= OPER_FLAG_SET;
1228   } | MODULE
1229   {
1230    if (conf_parser_ctx.pass == 2)
1231 <    yy_aconf->port |= OPER_FLAG_MODULE;
1231 >    block_state.port.value |= OPER_FLAG_MODULE;
1232 > } | T_OPME
1233 > {
1234 >  if (conf_parser_ctx.pass == 2)
1235 >    block_state.port.value |= OPER_FLAG_OPME;
1236 > } | NICK ':' RESV
1237 > {
1238 >  if (conf_parser_ctx.pass == 2)
1239 >    block_state.port.value |= OPER_FLAG_NICK_RESV;
1240 > } | JOIN ':' RESV
1241 > {
1242 >  if (conf_parser_ctx.pass == 2)
1243 >    block_state.port.value |= OPER_FLAG_JOIN_RESV;
1244 > } | RESV
1245 > {
1246 >  if (conf_parser_ctx.pass == 2)
1247 >    block_state.port.value |= OPER_FLAG_RESV;
1248 > } | T_UNRESV
1249 > {
1250 >  if (conf_parser_ctx.pass == 2)
1251 >    block_state.port.value |= OPER_FLAG_UNRESV;
1252 > } | CLOSE
1253 > {
1254 >  if (conf_parser_ctx.pass == 2)
1255 >    block_state.port.value |= OPER_FLAG_CLOSE;
1256   };
1257  
1258  
1259   /***************************************************************************
1260 < *  section class
1260 > * class {} section
1261   ***************************************************************************/
1262   class_entry: CLASS
1263   {
1264 <  if (conf_parser_ctx.pass == 1)
1265 <  {
1266 <    yy_conf = make_conf_item(CLASS_TYPE);
1267 <    yy_class = map_to_conf(yy_conf);
1268 <  }
1264 >  if (conf_parser_ctx.pass != 1)
1265 >    break;
1266 >
1267 >  reset_block_state();
1268 >
1269 >  block_state.ping_freq.value = DEFAULT_PINGFREQUENCY;
1270 >  block_state.con_freq.value  = DEFAULT_CONNECTFREQUENCY;
1271 >  block_state.max_total.value = MAXIMUM_LINKS_DEFAULT;
1272 >  block_state.max_sendq.value = DEFAULT_SENDQ;
1273 >  block_state.max_recvq.value = DEFAULT_RECVQ;
1274   } '{' class_items '}' ';'
1275   {
1276 <  if (conf_parser_ctx.pass == 1)
1277 <  {
1329 <    struct ConfItem *cconf = NULL;
1330 <    struct ClassItem *class = NULL;
1276 >  if (conf_parser_ctx.pass != 1)
1277 >    break;
1278  
1279 <    if (yy_class_name == NULL)
1280 <      delete_conf_item(yy_conf);
1334 <    else
1335 <    {
1336 <      cconf = find_exact_name_conf(CLASS_TYPE, NULL, yy_class_name, NULL, NULL);
1279 >  if (!block_state.class.buf[0])
1280 >    break;
1281  
1282 <      if (cconf != NULL)                /* The class existed already */
1283 <      {
1284 <        int user_count = 0;
1285 <
1286 <        rebuild_cidr_class(cconf, yy_class);
1287 <
1288 <        class = map_to_conf(cconf);
1289 <
1290 <        user_count = class->curr_user_count;
1291 <        memcpy(class, yy_class, sizeof(*class));
1292 <        class->curr_user_count = user_count;
1293 <        class->active = 1;
1294 <
1295 <        delete_conf_item(yy_conf);
1296 <
1297 <        MyFree(cconf->name);            /* Allows case change of class name */
1298 <        cconf->name = yy_class_name;
1299 <      }
1300 <      else      /* Brand new class */
1301 <      {
1302 <        MyFree(yy_conf->name);          /* just in case it was allocated */
1303 <        yy_conf->name = yy_class_name;
1304 <        yy_class->active = 1;
1305 <      }
1306 <    }
1282 >  struct ClassItem *class = class_find(block_state.class.buf, false);
1283 >  if (class == NULL)
1284 >    class = class_make();
1285 >
1286 >  class->active = true;
1287 >  xfree(class->name);
1288 >  class->name = xstrdup(block_state.class.buf);
1289 >  class->ping_freq = block_state.ping_freq.value;
1290 >  class->max_perip_local = block_state.max_perip_local.value;
1291 >  class->max_perip_global = block_state.max_perip_global.value;
1292 >  class->con_freq = block_state.con_freq.value;
1293 >  class->max_total = block_state.max_total.value;
1294 >  class->max_sendq = block_state.max_sendq.value;
1295 >  class->max_recvq = block_state.max_recvq.value;
1296 >  class->max_channels = block_state.max_channels.value;
1297 >
1298 >  if (block_state.min_idle.value > block_state.max_idle.value)
1299 >  {
1300 >    block_state.min_idle.value = 0;
1301 >    block_state.max_idle.value = 0;
1302 >    block_state.flags.value &= ~CLASS_FLAGS_FAKE_IDLE;
1303 >  }
1304 >
1305 >  class->flags = block_state.flags.value;
1306 >  class->min_idle = block_state.min_idle.value;
1307 >  class->max_idle = block_state.max_idle.value;
1308 >
1309 >  bool diff = (class->cidr_bitlen_ipv4 != block_state.cidr_bitlen_ipv4.value ||
1310 >               class->cidr_bitlen_ipv6 != block_state.cidr_bitlen_ipv6.value);
1311 >  class->cidr_bitlen_ipv4 = block_state.cidr_bitlen_ipv4.value;
1312 >  class->cidr_bitlen_ipv6 = block_state.cidr_bitlen_ipv6.value;
1313 >  class->number_per_cidr = block_state.number_per_cidr.value;
1314  
1315 <    yy_class_name = NULL;
1316 <  }
1315 >  if (diff)
1316 >    class_ip_limit_rebuild(class);
1317   };
1318  
1319   class_items:    class_items class_item | class_item;
1320   class_item:     class_name |
1321 <                class_cidr_bitlen_ipv4 | class_cidr_bitlen_ipv6 |
1321 >                class_cidr_bitlen_ipv4 |
1322 >                class_cidr_bitlen_ipv6 |
1323                  class_ping_time |
1324 <                class_ping_warning |
1325 <                class_number_per_cidr |
1326 <                class_number_per_ip |
1324 >                class_number_per_cidr |
1325 >                class_number_per_ip_local |
1326 >                class_number_per_ip_global |
1327                  class_connectfreq |
1328 +                class_max_channels |
1329                  class_max_number |
1377                class_max_global |
1378                class_max_local |
1379                class_max_ident |
1330                  class_sendq |
1331 <                error ';' ;
1331 >                class_recvq |
1332 >                class_min_idle |
1333 >                class_max_idle |
1334 >                class_flags |
1335 >                error ';' ;
1336  
1337 < class_name: NAME '=' QSTRING ';'
1337 > class_name: NAME '=' QSTRING ';'
1338   {
1339    if (conf_parser_ctx.pass == 1)
1340 <  {
1387 <    MyFree(yy_class_name);
1388 <    DupString(yy_class_name, yylval.string);
1389 <  }
1340 >    strlcpy(block_state.class.buf, yylval.string, sizeof(block_state.class.buf));
1341   };
1342  
1343   class_ping_time: PING_TIME '=' timespec ';'
1344   {
1345    if (conf_parser_ctx.pass == 1)
1346 <    PingFreq(yy_class) = $3;
1346 >    block_state.ping_freq.value = $3;
1347   };
1348  
1349 < class_ping_warning: PING_WARNING '=' timespec ';'
1349 > class_number_per_ip_local: NUMBER_PER_IP_LOCAL '=' NUMBER ';'
1350   {
1351    if (conf_parser_ctx.pass == 1)
1352 <    PingWarning(yy_class) = $3;
1352 >    block_state.max_perip_local.value = $3;
1353   };
1354  
1355 < class_number_per_ip: NUMBER_PER_IP '=' NUMBER ';'
1355 > class_number_per_ip_global: NUMBER_PER_IP_GLOBAL '=' NUMBER ';'
1356   {
1357    if (conf_parser_ctx.pass == 1)
1358 <    MaxPerIp(yy_class) = $3;
1358 >    block_state.max_perip_global.value = $3;
1359   };
1360  
1361   class_connectfreq: CONNECTFREQ '=' timespec ';'
1362   {
1363    if (conf_parser_ctx.pass == 1)
1364 <    ConFreq(yy_class) = $3;
1364 >    block_state.con_freq.value = $3;
1365   };
1366  
1367 < class_max_number: MAX_NUMBER '=' NUMBER ';'
1367 > class_max_channels: MAX_CHANNELS '=' NUMBER ';'
1368   {
1369    if (conf_parser_ctx.pass == 1)
1370 <    MaxTotal(yy_class) = $3;
1370 >    block_state.max_channels.value = $3;
1371   };
1372  
1373 < class_max_global: MAX_GLOBAL '=' NUMBER ';'
1373 > class_max_number: MAX_NUMBER '=' NUMBER ';'
1374   {
1375    if (conf_parser_ctx.pass == 1)
1376 <    MaxGlobal(yy_class) = $3;
1376 >    block_state.max_total.value = $3;
1377   };
1378  
1379 < class_max_local: MAX_LOCAL '=' NUMBER ';'
1379 > class_sendq: SENDQ '=' sizespec ';'
1380   {
1381    if (conf_parser_ctx.pass == 1)
1382 <    MaxLocal(yy_class) = $3;
1382 >    block_state.max_sendq.value = $3;
1383   };
1384  
1385 < class_max_ident: MAX_IDENT '=' NUMBER ';'
1385 > class_recvq: T_RECVQ '=' sizespec ';'
1386   {
1387    if (conf_parser_ctx.pass == 1)
1388 <    MaxIdent(yy_class) = $3;
1388 >    if ($3 >= CLIENT_FLOOD_MIN && $3 <= CLIENT_FLOOD_MAX)
1389 >      block_state.max_recvq.value = $3;
1390   };
1391  
1392 < class_sendq: SENDQ '=' sizespec ';'
1392 > class_cidr_bitlen_ipv4: CIDR_BITLEN_IPV4 '=' NUMBER ';'
1393   {
1394    if (conf_parser_ctx.pass == 1)
1395 <    MaxSendq(yy_class) = $3;
1395 >    block_state.cidr_bitlen_ipv4.value = $3 > 32 ? 32 : $3;
1396   };
1397  
1398 < class_cidr_bitlen_ipv4: CIDR_BITLEN_IPV4 '=' NUMBER ';'
1398 > class_cidr_bitlen_ipv6: CIDR_BITLEN_IPV6 '=' NUMBER ';'
1399   {
1400    if (conf_parser_ctx.pass == 1)
1401 <    CidrBitlenIPV4(yy_class) = $3;
1401 >    block_state.cidr_bitlen_ipv6.value = $3 > 128 ? 128 : $3;
1402   };
1403  
1404 < class_cidr_bitlen_ipv6: CIDR_BITLEN_IPV6 '=' NUMBER ';'
1404 > class_number_per_cidr: NUMBER_PER_CIDR '=' NUMBER ';'
1405   {
1406    if (conf_parser_ctx.pass == 1)
1407 <    CidrBitlenIPV6(yy_class) = $3;
1407 >    block_state.number_per_cidr.value = $3;
1408   };
1409  
1410 < class_number_per_cidr: NUMBER_PER_CIDR '=' NUMBER ';'
1410 > class_min_idle: MIN_IDLE '=' timespec ';'
1411 > {
1412 >  if (conf_parser_ctx.pass != 1)
1413 >    break;
1414 >
1415 >  block_state.min_idle.value = $3;
1416 >  block_state.flags.value |= CLASS_FLAGS_FAKE_IDLE;
1417 > };
1418 >
1419 > class_max_idle: MAX_IDLE '=' timespec ';'
1420 > {
1421 >  if (conf_parser_ctx.pass != 1)
1422 >    break;
1423 >
1424 >  block_state.max_idle.value = $3;
1425 >  block_state.flags.value |= CLASS_FLAGS_FAKE_IDLE;
1426 > };
1427 >
1428 > class_flags: IRCD_FLAGS
1429   {
1430    if (conf_parser_ctx.pass == 1)
1431 <    NumberPerCidr(yy_class) = $3;
1431 >    block_state.flags.value &= CLASS_FLAGS_FAKE_IDLE;
1432 > } '='  class_flags_items ';';
1433 >
1434 > class_flags_items: class_flags_items ',' class_flags_item | class_flags_item;
1435 > class_flags_item: RANDOM_IDLE
1436 > {
1437 >  if (conf_parser_ctx.pass == 1)
1438 >    block_state.flags.value |= CLASS_FLAGS_RANDOM_IDLE;
1439 > } | HIDE_IDLE_FROM_OPERS
1440 > {
1441 >  if (conf_parser_ctx.pass == 1)
1442 >    block_state.flags.value |= CLASS_FLAGS_HIDE_IDLE_FROM_OPERS;
1443   };
1444  
1445 +
1446   /***************************************************************************
1447 < *  section listen
1447 > * listen {} section
1448   ***************************************************************************/
1449   listen_entry: LISTEN
1450   {
1451    if (conf_parser_ctx.pass == 2)
1452 <  {
1453 <    listener_address = NULL;
1472 <    listener_flags = 0;
1473 <  }
1474 < } '{' listen_items '}' ';'
1475 < {
1476 <  if (conf_parser_ctx.pass == 2)
1477 <  {
1478 <    MyFree(listener_address);
1479 <    listener_address = NULL;
1480 <  }
1481 < };
1452 >    reset_block_state();
1453 > } '{' listen_items '}' ';';
1454  
1455   listen_flags: IRCD_FLAGS
1456   {
1457 <  listener_flags = 0;
1457 >  block_state.flags.value = 0;
1458   } '='  listen_flags_items ';';
1459  
1460   listen_flags_items: listen_flags_items ',' listen_flags_item | listen_flags_item;
1461   listen_flags_item: T_SSL
1462   {
1463    if (conf_parser_ctx.pass == 2)
1464 <    listener_flags |= LISTENER_SSL;
1464 >    block_state.flags.value |= LISTENER_SSL;
1465   } | HIDDEN
1466   {
1467    if (conf_parser_ctx.pass == 2)
1468 <    listener_flags |= LISTENER_HIDDEN;
1468 >    block_state.flags.value |= LISTENER_HIDDEN;
1469   } | T_SERVER
1470   {
1471    if (conf_parser_ctx.pass == 2)
1472 <    listener_flags |= LISTENER_SERVER;
1472 >   block_state.flags.value |= LISTENER_SERVER;
1473   };
1474  
1503
1504
1475   listen_items:   listen_items listen_item | listen_item;
1476   listen_item:    listen_port | listen_flags | listen_address | listen_host | error ';';
1477  
1478 < listen_port: PORT '=' port_items { listener_flags = 0; } ';';
1478 > listen_port: PORT '=' port_items { block_state.flags.value = 0; } ';';
1479  
1480   port_items: port_items ',' port_item | port_item;
1481  
# Line 1513 | Line 1483 | port_item: NUMBER
1483   {
1484    if (conf_parser_ctx.pass == 2)
1485    {
1486 <    if ((listener_flags & LISTENER_SSL))
1487 < #ifdef HAVE_LIBCRYPTO
1488 <      if (!ServerInfo.server_ctx)
1486 > #ifndef HAVE_TLS
1487 >    if (block_state.flags.value & LISTENER_SSL)
1488 >    {
1489 >      conf_error_report("TLS not available - port closed");
1490 >      break;
1491 >    }
1492   #endif
1493 <      {
1521 <        yyerror("SSL not available - port closed");
1522 <        break;
1523 <      }
1524 <    add_listener($1, listener_address, listener_flags);
1493 >    listener_add($1, block_state.addr.buf, block_state.flags.value);
1494    }
1495   } | NUMBER TWODOTS NUMBER
1496   {
1497    if (conf_parser_ctx.pass == 2)
1498    {
1499 <    int i;
1500 <
1501 <    if ((listener_flags & LISTENER_SSL))
1502 < #ifdef HAVE_LIBCRYPTO
1503 <      if (!ServerInfo.server_ctx)
1499 > #ifndef HAVE_TLS
1500 >    if (block_state.flags.value & LISTENER_SSL)
1501 >    {
1502 >      conf_error_report("TLS not available - port closed");
1503 >      break;
1504 >    }
1505   #endif
1536      {
1537        yyerror("SSL not available - port closed");
1538        break;
1539      }
1506  
1507 <    for (i = $1; i <= $3; ++i)
1508 <      add_listener(i, listener_address, listener_flags);
1507 >    for (int i = $1; i <= $3; ++i)
1508 >      listener_add(i, block_state.addr.buf, block_state.flags.value);
1509    }
1510   };
1511  
1512   listen_address: IP '=' QSTRING ';'
1513   {
1514    if (conf_parser_ctx.pass == 2)
1515 <  {
1550 <    MyFree(listener_address);
1551 <    DupString(listener_address, yylval.string);
1552 <  }
1515 >    strlcpy(block_state.addr.buf, yylval.string, sizeof(block_state.addr.buf));
1516   };
1517  
1518   listen_host: HOST '=' QSTRING ';'
1519   {
1520    if (conf_parser_ctx.pass == 2)
1521 <  {
1559 <    MyFree(listener_address);
1560 <    DupString(listener_address, yylval.string);
1561 <  }
1521 >    strlcpy(block_state.addr.buf, yylval.string, sizeof(block_state.addr.buf));
1522   };
1523  
1524 +
1525   /***************************************************************************
1526 < *  section auth
1526 > * auth {} section
1527   ***************************************************************************/
1528   auth_entry: IRCD_AUTH
1529   {
1530    if (conf_parser_ctx.pass == 2)
1531 <  {
1571 <    yy_conf = make_conf_item(CLIENT_TYPE);
1572 <    yy_aconf = map_to_conf(yy_conf);
1573 <  }
1574 <  else
1575 <  {
1576 <    MyFree(class_name);
1577 <    class_name = NULL;
1578 <  }
1531 >    reset_block_state();
1532   } '{' auth_items '}' ';'
1533   {
1534 <  if (conf_parser_ctx.pass == 2)
1582 <  {
1583 <    struct CollectItem *yy_tmp = NULL;
1584 <    dlink_node *ptr = NULL, *next_ptr = NULL;
1585 <
1586 <    if (yy_aconf->user && yy_aconf->host)
1587 <    {
1588 <      conf_add_class_to_conf(yy_conf, class_name);
1589 <      add_conf_by_address(CONF_CLIENT, yy_aconf);
1590 <    }
1591 <    else
1592 <      delete_conf_item(yy_conf);
1593 <
1594 <    /* copy over settings from first struct */
1595 <    DLINK_FOREACH_SAFE(ptr, next_ptr, col_conf_list.head)
1596 <    {
1597 <      struct AccessItem *new_aconf;
1598 <      struct ConfItem *new_conf;
1534 >  dlink_node *node = NULL;
1535  
1536 <      new_conf = make_conf_item(CLIENT_TYPE);
1537 <      new_aconf = map_to_conf(new_conf);
1536 >  if (conf_parser_ctx.pass != 2)
1537 >    break;
1538  
1539 <      yy_tmp = ptr->data;
1539 >  DLINK_FOREACH(node, block_state.mask.list.head)
1540 >  {
1541 >    struct split_nuh_item nuh;
1542 >    char *s = node->data;
1543  
1544 <      assert(yy_tmp->user && yy_tmp->host);
1544 >    if (EmptyString(s))
1545 >      continue;
1546  
1547 <      if (yy_aconf->passwd != NULL)
1548 <        DupString(new_aconf->passwd, yy_aconf->passwd);
1549 <      if (yy_conf->name != NULL)
1550 <        DupString(new_conf->name, yy_conf->name);
1611 <      if (yy_aconf->passwd != NULL)
1612 <        DupString(new_aconf->passwd, yy_aconf->passwd);
1547 >    nuh.nuhmask  = s;
1548 >    nuh.nickptr  = NULL;
1549 >    nuh.userptr  = block_state.user.buf;
1550 >    nuh.hostptr  = block_state.host.buf;
1551  
1552 <      new_aconf->flags = yy_aconf->flags;
1553 <      new_aconf->port  = yy_aconf->port;
1552 >    nuh.nicksize = 0;
1553 >    nuh.usersize = sizeof(block_state.user.buf);
1554 >    nuh.hostsize = sizeof(block_state.host.buf);
1555  
1556 <      DupString(new_aconf->user, yy_tmp->user);
1618 <      collapse(new_aconf->user);
1556 >    split_nuh(&nuh);
1557  
1558 <      DupString(new_aconf->host, yy_tmp->host);
1559 <      collapse(new_aconf->host);
1558 >    struct MaskItem *conf = conf_make(CONF_CLIENT);
1559 >    conf->user = xstrdup(block_state.user.buf);
1560 >    conf->host = xstrdup(block_state.host.buf);
1561 >
1562 >    if (block_state.rpass.buf[0])
1563 >      conf->passwd = xstrdup(block_state.rpass.buf);
1564 >    if (block_state.name.buf[0])
1565 >      conf->name = xstrdup(block_state.name.buf);
1566  
1567 <      conf_add_class_to_conf(new_conf, class_name);
1568 <      add_conf_by_address(CONF_CLIENT, new_aconf);
1625 <      dlinkDelete(&yy_tmp->node, &col_conf_list);
1626 <      free_collect_item(yy_tmp);
1627 <    }
1567 >    conf->flags = block_state.flags.value;
1568 >    conf->port  = block_state.port.value;
1569  
1570 <    MyFree(class_name);
1571 <    class_name = NULL;
1631 <    yy_conf = NULL;
1632 <    yy_aconf = NULL;
1570 >    conf_add_class_to_conf(conf, block_state.class.buf);
1571 >    add_conf_by_address(CONF_CLIENT, conf);
1572    }
1573 < };
1573 > };
1574  
1575   auth_items:     auth_items auth_item | auth_item;
1576 < auth_item:      auth_user | auth_passwd | auth_class | auth_flags |
1577 <                auth_spoof | auth_redir_serv | auth_redir_port |
1578 <                auth_encrypted | error ';' ;
1576 > auth_item:      auth_user |
1577 >                auth_passwd |
1578 >                auth_class |
1579 >                auth_flags |
1580 >                auth_spoof |
1581 >                auth_redir_serv |
1582 >                auth_redir_port |
1583 >                auth_encrypted |
1584 >                error ';' ;
1585  
1586   auth_user: USER '=' QSTRING ';'
1587   {
1588    if (conf_parser_ctx.pass == 2)
1589 <  {
1645 <    struct CollectItem *yy_tmp = NULL;
1646 <    struct split_nuh_item nuh;
1647 <
1648 <    nuh.nuhmask  = yylval.string;
1649 <    nuh.nickptr  = NULL;
1650 <    nuh.userptr  = userbuf;
1651 <    nuh.hostptr  = hostbuf;
1652 <
1653 <    nuh.nicksize = 0;
1654 <    nuh.usersize = sizeof(userbuf);
1655 <    nuh.hostsize = sizeof(hostbuf);
1656 <
1657 <    split_nuh(&nuh);
1658 <
1659 <    if (yy_aconf->user == NULL)
1660 <    {
1661 <      DupString(yy_aconf->user, userbuf);
1662 <      DupString(yy_aconf->host, hostbuf);
1663 <    }
1664 <    else
1665 <    {
1666 <      yy_tmp = MyMalloc(sizeof(struct CollectItem));
1667 <
1668 <      DupString(yy_tmp->user, userbuf);
1669 <      DupString(yy_tmp->host, hostbuf);
1670 <
1671 <      dlinkAdd(yy_tmp, &yy_tmp->node, &col_conf_list);
1672 <    }
1673 <  }
1589 >    dlinkAdd(xstrdup(yylval.string), make_dlink_node(), &block_state.mask.list);
1590   };
1591  
1676 /* XXX - IP/IPV6 tags don't exist anymore - put IP/IPV6 into user. */
1677
1592   auth_passwd: PASSWORD '=' QSTRING ';'
1593   {
1594    if (conf_parser_ctx.pass == 2)
1595 <  {
1682 <    /* be paranoid */
1683 <    if (yy_aconf->passwd != NULL)
1684 <      memset(yy_aconf->passwd, 0, strlen(yy_aconf->passwd));
1685 <
1686 <    MyFree(yy_aconf->passwd);
1687 <    DupString(yy_aconf->passwd, yylval.string);
1688 <  }
1595 >    strlcpy(block_state.rpass.buf, yylval.string, sizeof(block_state.rpass.buf));
1596   };
1597  
1598   auth_class: CLASS '=' QSTRING ';'
1599   {
1600    if (conf_parser_ctx.pass == 2)
1601 <  {
1695 <    MyFree(class_name);
1696 <    DupString(class_name, yylval.string);
1697 <  }
1601 >    strlcpy(block_state.class.buf, yylval.string, sizeof(block_state.class.buf));
1602   };
1603  
1604   auth_encrypted: ENCRYPTED '=' TBOOL ';'
# Line 1702 | Line 1606 | auth_encrypted: ENCRYPTED '=' TBOOL ';'
1606    if (conf_parser_ctx.pass == 2)
1607    {
1608      if (yylval.number)
1609 <      SetConfEncrypted(yy_aconf);
1609 >      block_state.flags.value |= CONF_FLAGS_ENCRYPTED;
1610      else
1611 <      ClearConfEncrypted(yy_aconf);
1611 >      block_state.flags.value &= ~CONF_FLAGS_ENCRYPTED;
1612    }
1613   };
1614  
1615   auth_flags: IRCD_FLAGS
1616   {
1617 < } '='  auth_flags_items ';';
1617 >  if (conf_parser_ctx.pass == 2)
1618 >    block_state.flags.value &= (CONF_FLAGS_ENCRYPTED | CONF_FLAGS_SPOOF_IP);
1619 > } '=' auth_flags_items ';';
1620  
1621   auth_flags_items: auth_flags_items ',' auth_flags_item | auth_flags_item;
1622   auth_flags_item: SPOOF_NOTICE
1623   {
1624    if (conf_parser_ctx.pass == 2)
1625 <    yy_aconf->flags |= CONF_FLAGS_SPOOF_NOTICE;
1625 >    block_state.flags.value |= CONF_FLAGS_SPOOF_NOTICE;
1626   } | EXCEED_LIMIT
1627   {
1628    if (conf_parser_ctx.pass == 2)
1629 <    yy_aconf->flags |= CONF_FLAGS_NOLIMIT;
1629 >    block_state.flags.value |= CONF_FLAGS_NOLIMIT;
1630   } | KLINE_EXEMPT
1631   {
1632    if (conf_parser_ctx.pass == 2)
1633 <    yy_aconf->flags |= CONF_FLAGS_EXEMPTKLINE;
1633 >    block_state.flags.value |= CONF_FLAGS_EXEMPTKLINE;
1634 > } | XLINE_EXEMPT
1635 > {
1636 >  if (conf_parser_ctx.pass == 2)
1637 >    block_state.flags.value |= CONF_FLAGS_EXEMPTXLINE;
1638   } | NEED_IDENT
1639   {
1640    if (conf_parser_ctx.pass == 2)
1641 <    yy_aconf->flags |= CONF_FLAGS_NEED_IDENTD;
1641 >    block_state.flags.value |= CONF_FLAGS_NEED_IDENTD;
1642   } | CAN_FLOOD
1643   {
1644    if (conf_parser_ctx.pass == 2)
1645 <    yy_aconf->flags |= CONF_FLAGS_CAN_FLOOD;
1645 >    block_state.flags.value |= CONF_FLAGS_CAN_FLOOD;
1646   } | NO_TILDE
1647   {
1648    if (conf_parser_ctx.pass == 2)
1649 <    yy_aconf->flags |= CONF_FLAGS_NO_TILDE;
1650 < } | GLINE_EXEMPT
1649 >    block_state.flags.value |= CONF_FLAGS_NO_TILDE;
1650 > } | RESV_EXEMPT
1651   {
1652    if (conf_parser_ctx.pass == 2)
1653 <    yy_aconf->flags |= CONF_FLAGS_EXEMPTGLINE;
1654 < } | RESV_EXEMPT
1653 >    block_state.flags.value |= CONF_FLAGS_EXEMPTRESV;
1654 > } | T_WEBIRC
1655   {
1656    if (conf_parser_ctx.pass == 2)
1657 <    yy_aconf->flags |= CONF_FLAGS_EXEMPTRESV;
1657 >    block_state.flags.value |= CONF_FLAGS_WEBIRC;
1658   } | NEED_PASSWORD
1659   {
1660    if (conf_parser_ctx.pass == 2)
1661 <    yy_aconf->flags |= CONF_FLAGS_NEED_PASSWORD;
1661 >    block_state.flags.value |= CONF_FLAGS_NEED_PASSWORD;
1662   };
1663  
1664 < /* XXX - need check for illegal hostnames here */
1755 < auth_spoof: SPOOF '=' QSTRING ';'
1664 > auth_spoof: SPOOF '=' QSTRING ';'
1665   {
1666 <  if (conf_parser_ctx.pass == 2)
1667 <  {
1759 <    MyFree(yy_conf->name);
1666 >  if (conf_parser_ctx.pass != 2)
1667 >    break;
1668  
1669 <    if (strlen(yylval.string) < HOSTLEN)
1670 <    {    
1671 <      DupString(yy_conf->name, yylval.string);
1672 <      yy_aconf->flags |= CONF_FLAGS_SPOOF_IP;
1765 <    }
1766 <    else
1767 <    {
1768 <      ilog(LOG_TYPE_IRCD, "Spoofs must be less than %d..ignoring it", HOSTLEN);
1769 <      yy_conf->name = NULL;
1770 <    }
1669 >  if (valid_hostname(yylval.string))
1670 >  {
1671 >    strlcpy(block_state.name.buf, yylval.string, sizeof(block_state.name.buf));
1672 >    block_state.flags.value |= CONF_FLAGS_SPOOF_IP;
1673    }
1674 +  else
1675 +    ilog(LOG_TYPE_IRCD, "Spoof either is too long or contains invalid characters. Ignoring it.");
1676   };
1677  
1678   auth_redir_serv: REDIRSERV '=' QSTRING ';'
1679   {
1680 <  if (conf_parser_ctx.pass == 2)
1681 <  {
1682 <    yy_aconf->flags |= CONF_FLAGS_REDIR;
1683 <    MyFree(yy_conf->name);
1684 <    DupString(yy_conf->name, yylval.string);
1781 <  }
1680 >  if (conf_parser_ctx.pass != 2)
1681 >    break;
1682 >
1683 >  strlcpy(block_state.name.buf, yylval.string, sizeof(block_state.name.buf));
1684 >  block_state.flags.value |= CONF_FLAGS_REDIR;
1685   };
1686  
1687   auth_redir_port: REDIRPORT '=' NUMBER ';'
1688   {
1689 <  if (conf_parser_ctx.pass == 2)
1690 <  {
1691 <    yy_aconf->flags |= CONF_FLAGS_REDIR;
1692 <    yy_aconf->port = $3;
1693 <  }
1689 >  if (conf_parser_ctx.pass != 2)
1690 >    break;
1691 >
1692 >  block_state.flags.value |= CONF_FLAGS_REDIR;
1693 >  block_state.port.value = $3;
1694   };
1695  
1696  
1697   /***************************************************************************
1698 < *  section resv
1698 > * resv {} section
1699   ***************************************************************************/
1700   resv_entry: RESV
1701   {
1702 <  if (conf_parser_ctx.pass == 2)
1703 <  {
1704 <    MyFree(resv_reason);
1705 <    resv_reason = NULL;
1706 <  }
1702 >  if (conf_parser_ctx.pass != 2)
1703 >    break;
1704 >
1705 >  reset_block_state();
1706 >  strlcpy(block_state.rpass.buf, CONF_NOREASON, sizeof(block_state.rpass.buf));
1707   } '{' resv_items '}' ';'
1708   {
1709 <  if (conf_parser_ctx.pass == 2)
1710 <  {
1711 <    MyFree(resv_reason);
1712 <    resv_reason = NULL;
1810 <  }
1709 >  if (conf_parser_ctx.pass != 2)
1710 >    break;
1711 >
1712 >  resv_make(block_state.name.buf, block_state.rpass.buf, &block_state.mask.list);
1713   };
1714  
1715 < resv_items:     resv_items resv_item | resv_item;
1716 < resv_item:      resv_creason | resv_channel | resv_nick | error ';' ;
1715 > resv_items:     resv_items resv_item | resv_item;
1716 > resv_item:      resv_mask | resv_reason | resv_exempt | error ';' ;
1717  
1718 < resv_creason: REASON '=' QSTRING ';'
1718 > resv_mask: MASK '=' QSTRING ';'
1719   {
1720    if (conf_parser_ctx.pass == 2)
1721 <  {
1820 <    MyFree(resv_reason);
1821 <    DupString(resv_reason, yylval.string);
1822 <  }
1721 >    strlcpy(block_state.name.buf, yylval.string, sizeof(block_state.name.buf));
1722   };
1723  
1724 < resv_channel: CHANNEL '=' QSTRING ';'
1724 > resv_reason: REASON '=' QSTRING ';'
1725   {
1726    if (conf_parser_ctx.pass == 2)
1727 <  {
1829 <    if (IsChanPrefix(*yylval.string))
1830 <    {
1831 <      char def_reason[] = "No reason";
1832 <
1833 <      create_channel_resv(yylval.string, resv_reason != NULL ? resv_reason : def_reason, 1);
1834 <    }
1835 <  }
1836 <  /* ignore it for now.. but we really should make a warning if
1837 <   * its an erroneous name --fl_ */
1727 >    strlcpy(block_state.rpass.buf, yylval.string, sizeof(block_state.rpass.buf));
1728   };
1729  
1730 < resv_nick: NICK '=' QSTRING ';'
1730 > resv_exempt: EXEMPT '=' QSTRING ';'
1731   {
1732    if (conf_parser_ctx.pass == 2)
1733 <  {
1844 <    char def_reason[] = "No reason";
1845 <
1846 <    create_nick_resv(yylval.string, resv_reason != NULL ? resv_reason : def_reason, 1);
1847 <  }
1733 >    dlinkAdd(xstrdup(yylval.string), make_dlink_node(), &block_state.mask.list);
1734   };
1735  
1736 +
1737   /***************************************************************************
1738 < *  section service
1738 > * service {} section
1739   ***************************************************************************/
1740   service_entry: T_SERVICE '{' service_items '}' ';';
1741  
# Line 1857 | Line 1744 | service_item:      service_name | error;
1744  
1745   service_name: NAME '=' QSTRING ';'
1746   {
1747 <  if (conf_parser_ctx.pass == 2)
1747 >  if (conf_parser_ctx.pass != 2)
1748 >    break;
1749 >
1750 >  if (server_valid_name(yylval.string) == true)
1751    {
1752 <    if (valid_servname(yylval.string))
1753 <    {
1864 <      yy_conf = make_conf_item(SERVICE_TYPE);
1865 <      DupString(yy_conf->name, yylval.string);
1866 <    }
1752 >    struct ServiceItem *service = service_make();
1753 >    service->name = xstrdup(yylval.string);
1754    }
1755   };
1756  
1757 +
1758   /***************************************************************************
1759 < *  section shared, for sharing remote klines etc.
1759 > * shared {} section, for sharing remote klines etc.
1760   ***************************************************************************/
1761   shared_entry: T_SHARED
1762   {
1763 <  if (conf_parser_ctx.pass == 2)
1764 <  {
1765 <    yy_conf = make_conf_item(ULINE_TYPE);
1766 <    yy_match_item = map_to_conf(yy_conf);
1767 <    yy_match_item->action = SHARED_ALL;
1768 <  }
1763 >  if (conf_parser_ctx.pass != 2)
1764 >    break;
1765 >
1766 >  reset_block_state();
1767 >
1768 >  strlcpy(block_state.name.buf, "*", sizeof(block_state.name.buf));
1769 >  strlcpy(block_state.user.buf, "*", sizeof(block_state.user.buf));
1770 >  strlcpy(block_state.host.buf, "*", sizeof(block_state.host.buf));
1771 >  block_state.flags.value = SHARED_ALL;
1772   } '{' shared_items '}' ';'
1773   {
1774 <  if (conf_parser_ctx.pass == 2)
1775 <  {
1776 <    yy_conf = NULL;
1777 <  }
1774 >  if (conf_parser_ctx.pass != 2)
1775 >    break;
1776 >
1777 >  struct SharedItem *shared = shared_make();
1778 >  shared->type = block_state.flags.value;
1779 >  shared->server = xstrdup(block_state.name.buf);
1780 >  shared->user = xstrdup(block_state.user.buf);
1781 >  shared->host = xstrdup(block_state.host.buf);
1782   };
1783  
1784   shared_items: shared_items shared_item | shared_item;
# Line 1892 | Line 1787 | shared_item:  shared_name | shared_user
1787   shared_name: NAME '=' QSTRING ';'
1788   {
1789    if (conf_parser_ctx.pass == 2)
1790 <  {
1896 <    MyFree(yy_conf->name);
1897 <    DupString(yy_conf->name, yylval.string);
1898 <  }
1790 >    strlcpy(block_state.name.buf, yylval.string, sizeof(block_state.name.buf));
1791   };
1792  
1793   shared_user: USER '=' QSTRING ';'
# Line 1906 | Line 1798 | shared_user: USER '=' QSTRING ';'
1798  
1799      nuh.nuhmask  = yylval.string;
1800      nuh.nickptr  = NULL;
1801 <    nuh.userptr  = userbuf;
1802 <    nuh.hostptr  = hostbuf;
1801 >    nuh.userptr  = block_state.user.buf;
1802 >    nuh.hostptr  = block_state.host.buf;
1803  
1804      nuh.nicksize = 0;
1805 <    nuh.usersize = sizeof(userbuf);
1806 <    nuh.hostsize = sizeof(hostbuf);
1805 >    nuh.usersize = sizeof(block_state.user.buf);
1806 >    nuh.hostsize = sizeof(block_state.host.buf);
1807  
1808      split_nuh(&nuh);
1917
1918    DupString(yy_match_item->user, userbuf);
1919    DupString(yy_match_item->host, hostbuf);
1809    }
1810   };
1811  
1812   shared_type: TYPE
1813   {
1814    if (conf_parser_ctx.pass == 2)
1815 <    yy_match_item->action = 0;
1815 >    block_state.flags.value = 0;
1816   } '=' shared_types ';' ;
1817  
1818   shared_types: shared_types ',' shared_type_item | shared_type_item;
1819   shared_type_item: KLINE
1820   {
1821    if (conf_parser_ctx.pass == 2)
1822 <    yy_match_item->action |= SHARED_KLINE;
1822 >    block_state.flags.value |= SHARED_KLINE;
1823   } | UNKLINE
1824   {
1825    if (conf_parser_ctx.pass == 2)
1826 <    yy_match_item->action |= SHARED_UNKLINE;
1826 >    block_state.flags.value |= SHARED_UNKLINE;
1827   } | T_DLINE
1828   {
1829    if (conf_parser_ctx.pass == 2)
1830 <    yy_match_item->action |= SHARED_DLINE;
1830 >    block_state.flags.value |= SHARED_DLINE;
1831   } | T_UNDLINE
1832   {
1833    if (conf_parser_ctx.pass == 2)
1834 <    yy_match_item->action |= SHARED_UNDLINE;
1834 >    block_state.flags.value |= SHARED_UNDLINE;
1835   } | XLINE
1836   {
1837    if (conf_parser_ctx.pass == 2)
1838 <    yy_match_item->action |= SHARED_XLINE;
1838 >    block_state.flags.value |= SHARED_XLINE;
1839   } | T_UNXLINE
1840   {
1841    if (conf_parser_ctx.pass == 2)
1842 <    yy_match_item->action |= SHARED_UNXLINE;
1842 >    block_state.flags.value |= SHARED_UNXLINE;
1843   } | RESV
1844   {
1845    if (conf_parser_ctx.pass == 2)
1846 <    yy_match_item->action |= SHARED_RESV;
1846 >    block_state.flags.value |= SHARED_RESV;
1847   } | T_UNRESV
1848   {
1849    if (conf_parser_ctx.pass == 2)
1850 <    yy_match_item->action |= SHARED_UNRESV;
1850 >    block_state.flags.value |= SHARED_UNRESV;
1851   } | T_LOCOPS
1852   {
1853    if (conf_parser_ctx.pass == 2)
1854 <    yy_match_item->action |= SHARED_LOCOPS;
1854 >    block_state.flags.value |= SHARED_LOCOPS;
1855   } | T_ALL
1856   {
1857    if (conf_parser_ctx.pass == 2)
1858 <    yy_match_item->action = SHARED_ALL;
1858 >    block_state.flags.value = SHARED_ALL;
1859   };
1860  
1861 +
1862   /***************************************************************************
1863 < *  section cluster
1863 > * cluster {} section
1864   ***************************************************************************/
1865   cluster_entry: T_CLUSTER
1866   {
1867 <  if (conf_parser_ctx.pass == 2)
1868 <  {
1869 <    yy_conf = make_conf_item(CLUSTER_TYPE);
1870 <    yy_conf->flags = SHARED_ALL;
1871 <  }
1867 >  if (conf_parser_ctx.pass != 2)
1868 >    break;
1869 >
1870 >  reset_block_state();
1871 >
1872 >  strlcpy(block_state.name.buf, "*", sizeof(block_state.name.buf));
1873 >  block_state.flags.value = CLUSTER_ALL;
1874   } '{' cluster_items '}' ';'
1875   {
1876 <  if (conf_parser_ctx.pass == 2)
1877 <  {
1878 <    if (yy_conf->name == NULL)
1879 <      DupString(yy_conf->name, "*");
1880 <    yy_conf = NULL;
1881 <  }
1876 >  if (conf_parser_ctx.pass != 2)
1877 >    break;
1878 >
1879 >  struct ClusterItem *cluster = cluster_make();
1880 >  cluster->type = block_state.flags.value;
1881 >  cluster->server = xstrdup(block_state.name.buf);
1882   };
1883  
1884 < cluster_items:  cluster_items cluster_item | cluster_item;
1885 < cluster_item:   cluster_name | cluster_type | error ';' ;
1884 > cluster_items:  cluster_items cluster_item | cluster_item;
1885 > cluster_item:   cluster_name | cluster_type | error ';' ;
1886  
1887   cluster_name: NAME '=' QSTRING ';'
1888   {
1889    if (conf_parser_ctx.pass == 2)
1890 <    DupString(yy_conf->name, yylval.string);
1890 >    strlcpy(block_state.name.buf, yylval.string, sizeof(block_state.name.buf));
1891   };
1892  
1893   cluster_type: TYPE
1894   {
1895    if (conf_parser_ctx.pass == 2)
1896 <    yy_conf->flags = 0;
1896 >    block_state.flags.value = 0;
1897   } '=' cluster_types ';' ;
1898  
1899 < cluster_types:  cluster_types ',' cluster_type_item | cluster_type_item;
1899 > cluster_types:  cluster_types ',' cluster_type_item | cluster_type_item;
1900   cluster_type_item: KLINE
1901   {
1902    if (conf_parser_ctx.pass == 2)
1903 <    yy_conf->flags |= SHARED_KLINE;
1903 >    block_state.flags.value |= CLUSTER_KLINE;
1904   } | UNKLINE
1905   {
1906    if (conf_parser_ctx.pass == 2)
1907 <    yy_conf->flags |= SHARED_UNKLINE;
1907 >    block_state.flags.value |= CLUSTER_UNKLINE;
1908   } | T_DLINE
1909   {
1910    if (conf_parser_ctx.pass == 2)
1911 <    yy_conf->flags |= SHARED_DLINE;
1911 >    block_state.flags.value |= CLUSTER_DLINE;
1912   } | T_UNDLINE
1913   {
1914    if (conf_parser_ctx.pass == 2)
1915 <    yy_conf->flags |= SHARED_UNDLINE;
1915 >    block_state.flags.value |= CLUSTER_UNDLINE;
1916   } | XLINE
1917   {
1918    if (conf_parser_ctx.pass == 2)
1919 <    yy_conf->flags |= SHARED_XLINE;
1919 >    block_state.flags.value |= CLUSTER_XLINE;
1920   } | T_UNXLINE
1921   {
1922    if (conf_parser_ctx.pass == 2)
1923 <    yy_conf->flags |= SHARED_UNXLINE;
1923 >    block_state.flags.value |= CLUSTER_UNXLINE;
1924   } | RESV
1925   {
1926    if (conf_parser_ctx.pass == 2)
1927 <    yy_conf->flags |= SHARED_RESV;
1927 >    block_state.flags.value |= CLUSTER_RESV;
1928   } | T_UNRESV
1929   {
1930    if (conf_parser_ctx.pass == 2)
1931 <    yy_conf->flags |= SHARED_UNRESV;
1931 >    block_state.flags.value |= CLUSTER_UNRESV;
1932   } | T_LOCOPS
1933   {
1934    if (conf_parser_ctx.pass == 2)
1935 <    yy_conf->flags |= SHARED_LOCOPS;
1935 >    block_state.flags.value |= CLUSTER_LOCOPS;
1936   } | T_ALL
1937   {
1938    if (conf_parser_ctx.pass == 2)
1939 <    yy_conf->flags = SHARED_ALL;
1939 >    block_state.flags.value = CLUSTER_ALL;
1940   };
1941  
1942 +
1943   /***************************************************************************
1944 < *  section connect
1944 > * connect {}  section
1945   ***************************************************************************/
1946 < connect_entry: CONNECT  
1946 > connect_entry: CONNECT
1947   {
2055  if (conf_parser_ctx.pass == 2)
2056  {
2057    yy_conf = make_conf_item(SERVER_TYPE);
2058    yy_aconf = map_to_conf(yy_conf);
1948  
1949 <    /* defaults */
1950 <    yy_aconf->port = PORTNUM;
1951 <  }
1952 <  else
1953 <  {
1954 <    MyFree(class_name);
1955 <    class_name = NULL;
2067 <  }
1949 >  if (conf_parser_ctx.pass != 2)
1950 >    break;
1951 >
1952 >  reset_block_state();
1953 >  block_state.aftype.value = AF_INET;
1954 >  block_state.port.value = PORTNUM;
1955 >  block_state.timeout.value = CONNECTTIMEOUT;
1956   } '{' connect_items '}' ';'
1957   {
1958 <  if (conf_parser_ctx.pass == 2)
1958 >  struct addrinfo hints, *res;
1959 >
1960 >  if (conf_parser_ctx.pass != 2)
1961 >    break;
1962 >
1963 >  if (!block_state.name.buf[0] ||
1964 >      !block_state.host.buf[0])
1965 >    break;
1966 >
1967 >  if (!block_state.rpass.buf[0] ||
1968 >      !block_state.spass.buf[0])
1969 >    break;
1970 >
1971 >  if (server_valid_name(block_state.name.buf) == false)
1972 >    break;
1973 >
1974 >  if (has_wildcards(block_state.name.buf) ||
1975 >      has_wildcards(block_state.host.buf))
1976 >    break;
1977 >
1978 >  struct MaskItem *conf = conf_make(CONF_SERVER);
1979 >  conf->addr = xcalloc(sizeof(*conf->addr));
1980 >  conf->port = block_state.port.value;
1981 >  conf->timeout = block_state.timeout.value;
1982 >  conf->flags = block_state.flags.value;
1983 >  conf->aftype = block_state.aftype.value;
1984 >  conf->host = xstrdup(block_state.host.buf);
1985 >  conf->name = xstrdup(block_state.name.buf);
1986 >  conf->passwd = xstrdup(block_state.rpass.buf);
1987 >  conf->spasswd = xstrdup(block_state.spass.buf);
1988 >
1989 >  if (block_state.cert.buf[0])
1990 >    conf->certfp = xstrdup(block_state.cert.buf);
1991 >
1992 >  if (block_state.ciph.buf[0])
1993 >    conf->cipher_list = xstrdup(block_state.ciph.buf);
1994 >
1995 >  dlinkMoveList(&block_state.leaf.list, &conf->leaf_list);
1996 >  dlinkMoveList(&block_state.hub.list, &conf->hub_list);
1997 >
1998 >  if (block_state.bind.buf[0])
1999    {
2000 <    struct CollectItem *yy_hconf=NULL;
2073 <    struct CollectItem *yy_lconf=NULL;
2074 <    dlink_node *ptr = NULL, *next_ptr = NULL;
2000 >    memset(&hints, 0, sizeof(hints));
2001  
2002 <    if (yy_aconf->host &&
2003 <        yy_aconf->passwd && yy_aconf->spasswd)
2004 <    {
2005 <      if (conf_add_server(yy_conf, class_name) == -1)
2006 <      {
2007 <        delete_conf_item(yy_conf);
2082 <        yy_conf = NULL;
2083 <        yy_aconf = NULL;
2084 <      }
2085 <    }
2002 >    hints.ai_family   = AF_UNSPEC;
2003 >    hints.ai_socktype = SOCK_STREAM;
2004 >    hints.ai_flags    = AI_PASSIVE | AI_NUMERICHOST;
2005 >
2006 >    if (getaddrinfo(block_state.bind.buf, NULL, &hints, &res))
2007 >      ilog(LOG_TYPE_IRCD, "Invalid netmask for server bind(%s)", block_state.bind.buf);
2008      else
2009      {
2010 <      /* Even if yy_conf ->name is NULL
2089 <       * should still unhook any hub/leaf confs still pending
2090 <       */
2091 <      unhook_hub_leaf_confs();
2092 <
2093 <      if (yy_conf->name != NULL)
2094 <      {
2095 <        if (yy_aconf->host == NULL)
2096 <          yyerror("Ignoring connect block -- missing host");
2097 <        else if (!yy_aconf->passwd || !yy_aconf->spasswd)
2098 <          yyerror("Ignoring connect block -- missing password");
2099 <      }
2100 <
2101 <
2102 <      /* XXX
2103 <       * This fixes a try_connections() core (caused by invalid class_ptr
2104 <       * pointers) reported by metalrock. That's an ugly fix, but there
2105 <       * is currently no better way. The entire config subsystem needs an
2106 <       * rewrite ASAP. make_conf_item() shouldn't really add things onto
2107 <       * a doubly linked list immediately without any sanity checks!  -Michael
2108 <       */
2109 <      delete_conf_item(yy_conf);
2010 >      assert(res);
2011  
2012 <      yy_aconf = NULL;
2112 <      yy_conf = NULL;
2113 <    }
2012 >      conf->bind = xcalloc(sizeof(*conf->bind));
2013  
2014 <      /*
2015 <       * yy_conf is still pointing at the server that is having
2016 <       * a connect block built for it. This means, y_aconf->name
2017 <       * points to the actual irc name this server will be known as.
2119 <       * Now this new server has a set or even just one hub_mask (or leaf_mask)
2120 <       * given in the link list at yy_hconf. Fill in the HUB confs
2121 <       * from this link list now.
2122 <       */        
2123 <      DLINK_FOREACH_SAFE(ptr, next_ptr, hub_conf_list.head)
2124 <      {
2125 <        struct ConfItem *new_hub_conf;
2126 <        struct MatchItem *match_item;
2127 <
2128 <        yy_hconf = ptr->data;
2129 <
2130 <        /* yy_conf == NULL is a fatal error for this connect block! */
2131 <        if ((yy_conf != NULL) && (yy_conf->name != NULL))
2132 <        {
2133 <          new_hub_conf = make_conf_item(HUB_TYPE);
2134 <          match_item = (struct MatchItem *)map_to_conf(new_hub_conf);
2135 <          DupString(new_hub_conf->name, yy_conf->name);
2136 <          if (yy_hconf->user != NULL)
2137 <            DupString(match_item->user, yy_hconf->user);
2138 <          else
2139 <            DupString(match_item->user, "*");
2140 <          if (yy_hconf->host != NULL)
2141 <            DupString(match_item->host, yy_hconf->host);
2142 <          else
2143 <            DupString(match_item->host, "*");
2144 <        }
2145 <        dlinkDelete(&yy_hconf->node, &hub_conf_list);
2146 <        free_collect_item(yy_hconf);
2147 <      }
2148 <
2149 <      /* Ditto for the LEAF confs */
2150 <
2151 <      DLINK_FOREACH_SAFE(ptr, next_ptr, leaf_conf_list.head)
2152 <      {
2153 <        struct ConfItem *new_leaf_conf;
2154 <        struct MatchItem *match_item;
2155 <
2156 <        yy_lconf = ptr->data;
2157 <
2158 <        if ((yy_conf != NULL) && (yy_conf->name != NULL))
2159 <        {
2160 <          new_leaf_conf = make_conf_item(LEAF_TYPE);
2161 <          match_item = (struct MatchItem *)map_to_conf(new_leaf_conf);
2162 <          DupString(new_leaf_conf->name, yy_conf->name);
2163 <          if (yy_lconf->user != NULL)
2164 <            DupString(match_item->user, yy_lconf->user);
2165 <          else
2166 <            DupString(match_item->user, "*");
2167 <          if (yy_lconf->host != NULL)
2168 <            DupString(match_item->host, yy_lconf->host);
2169 <          else
2170 <            DupString(match_item->host, "*");
2171 <        }
2172 <        dlinkDelete(&yy_lconf->node, &leaf_conf_list);
2173 <        free_collect_item(yy_lconf);
2174 <      }
2175 <      MyFree(class_name);
2176 <      class_name = NULL;
2177 <      yy_conf = NULL;
2178 <      yy_aconf = NULL;
2014 >      memcpy(conf->bind, res->ai_addr, res->ai_addrlen);
2015 >      conf->bind->ss_len = res->ai_addrlen;
2016 >      freeaddrinfo(res);
2017 >    }
2018    }
2019 +
2020 +  conf_add_class_to_conf(conf, block_state.class.buf);
2021 +  lookup_confhost(conf);
2022   };
2023  
2024   connect_items:  connect_items connect_item | connect_item;
2025 < connect_item:   connect_name | connect_host | connect_vhost |
2026 <                connect_send_password | connect_accept_password |
2027 <                connect_aftype | connect_port | connect_ssl_cipher_list |
2028 <                connect_flags | connect_hub_mask | connect_leaf_mask |
2029 <                connect_class | connect_encrypted |
2025 > connect_item:   connect_name |
2026 >                connect_host |
2027 >                connect_timeout |
2028 >                connect_bind |
2029 >                connect_send_password |
2030 >                connect_accept_password |
2031 >                connect_ssl_certificate_fingerprint |
2032 >                connect_aftype |
2033 >                connect_port |
2034 >                connect_ssl_cipher_list |
2035 >                connect_flags |
2036 >                connect_hub_mask |
2037 >                connect_leaf_mask |
2038 >                connect_class |
2039 >                connect_encrypted |
2040                  error ';' ;
2041  
2042   connect_name: NAME '=' QSTRING ';'
2043   {
2044    if (conf_parser_ctx.pass == 2)
2045 <  {
2194 <    if (yy_conf->name != NULL)
2195 <      yyerror("Multiple connect name entry");
2196 <
2197 <    MyFree(yy_conf->name);
2198 <    DupString(yy_conf->name, yylval.string);
2199 <  }
2045 >    strlcpy(block_state.name.buf, yylval.string, sizeof(block_state.name.buf));
2046   };
2047  
2048 < connect_host: HOST '=' QSTRING ';'
2048 > connect_host: HOST '=' QSTRING ';'
2049   {
2050    if (conf_parser_ctx.pass == 2)
2051 <  {
2206 <    MyFree(yy_aconf->host);
2207 <    DupString(yy_aconf->host, yylval.string);
2208 <  }
2051 >    strlcpy(block_state.host.buf, yylval.string, sizeof(block_state.host.buf));
2052   };
2053  
2054 < connect_vhost: VHOST '=' QSTRING ';'
2054 > connect_timeout: TIMEOUT '=' timespec ';'
2055   {
2056    if (conf_parser_ctx.pass == 2)
2057 <  {
2058 <    struct addrinfo hints, *res;
2216 <
2217 <    memset(&hints, 0, sizeof(hints));
2218 <
2219 <    hints.ai_family   = AF_UNSPEC;
2220 <    hints.ai_socktype = SOCK_STREAM;
2221 <    hints.ai_flags    = AI_PASSIVE | AI_NUMERICHOST;
2222 <
2223 <    if (getaddrinfo(yylval.string, NULL, &hints, &res))
2224 <      ilog(LOG_TYPE_IRCD, "Invalid netmask for server vhost(%s)", yylval.string);
2225 <    else
2226 <    {
2227 <      assert(res != NULL);
2057 >    block_state.timeout.value = $3;
2058 > };
2059  
2060 <      memcpy(&yy_aconf->my_ipnum, res->ai_addr, res->ai_addrlen);
2061 <      yy_aconf->my_ipnum.ss.ss_family = res->ai_family;
2062 <      yy_aconf->my_ipnum.ss_len = res->ai_addrlen;
2063 <      freeaddrinfo(res);
2233 <    }
2234 <  }
2060 > connect_bind: T_BIND '=' QSTRING ';'
2061 > {
2062 >  if (conf_parser_ctx.pass == 2)
2063 >    strlcpy(block_state.bind.buf, yylval.string, sizeof(block_state.bind.buf));
2064   };
2065 <
2065 >
2066   connect_send_password: SEND_PASSWORD '=' QSTRING ';'
2067   {
2068 <  if (conf_parser_ctx.pass == 2)
2069 <  {
2241 <    if ($3[0] == ':')
2242 <      yyerror("Server passwords cannot begin with a colon");
2243 <    else if (strchr($3, ' ') != NULL)
2244 <      yyerror("Server passwords cannot contain spaces");
2245 <    else {
2246 <      if (yy_aconf->spasswd != NULL)
2247 <        memset(yy_aconf->spasswd, 0, strlen(yy_aconf->spasswd));
2068 >  if (conf_parser_ctx.pass != 2)
2069 >    break;
2070  
2071 <      MyFree(yy_aconf->spasswd);
2072 <      DupString(yy_aconf->spasswd, yylval.string);
2073 <    }
2074 <  }
2071 >  if (*yylval.string == ':')
2072 >    conf_error_report("Server passwords cannot begin with a colon");
2073 >  else if (strchr(yylval.string, ' '))
2074 >    conf_error_report("Server passwords cannot contain spaces");
2075 >  else
2076 >    strlcpy(block_state.spass.buf, yylval.string, sizeof(block_state.spass.buf));
2077   };
2078  
2079   connect_accept_password: ACCEPT_PASSWORD '=' QSTRING ';'
2080   {
2081 <  if (conf_parser_ctx.pass == 2)
2082 <  {
2259 <    if ($3[0] == ':')
2260 <      yyerror("Server passwords cannot begin with a colon");
2261 <    else if (strchr($3, ' ') != NULL)
2262 <      yyerror("Server passwords cannot contain spaces");
2263 <    else {
2264 <      if (yy_aconf->passwd != NULL)
2265 <        memset(yy_aconf->passwd, 0, strlen(yy_aconf->passwd));
2081 >  if (conf_parser_ctx.pass != 2)
2082 >    break;
2083  
2084 <      MyFree(yy_aconf->passwd);
2085 <      DupString(yy_aconf->passwd, yylval.string);
2086 <    }
2087 <  }
2084 >  if (*yylval.string == ':')
2085 >    conf_error_report("Server passwords cannot begin with a colon");
2086 >  else if (strchr(yylval.string, ' '))
2087 >    conf_error_report("Server passwords cannot contain spaces");
2088 >  else
2089 >    strlcpy(block_state.rpass.buf, yylval.string, sizeof(block_state.rpass.buf));
2090 > };
2091 >
2092 > connect_ssl_certificate_fingerprint: SSL_CERTIFICATE_FINGERPRINT '=' QSTRING ';'
2093 > {
2094 >  if (conf_parser_ctx.pass == 2)
2095 >    strlcpy(block_state.cert.buf, yylval.string, sizeof(block_state.cert.buf));
2096   };
2097  
2098   connect_port: PORT '=' NUMBER ';'
2099   {
2100    if (conf_parser_ctx.pass == 2)
2101 <    yy_aconf->port = $3;
2101 >    block_state.port.value = $3;
2102   };
2103  
2104   connect_aftype: AFTYPE '=' T_IPV4 ';'
2105   {
2106    if (conf_parser_ctx.pass == 2)
2107 <    yy_aconf->aftype = AF_INET;
2107 >    block_state.aftype.value = AF_INET;
2108   } | AFTYPE '=' T_IPV6 ';'
2109   {
2285 #ifdef IPV6
2110    if (conf_parser_ctx.pass == 2)
2111 <    yy_aconf->aftype = AF_INET6;
2288 < #endif
2111 >    block_state.aftype.value = AF_INET6;
2112   };
2113  
2114   connect_flags: IRCD_FLAGS
2115   {
2116 < } '='  connect_flags_items ';';
2116 >  block_state.flags.value &= CONF_FLAGS_ENCRYPTED;
2117 > } '=' connect_flags_items ';';
2118  
2119   connect_flags_items: connect_flags_items ',' connect_flags_item | connect_flags_item;
2120   connect_flags_item: AUTOCONN
2121   {
2122    if (conf_parser_ctx.pass == 2)
2123 <    SetConfAllowAutoConn(yy_aconf);
2300 < } | BURST_AWAY
2301 < {
2302 <  if (conf_parser_ctx.pass == 2)
2303 <    SetConfAwayBurst(yy_aconf);
2304 < } | TOPICBURST
2305 < {
2306 <  if (conf_parser_ctx.pass == 2)
2307 <    SetConfTopicBurst(yy_aconf);
2123 >    block_state.flags.value |= CONF_FLAGS_ALLOW_AUTO_CONN;
2124   } | T_SSL
2125   {
2126    if (conf_parser_ctx.pass == 2)
2127 <    SetConfSSL(yy_aconf);
2127 >    block_state.flags.value |= CONF_FLAGS_SSL;
2128   };
2129  
2130   connect_encrypted: ENCRYPTED '=' TBOOL ';'
# Line 2316 | Line 2132 | connect_encrypted: ENCRYPTED '=' TBOOL '
2132    if (conf_parser_ctx.pass == 2)
2133    {
2134      if (yylval.number)
2135 <      yy_aconf->flags |= CONF_FLAGS_ENCRYPTED;
2135 >      block_state.flags.value |= CONF_FLAGS_ENCRYPTED;
2136      else
2137 <      yy_aconf->flags &= ~CONF_FLAGS_ENCRYPTED;
2137 >      block_state.flags.value &= ~CONF_FLAGS_ENCRYPTED;
2138    }
2139   };
2140  
2141 < connect_hub_mask: HUB_MASK '=' QSTRING ';'
2141 > connect_hub_mask: HUB_MASK '=' QSTRING ';'
2142   {
2143    if (conf_parser_ctx.pass == 2)
2144 <  {
2329 <    struct CollectItem *yy_tmp;
2330 <
2331 <    yy_tmp = (struct CollectItem *)MyMalloc(sizeof(struct CollectItem));
2332 <    DupString(yy_tmp->host, yylval.string);
2333 <    DupString(yy_tmp->user, "*");
2334 <    dlinkAdd(yy_tmp, &yy_tmp->node, &hub_conf_list);
2335 <  }
2144 >    dlinkAdd(xstrdup(yylval.string), make_dlink_node(), &block_state.hub.list);
2145   };
2146  
2147 < connect_leaf_mask: LEAF_MASK '=' QSTRING ';'
2147 > connect_leaf_mask: LEAF_MASK '=' QSTRING ';'
2148   {
2149    if (conf_parser_ctx.pass == 2)
2150 <  {
2342 <    struct CollectItem *yy_tmp;
2343 <
2344 <    yy_tmp = (struct CollectItem *)MyMalloc(sizeof(struct CollectItem));
2345 <    DupString(yy_tmp->host, yylval.string);
2346 <    DupString(yy_tmp->user, "*");
2347 <    dlinkAdd(yy_tmp, &yy_tmp->node, &leaf_conf_list);
2348 <  }
2150 >    dlinkAdd(xstrdup(yylval.string), make_dlink_node(), &block_state.leaf.list);
2151   };
2152  
2153   connect_class: CLASS '=' QSTRING ';'
2154   {
2155    if (conf_parser_ctx.pass == 2)
2156 <  {
2355 <    MyFree(class_name);
2356 <    DupString(class_name, yylval.string);
2357 <  }
2156 >    strlcpy(block_state.class.buf, yylval.string, sizeof(block_state.class.buf));
2157   };
2158  
2159   connect_ssl_cipher_list: T_SSL_CIPHER_LIST '=' QSTRING ';'
2160   {
2161 < #ifdef HAVE_LIBCRYPTO
2161 > #ifdef HAVE_TLS
2162    if (conf_parser_ctx.pass == 2)
2163 <  {
2365 <    MyFree(yy_aconf->cipher_list);
2366 <    DupString(yy_aconf->cipher_list, yylval.string);
2367 <  }
2163 >    strlcpy(block_state.ciph.buf, yylval.string, sizeof(block_state.ciph.buf));
2164   #else
2165    if (conf_parser_ctx.pass == 2)
2166 <    yyerror("Ignoring connect::ciphers -- no OpenSSL support");
2166 >    conf_error_report("Ignoring connect::ciphers -- no TLS support");
2167   #endif
2168   };
2169  
2170  
2171   /***************************************************************************
2172 < *  section kill
2172 > * kill {} section
2173   ***************************************************************************/
2174   kill_entry: KILL
2175   {
2176    if (conf_parser_ctx.pass == 2)
2177 <  {
2382 <    userbuf[0] = hostbuf[0] = reasonbuf[0] = '\0';
2383 <    regex_ban = 0;
2384 <  }
2177 >    reset_block_state();
2178   } '{' kill_items '}' ';'
2179   {
2180 <  if (conf_parser_ctx.pass == 2)
2181 <  {
2389 <    if (userbuf[0] && hostbuf[0])
2390 <    {
2391 <      if (regex_ban)
2392 <      {
2393 < #ifdef HAVE_LIBPCRE
2394 <        void *exp_user = NULL;
2395 <        void *exp_host = NULL;
2396 <        const char *errptr = NULL;
2397 <
2398 <        if (!(exp_user = ircd_pcre_compile(userbuf, &errptr)) ||
2399 <            !(exp_host = ircd_pcre_compile(hostbuf, &errptr)))
2400 <        {
2401 <          ilog(LOG_TYPE_IRCD, "Failed to add regular expression based K-Line: %s",
2402 <               errptr);
2403 <          break;
2404 <        }
2405 <
2406 <        yy_aconf = map_to_conf(make_conf_item(RKLINE_TYPE));
2407 <        yy_aconf->regexuser = exp_user;
2408 <        yy_aconf->regexhost = exp_host;
2409 <
2410 <        DupString(yy_aconf->user, userbuf);
2411 <        DupString(yy_aconf->host, hostbuf);
2412 <
2413 <        if (reasonbuf[0])
2414 <          DupString(yy_aconf->reason, reasonbuf);
2415 <        else
2416 <          DupString(yy_aconf->reason, "No reason");
2417 < #else
2418 <        ilog(LOG_TYPE_IRCD, "Failed to add regular expression based K-Line: no PCRE support");
2419 <        break;
2420 < #endif
2421 <      }
2422 <      else
2423 <      {
2424 <        yy_aconf = map_to_conf(make_conf_item(KLINE_TYPE));
2425 <
2426 <        DupString(yy_aconf->user, userbuf);
2427 <        DupString(yy_aconf->host, hostbuf);
2428 <
2429 <        if (reasonbuf[0])
2430 <          DupString(yy_aconf->reason, reasonbuf);
2431 <        else
2432 <          DupString(yy_aconf->reason, "No reason");
2433 <        add_conf_by_address(CONF_KILL, yy_aconf);
2434 <      }
2435 <    }
2436 <
2437 <    yy_aconf = NULL;
2438 <  }
2439 < };
2180 >  if (conf_parser_ctx.pass != 2)
2181 >    break;
2182  
2183 < kill_type: TYPE
2184 < {
2185 < } '='  kill_type_items ';';
2183 >  if (!block_state.user.buf[0] ||
2184 >      !block_state.host.buf[0])
2185 >    break;
2186 >
2187 >  struct MaskItem *conf = conf_make(CONF_KLINE);
2188 >  conf->user = xstrdup(block_state.user.buf);
2189 >  conf->host = xstrdup(block_state.host.buf);
2190  
2191 < kill_type_items: kill_type_items ',' kill_type_item | kill_type_item;
2192 < kill_type_item: REGEX_T
2193 < {
2194 <  if (conf_parser_ctx.pass == 2)
2195 <    regex_ban = 1;
2191 >  if (block_state.rpass.buf[0])
2192 >    conf->reason = xstrdup(block_state.rpass.buf);
2193 >  else
2194 >    conf->reason = xstrdup(CONF_NOREASON);
2195 >  add_conf_by_address(CONF_KLINE, conf);
2196   };
2197  
2198   kill_items:     kill_items kill_item | kill_item;
2199 < kill_item:      kill_user | kill_reason | kill_type | error;
2199 > kill_item:      kill_user | kill_reason | error;
2200  
2201   kill_user: USER '=' QSTRING ';'
2202   {
2203 +
2204    if (conf_parser_ctx.pass == 2)
2205    {
2206      struct split_nuh_item nuh;
2207  
2208      nuh.nuhmask  = yylval.string;
2209      nuh.nickptr  = NULL;
2210 <    nuh.userptr  = userbuf;
2211 <    nuh.hostptr  = hostbuf;
2210 >    nuh.userptr  = block_state.user.buf;
2211 >    nuh.hostptr  = block_state.host.buf;
2212  
2213      nuh.nicksize = 0;
2214 <    nuh.usersize = sizeof(userbuf);
2215 <    nuh.hostsize = sizeof(hostbuf);
2214 >    nuh.usersize = sizeof(block_state.user.buf);
2215 >    nuh.hostsize = sizeof(block_state.host.buf);
2216  
2217      split_nuh(&nuh);
2218    }
2219   };
2220  
2221 < kill_reason: REASON '=' QSTRING ';'
2221 > kill_reason: REASON '=' QSTRING ';'
2222   {
2223    if (conf_parser_ctx.pass == 2)
2224 <    strlcpy(reasonbuf, yylval.string, sizeof(reasonbuf));
2224 >    strlcpy(block_state.rpass.buf, yylval.string, sizeof(block_state.rpass.buf));
2225   };
2226  
2227 +
2228   /***************************************************************************
2229 < *  section deny
2229 > * deny {} section
2230   ***************************************************************************/
2231 < deny_entry: DENY
2231 > deny_entry: DENY
2232   {
2233    if (conf_parser_ctx.pass == 2)
2234 <    hostbuf[0] = reasonbuf[0] = '\0';
2234 >    reset_block_state();
2235   } '{' deny_items '}' ';'
2236   {
2237 <  if (conf_parser_ctx.pass == 2)
2237 >  if (conf_parser_ctx.pass != 2)
2238 >    break;
2239 >
2240 >  if (!block_state.addr.buf[0])
2241 >    break;
2242 >
2243 >  if (parse_netmask(block_state.addr.buf, NULL, NULL) != HM_HOST)
2244    {
2245 <    if (hostbuf[0] && parse_netmask(hostbuf, NULL, NULL) != HM_HOST)
2246 <    {
2493 <      yy_aconf = map_to_conf(make_conf_item(DLINE_TYPE));
2494 <      DupString(yy_aconf->host, hostbuf);
2245 >    struct MaskItem *conf = conf_make(CONF_DLINE);
2246 >    conf->host = xstrdup(block_state.addr.buf);
2247  
2248 <      if (reasonbuf[0])
2249 <        DupString(yy_aconf->reason, reasonbuf);
2250 <      else
2251 <        DupString(yy_aconf->reason, "No reason");
2252 <      add_conf_by_address(CONF_DLINE, yy_aconf);
2501 <      yy_aconf = NULL;
2502 <    }
2248 >    if (block_state.rpass.buf[0])
2249 >      conf->reason = xstrdup(block_state.rpass.buf);
2250 >    else
2251 >      conf->reason = xstrdup(CONF_NOREASON);
2252 >    add_conf_by_address(CONF_DLINE, conf);
2253    }
2254 < };
2254 > };
2255  
2256   deny_items:     deny_items deny_item | deny_item;
2257   deny_item:      deny_ip | deny_reason | error;
# Line 2509 | Line 2259 | deny_item:      deny_ip | deny_reason |
2259   deny_ip: IP '=' QSTRING ';'
2260   {
2261    if (conf_parser_ctx.pass == 2)
2262 <    strlcpy(hostbuf, yylval.string, sizeof(hostbuf));
2262 >    strlcpy(block_state.addr.buf, yylval.string, sizeof(block_state.addr.buf));
2263   };
2264  
2265 < deny_reason: REASON '=' QSTRING ';'
2265 > deny_reason: REASON '=' QSTRING ';'
2266   {
2267    if (conf_parser_ctx.pass == 2)
2268 <    strlcpy(reasonbuf, yylval.string, sizeof(reasonbuf));
2268 >    strlcpy(block_state.rpass.buf, yylval.string, sizeof(block_state.rpass.buf));
2269   };
2270  
2271 +
2272   /***************************************************************************
2273 < *  section exempt
2273 > * exempt {} section
2274   ***************************************************************************/
2275   exempt_entry: EXEMPT '{' exempt_items '}' ';';
2276  
2277 < exempt_items:     exempt_items exempt_item | exempt_item;
2278 < exempt_item:      exempt_ip | error;
2277 > exempt_items: exempt_items exempt_item | exempt_item;
2278 > exempt_item:  exempt_ip | error;
2279  
2280   exempt_ip: IP '=' QSTRING ';'
2281   {
2282    if (conf_parser_ctx.pass == 2)
2283    {
2284 <    if (yylval.string[0] && parse_netmask(yylval.string, NULL, NULL) != HM_HOST)
2284 >    if (*yylval.string && parse_netmask(yylval.string, NULL, NULL) != HM_HOST)
2285      {
2286 <      yy_aconf = map_to_conf(make_conf_item(EXEMPTDLINE_TYPE));
2287 <      DupString(yy_aconf->host, yylval.string);
2286 >      struct MaskItem *conf = conf_make(CONF_EXEMPT);
2287 >      conf->host = xstrdup(yylval.string);
2288  
2289 <      add_conf_by_address(CONF_EXEMPTDLINE, yy_aconf);
2539 <      yy_aconf = NULL;
2289 >      add_conf_by_address(CONF_EXEMPT, conf);
2290      }
2291    }
2292   };
2293  
2294   /***************************************************************************
2295 < *  section gecos
2295 > * gecos {} section
2296   ***************************************************************************/
2297   gecos_entry: GECOS
2298   {
2299    if (conf_parser_ctx.pass == 2)
2300 <  {
2551 <    regex_ban = 0;
2552 <    reasonbuf[0] = gecos_name[0] = '\0';
2553 <  }
2300 >    reset_block_state();
2301   } '{' gecos_items '}' ';'
2302   {
2303 <  if (conf_parser_ctx.pass == 2)
2304 <  {
2558 <    if (gecos_name[0])
2559 <    {
2560 <      if (regex_ban)
2561 <      {
2562 < #ifdef HAVE_LIBPCRE
2563 <        void *exp_p = NULL;
2564 <        const char *errptr = NULL;
2565 <
2566 <        if (!(exp_p = ircd_pcre_compile(gecos_name, &errptr)))
2567 <        {
2568 <          ilog(LOG_TYPE_IRCD, "Failed to add regular expression based X-Line: %s",
2569 <               errptr);
2570 <          break;
2571 <        }
2303 >  if (conf_parser_ctx.pass != 2)
2304 >    break;
2305  
2306 <        yy_conf = make_conf_item(RXLINE_TYPE);
2307 <        yy_conf->regexpname = exp_p;
2575 < #else
2576 <        ilog(LOG_TYPE_IRCD, "Failed to add regular expression based X-Line: no PCRE support");
2577 <        break;
2578 < #endif
2579 <      }
2580 <      else
2581 <        yy_conf = make_conf_item(XLINE_TYPE);
2582 <
2583 <      yy_match_item = map_to_conf(yy_conf);
2584 <      DupString(yy_conf->name, gecos_name);
2585 <
2586 <      if (reasonbuf[0])
2587 <        DupString(yy_match_item->reason, reasonbuf);
2588 <      else
2589 <        DupString(yy_match_item->reason, "No reason");
2590 <    }
2591 <  }
2592 < };
2306 >  if (!block_state.name.buf[0])
2307 >    break;
2308  
2309 < gecos_flags: TYPE
2310 < {
2596 < } '='  gecos_flags_items ';';
2309 >  struct GecosItem *gecos = gecos_make();
2310 >  gecos->mask = xstrdup(block_state.name.buf);
2311  
2312 < gecos_flags_items: gecos_flags_items ',' gecos_flags_item | gecos_flags_item;
2313 < gecos_flags_item: REGEX_T
2314 < {
2315 <  if (conf_parser_ctx.pass == 2)
2602 <    regex_ban = 1;
2312 >  if (block_state.rpass.buf[0])
2313 >    gecos->reason = xstrdup(block_state.rpass.buf);
2314 >  else
2315 >    gecos->reason = xstrdup(CONF_NOREASON);
2316   };
2317  
2318   gecos_items: gecos_items gecos_item | gecos_item;
2319 < gecos_item:  gecos_name | gecos_reason | gecos_flags | error;
2319 > gecos_item:  gecos_name | gecos_reason | error;
2320  
2321 < gecos_name: NAME '=' QSTRING ';'
2321 > gecos_name: NAME '=' QSTRING ';'
2322   {
2323    if (conf_parser_ctx.pass == 2)
2324 <    strlcpy(gecos_name, yylval.string, sizeof(gecos_name));
2324 >    strlcpy(block_state.name.buf, yylval.string, sizeof(block_state.name.buf));
2325   };
2326  
2327 < gecos_reason: REASON '=' QSTRING ';'
2327 > gecos_reason: REASON '=' QSTRING ';'
2328   {
2329    if (conf_parser_ctx.pass == 2)
2330 <    strlcpy(reasonbuf, yylval.string, sizeof(reasonbuf));
2330 >    strlcpy(block_state.rpass.buf, yylval.string, sizeof(block_state.rpass.buf));
2331   };
2332  
2333 +
2334   /***************************************************************************
2335 < *  section general
2335 > * general {} section
2336   ***************************************************************************/
2337 < general_entry: GENERAL
2624 <  '{' general_items '}' ';';
2337 > general_entry: GENERAL '{' general_items '}' ';';
2338  
2339   general_items:      general_items general_item | general_item;
2340 < general_item:       general_hide_spoof_ips | general_ignore_bogus_ts |
2341 <                    general_failed_oper_notice | general_anti_nick_flood |
2342 <                    general_max_nick_time | general_max_nick_changes |
2343 <                    general_max_accept | general_anti_spam_exit_message_time |
2344 <                    general_ts_warn_delta | general_ts_max_delta |
2345 <                    general_kill_chase_time_limit | general_kline_with_reason |
2346 <                    general_kline_reason | general_invisible_on_connect |
2347 <                    general_warn_no_nline | general_dots_in_ident |
2348 <                    general_stats_o_oper_only | general_stats_k_oper_only |
2349 <                    general_pace_wait | general_stats_i_oper_only |
2350 <                    general_pace_wait_simple | general_stats_P_oper_only |
2351 <                    general_short_motd | general_no_oper_flood |
2352 <                    general_true_no_oper_flood | general_oper_pass_resv |
2353 <                    general_message_locale |
2354 <                    general_oper_only_umodes | general_max_targets |
2355 <                    general_use_egd | general_egdpool_path |
2356 <                    general_oper_umodes | general_caller_id_wait |
2357 <                    general_opers_bypass_callerid | general_default_floodcount |
2358 <                    general_min_nonwildcard | general_min_nonwildcard_simple |
2359 <                    general_disable_remote_commands |
2360 <                    general_client_flood |
2361 <                    general_throttle_time | general_havent_read_conf |
2340 > general_item:       general_away_count |
2341 >                    general_away_time |
2342 >                    general_failed_oper_notice |
2343 >                    general_anti_nick_flood |
2344 >                    general_max_nick_time |
2345 >                    general_max_nick_changes |
2346 >                    general_max_accept |
2347 >                    general_whowas_history_length |
2348 >                    general_anti_spam_exit_message_time |
2349 >                    general_ts_warn_delta |
2350 >                    general_ts_max_delta |
2351 >                    general_kill_chase_time_limit |
2352 >                    general_invisible_on_connect |
2353 >                    general_warn_no_connect_block |
2354 >                    general_dots_in_ident |
2355 >                    general_stats_i_oper_only |
2356 >                    general_stats_k_oper_only |
2357 >                    general_stats_m_oper_only |
2358 >                    general_stats_o_oper_only |
2359 >                    general_stats_P_oper_only |
2360 >                    general_stats_u_oper_only |
2361 >                    general_pace_wait |
2362 >                    general_pace_wait_simple |
2363 >                    general_short_motd |
2364 >                    general_no_oper_flood |
2365 >                    general_oper_only_umodes |
2366 >                    general_max_targets |
2367 >                    general_oper_umodes |
2368 >                    general_caller_id_wait |
2369 >                    general_opers_bypass_callerid |
2370 >                    general_default_floodcount |
2371 >                    general_default_floodtime |
2372 >                    general_min_nonwildcard |
2373 >                    general_min_nonwildcard_simple |
2374 >                    general_throttle_count |
2375 >                    general_throttle_time |
2376                      general_ping_cookie |
2377 <                    general_disable_auth |
2378 <                    general_tkline_expire_notices | general_gline_min_cidr |
2379 <                    general_gline_min_cidr6 | general_use_whois_actually |
2380 <                    general_reject_hold_time | general_stats_e_disabled |
2381 <                    general_max_watch | general_services_name |
2382 <                    error;
2377 >                    general_disable_auth |
2378 >                    general_dline_min_cidr |
2379 >                    general_dline_min_cidr6 |
2380 >                    general_kline_min_cidr |
2381 >                    general_kline_min_cidr6 |
2382 >                    general_stats_e_disabled |
2383 >                    general_max_watch |
2384 >                    general_cycle_on_host_change |
2385 >                    error;
2386  
2387  
2388 < general_max_watch: MAX_WATCH '=' NUMBER ';'
2388 > general_away_count: AWAY_COUNT '=' NUMBER ';'
2389   {
2390 <  ConfigFileEntry.max_watch = $3;
2390 >  ConfigGeneral.away_count = $3;
2391   };
2392  
2393 < general_gline_min_cidr: GLINE_MIN_CIDR '=' NUMBER ';'
2393 > general_away_time: AWAY_TIME '=' timespec ';'
2394   {
2395 <  ConfigFileEntry.gline_min_cidr = $3;
2395 >  ConfigGeneral.away_time = $3;
2396   };
2397  
2398 < general_gline_min_cidr6: GLINE_MIN_CIDR6 '=' NUMBER ';'
2398 > general_max_watch: MAX_WATCH '=' NUMBER ';'
2399   {
2400 <  ConfigFileEntry.gline_min_cidr6 = $3;
2400 >  ConfigGeneral.max_watch = $3;
2401   };
2402  
2403 < general_use_whois_actually: USE_WHOIS_ACTUALLY '=' TBOOL ';'
2403 > general_whowas_history_length: WHOWAS_HISTORY_LENGTH '=' NUMBER ';'
2404   {
2405 <  ConfigFileEntry.use_whois_actually = yylval.number;
2405 >  ConfigGeneral.whowas_history_length = $3;
2406   };
2407  
2408 < general_reject_hold_time: TREJECT_HOLD_TIME '=' timespec ';'
2408 > general_cycle_on_host_change: CYCLE_ON_HOST_CHANGE '=' TBOOL ';'
2409   {
2410 <  GlobalSetOptions.rejecttime = yylval.number;
2410 >  ConfigGeneral.cycle_on_host_change = yylval.number;
2411   };
2412  
2413 < general_tkline_expire_notices: TKLINE_EXPIRE_NOTICES '=' TBOOL ';'
2413 > general_dline_min_cidr: DLINE_MIN_CIDR '=' NUMBER ';'
2414   {
2415 <  ConfigFileEntry.tkline_expire_notices = yylval.number;
2415 >  ConfigGeneral.dline_min_cidr = $3;
2416   };
2417  
2418 < general_kill_chase_time_limit: KILL_CHASE_TIME_LIMIT '=' timespec ';'
2418 > general_dline_min_cidr6: DLINE_MIN_CIDR6 '=' NUMBER ';'
2419   {
2420 <  ConfigFileEntry.kill_chase_time_limit = $3;
2420 >  ConfigGeneral.dline_min_cidr6 = $3;
2421   };
2422  
2423 < general_hide_spoof_ips: HIDE_SPOOF_IPS '=' TBOOL ';'
2423 > general_kline_min_cidr: KLINE_MIN_CIDR '=' NUMBER ';'
2424   {
2425 <  ConfigFileEntry.hide_spoof_ips = yylval.number;
2425 >  ConfigGeneral.kline_min_cidr = $3;
2426   };
2427  
2428 < general_ignore_bogus_ts: IGNORE_BOGUS_TS '=' TBOOL ';'
2428 > general_kline_min_cidr6: KLINE_MIN_CIDR6 '=' NUMBER ';'
2429   {
2430 <  ConfigFileEntry.ignore_bogus_ts = yylval.number;
2430 >  ConfigGeneral.kline_min_cidr6 = $3;
2431   };
2432  
2433 < general_disable_remote_commands: DISABLE_REMOTE_COMMANDS '=' TBOOL ';'
2433 > general_kill_chase_time_limit: KILL_CHASE_TIME_LIMIT '=' timespec ';'
2434   {
2435 <  ConfigFileEntry.disable_remote = yylval.number;
2435 >  ConfigGeneral.kill_chase_time_limit = $3;
2436   };
2437  
2438   general_failed_oper_notice: FAILED_OPER_NOTICE '=' TBOOL ';'
2439   {
2440 <  ConfigFileEntry.failed_oper_notice = yylval.number;
2440 >  ConfigGeneral.failed_oper_notice = yylval.number;
2441   };
2442  
2443   general_anti_nick_flood: ANTI_NICK_FLOOD '=' TBOOL ';'
2444   {
2445 <  ConfigFileEntry.anti_nick_flood = yylval.number;
2445 >  ConfigGeneral.anti_nick_flood = yylval.number;
2446   };
2447  
2448   general_max_nick_time: MAX_NICK_TIME '=' timespec ';'
2449   {
2450 <  ConfigFileEntry.max_nick_time = $3;
2450 >  ConfigGeneral.max_nick_time = $3;
2451   };
2452  
2453   general_max_nick_changes: MAX_NICK_CHANGES '=' NUMBER ';'
2454   {
2455 <  ConfigFileEntry.max_nick_changes = $3;
2455 >  ConfigGeneral.max_nick_changes = $3;
2456   };
2457  
2458   general_max_accept: MAX_ACCEPT '=' NUMBER ';'
2459   {
2460 <  ConfigFileEntry.max_accept = $3;
2460 >  ConfigGeneral.max_accept = $3;
2461   };
2462  
2463   general_anti_spam_exit_message_time: ANTI_SPAM_EXIT_MESSAGE_TIME '=' timespec ';'
2464   {
2465 <  ConfigFileEntry.anti_spam_exit_message_time = $3;
2465 >  ConfigGeneral.anti_spam_exit_message_time = $3;
2466   };
2467  
2468   general_ts_warn_delta: TS_WARN_DELTA '=' timespec ';'
2469   {
2470 <  ConfigFileEntry.ts_warn_delta = $3;
2470 >  ConfigGeneral.ts_warn_delta = $3;
2471   };
2472  
2473   general_ts_max_delta: TS_MAX_DELTA '=' timespec ';'
2474   {
2475 <  if (conf_parser_ctx.pass == 2)
2746 <    ConfigFileEntry.ts_max_delta = $3;
2747 < };
2748 <
2749 < general_havent_read_conf: HAVENT_READ_CONF '=' NUMBER ';'
2750 < {
2751 <  if (($3 > 0) && conf_parser_ctx.pass == 1)
2752 <  {
2753 <    ilog(LOG_TYPE_IRCD, "You haven't read your config file properly.");
2754 <    ilog(LOG_TYPE_IRCD, "There is a line in the example conf that will kill your server if not removed.");
2755 <    ilog(LOG_TYPE_IRCD, "Consider actually reading/editing the conf file, and removing this line.");
2756 <    exit(0);
2757 <  }
2475 >  ConfigGeneral.ts_max_delta = $3;
2476   };
2477  
2478 < general_kline_with_reason: KLINE_WITH_REASON '=' TBOOL ';'
2478 > general_invisible_on_connect: INVISIBLE_ON_CONNECT '=' TBOOL ';'
2479   {
2480 <  ConfigFileEntry.kline_with_reason = yylval.number;
2480 >  ConfigGeneral.invisible_on_connect = yylval.number;
2481   };
2482  
2483 < general_kline_reason: KLINE_REASON '=' QSTRING ';'
2483 > general_warn_no_connect_block: WARN_NO_CONNECT_BLOCK '=' TBOOL ';'
2484   {
2485 <  if (conf_parser_ctx.pass == 2)
2768 <  {
2769 <    MyFree(ConfigFileEntry.kline_reason);
2770 <    DupString(ConfigFileEntry.kline_reason, yylval.string);
2771 <  }
2485 >  ConfigGeneral.warn_no_connect_block = yylval.number;
2486   };
2487  
2488 < general_invisible_on_connect: INVISIBLE_ON_CONNECT '=' TBOOL ';'
2488 > general_stats_e_disabled: STATS_E_DISABLED '=' TBOOL ';'
2489   {
2490 <  ConfigFileEntry.invisible_on_connect = yylval.number;
2490 >  ConfigGeneral.stats_e_disabled = yylval.number;
2491   };
2492  
2493 < general_warn_no_nline: WARN_NO_NLINE '=' TBOOL ';'
2493 > general_stats_m_oper_only: STATS_M_OPER_ONLY '=' TBOOL ';'
2494   {
2495 <  ConfigFileEntry.warn_no_nline = yylval.number;
2495 >  ConfigGeneral.stats_m_oper_only = yylval.number;
2496   };
2497  
2498 < general_stats_e_disabled: STATS_E_DISABLED '=' TBOOL ';'
2498 > general_stats_o_oper_only: STATS_O_OPER_ONLY '=' TBOOL ';'
2499   {
2500 <  ConfigFileEntry.stats_e_disabled = yylval.number;
2500 >  ConfigGeneral.stats_o_oper_only = yylval.number;
2501   };
2502  
2503 < general_stats_o_oper_only: STATS_O_OPER_ONLY '=' TBOOL ';'
2503 > general_stats_P_oper_only: STATS_P_OPER_ONLY '=' TBOOL ';'
2504   {
2505 <  ConfigFileEntry.stats_o_oper_only = yylval.number;
2505 >  ConfigGeneral.stats_P_oper_only = yylval.number;
2506   };
2507  
2508 < general_stats_P_oper_only: STATS_P_OPER_ONLY '=' TBOOL ';'
2508 > general_stats_u_oper_only: STATS_U_OPER_ONLY '=' TBOOL ';'
2509   {
2510 <  ConfigFileEntry.stats_P_oper_only = yylval.number;
2510 >  ConfigGeneral.stats_u_oper_only = yylval.number;
2511   };
2512  
2513   general_stats_k_oper_only: STATS_K_OPER_ONLY '=' TBOOL ';'
2514   {
2515 <  ConfigFileEntry.stats_k_oper_only = 2 * yylval.number;
2515 >  ConfigGeneral.stats_k_oper_only = 2 * yylval.number;
2516   } | STATS_K_OPER_ONLY '=' TMASKED ';'
2517   {
2518 <  ConfigFileEntry.stats_k_oper_only = 1;
2518 >  ConfigGeneral.stats_k_oper_only = 1;
2519   };
2520  
2521   general_stats_i_oper_only: STATS_I_OPER_ONLY '=' TBOOL ';'
2522   {
2523 <  ConfigFileEntry.stats_i_oper_only = 2 * yylval.number;
2523 >  ConfigGeneral.stats_i_oper_only = 2 * yylval.number;
2524   } | STATS_I_OPER_ONLY '=' TMASKED ';'
2525   {
2526 <  ConfigFileEntry.stats_i_oper_only = 1;
2526 >  ConfigGeneral.stats_i_oper_only = 1;
2527   };
2528  
2529   general_pace_wait: PACE_WAIT '=' timespec ';'
2530   {
2531 <  ConfigFileEntry.pace_wait = $3;
2531 >  ConfigGeneral.pace_wait = $3;
2532   };
2533  
2534   general_caller_id_wait: CALLER_ID_WAIT '=' timespec ';'
2535   {
2536 <  ConfigFileEntry.caller_id_wait = $3;
2536 >  ConfigGeneral.caller_id_wait = $3;
2537   };
2538  
2539   general_opers_bypass_callerid: OPERS_BYPASS_CALLERID '=' TBOOL ';'
2540   {
2541 <  ConfigFileEntry.opers_bypass_callerid = yylval.number;
2541 >  ConfigGeneral.opers_bypass_callerid = yylval.number;
2542   };
2543  
2544   general_pace_wait_simple: PACE_WAIT_SIMPLE '=' timespec ';'
2545   {
2546 <  ConfigFileEntry.pace_wait_simple = $3;
2546 >  ConfigGeneral.pace_wait_simple = $3;
2547   };
2548  
2549   general_short_motd: SHORT_MOTD '=' TBOOL ';'
2550   {
2551 <  ConfigFileEntry.short_motd = yylval.number;
2838 < };
2839 <  
2840 < general_no_oper_flood: NO_OPER_FLOOD '=' TBOOL ';'
2841 < {
2842 <  ConfigFileEntry.no_oper_flood = yylval.number;
2843 < };
2844 <
2845 < general_true_no_oper_flood: TRUE_NO_OPER_FLOOD '=' TBOOL ';'
2846 < {
2847 <  ConfigFileEntry.true_no_oper_flood = yylval.number;
2848 < };
2849 <
2850 < general_oper_pass_resv: OPER_PASS_RESV '=' TBOOL ';'
2851 < {
2852 <  ConfigFileEntry.oper_pass_resv = yylval.number;
2551 >  ConfigGeneral.short_motd = yylval.number;
2552   };
2553  
2554 < general_message_locale: MESSAGE_LOCALE '=' QSTRING ';'
2554 > general_no_oper_flood: NO_OPER_FLOOD '=' TBOOL ';'
2555   {
2556 <  if (conf_parser_ctx.pass == 2)
2858 <  {
2859 <    if (strlen(yylval.string) > LOCALE_LENGTH-2)
2860 <      yylval.string[LOCALE_LENGTH-1] = '\0';
2861 <
2862 <    set_locale(yylval.string);
2863 <  }
2556 >  ConfigGeneral.no_oper_flood = yylval.number;
2557   };
2558  
2559   general_dots_in_ident: DOTS_IN_IDENT '=' NUMBER ';'
2560   {
2561 <  ConfigFileEntry.dots_in_ident = $3;
2561 >  ConfigGeneral.dots_in_ident = $3;
2562   };
2563  
2564   general_max_targets: MAX_TARGETS '=' NUMBER ';'
2565   {
2566 <  ConfigFileEntry.max_targets = $3;
2566 >  ConfigGeneral.max_targets = $3;
2567   };
2568  
2569 < general_use_egd: USE_EGD '=' TBOOL ';'
2877 < {
2878 <  ConfigFileEntry.use_egd = yylval.number;
2879 < };
2880 <
2881 < general_egdpool_path: EGDPOOL_PATH '=' QSTRING ';'
2882 < {
2883 <  if (conf_parser_ctx.pass == 2)
2884 <  {
2885 <    MyFree(ConfigFileEntry.egdpool_path);
2886 <    DupString(ConfigFileEntry.egdpool_path, yylval.string);
2887 <  }
2888 < };
2889 <
2890 < general_services_name: T_SERVICES_NAME '=' QSTRING ';'
2569 > general_ping_cookie: PING_COOKIE '=' TBOOL ';'
2570   {
2571 <  if (conf_parser_ctx.pass == 2 && valid_servname(yylval.string))
2893 <  {
2894 <    MyFree(ConfigFileEntry.service_name);
2895 <    DupString(ConfigFileEntry.service_name, yylval.string);
2896 <  }
2571 >  ConfigGeneral.ping_cookie = yylval.number;
2572   };
2573  
2574 < general_ping_cookie: PING_COOKIE '=' TBOOL ';'
2574 > general_disable_auth: DISABLE_AUTH '=' TBOOL ';'
2575   {
2576 <  ConfigFileEntry.ping_cookie = yylval.number;
2576 >  ConfigGeneral.disable_auth = yylval.number;
2577   };
2578  
2579 < general_disable_auth: DISABLE_AUTH '=' TBOOL ';'
2579 > general_throttle_count: THROTTLE_COUNT '=' NUMBER ';'
2580   {
2581 <  ConfigFileEntry.disable_auth = yylval.number;
2581 >  ConfigGeneral.throttle_count = $3;
2582   };
2583  
2584   general_throttle_time: THROTTLE_TIME '=' timespec ';'
2585   {
2586 <  ConfigFileEntry.throttle_time = yylval.number;
2586 >  ConfigGeneral.throttle_time = $3;
2587   };
2588  
2589   general_oper_umodes: OPER_UMODES
2590   {
2591 <  ConfigFileEntry.oper_umodes = 0;
2592 < } '='  umode_oitems ';' ;
2591 >  ConfigGeneral.oper_umodes = 0;
2592 > } '=' umode_oitems ';' ;
2593  
2594   umode_oitems:    umode_oitems ',' umode_oitem | umode_oitem;
2595   umode_oitem:     T_BOTS
2596   {
2597 <  ConfigFileEntry.oper_umodes |= UMODE_BOTS;
2597 >  ConfigGeneral.oper_umodes |= UMODE_BOTS;
2598   } | T_CCONN
2599   {
2600 <  ConfigFileEntry.oper_umodes |= UMODE_CCONN;
2926 < } | T_CCONN_FULL
2927 < {
2928 <  ConfigFileEntry.oper_umodes |= UMODE_CCONN_FULL;
2600 >  ConfigGeneral.oper_umodes |= UMODE_CCONN;
2601   } | T_DEAF
2602   {
2603 <  ConfigFileEntry.oper_umodes |= UMODE_DEAF;
2603 >  ConfigGeneral.oper_umodes |= UMODE_DEAF;
2604   } | T_DEBUG
2605   {
2606 <  ConfigFileEntry.oper_umodes |= UMODE_DEBUG;
2606 >  ConfigGeneral.oper_umodes |= UMODE_DEBUG;
2607   } | T_FULL
2608   {
2609 <  ConfigFileEntry.oper_umodes |= UMODE_FULL;
2609 >  ConfigGeneral.oper_umodes |= UMODE_FULL;
2610   } | HIDDEN
2611   {
2612 <  ConfigFileEntry.oper_umodes |= UMODE_HIDDEN;
2612 >  ConfigGeneral.oper_umodes |= UMODE_HIDDEN;
2613 > } | HIDE_CHANS
2614 > {
2615 >  ConfigGeneral.oper_umodes |= UMODE_HIDECHANS;
2616 > } | HIDE_IDLE
2617 > {
2618 >  ConfigGeneral.oper_umodes |= UMODE_HIDEIDLE;
2619   } | T_SKILL
2620   {
2621 <  ConfigFileEntry.oper_umodes |= UMODE_SKILL;
2621 >  ConfigGeneral.oper_umodes |= UMODE_SKILL;
2622   } | T_NCHANGE
2623   {
2624 <  ConfigFileEntry.oper_umodes |= UMODE_NCHANGE;
2624 >  ConfigGeneral.oper_umodes |= UMODE_NCHANGE;
2625   } | T_REJ
2626   {
2627 <  ConfigFileEntry.oper_umodes |= UMODE_REJ;
2627 >  ConfigGeneral.oper_umodes |= UMODE_REJ;
2628   } | T_UNAUTH
2629   {
2630 <  ConfigFileEntry.oper_umodes |= UMODE_UNAUTH;
2630 >  ConfigGeneral.oper_umodes |= UMODE_UNAUTH;
2631   } | T_SPY
2632   {
2633 <  ConfigFileEntry.oper_umodes |= UMODE_SPY;
2633 >  ConfigGeneral.oper_umodes |= UMODE_SPY;
2634   } | T_EXTERNAL
2635   {
2636 <  ConfigFileEntry.oper_umodes |= UMODE_EXTERNAL;
2959 < } | T_OPERWALL
2960 < {
2961 <  ConfigFileEntry.oper_umodes |= UMODE_OPERWALL;
2636 >  ConfigGeneral.oper_umodes |= UMODE_EXTERNAL;
2637   } | T_SERVNOTICE
2638   {
2639 <  ConfigFileEntry.oper_umodes |= UMODE_SERVNOTICE;
2639 >  ConfigGeneral.oper_umodes |= UMODE_SERVNOTICE;
2640   } | T_INVISIBLE
2641   {
2642 <  ConfigFileEntry.oper_umodes |= UMODE_INVISIBLE;
2642 >  ConfigGeneral.oper_umodes |= UMODE_INVISIBLE;
2643   } | T_WALLOP
2644   {
2645 <  ConfigFileEntry.oper_umodes |= UMODE_WALLOP;
2645 >  ConfigGeneral.oper_umodes |= UMODE_WALLOP;
2646   } | T_SOFTCALLERID
2647   {
2648 <  ConfigFileEntry.oper_umodes |= UMODE_SOFTCALLERID;
2648 >  ConfigGeneral.oper_umodes |= UMODE_SOFTCALLERID;
2649   } | T_CALLERID
2650   {
2651 <  ConfigFileEntry.oper_umodes |= UMODE_CALLERID;
2651 >  ConfigGeneral.oper_umodes |= UMODE_CALLERID;
2652   } | T_LOCOPS
2653   {
2654 <  ConfigFileEntry.oper_umodes |= UMODE_LOCOPS;
2654 >  ConfigGeneral.oper_umodes |= UMODE_LOCOPS;
2655 > } | T_NONONREG
2656 > {
2657 >  ConfigGeneral.oper_umodes |= UMODE_REGONLY;
2658 > } | T_FARCONNECT
2659 > {
2660 >  ConfigGeneral.oper_umodes |= UMODE_FARCONNECT;
2661 > } | EXPIRATION
2662 > {
2663 >  ConfigGeneral.oper_umodes |= UMODE_EXPIRATION;
2664   };
2665  
2666 < general_oper_only_umodes: OPER_ONLY_UMODES
2666 > general_oper_only_umodes: OPER_ONLY_UMODES
2667   {
2668 <  ConfigFileEntry.oper_only_umodes = 0;
2669 < } '='  umode_items ';' ;
2668 >  ConfigGeneral.oper_only_umodes = 0;
2669 > } '=' umode_items ';' ;
2670  
2671 < umode_items:    umode_items ',' umode_item | umode_item;
2672 < umode_item:     T_BOTS
2671 > umode_items:  umode_items ',' umode_item | umode_item;
2672 > umode_item:   T_BOTS
2673   {
2674 <  ConfigFileEntry.oper_only_umodes |= UMODE_BOTS;
2674 >  ConfigGeneral.oper_only_umodes |= UMODE_BOTS;
2675   } | T_CCONN
2676   {
2677 <  ConfigFileEntry.oper_only_umodes |= UMODE_CCONN;
2994 < } | T_CCONN_FULL
2995 < {
2996 <  ConfigFileEntry.oper_only_umodes |= UMODE_CCONN_FULL;
2677 >  ConfigGeneral.oper_only_umodes |= UMODE_CCONN;
2678   } | T_DEAF
2679   {
2680 <  ConfigFileEntry.oper_only_umodes |= UMODE_DEAF;
2680 >  ConfigGeneral.oper_only_umodes |= UMODE_DEAF;
2681   } | T_DEBUG
2682   {
2683 <  ConfigFileEntry.oper_only_umodes |= UMODE_DEBUG;
2683 >  ConfigGeneral.oper_only_umodes |= UMODE_DEBUG;
2684   } | T_FULL
2685 < {
2686 <  ConfigFileEntry.oper_only_umodes |= UMODE_FULL;
2685 > {
2686 >  ConfigGeneral.oper_only_umodes |= UMODE_FULL;
2687   } | T_SKILL
2688   {
2689 <  ConfigFileEntry.oper_only_umodes |= UMODE_SKILL;
2689 >  ConfigGeneral.oper_only_umodes |= UMODE_SKILL;
2690   } | HIDDEN
2691   {
2692 <  ConfigFileEntry.oper_only_umodes |= UMODE_HIDDEN;
2692 >  ConfigGeneral.oper_only_umodes |= UMODE_HIDDEN;
2693   } | T_NCHANGE
2694   {
2695 <  ConfigFileEntry.oper_only_umodes |= UMODE_NCHANGE;
2695 >  ConfigGeneral.oper_only_umodes |= UMODE_NCHANGE;
2696   } | T_REJ
2697   {
2698 <  ConfigFileEntry.oper_only_umodes |= UMODE_REJ;
2698 >  ConfigGeneral.oper_only_umodes |= UMODE_REJ;
2699   } | T_UNAUTH
2700   {
2701 <  ConfigFileEntry.oper_only_umodes |= UMODE_UNAUTH;
2701 >  ConfigGeneral.oper_only_umodes |= UMODE_UNAUTH;
2702   } | T_SPY
2703   {
2704 <  ConfigFileEntry.oper_only_umodes |= UMODE_SPY;
2704 >  ConfigGeneral.oper_only_umodes |= UMODE_SPY;
2705   } | T_EXTERNAL
2706   {
2707 <  ConfigFileEntry.oper_only_umodes |= UMODE_EXTERNAL;
3027 < } | T_OPERWALL
3028 < {
3029 <  ConfigFileEntry.oper_only_umodes |= UMODE_OPERWALL;
2707 >  ConfigGeneral.oper_only_umodes |= UMODE_EXTERNAL;
2708   } | T_SERVNOTICE
2709   {
2710 <  ConfigFileEntry.oper_only_umodes |= UMODE_SERVNOTICE;
2710 >  ConfigGeneral.oper_only_umodes |= UMODE_SERVNOTICE;
2711   } | T_INVISIBLE
2712   {
2713 <  ConfigFileEntry.oper_only_umodes |= UMODE_INVISIBLE;
2713 >  ConfigGeneral.oper_only_umodes |= UMODE_INVISIBLE;
2714   } | T_WALLOP
2715   {
2716 <  ConfigFileEntry.oper_only_umodes |= UMODE_WALLOP;
2716 >  ConfigGeneral.oper_only_umodes |= UMODE_WALLOP;
2717   } | T_SOFTCALLERID
2718   {
2719 <  ConfigFileEntry.oper_only_umodes |= UMODE_SOFTCALLERID;
2719 >  ConfigGeneral.oper_only_umodes |= UMODE_SOFTCALLERID;
2720   } | T_CALLERID
2721   {
2722 <  ConfigFileEntry.oper_only_umodes |= UMODE_CALLERID;
2722 >  ConfigGeneral.oper_only_umodes |= UMODE_CALLERID;
2723   } | T_LOCOPS
2724   {
2725 <  ConfigFileEntry.oper_only_umodes |= UMODE_LOCOPS;
2726 < };
3049 <
3050 < general_min_nonwildcard: MIN_NONWILDCARD '=' NUMBER ';'
3051 < {
3052 <  ConfigFileEntry.min_nonwildcard = $3;
3053 < };
3054 <
3055 < general_min_nonwildcard_simple: MIN_NONWILDCARD_SIMPLE '=' NUMBER ';'
3056 < {
3057 <  ConfigFileEntry.min_nonwildcard_simple = $3;
3058 < };
3059 <
3060 < general_default_floodcount: DEFAULT_FLOODCOUNT '=' NUMBER ';'
3061 < {
3062 <  ConfigFileEntry.default_floodcount = $3;
3063 < };
3064 <
3065 < general_client_flood: T_CLIENT_FLOOD '=' sizespec ';'
3066 < {
3067 <  ConfigFileEntry.client_flood = $3;
3068 < };
3069 <
3070 <
3071 < /***************************************************************************
3072 < *  section glines
3073 < ***************************************************************************/
3074 < gline_entry: GLINES
3075 < {
3076 <  if (conf_parser_ctx.pass == 2)
3077 <  {
3078 <    yy_conf = make_conf_item(GDENY_TYPE);
3079 <    yy_aconf = map_to_conf(yy_conf);
3080 <  }
3081 < } '{' gline_items '}' ';'
2725 >  ConfigGeneral.oper_only_umodes |= UMODE_LOCOPS;
2726 > } | T_NONONREG
2727   {
2728 <  if (conf_parser_ctx.pass == 2)
2729 <  {
3085 <    /*
3086 <     * since we re-allocate yy_conf/yy_aconf after the end of action=, at the
3087 <     * end we will have one extra, so we should free it.
3088 <     */
3089 <    if (yy_conf->name == NULL || yy_aconf->user == NULL)
3090 <    {
3091 <      delete_conf_item(yy_conf);
3092 <      yy_conf = NULL;
3093 <      yy_aconf = NULL;
3094 <    }
3095 <  }
3096 < };
3097 <
3098 < gline_items:        gline_items gline_item | gline_item;
3099 < gline_item:         gline_enable |
3100 <                    gline_duration |
3101 <                    gline_logging |
3102 <                    gline_user |
3103 <                    gline_server |
3104 <                    gline_action |
3105 <                    error;
3106 <
3107 < gline_enable: ENABLE '=' TBOOL ';'
2728 >  ConfigGeneral.oper_only_umodes |= UMODE_REGONLY;
2729 > } | T_FARCONNECT
2730   {
2731 <  if (conf_parser_ctx.pass == 2)
2732 <    ConfigFileEntry.glines = yylval.number;
3111 < };
3112 <
3113 < gline_duration: DURATION '=' timespec ';'
2731 >  ConfigGeneral.oper_only_umodes |= UMODE_FARCONNECT;
2732 > } | EXPIRATION
2733   {
2734 <  if (conf_parser_ctx.pass == 2)
3116 <    ConfigFileEntry.gline_time = $3;
2734 >  ConfigGeneral.oper_only_umodes |= UMODE_EXPIRATION;
2735   };
2736  
2737 < gline_logging: T_LOG
3120 < {
3121 <  if (conf_parser_ctx.pass == 2)
3122 <    ConfigFileEntry.gline_logging = 0;
3123 < } '=' gline_logging_types ';';
3124 < gline_logging_types:     gline_logging_types ',' gline_logging_type_item | gline_logging_type_item;
3125 < gline_logging_type_item: T_REJECT
3126 < {
3127 <  if (conf_parser_ctx.pass == 2)
3128 <    ConfigFileEntry.gline_logging |= GDENY_REJECT;
3129 < } | T_BLOCK
2737 > general_min_nonwildcard: MIN_NONWILDCARD '=' NUMBER ';'
2738   {
2739 <  if (conf_parser_ctx.pass == 2)
3132 <    ConfigFileEntry.gline_logging |= GDENY_BLOCK;
2739 >  ConfigGeneral.min_nonwildcard = $3;
2740   };
2741  
2742 < gline_user: USER '=' QSTRING ';'
2742 > general_min_nonwildcard_simple: MIN_NONWILDCARD_SIMPLE '=' NUMBER ';'
2743   {
2744 <  if (conf_parser_ctx.pass == 2)
3138 <  {
3139 <    struct split_nuh_item nuh;
3140 <
3141 <    nuh.nuhmask  = yylval.string;
3142 <    nuh.nickptr  = NULL;
3143 <    nuh.userptr  = userbuf;
3144 <    nuh.hostptr  = hostbuf;
3145 <
3146 <    nuh.nicksize = 0;
3147 <    nuh.usersize = sizeof(userbuf);
3148 <    nuh.hostsize = sizeof(hostbuf);
3149 <
3150 <    split_nuh(&nuh);
3151 <
3152 <    if (yy_aconf->user == NULL)
3153 <    {
3154 <      DupString(yy_aconf->user, userbuf);
3155 <      DupString(yy_aconf->host, hostbuf);
3156 <    }
3157 <    else
3158 <    {
3159 <      struct CollectItem *yy_tmp = MyMalloc(sizeof(struct CollectItem));
3160 <
3161 <      DupString(yy_tmp->user, userbuf);
3162 <      DupString(yy_tmp->host, hostbuf);
3163 <
3164 <      dlinkAdd(yy_tmp, &yy_tmp->node, &col_conf_list);
3165 <    }
3166 <  }
2744 >  ConfigGeneral.min_nonwildcard_simple = $3;
2745   };
2746  
2747 < gline_server: NAME '=' QSTRING ';'
2747 > general_default_floodcount: DEFAULT_FLOODCOUNT '=' NUMBER ';'
2748   {
2749 <  if (conf_parser_ctx.pass == 2)  
3172 <  {
3173 <    MyFree(yy_conf->name);
3174 <    DupString(yy_conf->name, yylval.string);
3175 <  }
2749 >  ConfigGeneral.default_floodcount = $3;
2750   };
2751  
2752 < gline_action: ACTION
3179 < {
3180 <  if (conf_parser_ctx.pass == 2)
3181 <    yy_aconf->flags = 0;
3182 < } '=' gdeny_types ';'
2752 > general_default_floodtime: DEFAULT_FLOODTIME '=' timespec ';'
2753   {
2754 <  if (conf_parser_ctx.pass == 2)
3185 <  {
3186 <    struct CollectItem *yy_tmp = NULL;
3187 <    dlink_node *ptr, *next_ptr;
3188 <
3189 <    DLINK_FOREACH_SAFE(ptr, next_ptr, col_conf_list.head)
3190 <    {
3191 <      struct AccessItem *new_aconf;
3192 <      struct ConfItem *new_conf;
3193 <
3194 <      yy_tmp = ptr->data;
3195 <      new_conf = make_conf_item(GDENY_TYPE);
3196 <      new_aconf = map_to_conf(new_conf);
3197 <
3198 <      new_aconf->flags = yy_aconf->flags;
3199 <
3200 <      if (yy_conf->name != NULL)
3201 <        DupString(new_conf->name, yy_conf->name);
3202 <      else
3203 <        DupString(new_conf->name, "*");
3204 <      if (yy_aconf->user != NULL)
3205 <         DupString(new_aconf->user, yy_tmp->user);
3206 <      else  
3207 <        DupString(new_aconf->user, "*");
3208 <      if (yy_aconf->host != NULL)
3209 <        DupString(new_aconf->host, yy_tmp->host);
3210 <      else
3211 <        DupString(new_aconf->host, "*");
3212 <
3213 <      dlinkDelete(&yy_tmp->node, &col_conf_list);
3214 <    }
3215 <
3216 <    /*
3217 <     * In case someone has fed us with more than one action= after user/name
3218 <     * which would leak memory  -Michael
3219 <     */
3220 <    if (yy_conf->name == NULL || yy_aconf->user == NULL)
3221 <      delete_conf_item(yy_conf);
3222 <
3223 <    yy_conf = make_conf_item(GDENY_TYPE);
3224 <    yy_aconf = map_to_conf(yy_conf);
3225 <  }
2754 >  ConfigGeneral.default_floodtime = $3;
2755   };
2756  
3228 gdeny_types: gdeny_types ',' gdeny_type_item | gdeny_type_item;
3229 gdeny_type_item: T_REJECT
3230 {
3231  if (conf_parser_ctx.pass == 2)
3232    yy_aconf->flags |= GDENY_REJECT;
3233 } | T_BLOCK
3234 {
3235  if (conf_parser_ctx.pass == 2)
3236    yy_aconf->flags |= GDENY_BLOCK;
3237 };
2757  
2758   /***************************************************************************
2759 < *  section channel
2759 > * channel {} section
2760   ***************************************************************************/
2761 < channel_entry: CHANNEL
3243 <  '{' channel_items '}' ';';
2761 > channel_entry: CHANNEL '{' channel_items '}' ';';
2762  
2763   channel_items:      channel_items channel_item | channel_item;
2764 < channel_item:       channel_disable_local_channels | channel_use_except |
2765 <                    channel_use_invex | channel_use_knock |
2766 <                    channel_max_bans | channel_knock_delay |
2767 <                    channel_knock_delay_channel | channel_max_chans_per_user |
2768 <                    channel_quiet_on_ban | channel_default_split_user_count |
2769 <                    channel_default_split_server_count |
2770 <                    channel_no_create_on_split | channel_restrict_channels |
2771 <                    channel_no_join_on_split | channel_burst_topicwho |
2772 <                    channel_jflood_count | channel_jflood_time |
2773 <                    channel_disable_fake_channels | error;
2764 > channel_item:       channel_max_bans |
2765 >                    channel_max_bans_large |
2766 >                    channel_invite_client_count |
2767 >                    channel_invite_client_time |
2768 >                    channel_invite_delay_channel |
2769 >                    channel_invite_expire_time |
2770 >                    channel_knock_client_count |
2771 >                    channel_knock_client_time |
2772 >                    channel_knock_delay_channel |
2773 >                    channel_max_channels |
2774 >                    channel_max_invites |
2775 >                    channel_default_join_flood_count |
2776 >                    channel_default_join_flood_time |
2777 >                    channel_disable_fake_channels |
2778 >                    error;
2779  
2780   channel_disable_fake_channels: DISABLE_FAKE_CHANNELS '=' TBOOL ';'
2781   {
2782    ConfigChannel.disable_fake_channels = yylval.number;
2783   };
2784  
2785 < channel_restrict_channels: RESTRICT_CHANNELS '=' TBOOL ';'
2785 > channel_invite_client_count: INVITE_CLIENT_COUNT '=' NUMBER ';'
2786   {
2787 <  ConfigChannel.restrict_channels = yylval.number;
2787 >  ConfigChannel.invite_client_count = $3;
2788   };
2789  
2790 < channel_disable_local_channels: DISABLE_LOCAL_CHANNELS '=' TBOOL ';'
2790 > channel_invite_client_time: INVITE_CLIENT_TIME '=' timespec ';'
2791   {
2792 <  ConfigChannel.disable_local_channels = yylval.number;
2792 >  ConfigChannel.invite_client_time = $3;
2793   };
2794  
2795 < channel_use_except: USE_EXCEPT '=' TBOOL ';'
2795 > channel_invite_delay_channel: INVITE_DELAY_CHANNEL '=' timespec ';'
2796   {
2797 <  ConfigChannel.use_except = yylval.number;
2797 >  ConfigChannel.invite_delay_channel = $3;
2798   };
2799  
2800 < channel_use_invex: USE_INVEX '=' TBOOL ';'
2800 > channel_invite_expire_time: INVITE_EXPIRE_TIME '=' timespec ';'
2801   {
2802 <  ConfigChannel.use_invex = yylval.number;
2802 >  ConfigChannel.invite_expire_time = $3;
2803   };
2804  
2805 < channel_use_knock: USE_KNOCK '=' TBOOL ';'
2805 > channel_knock_client_count: KNOCK_CLIENT_COUNT '=' NUMBER ';'
2806   {
2807 <  ConfigChannel.use_knock = yylval.number;
2807 >  ConfigChannel.knock_client_count = $3;
2808   };
2809  
2810 < channel_knock_delay: KNOCK_DELAY '=' timespec ';'
2810 > channel_knock_client_time: KNOCK_CLIENT_TIME '=' timespec ';'
2811   {
2812 <  ConfigChannel.knock_delay = $3;
2812 >  ConfigChannel.knock_client_time = $3;
2813   };
2814  
2815   channel_knock_delay_channel: KNOCK_DELAY_CHANNEL '=' timespec ';'
# Line 3294 | Line 2817 | channel_knock_delay_channel: KNOCK_DELAY
2817    ConfigChannel.knock_delay_channel = $3;
2818   };
2819  
2820 < channel_max_chans_per_user: MAX_CHANS_PER_USER '=' NUMBER ';'
2820 > channel_max_channels: MAX_CHANNELS '=' NUMBER ';'
2821   {
2822 <  ConfigChannel.max_chans_per_user = $3;
2822 >  ConfigChannel.max_channels = $3;
2823   };
2824  
2825 < channel_quiet_on_ban: QUIET_ON_BAN '=' TBOOL ';'
2825 > channel_max_invites: MAX_INVITES '=' NUMBER ';'
2826   {
2827 <  ConfigChannel.quiet_on_ban = yylval.number;
2827 >  ConfigChannel.max_invites = $3;
2828   };
2829  
2830   channel_max_bans: MAX_BANS '=' NUMBER ';'
# Line 3309 | Line 2832 | channel_max_bans: MAX_BANS '=' NUMBER ';
2832    ConfigChannel.max_bans = $3;
2833   };
2834  
2835 < channel_default_split_user_count: DEFAULT_SPLIT_USER_COUNT '=' NUMBER ';'
2835 > channel_max_bans_large: MAX_BANS_LARGE '=' NUMBER ';'
2836   {
2837 <  ConfigChannel.default_split_user_count = $3;
2837 >  ConfigChannel.max_bans_large = $3;
2838   };
2839  
2840 < channel_default_split_server_count: DEFAULT_SPLIT_SERVER_COUNT '=' NUMBER ';'
2840 > channel_default_join_flood_count: DEFAULT_JOIN_FLOOD_COUNT '=' NUMBER ';'
2841   {
2842 <  ConfigChannel.default_split_server_count = $3;
2842 >  ConfigChannel.default_join_flood_count = yylval.number;
2843   };
2844  
2845 < channel_no_create_on_split: NO_CREATE_ON_SPLIT '=' TBOOL ';'
2845 > channel_default_join_flood_time: DEFAULT_JOIN_FLOOD_TIME '=' timespec ';'
2846   {
2847 <  ConfigChannel.no_create_on_split = yylval.number;
2847 >  ConfigChannel.default_join_flood_time = $3;
2848   };
2849  
3327 channel_no_join_on_split: NO_JOIN_ON_SPLIT '=' TBOOL ';'
3328 {
3329  ConfigChannel.no_join_on_split = yylval.number;
3330 };
3331
3332 channel_burst_topicwho: BURST_TOPICWHO '=' TBOOL ';'
3333 {
3334  ConfigChannel.burst_topicwho = yylval.number;
3335 };
3336
3337 channel_jflood_count: JOIN_FLOOD_COUNT '=' NUMBER ';'
3338 {
3339  GlobalSetOptions.joinfloodcount = yylval.number;
3340 };
3341
3342 channel_jflood_time: JOIN_FLOOD_TIME '=' timespec ';'
3343 {
3344  GlobalSetOptions.joinfloodtime = yylval.number;
3345 };
2850  
2851   /***************************************************************************
2852 < *  section serverhide
2852 > * serverhide {} section
2853   ***************************************************************************/
2854 < serverhide_entry: SERVERHIDE
3351 <  '{' serverhide_items '}' ';';
2854 > serverhide_entry: SERVERHIDE '{' serverhide_items '}' ';';
2855  
2856   serverhide_items:   serverhide_items serverhide_item | serverhide_item;
2857 < serverhide_item:    serverhide_flatten_links | serverhide_hide_servers |
2858 <                    serverhide_links_delay |
2859 <                    serverhide_disable_hidden |
2860 <                    serverhide_hidden | serverhide_hidden_name |
2861 <                    serverhide_hide_server_ips |
2857 > serverhide_item:    serverhide_flatten_links |
2858 >                    serverhide_flatten_links_delay |
2859 >                    serverhide_flatten_links_file |
2860 >                    serverhide_disable_remote_commands |
2861 >                    serverhide_hide_servers |
2862 >                    serverhide_hide_services |
2863 >                    serverhide_hidden |
2864 >                    serverhide_hidden_name |
2865 >                    serverhide_hide_server_ips |
2866                      error;
2867  
2868   serverhide_flatten_links: FLATTEN_LINKS '=' TBOOL ';'
# Line 3364 | Line 2871 | serverhide_flatten_links: FLATTEN_LINKS
2871      ConfigServerHide.flatten_links = yylval.number;
2872   };
2873  
2874 < serverhide_hide_servers: HIDE_SERVERS '=' TBOOL ';'
2874 > serverhide_flatten_links_delay: FLATTEN_LINKS_DELAY '=' timespec ';'
2875   {
2876    if (conf_parser_ctx.pass == 2)
2877 <    ConfigServerHide.hide_servers = yylval.number;
2877 >  {
2878 >    if ($3 > 0)
2879 >    {
2880 >      event_write_links_file.when = $3;
2881 >      event_add(&event_write_links_file, NULL);
2882 >    }
2883 >    else
2884 >     event_delete(&event_write_links_file);
2885 >
2886 >    ConfigServerHide.flatten_links_delay = $3;
2887 >  }
2888   };
2889  
2890 < serverhide_hidden_name: HIDDEN_NAME '=' QSTRING ';'
2890 > serverhide_flatten_links_file: FLATTEN_LINKS_FILE '=' QSTRING ';'
2891   {
2892    if (conf_parser_ctx.pass == 2)
2893    {
2894 <    MyFree(ConfigServerHide.hidden_name);
2895 <    DupString(ConfigServerHide.hidden_name, yylval.string);
2894 >    xfree(ConfigServerHide.flatten_links_file);
2895 >    ConfigServerHide.flatten_links_file = xstrdup(yylval.string);
2896    }
2897   };
2898  
2899 < serverhide_links_delay: LINKS_DELAY '=' timespec ';'
2899 > serverhide_disable_remote_commands: DISABLE_REMOTE_COMMANDS '=' TBOOL ';'
2900   {
2901    if (conf_parser_ctx.pass == 2)
2902 <  {
2903 <    if (($3 > 0) && ConfigServerHide.links_disabled == 1)
3387 <    {
3388 <      eventAddIsh("write_links_file", write_links_file, NULL, $3);
3389 <      ConfigServerHide.links_disabled = 0;
3390 <    }
2902 >    ConfigServerHide.disable_remote_commands = yylval.number;
2903 > };
2904  
2905 <    ConfigServerHide.links_delay = $3;
2906 <  }
2905 > serverhide_hide_servers: HIDE_SERVERS '=' TBOOL ';'
2906 > {
2907 >  if (conf_parser_ctx.pass == 2)
2908 >    ConfigServerHide.hide_servers = yylval.number;
2909   };
2910  
2911 < serverhide_hidden: HIDDEN '=' TBOOL ';'
2911 > serverhide_hide_services: HIDE_SERVICES '=' TBOOL ';'
2912   {
2913    if (conf_parser_ctx.pass == 2)
2914 <    ConfigServerHide.hidden = yylval.number;
2914 >    ConfigServerHide.hide_services = yylval.number;
2915   };
2916  
2917 < serverhide_disable_hidden: DISABLE_HIDDEN '=' TBOOL ';'
2917 > serverhide_hidden_name: HIDDEN_NAME '=' QSTRING ';'
2918   {
2919    if (conf_parser_ctx.pass == 2)
2920 <    ConfigServerHide.disable_hidden = yylval.number;
2920 >  {
2921 >    xfree(ConfigServerHide.hidden_name);
2922 >    ConfigServerHide.hidden_name = xstrdup(yylval.string);
2923 >  }
2924 > };
2925 >
2926 > serverhide_hidden: HIDDEN '=' TBOOL ';'
2927 > {
2928 >  if (conf_parser_ctx.pass == 2)
2929 >    ConfigServerHide.hidden = yylval.number;
2930   };
2931  
2932   serverhide_hide_server_ips: HIDE_SERVER_IPS '=' TBOOL ';'

Comparing:
ircd-hybrid-8/src/conf_parser.y (property svn:keywords), Revision 1352 by michael, Fri Apr 13 09:57:08 2012 UTC vs.
ircd-hybrid/trunk/src/conf_parser.y (property svn:keywords), Revision 9101 by michael, Wed Jan 1 09:58:45 2020 UTC

# Line 1 | Line 1
1 < Id Revision
1 > Id

Diff Legend

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