/[svn]/ircd-hybrid-8/src/ircd_parser.y
ViewVC logotype

Annotation of /ircd-hybrid-8/src/ircd_parser.y

Parent Directory Parent Directory | Revision Log Revision Log


Revision 1216 - (hide annotations)
Tue Sep 13 18:22:31 2011 UTC (9 years ago) by michael
File size: 88492 byte(s)
- add 'globops' to operflags

1 adx 30 /*
2     * ircd-hybrid: an advanced Internet Relay Chat Daemon(ircd).
3     * ircd_parser.y: Parses the ircd configuration file.
4     *
5     * Copyright (C) 2005 by the past and present ircd coders, and others.
6     *
7     * This program is free software; you can redistribute it and/or modify
8     * it under the terms of the GNU General Public License as published by
9     * the Free Software Foundation; either version 2 of the License, or
10     * (at your option) any later version.
11     *
12     * This program is distributed in the hope that it will be useful,
13     * but WITHOUT ANY WARRANTY; without even the implied warranty of
14     * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15     * GNU General Public License for more details.
16     *
17     * You should have received a copy of the GNU General Public License
18     * along with this program; if not, write to the Free Software
19     * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
20     * USA
21     *
22 knight 31 * $Id$
23 adx 30 */
24    
25     %{
26    
27     #define YY_NO_UNPUT
28     #include <sys/types.h>
29 stu 909 #include <string.h>
30 adx 30
31 michael 1009 #include "config.h"
32 adx 30 #include "stdinc.h"
33     #include "ircd.h"
34     #include "list.h"
35     #include "s_conf.h"
36     #include "event.h"
37     #include "s_log.h"
38     #include "client.h" /* for UMODE_ALL only */
39     #include "irc_string.h"
40     #include "sprintf_irc.h"
41     #include "memory.h"
42     #include "modules.h"
43 michael 885 #include "s_serv.h"
44 adx 30 #include "hostmask.h"
45     #include "send.h"
46     #include "listener.h"
47     #include "resv.h"
48     #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     #endif
56    
57     static char *class_name = NULL;
58     static struct ConfItem *yy_conf = NULL;
59     static struct AccessItem *yy_aconf = NULL;
60     static struct MatchItem *yy_match_item = NULL;
61     static struct ClassItem *yy_class = NULL;
62     static char *yy_class_name = NULL;
63    
64     static dlink_list col_conf_list = { NULL, NULL, 0 };
65     static dlink_list hub_conf_list = { NULL, NULL, 0 };
66     static dlink_list leaf_conf_list = { NULL, NULL, 0 };
67     static unsigned int listener_flags = 0;
68     static unsigned int regex_ban = 0;
69     static char userbuf[IRCD_BUFSIZE];
70     static char hostbuf[IRCD_BUFSIZE];
71     static char reasonbuf[REASONLEN + 1];
72     static char gecos_name[REALLEN * 4];
73    
74     static char *resv_reason = NULL;
75     static char *listener_address = NULL;
76     static int not_atom = 0;
77    
78 michael 593 struct CollectItem
79     {
80 adx 30 dlink_node node;
81     char *name;
82     char *user;
83     char *host;
84     char *passwd;
85     int port;
86     int flags;
87     #ifdef HAVE_LIBCRYPTO
88     char *rsa_public_key_file;
89     RSA *rsa_public_key;
90     #endif
91     };
92    
93     static void
94     free_collect_item(struct CollectItem *item)
95     {
96     MyFree(item->name);
97     MyFree(item->user);
98     MyFree(item->host);
99     MyFree(item->passwd);
100     #ifdef HAVE_LIBCRYPTO
101     MyFree(item->rsa_public_key_file);
102     #endif
103     MyFree(item);
104     }
105    
106     static void
107     unhook_hub_leaf_confs(void)
108     {
109     dlink_node *ptr;
110     dlink_node *next_ptr;
111     struct CollectItem *yy_hconf;
112     struct CollectItem *yy_lconf;
113    
114     DLINK_FOREACH_SAFE(ptr, next_ptr, hub_conf_list.head)
115     {
116     yy_hconf = ptr->data;
117     dlinkDelete(&yy_hconf->node, &hub_conf_list);
118     free_collect_item(yy_hconf);
119     }
120    
121     DLINK_FOREACH_SAFE(ptr, next_ptr, leaf_conf_list.head)
122     {
123     yy_lconf = ptr->data;
124     dlinkDelete(&yy_lconf->node, &leaf_conf_list);
125     free_collect_item(yy_lconf);
126     }
127     }
128    
129     %}
130    
131     %union {
132     int number;
133     char *string;
134     }
135    
136     %token ACCEPT_PASSWORD
137     %token ACTION
138     %token ADMIN
139     %token AFTYPE
140     %token T_ALLOW
141     %token ANTI_NICK_FLOOD
142     %token ANTI_SPAM_EXIT_MESSAGE_TIME
143     %token AUTOCONN
144     %token T_BLOCK
145     %token BURST_AWAY
146     %token BURST_TOPICWHO
147     %token BYTES KBYTES MBYTES GBYTES TBYTES
148     %token CALLER_ID_WAIT
149     %token CAN_FLOOD
150     %token CHANNEL
151     %token CIDR_BITLEN_IPV4
152     %token CIDR_BITLEN_IPV6
153     %token CIPHER_PREFERENCE
154     %token CLASS
155     %token COMPRESSED
156     %token COMPRESSION_LEVEL
157     %token CONNECT
158     %token CONNECTFREQ
159     %token CRYPTLINK
160     %token DEFAULT_CIPHER_PREFERENCE
161     %token DEFAULT_FLOODCOUNT
162     %token DEFAULT_SPLIT_SERVER_COUNT
163     %token DEFAULT_SPLIT_USER_COUNT
164     %token DENY
165     %token DESCRIPTION
166     %token DIE
167     %token DISABLE_AUTH
168 michael 632 %token DISABLE_FAKE_CHANNELS
169 adx 30 %token DISABLE_HIDDEN
170     %token DISABLE_LOCAL_CHANNELS
171     %token DISABLE_REMOTE_COMMANDS
172     %token DOTS_IN_IDENT
173     %token DURATION
174     %token EGDPOOL_PATH
175     %token EMAIL
176     %token ENABLE
177     %token ENCRYPTED
178     %token EXCEED_LIMIT
179     %token EXEMPT
180     %token FAILED_OPER_NOTICE
181     %token IRCD_FLAGS
182     %token FLATTEN_LINKS
183     %token FFAILED_OPERLOG
184     %token FKILLLOG
185     %token FKLINELOG
186     %token FGLINELOG
187     %token FIOERRLOG
188     %token FOPERLOG
189     %token FOPERSPYLOG
190     %token FUSERLOG
191     %token GECOS
192     %token GENERAL
193     %token GLINE
194     %token GLINES
195     %token GLINE_EXEMPT
196     %token GLINE_LOG
197     %token GLINE_TIME
198     %token GLINE_MIN_CIDR
199     %token GLINE_MIN_CIDR6
200     %token GLOBAL_KILL
201     %token IRCD_AUTH
202     %token NEED_IDENT
203     %token HAVENT_READ_CONF
204     %token HIDDEN
205     %token HIDDEN_ADMIN
206     %token HIDDEN_NAME
207     %token HIDDEN_OPER
208     %token HIDE_SERVER_IPS
209     %token HIDE_SERVERS
210     %token HIDE_SPOOF_IPS
211     %token HOST
212     %token HUB
213     %token HUB_MASK
214     %token IGNORE_BOGUS_TS
215     %token INVISIBLE_ON_CONNECT
216     %token IP
217     %token KILL
218     %token KILL_CHASE_TIME_LIMIT
219     %token KLINE
220     %token KLINE_EXEMPT
221     %token KLINE_REASON
222     %token KLINE_WITH_REASON
223     %token KNOCK_DELAY
224     %token KNOCK_DELAY_CHANNEL
225     %token LEAF_MASK
226     %token LINKS_DELAY
227     %token LISTEN
228     %token T_LOG
229     %token LOGGING
230     %token LOG_LEVEL
231     %token MAX_ACCEPT
232     %token MAX_BANS
233     %token MAX_CHANS_PER_USER
234     %token MAX_GLOBAL
235     %token MAX_IDENT
236     %token MAX_LOCAL
237     %token MAX_NICK_CHANGES
238     %token MAX_NICK_TIME
239     %token MAX_NUMBER
240     %token MAX_TARGETS
241 michael 876 %token MAX_WATCH
242 adx 30 %token MESSAGE_LOCALE
243     %token MIN_NONWILDCARD
244     %token MIN_NONWILDCARD_SIMPLE
245     %token MODULE
246     %token MODULES
247     %token NAME
248     %token NEED_PASSWORD
249     %token NETWORK_DESC
250     %token NETWORK_NAME
251     %token NICK
252     %token NICK_CHANGES
253     %token NO_CREATE_ON_SPLIT
254     %token NO_JOIN_ON_SPLIT
255     %token NO_OPER_FLOOD
256     %token NO_TILDE
257     %token NOT
258     %token NUMBER
259     %token NUMBER_PER_IDENT
260     %token NUMBER_PER_CIDR
261     %token NUMBER_PER_IP
262     %token NUMBER_PER_IP_GLOBAL
263     %token OPERATOR
264     %token OPERS_BYPASS_CALLERID
265     %token OPER_LOG
266     %token OPER_ONLY_UMODES
267     %token OPER_PASS_RESV
268     %token OPER_SPY_T
269     %token OPER_UMODES
270     %token JOIN_FLOOD_COUNT
271     %token JOIN_FLOOD_TIME
272     %token PACE_WAIT
273     %token PACE_WAIT_SIMPLE
274     %token PASSWORD
275     %token PATH
276     %token PING_COOKIE
277     %token PING_TIME
278     %token PING_WARNING
279     %token PORT
280     %token QSTRING
281     %token QUIET_ON_BAN
282     %token REASON
283     %token REDIRPORT
284     %token REDIRSERV
285     %token REGEX_T
286     %token REHASH
287     %token TREJECT_HOLD_TIME
288     %token REMOTE
289     %token REMOTEBAN
290     %token RESTRICT_CHANNELS
291     %token RESTRICTED
292     %token RSA_PRIVATE_KEY_FILE
293     %token RSA_PUBLIC_KEY_FILE
294     %token SSL_CERTIFICATE_FILE
295 michael 967 %token T_SSL_CONNECTION_METHOD
296     %token T_SSLV3
297     %token T_TLSV1
298 adx 30 %token RESV
299     %token RESV_EXEMPT
300     %token SECONDS MINUTES HOURS DAYS WEEKS
301     %token SENDQ
302     %token SEND_PASSWORD
303     %token SERVERHIDE
304     %token SERVERINFO
305     %token SERVLINK_PATH
306     %token IRCD_SID
307     %token TKLINE_EXPIRE_NOTICES
308     %token T_SHARED
309     %token T_CLUSTER
310     %token TYPE
311     %token SHORT_MOTD
312     %token SILENT
313     %token SPOOF
314     %token SPOOF_NOTICE
315 michael 584 %token STATS_E_DISABLED
316 adx 30 %token STATS_I_OPER_ONLY
317     %token STATS_K_OPER_ONLY
318     %token STATS_O_OPER_ONLY
319     %token STATS_P_OPER_ONLY
320     %token TBOOL
321     %token TMASKED
322     %token T_REJECT
323     %token TS_MAX_DELTA
324     %token TS_WARN_DELTA
325     %token TWODOTS
326     %token T_ALL
327     %token T_BOTS
328     %token T_SOFTCALLERID
329     %token T_CALLERID
330     %token T_CCONN
331 db 849 %token T_CCONN_FULL
332 adx 30 %token T_CLIENT_FLOOD
333     %token T_DEAF
334     %token T_DEBUG
335     %token T_DRONE
336     %token T_EXTERNAL
337     %token T_FULL
338     %token T_INVISIBLE
339     %token T_IPV4
340     %token T_IPV6
341     %token T_LOCOPS
342     %token T_LOGPATH
343     %token T_L_CRIT
344     %token T_L_DEBUG
345     %token T_L_ERROR
346     %token T_L_INFO
347     %token T_L_NOTICE
348     %token T_L_TRACE
349     %token T_L_WARN
350     %token T_MAX_CLIENTS
351     %token T_NCHANGE
352     %token T_OPERWALL
353     %token T_REJ
354 michael 900 %token T_SERVER
355 adx 30 %token T_SERVNOTICE
356     %token T_SKILL
357     %token T_SPY
358     %token T_SSL
359 michael 56 %token T_UMODES
360 adx 30 %token T_UNAUTH
361     %token T_UNRESV
362     %token T_UNXLINE
363 michael 1216 %token T_GLOBOPS
364 adx 30 %token T_WALLOP
365 michael 1157 %token T_SERVICE
366 michael 1176 %token T_SERVICES_NAME
367 adx 30 %token THROTTLE_TIME
368     %token TOPICBURST
369     %token TRUE_NO_OPER_FLOOD
370     %token TKLINE
371     %token TXLINE
372     %token TRESV
373     %token UNKLINE
374     %token USER
375     %token USE_EGD
376     %token USE_EXCEPT
377     %token USE_INVEX
378     %token USE_KNOCK
379     %token USE_LOGGING
380     %token USE_WHOIS_ACTUALLY
381     %token VHOST
382     %token VHOST6
383     %token XLINE
384     %token WARN
385     %token WARN_NO_NLINE
386    
387     %type <string> QSTRING
388     %type <number> NUMBER
389     %type <number> timespec
390     %type <number> timespec_
391     %type <number> sizespec
392     %type <number> sizespec_
393    
394     %%
395     conf:
396     | conf conf_item
397     ;
398    
399     conf_item: admin_entry
400     | logging_entry
401     | oper_entry
402     | channel_entry
403     | class_entry
404     | listen_entry
405     | auth_entry
406     | serverinfo_entry
407     | serverhide_entry
408     | resv_entry
409 michael 1157 | service_entry
410 adx 30 | shared_entry
411     | cluster_entry
412     | connect_entry
413     | kill_entry
414     | deny_entry
415     | exempt_entry
416     | general_entry
417     | gline_entry
418     | gecos_entry
419     | modules_entry
420     | error ';'
421     | error '}'
422     ;
423    
424    
425     timespec_: { $$ = 0; } | timespec;
426     timespec: NUMBER timespec_
427     {
428     $$ = $1 + $2;
429     }
430     | NUMBER SECONDS timespec_
431     {
432     $$ = $1 + $3;
433     }
434     | NUMBER MINUTES timespec_
435     {
436     $$ = $1 * 60 + $3;
437     }
438     | NUMBER HOURS timespec_
439     {
440     $$ = $1 * 60 * 60 + $3;
441     }
442     | NUMBER DAYS timespec_
443     {
444     $$ = $1 * 60 * 60 * 24 + $3;
445     }
446     | NUMBER WEEKS timespec_
447     {
448     $$ = $1 * 60 * 60 * 24 * 7 + $3;
449     }
450     ;
451    
452     sizespec_: { $$ = 0; } | sizespec;
453     sizespec: NUMBER sizespec_ { $$ = $1 + $2; }
454     | NUMBER BYTES sizespec_ { $$ = $1 + $3; }
455     | NUMBER KBYTES sizespec_ { $$ = $1 * 1024 + $3; }
456     | NUMBER MBYTES sizespec_ { $$ = $1 * 1024 * 1024 + $3; }
457     ;
458    
459    
460     /***************************************************************************
461     * section modules
462     ***************************************************************************/
463     modules_entry: MODULES
464     '{' modules_items '}' ';';
465    
466     modules_items: modules_items modules_item | modules_item;
467     modules_item: modules_module | modules_path | error ';' ;
468    
469     modules_module: MODULE '=' QSTRING ';'
470     {
471 michael 967 if (conf_parser_ctx.pass == 2)
472 michael 978 add_conf_module(libio_basename(yylval.string));
473 adx 30 };
474    
475     modules_path: PATH '=' QSTRING ';'
476     {
477 michael 967 if (conf_parser_ctx.pass == 2)
478 adx 30 mod_add_path(yylval.string);
479     };
480    
481    
482 michael 967 serverinfo_entry: SERVERINFO '{' serverinfo_items '}' ';';
483    
484     serverinfo_items: serverinfo_items serverinfo_item | serverinfo_item ;
485 adx 30 serverinfo_item: serverinfo_name | serverinfo_vhost |
486     serverinfo_hub | serverinfo_description |
487     serverinfo_network_name | serverinfo_network_desc |
488     serverinfo_max_clients |
489     serverinfo_rsa_private_key_file | serverinfo_vhost6 |
490     serverinfo_sid | serverinfo_ssl_certificate_file |
491 michael 967 serverinfo_ssl_connection_method |
492 adx 30 error ';' ;
493    
494 michael 967
495     serverinfo_ssl_connection_method: T_SSL_CONNECTION_METHOD
496     {
497 michael 1024 #ifdef HAVE_LIBCRYPTO
498 michael 967 if (conf_parser_ctx.boot && conf_parser_ctx.pass == 2)
499     ServerInfo.tls_version = 0;
500 michael 1024 #endif
501 michael 967 } '=' method_types ';'
502     {
503 michael 1024 #ifdef HAVE_LIBCRYPTO
504 michael 967 if (conf_parser_ctx.boot && conf_parser_ctx.pass == 2)
505     {
506     if (!(ServerInfo.tls_version & CONF_SERVER_INFO_TLS_VERSION_SSLV3))
507     SSL_CTX_set_options(ServerInfo.server_ctx, SSL_OP_NO_SSLv3);
508     if (!(ServerInfo.tls_version & CONF_SERVER_INFO_TLS_VERSION_TLSV1))
509     SSL_CTX_set_options(ServerInfo.server_ctx, SSL_OP_NO_TLSv1);
510     }
511 michael 1024 #endif
512 michael 967 };
513    
514     method_types: method_types ',' method_type_item | method_type_item;
515     method_type_item: T_SSLV3
516     {
517 michael 1024 #ifdef HAVE_LIBCRYPTO
518 michael 967 if (conf_parser_ctx.boot && conf_parser_ctx.pass == 2)
519     ServerInfo.tls_version |= CONF_SERVER_INFO_TLS_VERSION_SSLV3;
520 michael 1024 #endif
521 michael 967 } | T_TLSV1
522     {
523 michael 1024 #ifdef HAVE_LIBCRYPTO
524 michael 967 if (conf_parser_ctx.boot && conf_parser_ctx.pass == 2)
525     ServerInfo.tls_version |= CONF_SERVER_INFO_TLS_VERSION_TLSV1;
526 michael 1024 #endif
527 michael 967 };
528    
529 adx 30 serverinfo_ssl_certificate_file: SSL_CERTIFICATE_FILE '=' QSTRING ';'
530     {
531     #ifdef HAVE_LIBCRYPTO
532 michael 967 if (conf_parser_ctx.pass == 2 && ServerInfo.server_ctx)
533 adx 30 {
534     if (!ServerInfo.rsa_private_key_file)
535     {
536     yyerror("No rsa_private_key_file specified, SSL disabled");
537     break;
538     }
539    
540 michael 967 if (SSL_CTX_use_certificate_file(ServerInfo.server_ctx, yylval.string,
541     SSL_FILETYPE_PEM) <= 0)
542 adx 30 {
543     yyerror(ERR_lib_error_string(ERR_get_error()));
544     break;
545     }
546    
547 michael 967 if (SSL_CTX_use_PrivateKey_file(ServerInfo.server_ctx, ServerInfo.rsa_private_key_file,
548     SSL_FILETYPE_PEM) <= 0)
549 adx 30 {
550     yyerror(ERR_lib_error_string(ERR_get_error()));
551     break;
552     }
553    
554 michael 967 if (!SSL_CTX_check_private_key(ServerInfo.server_ctx))
555 adx 30 {
556 michael 967 yyerror(ERR_lib_error_string(ERR_get_error()));
557 adx 30 break;
558     }
559     }
560     #endif
561     };
562    
563     serverinfo_rsa_private_key_file: RSA_PRIVATE_KEY_FILE '=' QSTRING ';'
564     {
565     #ifdef HAVE_LIBCRYPTO
566 michael 967 if (conf_parser_ctx.pass == 1)
567 adx 30 {
568     BIO *file;
569    
570     if (ServerInfo.rsa_private_key)
571     {
572     RSA_free(ServerInfo.rsa_private_key);
573     ServerInfo.rsa_private_key = NULL;
574     }
575    
576     if (ServerInfo.rsa_private_key_file)
577     {
578     MyFree(ServerInfo.rsa_private_key_file);
579     ServerInfo.rsa_private_key_file = NULL;
580     }
581    
582     DupString(ServerInfo.rsa_private_key_file, yylval.string);
583    
584     if ((file = BIO_new_file(yylval.string, "r")) == NULL)
585     {
586     yyerror("File open failed, ignoring");
587     break;
588     }
589    
590     ServerInfo.rsa_private_key = (RSA *)PEM_read_bio_RSAPrivateKey(file, NULL,
591     0, NULL);
592    
593     BIO_set_close(file, BIO_CLOSE);
594     BIO_free(file);
595    
596     if (ServerInfo.rsa_private_key == NULL)
597     {
598     yyerror("Couldn't extract key, ignoring");
599     break;
600     }
601    
602     if (!RSA_check_key(ServerInfo.rsa_private_key))
603     {
604     RSA_free(ServerInfo.rsa_private_key);
605     ServerInfo.rsa_private_key = NULL;
606    
607     yyerror("Invalid key, ignoring");
608     break;
609     }
610    
611     /* require 2048 bit (256 byte) key */
612     if (RSA_size(ServerInfo.rsa_private_key) != 256)
613     {
614     RSA_free(ServerInfo.rsa_private_key);
615     ServerInfo.rsa_private_key = NULL;
616    
617     yyerror("Not a 2048 bit key, ignoring");
618     }
619     }
620     #endif
621     };
622    
623     serverinfo_name: NAME '=' QSTRING ';'
624     {
625     /* this isn't rehashable */
626 michael 1117 if (conf_parser_ctx.pass == 2 && !ServerInfo.name)
627 adx 30 {
628 michael 1117 if (valid_servname(yylval.string))
629     DupString(ServerInfo.name, yylval.string);
630     else
631 adx 30 {
632 michael 1117 ilog(L_ERROR, "Ignoring serverinfo::name -- invalid name. Aborting.");
633     exit(0);
634 adx 30 }
635     }
636     };
637    
638     serverinfo_sid: IRCD_SID '=' QSTRING ';'
639     {
640     /* this isn't rehashable */
641 michael 967 if (conf_parser_ctx.pass == 2 && !ServerInfo.sid)
642 adx 30 {
643 michael 573 if (valid_sid(yylval.string))
644 adx 30 DupString(ServerInfo.sid, yylval.string);
645     else
646     {
647 michael 1117 ilog(L_ERROR, "Ignoring serverinfo::sid -- invalid SID. Aborting.");
648 adx 30 exit(0);
649     }
650     }
651     };
652    
653     serverinfo_description: DESCRIPTION '=' QSTRING ';'
654     {
655 michael 967 if (conf_parser_ctx.pass == 2)
656 adx 30 {
657     MyFree(ServerInfo.description);
658     DupString(ServerInfo.description,yylval.string);
659     }
660     };
661    
662     serverinfo_network_name: NETWORK_NAME '=' QSTRING ';'
663     {
664 michael 967 if (conf_parser_ctx.pass == 2)
665 adx 30 {
666     char *p;
667    
668     if ((p = strchr(yylval.string, ' ')) != NULL)
669     p = '\0';
670    
671     MyFree(ServerInfo.network_name);
672     DupString(ServerInfo.network_name, yylval.string);
673     }
674     };
675    
676     serverinfo_network_desc: NETWORK_DESC '=' QSTRING ';'
677     {
678 michael 967 if (conf_parser_ctx.pass == 2)
679 adx 30 {
680     MyFree(ServerInfo.network_desc);
681     DupString(ServerInfo.network_desc, yylval.string);
682     }
683     };
684    
685     serverinfo_vhost: VHOST '=' QSTRING ';'
686     {
687 michael 967 if (conf_parser_ctx.pass == 2 && *yylval.string != '*')
688 adx 30 {
689     struct addrinfo hints, *res;
690    
691     memset(&hints, 0, sizeof(hints));
692    
693     hints.ai_family = AF_UNSPEC;
694     hints.ai_socktype = SOCK_STREAM;
695     hints.ai_flags = AI_PASSIVE | AI_NUMERICHOST;
696    
697 michael 1123 if (getaddrinfo(yylval.string, NULL, &hints, &res))
698 adx 30 ilog(L_ERROR, "Invalid netmask for server vhost(%s)", yylval.string);
699     else
700     {
701     assert(res != NULL);
702    
703     memcpy(&ServerInfo.ip, res->ai_addr, res->ai_addrlen);
704     ServerInfo.ip.ss.ss_family = res->ai_family;
705     ServerInfo.ip.ss_len = res->ai_addrlen;
706 michael 1123 freeaddrinfo(res);
707 adx 30
708     ServerInfo.specific_ipv4_vhost = 1;
709     }
710     }
711     };
712    
713     serverinfo_vhost6: VHOST6 '=' QSTRING ';'
714     {
715     #ifdef IPV6
716 michael 967 if (conf_parser_ctx.pass == 2 && *yylval.string != '*')
717 adx 30 {
718     struct addrinfo hints, *res;
719    
720     memset(&hints, 0, sizeof(hints));
721    
722     hints.ai_family = AF_UNSPEC;
723     hints.ai_socktype = SOCK_STREAM;
724     hints.ai_flags = AI_PASSIVE | AI_NUMERICHOST;
725    
726 michael 1123 if (getaddrinfo(yylval.string, NULL, &hints, &res))
727 adx 30 ilog(L_ERROR, "Invalid netmask for server vhost6(%s)", yylval.string);
728     else
729     {
730     assert(res != NULL);
731    
732     memcpy(&ServerInfo.ip6, res->ai_addr, res->ai_addrlen);
733     ServerInfo.ip6.ss.ss_family = res->ai_family;
734     ServerInfo.ip6.ss_len = res->ai_addrlen;
735 michael 1123 freeaddrinfo(res);
736 adx 30
737     ServerInfo.specific_ipv6_vhost = 1;
738     }
739     }
740     #endif
741     };
742    
743     serverinfo_max_clients: T_MAX_CLIENTS '=' NUMBER ';'
744     {
745 michael 967 if (conf_parser_ctx.pass == 2)
746 adx 30 {
747     recalc_fdlimit(NULL);
748    
749     if ($3 < MAXCLIENTS_MIN)
750     {
751     char buf[IRCD_BUFSIZE];
752     ircsprintf(buf, "MAXCLIENTS too low, setting to %d", MAXCLIENTS_MIN);
753     yyerror(buf);
754     }
755     else if ($3 > MAXCLIENTS_MAX)
756     {
757     char buf[IRCD_BUFSIZE];
758     ircsprintf(buf, "MAXCLIENTS too high, setting to %d", MAXCLIENTS_MAX);
759     yyerror(buf);
760     }
761     else
762     ServerInfo.max_clients = $3;
763     }
764     };
765    
766     serverinfo_hub: HUB '=' TBOOL ';'
767     {
768 michael 967 if (conf_parser_ctx.pass == 2)
769 michael 1119 ServerInfo.hub = yylval.number;
770 adx 30 };
771    
772     /***************************************************************************
773     * admin section
774     ***************************************************************************/
775     admin_entry: ADMIN '{' admin_items '}' ';' ;
776    
777     admin_items: admin_items admin_item | admin_item;
778     admin_item: admin_name | admin_description |
779     admin_email | error ';' ;
780    
781     admin_name: NAME '=' QSTRING ';'
782     {
783 michael 967 if (conf_parser_ctx.pass == 2)
784 adx 30 {
785     MyFree(AdminInfo.name);
786     DupString(AdminInfo.name, yylval.string);
787     }
788     };
789    
790     admin_email: EMAIL '=' QSTRING ';'
791     {
792 michael 967 if (conf_parser_ctx.pass == 2)
793 adx 30 {
794     MyFree(AdminInfo.email);
795     DupString(AdminInfo.email, yylval.string);
796     }
797     };
798    
799     admin_description: DESCRIPTION '=' QSTRING ';'
800     {
801 michael 967 if (conf_parser_ctx.pass == 2)
802 adx 30 {
803     MyFree(AdminInfo.description);
804     DupString(AdminInfo.description, yylval.string);
805     }
806     };
807    
808     /***************************************************************************
809     * section logging
810     ***************************************************************************/
811     /* XXX */
812     logging_entry: LOGGING '{' logging_items '}' ';' ;
813    
814     logging_items: logging_items logging_item |
815     logging_item ;
816    
817     logging_item: logging_path | logging_oper_log |
818     logging_log_level |
819     logging_use_logging | logging_fuserlog |
820     logging_foperlog | logging_fglinelog |
821     logging_fklinelog | logging_killlog |
822     logging_foperspylog | logging_ioerrlog |
823     logging_ffailed_operlog |
824     error ';' ;
825    
826     logging_path: T_LOGPATH '=' QSTRING ';'
827     {
828     };
829    
830     logging_oper_log: OPER_LOG '=' QSTRING ';'
831     {
832     };
833    
834     logging_fuserlog: FUSERLOG '=' QSTRING ';'
835     {
836 michael 967 if (conf_parser_ctx.pass == 2)
837 adx 30 strlcpy(ConfigLoggingEntry.userlog, yylval.string,
838     sizeof(ConfigLoggingEntry.userlog));
839     };
840    
841     logging_ffailed_operlog: FFAILED_OPERLOG '=' QSTRING ';'
842     {
843 michael 967 if (conf_parser_ctx.pass == 2)
844 adx 30 strlcpy(ConfigLoggingEntry.failed_operlog, yylval.string,
845     sizeof(ConfigLoggingEntry.failed_operlog));
846     };
847    
848     logging_foperlog: FOPERLOG '=' QSTRING ';'
849     {
850 michael 967 if (conf_parser_ctx.pass == 2)
851 adx 30 strlcpy(ConfigLoggingEntry.operlog, yylval.string,
852     sizeof(ConfigLoggingEntry.operlog));
853     };
854    
855     logging_foperspylog: FOPERSPYLOG '=' QSTRING ';'
856     {
857 michael 967 if (conf_parser_ctx.pass == 2)
858 adx 30 strlcpy(ConfigLoggingEntry.operspylog, yylval.string,
859     sizeof(ConfigLoggingEntry.operspylog));
860     };
861    
862     logging_fglinelog: FGLINELOG '=' QSTRING ';'
863     {
864 michael 967 if (conf_parser_ctx.pass == 2)
865 adx 30 strlcpy(ConfigLoggingEntry.glinelog, yylval.string,
866     sizeof(ConfigLoggingEntry.glinelog));
867     };
868    
869     logging_fklinelog: FKLINELOG '=' QSTRING ';'
870     {
871 michael 967 if (conf_parser_ctx.pass == 2)
872 adx 30 strlcpy(ConfigLoggingEntry.klinelog, yylval.string,
873     sizeof(ConfigLoggingEntry.klinelog));
874     };
875    
876     logging_ioerrlog: FIOERRLOG '=' QSTRING ';'
877     {
878 michael 967 if (conf_parser_ctx.pass == 2)
879 adx 30 strlcpy(ConfigLoggingEntry.ioerrlog, yylval.string,
880     sizeof(ConfigLoggingEntry.ioerrlog));
881     };
882    
883     logging_killlog: FKILLLOG '=' QSTRING ';'
884     {
885 michael 967 if (conf_parser_ctx.pass == 2)
886 adx 30 strlcpy(ConfigLoggingEntry.killlog, yylval.string,
887     sizeof(ConfigLoggingEntry.killlog));
888     };
889    
890     logging_log_level: LOG_LEVEL '=' T_L_CRIT ';'
891     {
892 michael 967 if (conf_parser_ctx.pass == 2)
893 adx 30 set_log_level(L_CRIT);
894     } | LOG_LEVEL '=' T_L_ERROR ';'
895     {
896 michael 967 if (conf_parser_ctx.pass == 2)
897 adx 30 set_log_level(L_ERROR);
898     } | LOG_LEVEL '=' T_L_WARN ';'
899     {
900 michael 967 if (conf_parser_ctx.pass == 2)
901 adx 30 set_log_level(L_WARN);
902     } | LOG_LEVEL '=' T_L_NOTICE ';'
903     {
904 michael 967 if (conf_parser_ctx.pass == 2)
905 adx 30 set_log_level(L_NOTICE);
906     } | LOG_LEVEL '=' T_L_TRACE ';'
907     {
908 michael 967 if (conf_parser_ctx.pass == 2)
909 adx 30 set_log_level(L_TRACE);
910     } | LOG_LEVEL '=' T_L_INFO ';'
911     {
912 michael 967 if (conf_parser_ctx.pass == 2)
913 adx 30 set_log_level(L_INFO);
914     } | LOG_LEVEL '=' T_L_DEBUG ';'
915     {
916 michael 967 if (conf_parser_ctx.pass == 2)
917 adx 30 set_log_level(L_DEBUG);
918     };
919    
920     logging_use_logging: USE_LOGGING '=' TBOOL ';'
921     {
922 michael 967 if (conf_parser_ctx.pass == 2)
923 adx 30 ConfigLoggingEntry.use_logging = yylval.number;
924     };
925    
926     /***************************************************************************
927     * section oper
928     ***************************************************************************/
929     oper_entry: OPERATOR
930     {
931 michael 967 if (conf_parser_ctx.pass == 2)
932 adx 30 {
933     yy_conf = make_conf_item(OPER_TYPE);
934     yy_aconf = map_to_conf(yy_conf);
935     SetConfEncrypted(yy_aconf); /* Yes, the default is encrypted */
936     }
937     else
938     {
939     MyFree(class_name);
940     class_name = NULL;
941     }
942     } oper_name_b '{' oper_items '}' ';'
943     {
944 michael 967 if (conf_parser_ctx.pass == 2)
945 adx 30 {
946     struct CollectItem *yy_tmp;
947     dlink_node *ptr;
948     dlink_node *next_ptr;
949    
950     conf_add_class_to_conf(yy_conf, class_name);
951    
952     /* Now, make sure there is a copy of the "base" given oper
953     * block in each of the collected copies
954     */
955    
956     DLINK_FOREACH_SAFE(ptr, next_ptr, col_conf_list.head)
957     {
958     struct AccessItem *new_aconf;
959     struct ConfItem *new_conf;
960     yy_tmp = ptr->data;
961    
962     new_conf = make_conf_item(OPER_TYPE);
963     new_aconf = (struct AccessItem *)map_to_conf(new_conf);
964    
965     new_aconf->flags = yy_aconf->flags;
966    
967     if (yy_conf->name != NULL)
968     DupString(new_conf->name, yy_conf->name);
969     if (yy_tmp->user != NULL)
970     DupString(new_aconf->user, yy_tmp->user);
971     else
972     DupString(new_aconf->user, "*");
973     if (yy_tmp->host != NULL)
974     DupString(new_aconf->host, yy_tmp->host);
975     else
976     DupString(new_aconf->host, "*");
977     conf_add_class_to_conf(new_conf, class_name);
978     if (yy_aconf->passwd != NULL)
979     DupString(new_aconf->passwd, yy_aconf->passwd);
980    
981     new_aconf->port = yy_aconf->port;
982     #ifdef HAVE_LIBCRYPTO
983     if (yy_aconf->rsa_public_key_file != NULL)
984     {
985     BIO *file;
986    
987     DupString(new_aconf->rsa_public_key_file,
988     yy_aconf->rsa_public_key_file);
989    
990     file = BIO_new_file(yy_aconf->rsa_public_key_file, "r");
991     new_aconf->rsa_public_key = (RSA *)PEM_read_bio_RSA_PUBKEY(file,
992     NULL, 0, NULL);
993     BIO_set_close(file, BIO_CLOSE);
994     BIO_free(file);
995     }
996     #endif
997    
998     #ifdef HAVE_LIBCRYPTO
999     if (yy_tmp->name && (yy_tmp->passwd || yy_aconf->rsa_public_key)
1000     && yy_tmp->host)
1001     #else
1002     if (yy_tmp->name && yy_tmp->passwd && yy_tmp->host)
1003     #endif
1004     {
1005     conf_add_class_to_conf(new_conf, class_name);
1006     if (yy_tmp->name != NULL)
1007     DupString(new_conf->name, yy_tmp->name);
1008     }
1009    
1010     dlinkDelete(&yy_tmp->node, &col_conf_list);
1011     free_collect_item(yy_tmp);
1012     }
1013    
1014     yy_conf = NULL;
1015     yy_aconf = NULL;
1016    
1017    
1018     MyFree(class_name);
1019     class_name = NULL;
1020     }
1021     };
1022    
1023     oper_name_b: | oper_name_t;
1024     oper_items: oper_items oper_item | oper_item;
1025 michael 1076 oper_item: oper_name | oper_user | oper_password |
1026     oper_umodes | oper_class | oper_encrypted |
1027     oper_rsa_public_key_file | oper_flags | error ';' ;
1028 adx 30
1029     oper_name: NAME '=' QSTRING ';'
1030     {
1031 michael 967 if (conf_parser_ctx.pass == 2)
1032 adx 30 {
1033     if (strlen(yylval.string) > OPERNICKLEN)
1034     yylval.string[OPERNICKLEN] = '\0';
1035    
1036     MyFree(yy_conf->name);
1037     DupString(yy_conf->name, yylval.string);
1038     }
1039     };
1040    
1041     oper_name_t: QSTRING
1042     {
1043 michael 967 if (conf_parser_ctx.pass == 2)
1044 adx 30 {
1045     if (strlen(yylval.string) > OPERNICKLEN)
1046     yylval.string[OPERNICKLEN] = '\0';
1047    
1048     MyFree(yy_conf->name);
1049     DupString(yy_conf->name, yylval.string);
1050     }
1051     };
1052    
1053     oper_user: USER '=' QSTRING ';'
1054     {
1055 michael 967 if (conf_parser_ctx.pass == 2)
1056 adx 30 {
1057 michael 593 struct split_nuh_item nuh;
1058 adx 30
1059 michael 593 nuh.nuhmask = yylval.string;
1060     nuh.nickptr = NULL;
1061     nuh.userptr = userbuf;
1062     nuh.hostptr = hostbuf;
1063    
1064     nuh.nicksize = 0;
1065     nuh.usersize = sizeof(userbuf);
1066     nuh.hostsize = sizeof(hostbuf);
1067    
1068     split_nuh(&nuh);
1069    
1070 adx 30 if (yy_aconf->user == NULL)
1071     {
1072 michael 593 DupString(yy_aconf->user, userbuf);
1073     DupString(yy_aconf->host, hostbuf);
1074 adx 30 }
1075     else
1076     {
1077 michael 593 struct CollectItem *yy_tmp = MyMalloc(sizeof(struct CollectItem));
1078    
1079     DupString(yy_tmp->user, userbuf);
1080     DupString(yy_tmp->host, hostbuf);
1081    
1082 adx 30 dlinkAdd(yy_tmp, &yy_tmp->node, &col_conf_list);
1083     }
1084     }
1085     };
1086    
1087     oper_password: PASSWORD '=' QSTRING ';'
1088     {
1089 michael 967 if (conf_parser_ctx.pass == 2)
1090 adx 30 {
1091     if (yy_aconf->passwd != NULL)
1092     memset(yy_aconf->passwd, 0, strlen(yy_aconf->passwd));
1093    
1094     MyFree(yy_aconf->passwd);
1095     DupString(yy_aconf->passwd, yylval.string);
1096     }
1097     };
1098    
1099     oper_encrypted: ENCRYPTED '=' TBOOL ';'
1100     {
1101 michael 967 if (conf_parser_ctx.pass == 2)
1102 adx 30 {
1103     if (yylval.number)
1104     SetConfEncrypted(yy_aconf);
1105     else
1106     ClearConfEncrypted(yy_aconf);
1107     }
1108     };
1109    
1110     oper_rsa_public_key_file: RSA_PUBLIC_KEY_FILE '=' QSTRING ';'
1111     {
1112     #ifdef HAVE_LIBCRYPTO
1113 michael 967 if (conf_parser_ctx.pass == 2)
1114 adx 30 {
1115     BIO *file;
1116    
1117     if (yy_aconf->rsa_public_key != NULL)
1118     {
1119     RSA_free(yy_aconf->rsa_public_key);
1120     yy_aconf->rsa_public_key = NULL;
1121     }
1122    
1123     if (yy_aconf->rsa_public_key_file != NULL)
1124     {
1125     MyFree(yy_aconf->rsa_public_key_file);
1126     yy_aconf->rsa_public_key_file = NULL;
1127     }
1128    
1129     DupString(yy_aconf->rsa_public_key_file, yylval.string);
1130     file = BIO_new_file(yylval.string, "r");
1131    
1132     if (file == NULL)
1133     {
1134     yyerror("Ignoring rsa_public_key_file -- file doesn't exist");
1135     break;
1136     }
1137    
1138     yy_aconf->rsa_public_key = (RSA *)PEM_read_bio_RSA_PUBKEY(file, NULL, 0, NULL);
1139    
1140     if (yy_aconf->rsa_public_key == NULL)
1141     {
1142     yyerror("Ignoring rsa_public_key_file -- Key invalid; check key syntax.");
1143     break;
1144     }
1145    
1146     BIO_set_close(file, BIO_CLOSE);
1147     BIO_free(file);
1148     }
1149     #endif /* HAVE_LIBCRYPTO */
1150     };
1151    
1152     oper_class: CLASS '=' QSTRING ';'
1153     {
1154 michael 967 if (conf_parser_ctx.pass == 2)
1155 adx 30 {
1156     MyFree(class_name);
1157     DupString(class_name, yylval.string);
1158     }
1159     };
1160    
1161 michael 56 oper_umodes: T_UMODES
1162     {
1163 michael 967 if (conf_parser_ctx.pass == 2)
1164 db 298 yy_aconf->modes = 0;
1165 michael 56 } '=' oper_umodes_items ';' ;
1166    
1167     oper_umodes_items: oper_umodes_items ',' oper_umodes_item | oper_umodes_item;
1168     oper_umodes_item: T_BOTS
1169     {
1170 michael 967 if (conf_parser_ctx.pass == 2)
1171 db 298 yy_aconf->modes |= UMODE_BOTS;
1172 michael 56 } | T_CCONN
1173     {
1174 michael 967 if (conf_parser_ctx.pass == 2)
1175 db 298 yy_aconf->modes |= UMODE_CCONN;
1176 db 849 } | T_CCONN_FULL
1177     {
1178 michael 967 if (conf_parser_ctx.pass == 2)
1179 db 849 yy_aconf->modes |= UMODE_CCONN_FULL;
1180 michael 56 } | T_DEAF
1181     {
1182 michael 967 if (conf_parser_ctx.pass == 2)
1183 db 298 yy_aconf->modes |= UMODE_DEAF;
1184 michael 56 } | T_DEBUG
1185     {
1186 michael 967 if (conf_parser_ctx.pass == 2)
1187 db 298 yy_aconf->modes |= UMODE_DEBUG;
1188 michael 56 } | T_FULL
1189     {
1190 michael 967 if (conf_parser_ctx.pass == 2)
1191 db 298 yy_aconf->modes |= UMODE_FULL;
1192 michael 56 } | T_SKILL
1193     {
1194 michael 967 if (conf_parser_ctx.pass == 2)
1195 db 298 yy_aconf->modes |= UMODE_SKILL;
1196 michael 56 } | T_NCHANGE
1197     {
1198 michael 967 if (conf_parser_ctx.pass == 2)
1199 db 298 yy_aconf->modes |= UMODE_NCHANGE;
1200 michael 56 } | T_REJ
1201     {
1202 michael 967 if (conf_parser_ctx.pass == 2)
1203 db 298 yy_aconf->modes |= UMODE_REJ;
1204 michael 56 } | T_UNAUTH
1205     {
1206 michael 967 if (conf_parser_ctx.pass == 2)
1207 db 298 yy_aconf->modes |= UMODE_UNAUTH;
1208 michael 56 } | T_SPY
1209     {
1210 michael 967 if (conf_parser_ctx.pass == 2)
1211 db 298 yy_aconf->modes |= UMODE_SPY;
1212 michael 56 } | T_EXTERNAL
1213     {
1214 michael 967 if (conf_parser_ctx.pass == 2)
1215 db 298 yy_aconf->modes |= UMODE_EXTERNAL;
1216 michael 56 } | T_OPERWALL
1217     {
1218 michael 967 if (conf_parser_ctx.pass == 2)
1219 db 298 yy_aconf->modes |= UMODE_OPERWALL;
1220 michael 56 } | T_SERVNOTICE
1221     {
1222 michael 967 if (conf_parser_ctx.pass == 2)
1223 db 298 yy_aconf->modes |= UMODE_SERVNOTICE;
1224 michael 56 } | T_INVISIBLE
1225     {
1226 michael 967 if (conf_parser_ctx.pass == 2)
1227 db 298 yy_aconf->modes |= UMODE_INVISIBLE;
1228 michael 56 } | T_WALLOP
1229     {
1230 michael 967 if (conf_parser_ctx.pass == 2)
1231 db 298 yy_aconf->modes |= UMODE_WALLOP;
1232 michael 56 } | T_SOFTCALLERID
1233     {
1234 michael 967 if (conf_parser_ctx.pass == 2)
1235 db 298 yy_aconf->modes |= UMODE_SOFTCALLERID;
1236 michael 56 } | T_CALLERID
1237     {
1238 michael 967 if (conf_parser_ctx.pass == 2)
1239 db 298 yy_aconf->modes |= UMODE_CALLERID;
1240 michael 56 } | T_LOCOPS
1241     {
1242 michael 967 if (conf_parser_ctx.pass == 2)
1243 db 298 yy_aconf->modes |= UMODE_LOCOPS;
1244 michael 56 };
1245    
1246 adx 30 oper_flags: IRCD_FLAGS
1247     {
1248     } '=' oper_flags_items ';';
1249    
1250     oper_flags_items: oper_flags_items ',' oper_flags_item | oper_flags_item;
1251 db 136 oper_flags_item: NOT { not_atom = 1; } oper_flags_item_atom
1252     | { not_atom = 0; } oper_flags_item_atom;
1253 adx 30
1254     oper_flags_item_atom: GLOBAL_KILL
1255     {
1256 michael 967 if (conf_parser_ctx.pass == 2)
1257 adx 30 {
1258     if (not_atom)yy_aconf->port &= ~OPER_FLAG_GLOBAL_KILL;
1259     else yy_aconf->port |= OPER_FLAG_GLOBAL_KILL;
1260     }
1261     } | REMOTE
1262     {
1263 michael 967 if (conf_parser_ctx.pass == 2)
1264 adx 30 {
1265     if (not_atom) yy_aconf->port &= ~OPER_FLAG_REMOTE;
1266     else yy_aconf->port |= OPER_FLAG_REMOTE;
1267     }
1268     } | KLINE
1269     {
1270 michael 967 if (conf_parser_ctx.pass == 2)
1271 adx 30 {
1272     if (not_atom) yy_aconf->port &= ~OPER_FLAG_K;
1273     else yy_aconf->port |= OPER_FLAG_K;
1274     }
1275     } | UNKLINE
1276     {
1277 michael 967 if (conf_parser_ctx.pass == 2)
1278 adx 30 {
1279     if (not_atom) yy_aconf->port &= ~OPER_FLAG_UNKLINE;
1280     else yy_aconf->port |= OPER_FLAG_UNKLINE;
1281     }
1282     } | XLINE
1283     {
1284 michael 967 if (conf_parser_ctx.pass == 2)
1285 adx 30 {
1286     if (not_atom) yy_aconf->port &= ~OPER_FLAG_X;
1287     else yy_aconf->port |= OPER_FLAG_X;
1288     }
1289     } | GLINE
1290     {
1291 michael 967 if (conf_parser_ctx.pass == 2)
1292 adx 30 {
1293     if (not_atom) yy_aconf->port &= ~OPER_FLAG_GLINE;
1294     else yy_aconf->port |= OPER_FLAG_GLINE;
1295     }
1296     } | DIE
1297     {
1298 michael 967 if (conf_parser_ctx.pass == 2)
1299 adx 30 {
1300     if (not_atom) yy_aconf->port &= ~OPER_FLAG_DIE;
1301     else yy_aconf->port |= OPER_FLAG_DIE;
1302     }
1303     } | REHASH
1304     {
1305 michael 967 if (conf_parser_ctx.pass == 2)
1306 adx 30 {
1307     if (not_atom) yy_aconf->port &= ~OPER_FLAG_REHASH;
1308     else yy_aconf->port |= OPER_FLAG_REHASH;
1309     }
1310     } | ADMIN
1311     {
1312 michael 967 if (conf_parser_ctx.pass == 2)
1313 adx 30 {
1314     if (not_atom) yy_aconf->port &= ~OPER_FLAG_ADMIN;
1315     else yy_aconf->port |= OPER_FLAG_ADMIN;
1316     }
1317     } | HIDDEN_ADMIN
1318     {
1319 michael 967 if (conf_parser_ctx.pass == 2)
1320 adx 30 {
1321     if (not_atom) yy_aconf->port &= ~OPER_FLAG_HIDDEN_ADMIN;
1322     else yy_aconf->port |= OPER_FLAG_HIDDEN_ADMIN;
1323     }
1324     } | NICK_CHANGES
1325     {
1326 michael 967 if (conf_parser_ctx.pass == 2)
1327 adx 30 {
1328     if (not_atom) yy_aconf->port &= ~OPER_FLAG_N;
1329     else yy_aconf->port |= OPER_FLAG_N;
1330     }
1331     } | T_OPERWALL
1332     {
1333 michael 967 if (conf_parser_ctx.pass == 2)
1334 adx 30 {
1335     if (not_atom) yy_aconf->port &= ~OPER_FLAG_OPERWALL;
1336     else yy_aconf->port |= OPER_FLAG_OPERWALL;
1337     }
1338 michael 1216 } | T_GLOBOPS
1339     {
1340     if (conf_parser_ctx.pass == 2)
1341     {
1342     if (not_atom) yy_aconf->port &= ~OPER_FLAG_GLOBOPS;
1343     else yy_aconf->port |= OPER_FLAG_GLOBOPS;
1344     }
1345 adx 30 } | OPER_SPY_T
1346     {
1347 michael 967 if (conf_parser_ctx.pass == 2)
1348 adx 30 {
1349     if (not_atom) yy_aconf->port &= ~OPER_FLAG_OPER_SPY;
1350     else yy_aconf->port |= OPER_FLAG_OPER_SPY;
1351     }
1352     } | HIDDEN_OPER
1353     {
1354 michael 967 if (conf_parser_ctx.pass == 2)
1355 adx 30 {
1356     if (not_atom) yy_aconf->port &= ~OPER_FLAG_HIDDEN_OPER;
1357     else yy_aconf->port |= OPER_FLAG_HIDDEN_OPER;
1358     }
1359     } | REMOTEBAN
1360     {
1361 michael 967 if (conf_parser_ctx.pass == 2)
1362 adx 30 {
1363     if (not_atom) yy_aconf->port &= ~OPER_FLAG_REMOTEBAN;
1364     else yy_aconf->port |= OPER_FLAG_REMOTEBAN;
1365     }
1366     } | ENCRYPTED
1367     {
1368 michael 967 if (conf_parser_ctx.pass == 2)
1369 adx 30 {
1370     if (not_atom) ClearConfEncrypted(yy_aconf);
1371     else SetConfEncrypted(yy_aconf);
1372     }
1373     };
1374    
1375    
1376     /***************************************************************************
1377     * section class
1378     ***************************************************************************/
1379     class_entry: CLASS
1380     {
1381 michael 967 if (conf_parser_ctx.pass == 1)
1382 adx 30 {
1383     yy_conf = make_conf_item(CLASS_TYPE);
1384 michael 671 yy_class = map_to_conf(yy_conf);
1385 adx 30 }
1386     } class_name_b '{' class_items '}' ';'
1387     {
1388 michael 967 if (conf_parser_ctx.pass == 1)
1389 adx 30 {
1390 michael 671 struct ConfItem *cconf = NULL;
1391 adx 30 struct ClassItem *class = NULL;
1392    
1393     if (yy_class_name == NULL)
1394     delete_conf_item(yy_conf);
1395     else
1396     {
1397     cconf = find_exact_name_conf(CLASS_TYPE, yy_class_name, NULL, NULL);
1398    
1399     if (cconf != NULL) /* The class existed already */
1400     {
1401 michael 671 int user_count = 0;
1402    
1403 adx 30 rebuild_cidr_class(cconf, yy_class);
1404 michael 671
1405     class = map_to_conf(cconf);
1406    
1407     user_count = class->curr_user_count;
1408     memcpy(class, yy_class, sizeof(*class));
1409     class->curr_user_count = user_count;
1410     class->active = 1;
1411    
1412 adx 30 delete_conf_item(yy_conf);
1413    
1414     MyFree(cconf->name); /* Allows case change of class name */
1415     cconf->name = yy_class_name;
1416     }
1417     else /* Brand new class */
1418     {
1419     MyFree(yy_conf->name); /* just in case it was allocated */
1420     yy_conf->name = yy_class_name;
1421 michael 671 yy_class->active = 1;
1422 adx 30 }
1423     }
1424 michael 671
1425 adx 30 yy_class_name = NULL;
1426     }
1427     };
1428    
1429     class_name_b: | class_name_t;
1430    
1431     class_items: class_items class_item | class_item;
1432     class_item: class_name |
1433     class_cidr_bitlen_ipv4 | class_cidr_bitlen_ipv6 |
1434     class_ping_time |
1435     class_ping_warning |
1436     class_number_per_cidr |
1437     class_number_per_ip |
1438     class_connectfreq |
1439     class_max_number |
1440     class_max_global |
1441     class_max_local |
1442     class_max_ident |
1443     class_sendq |
1444     error ';' ;
1445    
1446     class_name: NAME '=' QSTRING ';'
1447     {
1448 michael 967 if (conf_parser_ctx.pass == 1)
1449 adx 30 {
1450     MyFree(yy_class_name);
1451     DupString(yy_class_name, yylval.string);
1452     }
1453     };
1454    
1455     class_name_t: QSTRING
1456     {
1457 michael 967 if (conf_parser_ctx.pass == 1)
1458 adx 30 {
1459     MyFree(yy_class_name);
1460     DupString(yy_class_name, yylval.string);
1461     }
1462     };
1463    
1464     class_ping_time: PING_TIME '=' timespec ';'
1465     {
1466 michael 967 if (conf_parser_ctx.pass == 1)
1467 adx 30 PingFreq(yy_class) = $3;
1468     };
1469    
1470     class_ping_warning: PING_WARNING '=' timespec ';'
1471     {
1472 michael 967 if (conf_parser_ctx.pass == 1)
1473 adx 30 PingWarning(yy_class) = $3;
1474     };
1475    
1476     class_number_per_ip: NUMBER_PER_IP '=' NUMBER ';'
1477     {
1478 michael 967 if (conf_parser_ctx.pass == 1)
1479 adx 30 MaxPerIp(yy_class) = $3;
1480     };
1481    
1482     class_connectfreq: CONNECTFREQ '=' timespec ';'
1483     {
1484 michael 967 if (conf_parser_ctx.pass == 1)
1485 adx 30 ConFreq(yy_class) = $3;
1486     };
1487    
1488     class_max_number: MAX_NUMBER '=' NUMBER ';'
1489     {
1490 michael 967 if (conf_parser_ctx.pass == 1)
1491 adx 30 MaxTotal(yy_class) = $3;
1492     };
1493    
1494     class_max_global: MAX_GLOBAL '=' NUMBER ';'
1495     {
1496 michael 967 if (conf_parser_ctx.pass == 1)
1497 adx 30 MaxGlobal(yy_class) = $3;
1498     };
1499    
1500     class_max_local: MAX_LOCAL '=' NUMBER ';'
1501     {
1502 michael 967 if (conf_parser_ctx.pass == 1)
1503 adx 30 MaxLocal(yy_class) = $3;
1504     };
1505    
1506     class_max_ident: MAX_IDENT '=' NUMBER ';'
1507     {
1508 michael 967 if (conf_parser_ctx.pass == 1)
1509 adx 30 MaxIdent(yy_class) = $3;
1510     };
1511    
1512     class_sendq: SENDQ '=' sizespec ';'
1513     {
1514 michael 967 if (conf_parser_ctx.pass == 1)
1515 adx 30 MaxSendq(yy_class) = $3;
1516     };
1517    
1518     class_cidr_bitlen_ipv4: CIDR_BITLEN_IPV4 '=' NUMBER ';'
1519     {
1520 michael 967 if (conf_parser_ctx.pass == 1)
1521 adx 30 CidrBitlenIPV4(yy_class) = $3;
1522     };
1523    
1524     class_cidr_bitlen_ipv6: CIDR_BITLEN_IPV6 '=' NUMBER ';'
1525     {
1526 michael 967 if (conf_parser_ctx.pass == 1)
1527 adx 30 CidrBitlenIPV6(yy_class) = $3;
1528     };
1529    
1530     class_number_per_cidr: NUMBER_PER_CIDR '=' NUMBER ';'
1531     {
1532 michael 967 if (conf_parser_ctx.pass == 1)
1533 adx 30 NumberPerCidr(yy_class) = $3;
1534     };
1535    
1536     /***************************************************************************
1537     * section listen
1538     ***************************************************************************/
1539     listen_entry: LISTEN
1540     {
1541 michael 967 if (conf_parser_ctx.pass == 2)
1542 adx 30 {
1543     listener_address = NULL;
1544     listener_flags = 0;
1545     }
1546     } '{' listen_items '}' ';'
1547     {
1548 michael 967 if (conf_parser_ctx.pass == 2)
1549 adx 30 {
1550     MyFree(listener_address);
1551     listener_address = NULL;
1552     }
1553     };
1554    
1555     listen_flags: IRCD_FLAGS
1556     {
1557 michael 440 listener_flags = 0;
1558 adx 30 } '=' listen_flags_items ';';
1559    
1560     listen_flags_items: listen_flags_items ',' listen_flags_item | listen_flags_item;
1561     listen_flags_item: T_SSL
1562     {
1563 michael 967 if (conf_parser_ctx.pass == 2)
1564 adx 30 listener_flags |= LISTENER_SSL;
1565     } | HIDDEN
1566     {
1567 michael 967 if (conf_parser_ctx.pass == 2)
1568 adx 30 listener_flags |= LISTENER_HIDDEN;
1569 michael 900 } | T_SERVER
1570     {
1571 michael 967 if (conf_parser_ctx.pass == 2)
1572 michael 900 listener_flags |= LISTENER_SERVER;
1573 adx 30 };
1574    
1575 michael 900
1576    
1577 adx 30 listen_items: listen_items listen_item | listen_item;
1578 michael 440 listen_item: listen_port | listen_flags | listen_address | listen_host | error ';';
1579 adx 30
1580 michael 440 listen_port: PORT '=' port_items { listener_flags = 0; } ';';
1581 adx 30
1582     port_items: port_items ',' port_item | port_item;
1583    
1584     port_item: NUMBER
1585     {
1586 michael 967 if (conf_parser_ctx.pass == 2)
1587 adx 30 {
1588     if ((listener_flags & LISTENER_SSL))
1589     #ifdef HAVE_LIBCRYPTO
1590 michael 967 if (!ServerInfo.server_ctx)
1591 adx 30 #endif
1592     {
1593     yyerror("SSL not available - port closed");
1594     break;
1595     }
1596     add_listener($1, listener_address, listener_flags);
1597     }
1598     } | NUMBER TWODOTS NUMBER
1599     {
1600 michael 967 if (conf_parser_ctx.pass == 2)
1601 adx 30 {
1602     int i;
1603    
1604     if ((listener_flags & LISTENER_SSL))
1605     #ifdef HAVE_LIBCRYPTO
1606 michael 967 if (!ServerInfo.server_ctx)
1607 adx 30 #endif
1608     {
1609     yyerror("SSL not available - port closed");
1610     break;
1611     }
1612    
1613     for (i = $1; i <= $3; ++i)
1614     add_listener(i, listener_address, listener_flags);
1615     }
1616     };
1617    
1618     listen_address: IP '=' QSTRING ';'
1619     {
1620 michael 967 if (conf_parser_ctx.pass == 2)
1621 adx 30 {
1622     MyFree(listener_address);
1623     DupString(listener_address, yylval.string);
1624     }
1625     };
1626    
1627     listen_host: HOST '=' QSTRING ';'
1628     {
1629 michael 967 if (conf_parser_ctx.pass == 2)
1630 adx 30 {
1631     MyFree(listener_address);
1632     DupString(listener_address, yylval.string);
1633     }
1634     };
1635    
1636     /***************************************************************************
1637     * section auth
1638     ***************************************************************************/
1639     auth_entry: IRCD_AUTH
1640     {
1641 michael 967 if (conf_parser_ctx.pass == 2)
1642 adx 30 {
1643     yy_conf = make_conf_item(CLIENT_TYPE);
1644     yy_aconf = map_to_conf(yy_conf);
1645     }
1646     else
1647     {
1648     MyFree(class_name);
1649     class_name = NULL;
1650     }
1651     } '{' auth_items '}' ';'
1652     {
1653 michael 967 if (conf_parser_ctx.pass == 2)
1654 adx 30 {
1655     struct CollectItem *yy_tmp = NULL;
1656     dlink_node *ptr = NULL, *next_ptr = NULL;
1657    
1658     if (yy_aconf->user && yy_aconf->host)
1659     {
1660     conf_add_class_to_conf(yy_conf, class_name);
1661     add_conf_by_address(CONF_CLIENT, yy_aconf);
1662     }
1663     else
1664     delete_conf_item(yy_conf);
1665    
1666     /* copy over settings from first struct */
1667     DLINK_FOREACH_SAFE(ptr, next_ptr, col_conf_list.head)
1668     {
1669     struct AccessItem *new_aconf;
1670     struct ConfItem *new_conf;
1671    
1672     new_conf = make_conf_item(CLIENT_TYPE);
1673     new_aconf = map_to_conf(new_conf);
1674    
1675     yy_tmp = ptr->data;
1676    
1677     assert(yy_tmp->user && yy_tmp->host);
1678    
1679     if (yy_aconf->passwd != NULL)
1680     DupString(new_aconf->passwd, yy_aconf->passwd);
1681     if (yy_conf->name != NULL)
1682     DupString(new_conf->name, yy_conf->name);
1683     if (yy_aconf->passwd != NULL)
1684     DupString(new_aconf->passwd, yy_aconf->passwd);
1685    
1686     new_aconf->flags = yy_aconf->flags;
1687     new_aconf->port = yy_aconf->port;
1688    
1689     DupString(new_aconf->user, yy_tmp->user);
1690     collapse(new_aconf->user);
1691    
1692     DupString(new_aconf->host, yy_tmp->host);
1693     collapse(new_aconf->host);
1694    
1695     conf_add_class_to_conf(new_conf, class_name);
1696     add_conf_by_address(CONF_CLIENT, new_aconf);
1697     dlinkDelete(&yy_tmp->node, &col_conf_list);
1698     free_collect_item(yy_tmp);
1699     }
1700    
1701     MyFree(class_name);
1702     class_name = NULL;
1703     yy_conf = NULL;
1704     yy_aconf = NULL;
1705     }
1706     };
1707    
1708     auth_items: auth_items auth_item | auth_item;
1709     auth_item: auth_user | auth_passwd | auth_class | auth_flags |
1710 michael 1076 auth_spoof | auth_redir_serv | auth_redir_port |
1711     auth_encrypted | error ';' ;
1712 adx 30
1713     auth_user: USER '=' QSTRING ';'
1714     {
1715 michael 967 if (conf_parser_ctx.pass == 2)
1716 adx 30 {
1717 michael 593 struct CollectItem *yy_tmp = NULL;
1718     struct split_nuh_item nuh;
1719 adx 30
1720 michael 593 nuh.nuhmask = yylval.string;
1721     nuh.nickptr = NULL;
1722     nuh.userptr = userbuf;
1723     nuh.hostptr = hostbuf;
1724    
1725     nuh.nicksize = 0;
1726     nuh.usersize = sizeof(userbuf);
1727     nuh.hostsize = sizeof(hostbuf);
1728    
1729     split_nuh(&nuh);
1730    
1731 adx 30 if (yy_aconf->user == NULL)
1732 michael 593 {
1733     DupString(yy_aconf->user, userbuf);
1734     DupString(yy_aconf->host, hostbuf);
1735     }
1736 adx 30 else
1737     {
1738     yy_tmp = MyMalloc(sizeof(struct CollectItem));
1739 michael 593
1740     DupString(yy_tmp->user, userbuf);
1741     DupString(yy_tmp->host, hostbuf);
1742    
1743 adx 30 dlinkAdd(yy_tmp, &yy_tmp->node, &col_conf_list);
1744     }
1745     }
1746     };
1747    
1748     /* XXX - IP/IPV6 tags don't exist anymore - put IP/IPV6 into user. */
1749    
1750     auth_passwd: PASSWORD '=' QSTRING ';'
1751     {
1752 michael 967 if (conf_parser_ctx.pass == 2)
1753 adx 30 {
1754     /* be paranoid */
1755     if (yy_aconf->passwd != NULL)
1756     memset(yy_aconf->passwd, 0, strlen(yy_aconf->passwd));
1757    
1758     MyFree(yy_aconf->passwd);
1759     DupString(yy_aconf->passwd, yylval.string);
1760     }
1761     };
1762    
1763     auth_class: CLASS '=' QSTRING ';'
1764     {
1765 michael 967 if (conf_parser_ctx.pass == 2)
1766 adx 30 {
1767     MyFree(class_name);
1768     DupString(class_name, yylval.string);
1769     }
1770     };
1771    
1772     auth_encrypted: ENCRYPTED '=' TBOOL ';'
1773     {
1774 michael 967 if (conf_parser_ctx.pass == 2)
1775 adx 30 {
1776     if (yylval.number)
1777     SetConfEncrypted(yy_aconf);
1778     else
1779     ClearConfEncrypted(yy_aconf);
1780     }
1781     };
1782    
1783     auth_flags: IRCD_FLAGS
1784     {
1785     } '=' auth_flags_items ';';
1786    
1787     auth_flags_items: auth_flags_items ',' auth_flags_item | auth_flags_item;
1788 db 136 auth_flags_item: NOT { not_atom = 1; } auth_flags_item_atom
1789     | { not_atom = 0; } auth_flags_item_atom;
1790 adx 30
1791     auth_flags_item_atom: SPOOF_NOTICE
1792     {
1793 michael 967 if (conf_parser_ctx.pass == 2)
1794 adx 30 {
1795     if (not_atom) yy_aconf->flags &= ~CONF_FLAGS_SPOOF_NOTICE;
1796     else yy_aconf->flags |= CONF_FLAGS_SPOOF_NOTICE;
1797     }
1798     } | EXCEED_LIMIT
1799     {
1800 michael 967 if (conf_parser_ctx.pass == 2)
1801 adx 30 {
1802     if (not_atom) yy_aconf->flags &= ~CONF_FLAGS_NOLIMIT;
1803     else yy_aconf->flags |= CONF_FLAGS_NOLIMIT;
1804     }
1805     } | KLINE_EXEMPT
1806     {
1807 michael 967 if (conf_parser_ctx.pass == 2)
1808 adx 30 {
1809     if (not_atom) yy_aconf->flags &= ~CONF_FLAGS_EXEMPTKLINE;
1810     else yy_aconf->flags |= CONF_FLAGS_EXEMPTKLINE;
1811     }
1812     } | NEED_IDENT
1813     {
1814 michael 967 if (conf_parser_ctx.pass == 2)
1815 adx 30 {
1816     if (not_atom) yy_aconf->flags &= ~CONF_FLAGS_NEED_IDENTD;
1817     else yy_aconf->flags |= CONF_FLAGS_NEED_IDENTD;
1818     }
1819     } | CAN_FLOOD
1820     {
1821 michael 967 if (conf_parser_ctx.pass == 2)
1822 adx 30 {
1823     if (not_atom) yy_aconf->flags &= ~CONF_FLAGS_CAN_FLOOD;
1824     else yy_aconf->flags |= CONF_FLAGS_CAN_FLOOD;
1825     }
1826     } | NO_TILDE
1827     {
1828 michael 967 if (conf_parser_ctx.pass == 2)
1829 adx 30 {
1830     if (not_atom) yy_aconf->flags &= ~CONF_FLAGS_NO_TILDE;
1831     else yy_aconf->flags |= CONF_FLAGS_NO_TILDE;
1832     }
1833     } | GLINE_EXEMPT
1834     {
1835 michael 967 if (conf_parser_ctx.pass == 2)
1836 adx 30 {
1837     if (not_atom) yy_aconf->flags &= ~CONF_FLAGS_EXEMPTGLINE;
1838     else yy_aconf->flags |= CONF_FLAGS_EXEMPTGLINE;
1839     }
1840     } | RESV_EXEMPT
1841     {
1842 michael 967 if (conf_parser_ctx.pass == 2)
1843 adx 30 {
1844     if (not_atom) yy_aconf->flags &= ~CONF_FLAGS_EXEMPTRESV;
1845     else yy_aconf->flags |= CONF_FLAGS_EXEMPTRESV;
1846     }
1847     } | NEED_PASSWORD
1848     {
1849 michael 967 if (conf_parser_ctx.pass == 2)
1850 adx 30 {
1851     if (not_atom) yy_aconf->flags &= ~CONF_FLAGS_NEED_PASSWORD;
1852     else yy_aconf->flags |= CONF_FLAGS_NEED_PASSWORD;
1853     }
1854     };
1855    
1856     /* XXX - need check for illegal hostnames here */
1857     auth_spoof: SPOOF '=' QSTRING ';'
1858     {
1859 michael 967 if (conf_parser_ctx.pass == 2)
1860 adx 30 {
1861     MyFree(yy_conf->name);
1862    
1863     if (strlen(yylval.string) < HOSTLEN)
1864     {
1865     DupString(yy_conf->name, yylval.string);
1866     yy_aconf->flags |= CONF_FLAGS_SPOOF_IP;
1867     }
1868     else
1869     {
1870     ilog(L_ERROR, "Spoofs must be less than %d..ignoring it", HOSTLEN);
1871     yy_conf->name = NULL;
1872     }
1873     }
1874     };
1875    
1876     auth_redir_serv: REDIRSERV '=' QSTRING ';'
1877     {
1878 michael 967 if (conf_parser_ctx.pass == 2)
1879 adx 30 {
1880     yy_aconf->flags |= CONF_FLAGS_REDIR;
1881     MyFree(yy_conf->name);
1882     DupString(yy_conf->name, yylval.string);
1883     }
1884     };
1885    
1886     auth_redir_port: REDIRPORT '=' NUMBER ';'
1887     {
1888 michael 967 if (conf_parser_ctx.pass == 2)
1889 adx 30 {
1890     yy_aconf->flags |= CONF_FLAGS_REDIR;
1891     yy_aconf->port = $3;
1892     }
1893     };
1894    
1895    
1896     /***************************************************************************
1897     * section resv
1898     ***************************************************************************/
1899     resv_entry: RESV
1900     {
1901 michael 967 if (conf_parser_ctx.pass == 2)
1902 adx 30 {
1903     MyFree(resv_reason);
1904     resv_reason = NULL;
1905     }
1906     } '{' resv_items '}' ';'
1907     {
1908 michael 967 if (conf_parser_ctx.pass == 2)
1909 adx 30 {
1910     MyFree(resv_reason);
1911     resv_reason = NULL;
1912     }
1913     };
1914    
1915     resv_items: resv_items resv_item | resv_item;
1916     resv_item: resv_creason | resv_channel | resv_nick | error ';' ;
1917    
1918     resv_creason: REASON '=' QSTRING ';'
1919     {
1920 michael 967 if (conf_parser_ctx.pass == 2)
1921 adx 30 {
1922     MyFree(resv_reason);
1923     DupString(resv_reason, yylval.string);
1924     }
1925     };
1926    
1927     resv_channel: CHANNEL '=' QSTRING ';'
1928     {
1929 michael 967 if (conf_parser_ctx.pass == 2)
1930 adx 30 {
1931     if (IsChanPrefix(*yylval.string))
1932     {
1933     char def_reason[] = "No reason";
1934    
1935     create_channel_resv(yylval.string, resv_reason != NULL ? resv_reason : def_reason, 1);
1936     }
1937     }
1938     /* ignore it for now.. but we really should make a warning if
1939     * its an erroneous name --fl_ */
1940     };
1941    
1942     resv_nick: NICK '=' QSTRING ';'
1943     {
1944 michael 967 if (conf_parser_ctx.pass == 2)
1945 adx 30 {
1946     char def_reason[] = "No reason";
1947    
1948     create_nick_resv(yylval.string, resv_reason != NULL ? resv_reason : def_reason, 1);
1949     }
1950     };
1951    
1952     /***************************************************************************
1953 michael 1157 * section service
1954     ***************************************************************************/
1955     service_entry: T_SERVICE '{' service_items '}' ';';
1956    
1957     service_items: service_items service_item | service_item;
1958     service_item: service_name | error;
1959    
1960     service_name: NAME '=' QSTRING ';'
1961     {
1962     if (conf_parser_ctx.pass == 2)
1963     {
1964     if (valid_servname(yylval.string))
1965     {
1966     yy_conf = make_conf_item(SERVICE_TYPE);
1967     DupString(yy_conf->name, yylval.string);
1968     }
1969     }
1970     };
1971    
1972     /***************************************************************************
1973 adx 30 * section shared, for sharing remote klines etc.
1974     ***************************************************************************/
1975     shared_entry: T_SHARED
1976     {
1977 michael 967 if (conf_parser_ctx.pass == 2)
1978 adx 30 {
1979     yy_conf = make_conf_item(ULINE_TYPE);
1980     yy_match_item = map_to_conf(yy_conf);
1981     yy_match_item->action = SHARED_ALL;
1982     }
1983     } '{' shared_items '}' ';'
1984     {
1985 michael 967 if (conf_parser_ctx.pass == 2)
1986 adx 30 {
1987     yy_conf = NULL;
1988     }
1989     };
1990    
1991     shared_items: shared_items shared_item | shared_item;
1992     shared_item: shared_name | shared_user | shared_type | error ';' ;
1993    
1994     shared_name: NAME '=' QSTRING ';'
1995     {
1996 michael 967 if (conf_parser_ctx.pass == 2)
1997 adx 30 {
1998     MyFree(yy_conf->name);
1999     DupString(yy_conf->name, yylval.string);
2000     }
2001     };
2002    
2003     shared_user: USER '=' QSTRING ';'
2004     {
2005 michael 967 if (conf_parser_ctx.pass == 2)
2006 adx 30 {
2007 michael 593 struct split_nuh_item nuh;
2008    
2009     nuh.nuhmask = yylval.string;
2010     nuh.nickptr = NULL;
2011     nuh.userptr = userbuf;
2012     nuh.hostptr = hostbuf;
2013    
2014     nuh.nicksize = 0;
2015     nuh.usersize = sizeof(userbuf);
2016     nuh.hostsize = sizeof(hostbuf);
2017    
2018     split_nuh(&nuh);
2019    
2020     DupString(yy_match_item->user, userbuf);
2021     DupString(yy_match_item->host, hostbuf);
2022 adx 30 }
2023     };
2024    
2025     shared_type: TYPE
2026     {
2027 michael 967 if (conf_parser_ctx.pass == 2)
2028 adx 30 yy_match_item->action = 0;
2029     } '=' shared_types ';' ;
2030    
2031     shared_types: shared_types ',' shared_type_item | shared_type_item;
2032     shared_type_item: KLINE
2033     {
2034 michael 967 if (conf_parser_ctx.pass == 2)
2035 adx 30 yy_match_item->action |= SHARED_KLINE;
2036     } | TKLINE
2037     {
2038 michael 967 if (conf_parser_ctx.pass == 2)
2039 adx 30 yy_match_item->action |= SHARED_TKLINE;
2040     } | UNKLINE
2041     {
2042 michael 967 if (conf_parser_ctx.pass == 2)
2043 adx 30 yy_match_item->action |= SHARED_UNKLINE;
2044     } | XLINE
2045     {
2046 michael 967 if (conf_parser_ctx.pass == 2)
2047 adx 30 yy_match_item->action |= SHARED_XLINE;
2048     } | TXLINE
2049     {
2050 michael 967 if (conf_parser_ctx.pass == 2)
2051 adx 30 yy_match_item->action |= SHARED_TXLINE;
2052     } | T_UNXLINE
2053     {
2054 michael 967 if (conf_parser_ctx.pass == 2)
2055 adx 30 yy_match_item->action |= SHARED_UNXLINE;
2056     } | RESV
2057     {
2058 michael 967 if (conf_parser_ctx.pass == 2)
2059 adx 30 yy_match_item->action |= SHARED_RESV;
2060     } | TRESV
2061     {
2062 michael 967 if (conf_parser_ctx.pass == 2)
2063 adx 30 yy_match_item->action |= SHARED_TRESV;
2064     } | T_UNRESV
2065     {
2066 michael 967 if (conf_parser_ctx.pass == 2)
2067 adx 30 yy_match_item->action |= SHARED_UNRESV;
2068     } | T_LOCOPS
2069     {
2070 michael 967 if (conf_parser_ctx.pass == 2)
2071 adx 30 yy_match_item->action |= SHARED_LOCOPS;
2072     } | T_ALL
2073     {
2074 michael 967 if (conf_parser_ctx.pass == 2)
2075 adx 30 yy_match_item->action = SHARED_ALL;
2076     };
2077    
2078     /***************************************************************************
2079     * section cluster
2080     ***************************************************************************/
2081     cluster_entry: T_CLUSTER
2082     {
2083 michael 967 if (conf_parser_ctx.pass == 2)
2084 adx 30 {
2085     yy_conf = make_conf_item(CLUSTER_TYPE);
2086     yy_conf->flags = SHARED_ALL;
2087     }
2088     } '{' cluster_items '}' ';'
2089     {
2090 michael 967 if (conf_parser_ctx.pass == 2)
2091 adx 30 {
2092     if (yy_conf->name == NULL)
2093     DupString(yy_conf->name, "*");
2094     yy_conf = NULL;
2095     }
2096     };
2097    
2098     cluster_items: cluster_items cluster_item | cluster_item;
2099     cluster_item: cluster_name | cluster_type | error ';' ;
2100    
2101     cluster_name: NAME '=' QSTRING ';'
2102     {
2103 michael 967 if (conf_parser_ctx.pass == 2)
2104 adx 30 DupString(yy_conf->name, yylval.string);
2105     };
2106    
2107     cluster_type: TYPE
2108     {
2109 michael 967 if (conf_parser_ctx.pass == 2)
2110 adx 30 yy_conf->flags = 0;
2111     } '=' cluster_types ';' ;
2112    
2113     cluster_types: cluster_types ',' cluster_type_item | cluster_type_item;
2114     cluster_type_item: KLINE
2115     {
2116 michael 967 if (conf_parser_ctx.pass == 2)
2117 adx 30 yy_conf->flags |= SHARED_KLINE;
2118     } | TKLINE
2119     {
2120 michael 967 if (conf_parser_ctx.pass == 2)
2121 adx 30 yy_conf->flags |= SHARED_TKLINE;
2122     } | UNKLINE
2123     {
2124 michael 967 if (conf_parser_ctx.pass == 2)
2125 adx 30 yy_conf->flags |= SHARED_UNKLINE;
2126     } | XLINE
2127     {
2128 michael 967 if (conf_parser_ctx.pass == 2)
2129 adx 30 yy_conf->flags |= SHARED_XLINE;
2130     } | TXLINE
2131     {
2132 michael 967 if (conf_parser_ctx.pass == 2)
2133 adx 30 yy_conf->flags |= SHARED_TXLINE;
2134     } | T_UNXLINE
2135     {
2136 michael 967 if (conf_parser_ctx.pass == 2)
2137 adx 30 yy_conf->flags |= SHARED_UNXLINE;
2138     } | RESV
2139     {
2140 michael 967 if (conf_parser_ctx.pass == 2)
2141 adx 30 yy_conf->flags |= SHARED_RESV;
2142     } | TRESV
2143     {
2144 michael 967 if (conf_parser_ctx.pass == 2)
2145 adx 30 yy_conf->flags |= SHARED_TRESV;
2146     } | T_UNRESV
2147     {
2148 michael 967 if (conf_parser_ctx.pass == 2)
2149 adx 30 yy_conf->flags |= SHARED_UNRESV;
2150     } | T_LOCOPS
2151     {
2152 michael 967 if (conf_parser_ctx.pass == 2)
2153 adx 30 yy_conf->flags |= SHARED_LOCOPS;
2154     } | T_ALL
2155     {
2156 michael 967 if (conf_parser_ctx.pass == 2)
2157 adx 30 yy_conf->flags = SHARED_ALL;
2158     };
2159    
2160     /***************************************************************************
2161     * section connect
2162     ***************************************************************************/
2163     connect_entry: CONNECT
2164     {
2165 michael 967 if (conf_parser_ctx.pass == 2)
2166 adx 30 {
2167     yy_conf = make_conf_item(SERVER_TYPE);
2168     yy_aconf = (struct AccessItem *)map_to_conf(yy_conf);
2169     yy_aconf->passwd = NULL;
2170     /* defaults */
2171     yy_aconf->port = PORTNUM;
2172    
2173     if (ConfigFileEntry.burst_away)
2174     yy_aconf->flags = CONF_FLAGS_BURST_AWAY;
2175     }
2176     else
2177     {
2178     MyFree(class_name);
2179     class_name = NULL;
2180     }
2181     } connect_name_b '{' connect_items '}' ';'
2182     {
2183 michael 967 if (conf_parser_ctx.pass == 2)
2184 adx 30 {
2185     struct CollectItem *yy_hconf=NULL;
2186     struct CollectItem *yy_lconf=NULL;
2187     dlink_node *ptr;
2188     dlink_node *next_ptr;
2189     #ifdef HAVE_LIBCRYPTO
2190     if (yy_aconf->host &&
2191     ((yy_aconf->passwd && yy_aconf->spasswd) ||
2192     (yy_aconf->rsa_public_key && IsConfCryptLink(yy_aconf))))
2193     #else /* !HAVE_LIBCRYPTO */
2194     if (yy_aconf->host && !IsConfCryptLink(yy_aconf) &&
2195     yy_aconf->passwd && yy_aconf->spasswd)
2196     #endif /* !HAVE_LIBCRYPTO */
2197     {
2198 michael 593 if (conf_add_server(yy_conf, class_name) == -1)
2199 adx 30 {
2200     delete_conf_item(yy_conf);
2201     yy_conf = NULL;
2202     yy_aconf = NULL;
2203     }
2204     }
2205     else
2206     {
2207     /* Even if yy_conf ->name is NULL
2208     * should still unhook any hub/leaf confs still pending
2209     */
2210     unhook_hub_leaf_confs();
2211    
2212     if (yy_conf->name != NULL)
2213     {
2214     #ifndef HAVE_LIBCRYPTO
2215     if (IsConfCryptLink(yy_aconf))
2216     yyerror("Ignoring connect block -- no OpenSSL support");
2217     #else
2218     if (IsConfCryptLink(yy_aconf) && !yy_aconf->rsa_public_key)
2219     yyerror("Ignoring connect block -- missing key");
2220     #endif
2221     if (yy_aconf->host == NULL)
2222     yyerror("Ignoring connect block -- missing host");
2223     else if (!IsConfCryptLink(yy_aconf) &&
2224     (!yy_aconf->passwd || !yy_aconf->spasswd))
2225     yyerror("Ignoring connect block -- missing password");
2226     }
2227    
2228    
2229     /* XXX
2230     * This fixes a try_connections() core (caused by invalid class_ptr
2231     * pointers) reported by metalrock. That's an ugly fix, but there
2232     * is currently no better way. The entire config subsystem needs an
2233     * rewrite ASAP. make_conf_item() shouldn't really add things onto
2234     * a doubly linked list immediately without any sanity checks! -Michael
2235     */
2236     delete_conf_item(yy_conf);
2237    
2238     yy_aconf = NULL;
2239     yy_conf = NULL;
2240     }
2241    
2242     /*
2243     * yy_conf is still pointing at the server that is having
2244     * a connect block built for it. This means, y_aconf->name
2245     * points to the actual irc name this server will be known as.
2246     * Now this new server has a set or even just one hub_mask (or leaf_mask)
2247     * given in the link list at yy_hconf. Fill in the HUB confs
2248     * from this link list now.
2249     */
2250     DLINK_FOREACH_SAFE(ptr, next_ptr, hub_conf_list.head)
2251     {
2252     struct ConfItem *new_hub_conf;
2253     struct MatchItem *match_item;
2254    
2255     yy_hconf = ptr->data;
2256    
2257     /* yy_conf == NULL is a fatal error for this connect block! */
2258     if ((yy_conf != NULL) && (yy_conf->name != NULL))
2259     {
2260     new_hub_conf = make_conf_item(HUB_TYPE);
2261     match_item = (struct MatchItem *)map_to_conf(new_hub_conf);
2262     DupString(new_hub_conf->name, yy_conf->name);
2263     if (yy_hconf->user != NULL)
2264     DupString(match_item->user, yy_hconf->user);
2265     else
2266     DupString(match_item->user, "*");
2267     if (yy_hconf->host != NULL)
2268     DupString(match_item->host, yy_hconf->host);
2269     else
2270     DupString(match_item->host, "*");
2271     }
2272     dlinkDelete(&yy_hconf->node, &hub_conf_list);
2273     free_collect_item(yy_hconf);
2274     }
2275    
2276     /* Ditto for the LEAF confs */
2277    
2278     DLINK_FOREACH_SAFE(ptr, next_ptr, leaf_conf_list.head)
2279     {
2280     struct ConfItem *new_leaf_conf;
2281     struct MatchItem *match_item;
2282    
2283     yy_lconf = ptr->data;
2284    
2285     if ((yy_conf != NULL) && (yy_conf->name != NULL))
2286     {
2287     new_leaf_conf = make_conf_item(LEAF_TYPE);
2288     match_item = (struct MatchItem *)map_to_conf(new_leaf_conf);
2289     DupString(new_leaf_conf->name, yy_conf->name);
2290     if (yy_lconf->user != NULL)
2291     DupString(match_item->user, yy_lconf->user);
2292     else
2293     DupString(match_item->user, "*");
2294     if (yy_lconf->host != NULL)
2295     DupString(match_item->host, yy_lconf->host);
2296     else
2297     DupString(match_item->host, "*");
2298     }
2299     dlinkDelete(&yy_lconf->node, &leaf_conf_list);
2300     free_collect_item(yy_lconf);
2301     }
2302     MyFree(class_name);
2303     class_name = NULL;
2304     yy_conf = NULL;
2305     yy_aconf = NULL;
2306     }
2307     };
2308    
2309     connect_name_b: | connect_name_t;
2310     connect_items: connect_items connect_item | connect_item;
2311     connect_item: connect_name | connect_host | connect_vhost |
2312     connect_send_password | connect_accept_password |
2313 michael 1118 connect_aftype | connect_port |
2314 michael 1076 connect_flags | connect_hub_mask | connect_leaf_mask |
2315     connect_class | connect_encrypted |
2316 adx 30 connect_rsa_public_key_file | connect_cipher_preference |
2317 michael 1076 error ';' ;
2318 adx 30
2319     connect_name: NAME '=' QSTRING ';'
2320     {
2321 michael 967 if (conf_parser_ctx.pass == 2)
2322 adx 30 {
2323     if (yy_conf->name != NULL)
2324     yyerror("Multiple connect name entry");
2325    
2326     MyFree(yy_conf->name);
2327     DupString(yy_conf->name, yylval.string);
2328     }
2329     };
2330    
2331     connect_name_t: QSTRING
2332     {
2333 michael 967 if (conf_parser_ctx.pass == 2)
2334 adx 30 {
2335     if (yy_conf->name != NULL)
2336     yyerror("Multiple connect name entry");
2337    
2338     MyFree(yy_conf->name);
2339     DupString(yy_conf->name, yylval.string);
2340     }
2341     };
2342    
2343     connect_host: HOST '=' QSTRING ';'
2344     {
2345 michael 967 if (conf_parser_ctx.pass == 2)
2346 adx 30 {
2347     MyFree(yy_aconf->host);
2348     DupString(yy_aconf->host, yylval.string);
2349     }
2350     };
2351    
2352     connect_vhost: VHOST '=' QSTRING ';'
2353     {
2354 michael 967 if (conf_parser_ctx.pass == 2)
2355 adx 30 {
2356     struct addrinfo hints, *res;
2357    
2358     memset(&hints, 0, sizeof(hints));
2359    
2360     hints.ai_family = AF_UNSPEC;
2361     hints.ai_socktype = SOCK_STREAM;
2362     hints.ai_flags = AI_PASSIVE | AI_NUMERICHOST;
2363    
2364 michael 1123 if (getaddrinfo(yylval.string, NULL, &hints, &res))
2365 adx 30 ilog(L_ERROR, "Invalid netmask for server vhost(%s)", yylval.string);
2366     else
2367     {
2368     assert(res != NULL);
2369    
2370     memcpy(&yy_aconf->my_ipnum, res->ai_addr, res->ai_addrlen);
2371     yy_aconf->my_ipnum.ss.ss_family = res->ai_family;
2372     yy_aconf->my_ipnum.ss_len = res->ai_addrlen;
2373 michael 1123 freeaddrinfo(res);
2374 adx 30 }
2375     }
2376     };
2377    
2378     connect_send_password: SEND_PASSWORD '=' QSTRING ';'
2379     {
2380 michael 967 if (conf_parser_ctx.pass == 2)
2381 adx 30 {
2382 adx 38 if ($3[0] == ':')
2383     yyerror("Server passwords cannot begin with a colon");
2384     else if (strchr($3, ' ') != NULL)
2385     yyerror("Server passwords cannot contain spaces");
2386     else {
2387     if (yy_aconf->spasswd != NULL)
2388     memset(yy_aconf->spasswd, 0, strlen(yy_aconf->spasswd));
2389 adx 30
2390 adx 38 MyFree(yy_aconf->spasswd);
2391     DupString(yy_aconf->spasswd, yylval.string);
2392     }
2393 adx 30 }
2394     };
2395    
2396     connect_accept_password: ACCEPT_PASSWORD '=' QSTRING ';'
2397     {
2398 michael 967 if (conf_parser_ctx.pass == 2)
2399 adx 30 {
2400 adx 38 if ($3[0] == ':')
2401     yyerror("Server passwords cannot begin with a colon");
2402     else if (strchr($3, ' ') != NULL)
2403     yyerror("Server passwords cannot contain spaces");
2404     else {
2405     if (yy_aconf->passwd != NULL)
2406     memset(yy_aconf->passwd, 0, strlen(yy_aconf->passwd));
2407 adx 30
2408 adx 38 MyFree(yy_aconf->passwd);
2409     DupString(yy_aconf->passwd, yylval.string);
2410     }
2411 adx 30 }
2412     };
2413    
2414     connect_port: PORT '=' NUMBER ';'
2415     {
2416 michael 967 if (conf_parser_ctx.pass == 2)
2417 adx 30 yy_aconf->port = $3;
2418     };
2419    
2420     connect_aftype: AFTYPE '=' T_IPV4 ';'
2421     {
2422 michael 967 if (conf_parser_ctx.pass == 2)
2423 adx 30 yy_aconf->aftype = AF_INET;
2424     } | AFTYPE '=' T_IPV6 ';'
2425     {
2426     #ifdef IPV6
2427 michael 967 if (conf_parser_ctx.pass == 2)
2428 adx 30 yy_aconf->aftype = AF_INET6;
2429     #endif
2430     };
2431    
2432     connect_flags: IRCD_FLAGS
2433     {
2434     } '=' connect_flags_items ';';
2435    
2436     connect_flags_items: connect_flags_items ',' connect_flags_item | connect_flags_item;
2437 db 136 connect_flags_item: NOT { not_atom = 1; } connect_flags_item_atom
2438     | { not_atom = 0; } connect_flags_item_atom;
2439 adx 30
2440 michael 885 connect_flags_item_atom: COMPRESSED
2441 adx 30 {
2442 michael 967 if (conf_parser_ctx.pass == 2)
2443 adx 30 #ifndef HAVE_LIBZ
2444     yyerror("Ignoring flags = compressed; -- no zlib support");
2445     #else
2446     {
2447     if (not_atom)ClearConfCompressed(yy_aconf);
2448     else SetConfCompressed(yy_aconf);
2449     }
2450     #endif
2451     } | CRYPTLINK
2452     {
2453 michael 967 if (conf_parser_ctx.pass == 2)
2454 adx 30 {
2455     if (not_atom)ClearConfCryptLink(yy_aconf);
2456     else SetConfCryptLink(yy_aconf);
2457     }
2458     } | AUTOCONN
2459     {
2460 michael 967 if (conf_parser_ctx.pass == 2)
2461 adx 30 {
2462     if (not_atom)ClearConfAllowAutoConn(yy_aconf);
2463     else SetConfAllowAutoConn(yy_aconf);
2464     }
2465     } | BURST_AWAY
2466     {
2467 michael 967 if (conf_parser_ctx.pass == 2)
2468 adx 30 {
2469     if (not_atom)ClearConfAwayBurst(yy_aconf);
2470     else SetConfAwayBurst(yy_aconf);
2471     }
2472     } | TOPICBURST
2473     {
2474 michael 967 if (conf_parser_ctx.pass == 2)
2475 adx 30 {
2476     if (not_atom)ClearConfTopicBurst(yy_aconf);
2477     else SetConfTopicBurst(yy_aconf);
2478     }
2479     }
2480     ;
2481    
2482     connect_rsa_public_key_file: RSA_PUBLIC_KEY_FILE '=' QSTRING ';'
2483     {
2484     #ifdef HAVE_LIBCRYPTO
2485 michael 967 if (conf_parser_ctx.pass == 2)
2486 adx 30 {
2487     BIO *file;
2488    
2489     if (yy_aconf->rsa_public_key != NULL)
2490     {
2491     RSA_free(yy_aconf->rsa_public_key);
2492     yy_aconf->rsa_public_key = NULL;
2493     }
2494    
2495     if (yy_aconf->rsa_public_key_file != NULL)
2496     {
2497     MyFree(yy_aconf->rsa_public_key_file);
2498     yy_aconf->rsa_public_key_file = NULL;
2499     }
2500    
2501     DupString(yy_aconf->rsa_public_key_file, yylval.string);
2502    
2503     if ((file = BIO_new_file(yylval.string, "r")) == NULL)
2504     {
2505     yyerror("Ignoring rsa_public_key_file -- file doesn't exist");
2506     break;
2507     }
2508    
2509     yy_aconf->rsa_public_key = (RSA *)PEM_read_bio_RSA_PUBKEY(file, NULL, 0, NULL);
2510    
2511     if (yy_aconf->rsa_public_key == NULL)
2512     {
2513     yyerror("Ignoring rsa_public_key_file -- Key invalid; check key syntax.");
2514     break;
2515     }
2516    
2517     BIO_set_close(file, BIO_CLOSE);
2518     BIO_free(file);
2519     }
2520     #endif /* HAVE_LIBCRYPTO */
2521     };
2522    
2523     connect_encrypted: ENCRYPTED '=' TBOOL ';'
2524     {
2525 michael 967 if (conf_parser_ctx.pass == 2)
2526 adx 30 {
2527     if (yylval.number)
2528     yy_aconf->flags |= CONF_FLAGS_ENCRYPTED;
2529     else
2530     yy_aconf->flags &= ~CONF_FLAGS_ENCRYPTED;
2531     }
2532     };
2533    
2534     connect_hub_mask: HUB_MASK '=' QSTRING ';'
2535     {
2536 michael 967 if (conf_parser_ctx.pass == 2)
2537 adx 30 {
2538     struct CollectItem *yy_tmp;
2539    
2540     yy_tmp = (struct CollectItem *)MyMalloc(sizeof(struct CollectItem));
2541     DupString(yy_tmp->host, yylval.string);
2542     DupString(yy_tmp->user, "*");
2543     dlinkAdd(yy_tmp, &yy_tmp->node, &hub_conf_list);
2544     }
2545     };
2546    
2547     connect_leaf_mask: LEAF_MASK '=' QSTRING ';'
2548     {
2549 michael 967 if (conf_parser_ctx.pass == 2)
2550 adx 30 {
2551     struct CollectItem *yy_tmp;
2552    
2553     yy_tmp = (struct CollectItem *)MyMalloc(sizeof(struct CollectItem));
2554     DupString(yy_tmp->host, yylval.string);
2555     DupString(yy_tmp->user, "*");
2556     dlinkAdd(yy_tmp, &yy_tmp->node, &leaf_conf_list);
2557     }
2558     };
2559    
2560     connect_class: CLASS '=' QSTRING ';'
2561     {
2562 michael 967 if (conf_parser_ctx.pass == 2)
2563 adx 30 {
2564     MyFree(class_name);
2565     DupString(class_name, yylval.string);
2566     }
2567     };
2568    
2569     connect_cipher_preference: CIPHER_PREFERENCE '=' QSTRING ';'
2570     {
2571     #ifdef HAVE_LIBCRYPTO
2572 michael 967 if (conf_parser_ctx.pass == 2)
2573 adx 30 {
2574     struct EncCapability *ecap;
2575     const char *cipher_name;
2576     int found = 0;
2577    
2578     yy_aconf->cipher_preference = NULL;
2579     cipher_name = yylval.string;
2580    
2581     for (ecap = CipherTable; ecap->name; ecap++)
2582     {
2583     if ((irccmp(ecap->name, cipher_name) == 0) &&
2584     (ecap->cap & CAP_ENC_MASK))
2585     {
2586     yy_aconf->cipher_preference = ecap;
2587     found = 1;
2588     break;
2589     }
2590     }
2591    
2592     if (!found)
2593     yyerror("Invalid cipher");
2594     }
2595     #else
2596 michael 967 if (conf_parser_ctx.pass == 2)
2597 adx 30 yyerror("Ignoring cipher_preference -- no OpenSSL support");
2598     #endif
2599     };
2600    
2601     /***************************************************************************
2602     * section kill
2603     ***************************************************************************/
2604     kill_entry: KILL
2605     {
2606 michael 967 if (conf_parser_ctx.pass == 2)
2607 adx 30 {
2608     userbuf[0] = hostbuf[0] = reasonbuf[0] = '\0';
2609     regex_ban = 0;
2610     }
2611     } '{' kill_items '}' ';'
2612     {
2613 michael 967 if (conf_parser_ctx.pass == 2)
2614 adx 30 {
2615     if (userbuf[0] && hostbuf[0])
2616     {
2617     if (regex_ban)
2618     {
2619 michael 1009 #ifdef HAVE_LIBPCRE
2620     void *exp_user = NULL;
2621     void *exp_host = NULL;
2622 adx 30 const char *errptr = NULL;
2623    
2624     if (!(exp_user = ircd_pcre_compile(userbuf, &errptr)) ||
2625     !(exp_host = ircd_pcre_compile(hostbuf, &errptr)))
2626     {
2627 michael 595 ilog(L_ERROR, "Failed to add regular expression based K-Line: %s",
2628     errptr);
2629 adx 30 break;
2630     }
2631    
2632 michael 1005 yy_aconf = map_to_conf(make_conf_item(RKLINE_TYPE));
2633 adx 30 yy_aconf->regexuser = exp_user;
2634     yy_aconf->regexhost = exp_host;
2635    
2636     DupString(yy_aconf->user, userbuf);
2637     DupString(yy_aconf->host, hostbuf);
2638    
2639     if (reasonbuf[0])
2640     DupString(yy_aconf->reason, reasonbuf);
2641     else
2642     DupString(yy_aconf->reason, "No reason");
2643 michael 1009 #else
2644     ilog(L_ERROR, "Failed to add regular expression based K-Line: no PCRE support");
2645     break;
2646     #endif
2647 adx 30 }
2648     else
2649     {
2650 michael 1005 yy_aconf = map_to_conf(make_conf_item(KLINE_TYPE));
2651 adx 30
2652     DupString(yy_aconf->user, userbuf);
2653     DupString(yy_aconf->host, hostbuf);
2654    
2655     if (reasonbuf[0])
2656     DupString(yy_aconf->reason, reasonbuf);
2657     else
2658     DupString(yy_aconf->reason, "No reason");
2659     add_conf_by_address(CONF_KILL, yy_aconf);
2660     }
2661     }
2662    
2663     yy_aconf = NULL;
2664     }
2665     };
2666    
2667     kill_type: TYPE
2668     {
2669     } '=' kill_type_items ';';
2670    
2671     kill_type_items: kill_type_items ',' kill_type_item | kill_type_item;
2672     kill_type_item: REGEX_T
2673     {
2674 michael 967 if (conf_parser_ctx.pass == 2)
2675 adx 30 regex_ban = 1;
2676     };
2677    
2678     kill_items: kill_items kill_item | kill_item;
2679     kill_item: kill_user | kill_reason | kill_type | error;
2680    
2681     kill_user: USER '=' QSTRING ';'
2682     {
2683 michael 967 if (conf_parser_ctx.pass == 2)
2684 adx 30 {
2685 michael 593 struct split_nuh_item nuh;
2686 adx 30
2687 michael 593 nuh.nuhmask = yylval.string;
2688     nuh.nickptr = NULL;
2689     nuh.userptr = userbuf;
2690     nuh.hostptr = hostbuf;
2691 adx 30
2692 michael 593 nuh.nicksize = 0;
2693     nuh.usersize = sizeof(userbuf);
2694     nuh.hostsize = sizeof(hostbuf);
2695 adx 30
2696 michael 593 split_nuh(&nuh);
2697 adx 30 }
2698     };
2699    
2700     kill_reason: REASON '=' QSTRING ';'
2701     {
2702 michael 967 if (conf_parser_ctx.pass == 2)
2703 adx 30 strlcpy(reasonbuf, yylval.string, sizeof(reasonbuf));
2704     };
2705    
2706     /***************************************************************************
2707     * section deny
2708     ***************************************************************************/
2709     deny_entry: DENY
2710     {
2711 michael 967 if (conf_parser_ctx.pass == 2)
2712 michael 1005 hostbuf[0] = reasonbuf[0] = '\0';
2713 adx 30 } '{' deny_items '}' ';'
2714     {
2715 michael 967 if (conf_parser_ctx.pass == 2)
2716 adx 30 {
2717 michael 1005 if (hostbuf[0] && parse_netmask(hostbuf, NULL, NULL) != HM_HOST)
2718     {
2719     yy_aconf = map_to_conf(make_conf_item(DLINE_TYPE));
2720     DupString(yy_aconf->host, hostbuf);
2721    
2722     if (reasonbuf[0])
2723     DupString(yy_aconf->reason, reasonbuf);
2724     else
2725     DupString(yy_aconf->reason, "No reason");
2726 adx 30 add_conf_by_address(CONF_DLINE, yy_aconf);
2727 michael 1005 yy_aconf = NULL;
2728     }
2729 adx 30 }
2730     };
2731    
2732     deny_items: deny_items deny_item | deny_item;
2733     deny_item: deny_ip | deny_reason | error;
2734    
2735     deny_ip: IP '=' QSTRING ';'
2736     {
2737 michael 967 if (conf_parser_ctx.pass == 2)
2738 michael 1005 strlcpy(hostbuf, yylval.string, sizeof(hostbuf));
2739 adx 30 };
2740    
2741     deny_reason: REASON '=' QSTRING ';'
2742     {
2743 michael 967 if (conf_parser_ctx.pass == 2)
2744 michael 1005 strlcpy(reasonbuf, yylval.string, sizeof(reasonbuf));
2745 adx 30 };
2746    
2747     /***************************************************************************
2748     * section exempt
2749     ***************************************************************************/
2750     exempt_entry: EXEMPT '{' exempt_items '}' ';';
2751    
2752     exempt_items: exempt_items exempt_item | exempt_item;
2753     exempt_item: exempt_ip | error;
2754    
2755     exempt_ip: IP '=' QSTRING ';'
2756     {
2757 michael 967 if (conf_parser_ctx.pass == 2)
2758 adx 30 {
2759     if (yylval.string[0] && parse_netmask(yylval.string, NULL, NULL) != HM_HOST)
2760     {
2761 michael 1005