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

Contents of /ircd-hybrid-7.2/src/ircd_parser.y

Parent Directory Parent Directory | Revision Log Revision Log


Revision 1011 - (show annotations)
Fri Sep 18 10:14:09 2009 UTC (11 years, 5 months ago) by michael
File size: 94388 byte(s)
- move list manipulation routines from tools.c to list.c
- mem_frob() goes to memory.c
- sort out redundant/unneeded header includes

1 /*
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 * $Id$
23 */
24
25 %{
26
27 #define YY_NO_UNPUT
28 #include <sys/types.h>
29 #include <string.h>
30
31 #include "config.h"
32 #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 "irc_getaddrinfo.h"
41 #include "sprintf_irc.h"
42 #include "memory.h"
43 #include "modules.h"
44 #include "s_serv.h"
45 #include "hostmask.h"
46 #include "send.h"
47 #include "listener.h"
48 #include "resv.h"
49 #include "numeric.h"
50 #include "s_user.h"
51
52 #ifdef HAVE_LIBCRYPTO
53 #include <openssl/rsa.h>
54 #include <openssl/bio.h>
55 #include <openssl/pem.h>
56 #endif
57
58 static char *class_name = NULL;
59 static struct ConfItem *yy_conf = NULL;
60 static struct AccessItem *yy_aconf = NULL;
61 static struct MatchItem *yy_match_item = NULL;
62 static struct ClassItem *yy_class = NULL;
63 static char *yy_class_name = NULL;
64
65 static dlink_list col_conf_list = { NULL, NULL, 0 };
66 static dlink_list hub_conf_list = { NULL, NULL, 0 };
67 static dlink_list leaf_conf_list = { NULL, NULL, 0 };
68 static unsigned int listener_flags = 0;
69 static unsigned int regex_ban = 0;
70 static char userbuf[IRCD_BUFSIZE];
71 static char hostbuf[IRCD_BUFSIZE];
72 static char reasonbuf[REASONLEN + 1];
73 static char gecos_name[REALLEN * 4];
74
75 static char *resv_reason = NULL;
76 static char *listener_address = NULL;
77 static int not_atom = 0;
78
79 struct CollectItem
80 {
81 dlink_node node;
82 char *name;
83 char *user;
84 char *host;
85 char *passwd;
86 int port;
87 int flags;
88 #ifdef HAVE_LIBCRYPTO
89 char *rsa_public_key_file;
90 RSA *rsa_public_key;
91 #endif
92 };
93
94 static void
95 free_collect_item(struct CollectItem *item)
96 {
97 MyFree(item->name);
98 MyFree(item->user);
99 MyFree(item->host);
100 MyFree(item->passwd);
101 #ifdef HAVE_LIBCRYPTO
102 MyFree(item->rsa_public_key_file);
103 #endif
104 MyFree(item);
105 }
106
107 static void
108 unhook_hub_leaf_confs(void)
109 {
110 dlink_node *ptr;
111 dlink_node *next_ptr;
112 struct CollectItem *yy_hconf;
113 struct CollectItem *yy_lconf;
114
115 DLINK_FOREACH_SAFE(ptr, next_ptr, hub_conf_list.head)
116 {
117 yy_hconf = ptr->data;
118 dlinkDelete(&yy_hconf->node, &hub_conf_list);
119 free_collect_item(yy_hconf);
120 }
121
122 DLINK_FOREACH_SAFE(ptr, next_ptr, leaf_conf_list.head)
123 {
124 yy_lconf = ptr->data;
125 dlinkDelete(&yy_lconf->node, &leaf_conf_list);
126 free_collect_item(yy_lconf);
127 }
128 }
129
130 %}
131
132 %union {
133 int number;
134 char *string;
135 }
136
137 %token ACCEPT_PASSWORD
138 %token ACTION
139 %token ADMIN
140 %token AFTYPE
141 %token T_ALLOW
142 %token ANTI_NICK_FLOOD
143 %token ANTI_SPAM_EXIT_MESSAGE_TIME
144 %token AUTOCONN
145 %token T_BLOCK
146 %token BURST_AWAY
147 %token BURST_TOPICWHO
148 %token BYTES KBYTES MBYTES GBYTES TBYTES
149 %token CALLER_ID_WAIT
150 %token CAN_FLOOD
151 %token CAN_IDLE
152 %token CHANNEL
153 %token CIDR_BITLEN_IPV4
154 %token CIDR_BITLEN_IPV6
155 %token CIPHER_PREFERENCE
156 %token CLASS
157 %token COMPRESSED
158 %token COMPRESSION_LEVEL
159 %token CONNECT
160 %token CONNECTFREQ
161 %token CRYPTLINK
162 %token DEFAULT_CIPHER_PREFERENCE
163 %token DEFAULT_FLOODCOUNT
164 %token DEFAULT_SPLIT_SERVER_COUNT
165 %token DEFAULT_SPLIT_USER_COUNT
166 %token DENY
167 %token DESCRIPTION
168 %token DIE
169 %token DISABLE_AUTH
170 %token DISABLE_FAKE_CHANNELS
171 %token DISABLE_HIDDEN
172 %token DISABLE_LOCAL_CHANNELS
173 %token DISABLE_REMOTE_COMMANDS
174 %token DOT_IN_IP6_ADDR
175 %token DOTS_IN_IDENT
176 %token DURATION
177 %token EGDPOOL_PATH
178 %token EMAIL
179 %token ENABLE
180 %token ENCRYPTED
181 %token EXCEED_LIMIT
182 %token EXEMPT
183 %token FAILED_OPER_NOTICE
184 %token FAKENAME
185 %token IRCD_FLAGS
186 %token FLATTEN_LINKS
187 %token FFAILED_OPERLOG
188 %token FKILLLOG
189 %token FKLINELOG
190 %token FGLINELOG
191 %token FIOERRLOG
192 %token FOPERLOG
193 %token FOPERSPYLOG
194 %token FUSERLOG
195 %token GECOS
196 %token GENERAL
197 %token GLINE
198 %token GLINES
199 %token GLINE_EXEMPT
200 %token GLINE_LOG
201 %token GLINE_TIME
202 %token GLINE_MIN_CIDR
203 %token GLINE_MIN_CIDR6
204 %token GLOBAL_KILL
205 %token IRCD_AUTH
206 %token NEED_IDENT
207 %token HAVENT_READ_CONF
208 %token HIDDEN
209 %token HIDDEN_ADMIN
210 %token HIDDEN_NAME
211 %token HIDDEN_OPER
212 %token HIDE_SERVER_IPS
213 %token HIDE_SERVERS
214 %token HIDE_SPOOF_IPS
215 %token HOST
216 %token HUB
217 %token HUB_MASK
218 %token IDLETIME
219 %token IGNORE_BOGUS_TS
220 %token INVISIBLE_ON_CONNECT
221 %token IP
222 %token KILL
223 %token KILL_CHASE_TIME_LIMIT
224 %token KLINE
225 %token KLINE_EXEMPT
226 %token KLINE_REASON
227 %token KLINE_WITH_REASON
228 %token KNOCK_DELAY
229 %token KNOCK_DELAY_CHANNEL
230 %token LEAF_MASK
231 %token LINKS_DELAY
232 %token LISTEN
233 %token T_LOG
234 %token LOGGING
235 %token LOG_LEVEL
236 %token MAX_ACCEPT
237 %token MAX_BANS
238 %token MAX_CHANS_PER_USER
239 %token MAX_GLOBAL
240 %token MAX_IDENT
241 %token MAX_LOCAL
242 %token MAX_NICK_CHANGES
243 %token MAX_NICK_TIME
244 %token MAX_NUMBER
245 %token MAX_TARGETS
246 %token MAX_WATCH
247 %token MESSAGE_LOCALE
248 %token MIN_NONWILDCARD
249 %token MIN_NONWILDCARD_SIMPLE
250 %token MODULE
251 %token MODULES
252 %token NAME
253 %token NEED_PASSWORD
254 %token NETWORK_DESC
255 %token NETWORK_NAME
256 %token NICK
257 %token NICK_CHANGES
258 %token NO_CREATE_ON_SPLIT
259 %token NO_JOIN_ON_SPLIT
260 %token NO_OPER_FLOOD
261 %token NO_TILDE
262 %token NOT
263 %token NUMBER
264 %token NUMBER_PER_IDENT
265 %token NUMBER_PER_CIDR
266 %token NUMBER_PER_IP
267 %token NUMBER_PER_IP_GLOBAL
268 %token OPERATOR
269 %token OPERS_BYPASS_CALLERID
270 %token OPER_LOG
271 %token OPER_ONLY_UMODES
272 %token OPER_PASS_RESV
273 %token OPER_SPY_T
274 %token OPER_UMODES
275 %token JOIN_FLOOD_COUNT
276 %token JOIN_FLOOD_TIME
277 %token PACE_WAIT
278 %token PACE_WAIT_SIMPLE
279 %token PASSWORD
280 %token PATH
281 %token PING_COOKIE
282 %token PING_TIME
283 %token PING_WARNING
284 %token PORT
285 %token QSTRING
286 %token QUIET_ON_BAN
287 %token REASON
288 %token REDIRPORT
289 %token REDIRSERV
290 %token REGEX_T
291 %token REHASH
292 %token TREJECT_HOLD_TIME
293 %token REMOTE
294 %token REMOTEBAN
295 %token RESTRICT_CHANNELS
296 %token RESTRICTED
297 %token RSA_PRIVATE_KEY_FILE
298 %token RSA_PUBLIC_KEY_FILE
299 %token SSL_CERTIFICATE_FILE
300 %token T_SSL_CONNECTION_METHOD
301 %token T_SSLV3
302 %token T_TLSV1
303 %token RESV
304 %token RESV_EXEMPT
305 %token SECONDS MINUTES HOURS DAYS WEEKS
306 %token SENDQ
307 %token SEND_PASSWORD
308 %token SERVERHIDE
309 %token SERVERINFO
310 %token SERVLINK_PATH
311 %token IRCD_SID
312 %token TKLINE_EXPIRE_NOTICES
313 %token T_SHARED
314 %token T_CLUSTER
315 %token TYPE
316 %token SHORT_MOTD
317 %token SILENT
318 %token SPOOF
319 %token SPOOF_NOTICE
320 %token STATS_E_DISABLED
321 %token STATS_I_OPER_ONLY
322 %token STATS_K_OPER_ONLY
323 %token STATS_O_OPER_ONLY
324 %token STATS_P_OPER_ONLY
325 %token TBOOL
326 %token TMASKED
327 %token T_REJECT
328 %token TS_MAX_DELTA
329 %token TS_WARN_DELTA
330 %token TWODOTS
331 %token T_ALL
332 %token T_BOTS
333 %token T_SOFTCALLERID
334 %token T_CALLERID
335 %token T_CCONN
336 %token T_CCONN_FULL
337 %token T_CLIENT_FLOOD
338 %token T_DEAF
339 %token T_DEBUG
340 %token T_DRONE
341 %token T_EXTERNAL
342 %token T_FULL
343 %token T_INVISIBLE
344 %token T_IPV4
345 %token T_IPV6
346 %token T_LOCOPS
347 %token T_LOGPATH
348 %token T_L_CRIT
349 %token T_L_DEBUG
350 %token T_L_ERROR
351 %token T_L_INFO
352 %token T_L_NOTICE
353 %token T_L_TRACE
354 %token T_L_WARN
355 %token T_MAX_CLIENTS
356 %token T_NCHANGE
357 %token T_OPERWALL
358 %token T_REJ
359 %token T_SERVER
360 %token T_SERVNOTICE
361 %token T_SKILL
362 %token T_SPY
363 %token T_SSL
364 %token T_UMODES
365 %token T_UNAUTH
366 %token T_UNRESV
367 %token T_UNXLINE
368 %token T_WALLOP
369 %token THROTTLE_TIME
370 %token TOPICBURST
371 %token TRUE_NO_OPER_FLOOD
372 %token TKLINE
373 %token TXLINE
374 %token TRESV
375 %token UNKLINE
376 %token USER
377 %token USE_EGD
378 %token USE_EXCEPT
379 %token USE_INVEX
380 %token USE_KNOCK
381 %token USE_LOGGING
382 %token USE_WHOIS_ACTUALLY
383 %token VHOST
384 %token VHOST6
385 %token XLINE
386 %token WARN
387 %token WARN_NO_NLINE
388
389 %type <string> QSTRING
390 %type <number> NUMBER
391 %type <number> timespec
392 %type <number> timespec_
393 %type <number> sizespec
394 %type <number> sizespec_
395
396 %%
397 conf:
398 | conf conf_item
399 ;
400
401 conf_item: admin_entry
402 | logging_entry
403 | oper_entry
404 | channel_entry
405 | class_entry
406 | listen_entry
407 | auth_entry
408 | serverinfo_entry
409 | serverhide_entry
410 | resv_entry
411 | shared_entry
412 | cluster_entry
413 | connect_entry
414 | kill_entry
415 | deny_entry
416 | exempt_entry
417 | general_entry
418 | gline_entry
419 | gecos_entry
420 | modules_entry
421 | error ';'
422 | error '}'
423 ;
424
425
426 timespec_: { $$ = 0; } | timespec;
427 timespec: NUMBER timespec_
428 {
429 $$ = $1 + $2;
430 }
431 | NUMBER SECONDS timespec_
432 {
433 $$ = $1 + $3;
434 }
435 | NUMBER MINUTES timespec_
436 {
437 $$ = $1 * 60 + $3;
438 }
439 | NUMBER HOURS timespec_
440 {
441 $$ = $1 * 60 * 60 + $3;
442 }
443 | NUMBER DAYS timespec_
444 {
445 $$ = $1 * 60 * 60 * 24 + $3;
446 }
447 | NUMBER WEEKS timespec_
448 {
449 $$ = $1 * 60 * 60 * 24 * 7 + $3;
450 }
451 ;
452
453 sizespec_: { $$ = 0; } | sizespec;
454 sizespec: NUMBER sizespec_ { $$ = $1 + $2; }
455 | NUMBER BYTES sizespec_ { $$ = $1 + $3; }
456 | NUMBER KBYTES sizespec_ { $$ = $1 * 1024 + $3; }
457 | NUMBER MBYTES sizespec_ { $$ = $1 * 1024 * 1024 + $3; }
458 ;
459
460
461 /***************************************************************************
462 * section modules
463 ***************************************************************************/
464 modules_entry: MODULES
465 '{' modules_items '}' ';';
466
467 modules_items: modules_items modules_item | modules_item;
468 modules_item: modules_module | modules_path | error ';' ;
469
470 modules_module: MODULE '=' QSTRING ';'
471 {
472 #ifndef STATIC_MODULES /* NOOP in the static case */
473 if (conf_parser_ctx.pass == 2)
474 add_conf_module(libio_basename(yylval.string));
475 #endif
476 };
477
478 modules_path: PATH '=' QSTRING ';'
479 {
480 #ifndef STATIC_MODULES
481 if (conf_parser_ctx.pass == 2)
482 mod_add_path(yylval.string);
483 #endif
484 };
485
486
487 serverinfo_entry: SERVERINFO '{' serverinfo_items '}' ';';
488
489 serverinfo_items: serverinfo_items serverinfo_item | serverinfo_item ;
490 serverinfo_item: serverinfo_name | serverinfo_vhost |
491 serverinfo_hub | serverinfo_description |
492 serverinfo_network_name | serverinfo_network_desc |
493 serverinfo_max_clients |
494 serverinfo_rsa_private_key_file | serverinfo_vhost6 |
495 serverinfo_sid | serverinfo_ssl_certificate_file |
496 serverinfo_ssl_connection_method |
497 error ';' ;
498
499
500 serverinfo_ssl_connection_method: T_SSL_CONNECTION_METHOD
501 {
502 if (conf_parser_ctx.boot && conf_parser_ctx.pass == 2)
503 ServerInfo.tls_version = 0;
504 } '=' method_types ';'
505 {
506 if (conf_parser_ctx.boot && conf_parser_ctx.pass == 2)
507 {
508 if (!(ServerInfo.tls_version & CONF_SERVER_INFO_TLS_VERSION_SSLV3))
509 SSL_CTX_set_options(ServerInfo.server_ctx, SSL_OP_NO_SSLv3);
510 if (!(ServerInfo.tls_version & CONF_SERVER_INFO_TLS_VERSION_TLSV1))
511 SSL_CTX_set_options(ServerInfo.server_ctx, SSL_OP_NO_TLSv1);
512 }
513 };
514
515 method_types: method_types ',' method_type_item | method_type_item;
516 method_type_item: T_SSLV3
517 {
518 if (conf_parser_ctx.boot && conf_parser_ctx.pass == 2)
519 ServerInfo.tls_version |= CONF_SERVER_INFO_TLS_VERSION_SSLV3;
520 } | T_TLSV1
521 {
522 if (conf_parser_ctx.boot && conf_parser_ctx.pass == 2)
523 ServerInfo.tls_version |= CONF_SERVER_INFO_TLS_VERSION_TLSV1;
524 };
525
526 serverinfo_ssl_certificate_file: SSL_CERTIFICATE_FILE '=' QSTRING ';'
527 {
528 #ifdef HAVE_LIBCRYPTO
529 if (conf_parser_ctx.pass == 2 && ServerInfo.server_ctx)
530 {
531 if (!ServerInfo.rsa_private_key_file)
532 {
533 yyerror("No rsa_private_key_file specified, SSL disabled");
534 break;
535 }
536
537 if (SSL_CTX_use_certificate_file(ServerInfo.server_ctx, yylval.string,
538 SSL_FILETYPE_PEM) <= 0)
539 {
540 yyerror(ERR_lib_error_string(ERR_get_error()));
541 break;
542 }
543
544 if (SSL_CTX_use_PrivateKey_file(ServerInfo.server_ctx, ServerInfo.rsa_private_key_file,
545 SSL_FILETYPE_PEM) <= 0)
546 {
547 yyerror(ERR_lib_error_string(ERR_get_error()));
548 break;
549 }
550
551 if (!SSL_CTX_check_private_key(ServerInfo.server_ctx))
552 {
553 yyerror(ERR_lib_error_string(ERR_get_error()));
554 break;
555 }
556 }
557 #endif
558 };
559
560 serverinfo_rsa_private_key_file: RSA_PRIVATE_KEY_FILE '=' QSTRING ';'
561 {
562 #ifdef HAVE_LIBCRYPTO
563 if (conf_parser_ctx.pass == 1)
564 {
565 BIO *file;
566
567 if (ServerInfo.rsa_private_key)
568 {
569 RSA_free(ServerInfo.rsa_private_key);
570 ServerInfo.rsa_private_key = NULL;
571 }
572
573 if (ServerInfo.rsa_private_key_file)
574 {
575 MyFree(ServerInfo.rsa_private_key_file);
576 ServerInfo.rsa_private_key_file = NULL;
577 }
578
579 DupString(ServerInfo.rsa_private_key_file, yylval.string);
580
581 if ((file = BIO_new_file(yylval.string, "r")) == NULL)
582 {
583 yyerror("File open failed, ignoring");
584 break;
585 }
586
587 ServerInfo.rsa_private_key = (RSA *)PEM_read_bio_RSAPrivateKey(file, NULL,
588 0, NULL);
589
590 BIO_set_close(file, BIO_CLOSE);
591 BIO_free(file);
592
593 if (ServerInfo.rsa_private_key == NULL)
594 {
595 yyerror("Couldn't extract key, ignoring");
596 break;
597 }
598
599 if (!RSA_check_key(ServerInfo.rsa_private_key))
600 {
601 RSA_free(ServerInfo.rsa_private_key);
602 ServerInfo.rsa_private_key = NULL;
603
604 yyerror("Invalid key, ignoring");
605 break;
606 }
607
608 /* require 2048 bit (256 byte) key */
609 if (RSA_size(ServerInfo.rsa_private_key) != 256)
610 {
611 RSA_free(ServerInfo.rsa_private_key);
612 ServerInfo.rsa_private_key = NULL;
613
614 yyerror("Not a 2048 bit key, ignoring");
615 }
616 }
617 #endif
618 };
619
620 serverinfo_name: NAME '=' QSTRING ';'
621 {
622 /* this isn't rehashable */
623 if (conf_parser_ctx.pass == 2)
624 {
625 if (ServerInfo.name == NULL)
626 {
627 /* the ircd will exit() in main() if we dont set one */
628 if (strlen(yylval.string) <= HOSTLEN)
629 DupString(ServerInfo.name, yylval.string);
630 }
631 }
632 };
633
634 serverinfo_sid: IRCD_SID '=' QSTRING ';'
635 {
636 /* this isn't rehashable */
637 if (conf_parser_ctx.pass == 2 && !ServerInfo.sid)
638 {
639 if (valid_sid(yylval.string))
640 DupString(ServerInfo.sid, yylval.string);
641 else
642 {
643 ilog(L_ERROR, "Ignoring config file entry SID -- invalid SID. Aborting.");
644 exit(0);
645 }
646 }
647 };
648
649 serverinfo_description: DESCRIPTION '=' QSTRING ';'
650 {
651 if (conf_parser_ctx.pass == 2)
652 {
653 MyFree(ServerInfo.description);
654 DupString(ServerInfo.description,yylval.string);
655 }
656 };
657
658 serverinfo_network_name: NETWORK_NAME '=' QSTRING ';'
659 {
660 if (conf_parser_ctx.pass == 2)
661 {
662 char *p;
663
664 if ((p = strchr(yylval.string, ' ')) != NULL)
665 p = '\0';
666
667 MyFree(ServerInfo.network_name);
668 DupString(ServerInfo.network_name, yylval.string);
669 }
670 };
671
672 serverinfo_network_desc: NETWORK_DESC '=' QSTRING ';'
673 {
674 if (conf_parser_ctx.pass == 2)
675 {
676 MyFree(ServerInfo.network_desc);
677 DupString(ServerInfo.network_desc, yylval.string);
678 }
679 };
680
681 serverinfo_vhost: VHOST '=' QSTRING ';'
682 {
683 if (conf_parser_ctx.pass == 2 && *yylval.string != '*')
684 {
685 struct addrinfo hints, *res;
686
687 memset(&hints, 0, sizeof(hints));
688
689 hints.ai_family = AF_UNSPEC;
690 hints.ai_socktype = SOCK_STREAM;
691 hints.ai_flags = AI_PASSIVE | AI_NUMERICHOST;
692
693 if (irc_getaddrinfo(yylval.string, NULL, &hints, &res))
694 ilog(L_ERROR, "Invalid netmask for server vhost(%s)", yylval.string);
695 else
696 {
697 assert(res != NULL);
698
699 memcpy(&ServerInfo.ip, res->ai_addr, res->ai_addrlen);
700 ServerInfo.ip.ss.ss_family = res->ai_family;
701 ServerInfo.ip.ss_len = res->ai_addrlen;
702 irc_freeaddrinfo(res);
703
704 ServerInfo.specific_ipv4_vhost = 1;
705 }
706 }
707 };
708
709 serverinfo_vhost6: VHOST6 '=' QSTRING ';'
710 {
711 #ifdef IPV6
712 if (conf_parser_ctx.pass == 2 && *yylval.string != '*')
713 {
714 struct addrinfo hints, *res;
715
716 memset(&hints, 0, sizeof(hints));
717
718 hints.ai_family = AF_UNSPEC;
719 hints.ai_socktype = SOCK_STREAM;
720 hints.ai_flags = AI_PASSIVE | AI_NUMERICHOST;
721
722 if (irc_getaddrinfo(yylval.string, NULL, &hints, &res))
723 ilog(L_ERROR, "Invalid netmask for server vhost6(%s)", yylval.string);
724 else
725 {
726 assert(res != NULL);
727
728 memcpy(&ServerInfo.ip6, res->ai_addr, res->ai_addrlen);
729 ServerInfo.ip6.ss.ss_family = res->ai_family;
730 ServerInfo.ip6.ss_len = res->ai_addrlen;
731 irc_freeaddrinfo(res);
732
733 ServerInfo.specific_ipv6_vhost = 1;
734 }
735 }
736 #endif
737 };
738
739 serverinfo_max_clients: T_MAX_CLIENTS '=' NUMBER ';'
740 {
741 if (conf_parser_ctx.pass == 2)
742 {
743 recalc_fdlimit(NULL);
744
745 if ($3 < MAXCLIENTS_MIN)
746 {
747 char buf[IRCD_BUFSIZE];
748 ircsprintf(buf, "MAXCLIENTS too low, setting to %d", MAXCLIENTS_MIN);
749 yyerror(buf);
750 }
751 else if ($3 > MAXCLIENTS_MAX)
752 {
753 char buf[IRCD_BUFSIZE];
754 ircsprintf(buf, "MAXCLIENTS too high, setting to %d", MAXCLIENTS_MAX);
755 yyerror(buf);
756 }
757 else
758 ServerInfo.max_clients = $3;
759 }
760 };
761
762 serverinfo_hub: HUB '=' TBOOL ';'
763 {
764 if (conf_parser_ctx.pass == 2)
765 {
766 if (yylval.number)
767 {
768 ServerInfo.hub = 1;
769 delete_capability("HUB");
770 add_capability("HUB", CAP_HUB, 1);
771 }
772 else if (ServerInfo.hub)
773 {
774
775 ServerInfo.hub = 0;
776 delete_capability("HUB");
777 }
778 }
779 };
780
781 /***************************************************************************
782 * admin section
783 ***************************************************************************/
784 admin_entry: ADMIN '{' admin_items '}' ';' ;
785
786 admin_items: admin_items admin_item | admin_item;
787 admin_item: admin_name | admin_description |
788 admin_email | error ';' ;
789
790 admin_name: NAME '=' QSTRING ';'
791 {
792 if (conf_parser_ctx.pass == 2)
793 {
794 MyFree(AdminInfo.name);
795 DupString(AdminInfo.name, yylval.string);
796 }
797 };
798
799 admin_email: EMAIL '=' QSTRING ';'
800 {
801 if (conf_parser_ctx.pass == 2)
802 {
803 MyFree(AdminInfo.email);
804 DupString(AdminInfo.email, yylval.string);
805 }
806 };
807
808 admin_description: DESCRIPTION '=' QSTRING ';'
809 {
810 if (conf_parser_ctx.pass == 2)
811 {
812 MyFree(AdminInfo.description);
813 DupString(AdminInfo.description, yylval.string);
814 }
815 };
816
817 /***************************************************************************
818 * section logging
819 ***************************************************************************/
820 /* XXX */
821 logging_entry: LOGGING '{' logging_items '}' ';' ;
822
823 logging_items: logging_items logging_item |
824 logging_item ;
825
826 logging_item: logging_path | logging_oper_log |
827 logging_log_level |
828 logging_use_logging | logging_fuserlog |
829 logging_foperlog | logging_fglinelog |
830 logging_fklinelog | logging_killlog |
831 logging_foperspylog | logging_ioerrlog |
832 logging_ffailed_operlog |
833 error ';' ;
834
835 logging_path: T_LOGPATH '=' QSTRING ';'
836 {
837 };
838
839 logging_oper_log: OPER_LOG '=' QSTRING ';'
840 {
841 };
842
843 logging_fuserlog: FUSERLOG '=' QSTRING ';'
844 {
845 if (conf_parser_ctx.pass == 2)
846 strlcpy(ConfigLoggingEntry.userlog, yylval.string,
847 sizeof(ConfigLoggingEntry.userlog));
848 };
849
850 logging_ffailed_operlog: FFAILED_OPERLOG '=' QSTRING ';'
851 {
852 if (conf_parser_ctx.pass == 2)
853 strlcpy(ConfigLoggingEntry.failed_operlog, yylval.string,
854 sizeof(ConfigLoggingEntry.failed_operlog));
855 };
856
857 logging_foperlog: FOPERLOG '=' QSTRING ';'
858 {
859 if (conf_parser_ctx.pass == 2)
860 strlcpy(ConfigLoggingEntry.operlog, yylval.string,
861 sizeof(ConfigLoggingEntry.operlog));
862 };
863
864 logging_foperspylog: FOPERSPYLOG '=' QSTRING ';'
865 {
866 if (conf_parser_ctx.pass == 2)
867 strlcpy(ConfigLoggingEntry.operspylog, yylval.string,
868 sizeof(ConfigLoggingEntry.operspylog));
869 };
870
871 logging_fglinelog: FGLINELOG '=' QSTRING ';'
872 {
873 if (conf_parser_ctx.pass == 2)
874 strlcpy(ConfigLoggingEntry.glinelog, yylval.string,
875 sizeof(ConfigLoggingEntry.glinelog));
876 };
877
878 logging_fklinelog: FKLINELOG '=' QSTRING ';'
879 {
880 if (conf_parser_ctx.pass == 2)
881 strlcpy(ConfigLoggingEntry.klinelog, yylval.string,
882 sizeof(ConfigLoggingEntry.klinelog));
883 };
884
885 logging_ioerrlog: FIOERRLOG '=' QSTRING ';'
886 {
887 if (conf_parser_ctx.pass == 2)
888 strlcpy(ConfigLoggingEntry.ioerrlog, yylval.string,
889 sizeof(ConfigLoggingEntry.ioerrlog));
890 };
891
892 logging_killlog: FKILLLOG '=' QSTRING ';'
893 {
894 if (conf_parser_ctx.pass == 2)
895 strlcpy(ConfigLoggingEntry.killlog, yylval.string,
896 sizeof(ConfigLoggingEntry.killlog));
897 };
898
899 logging_log_level: LOG_LEVEL '=' T_L_CRIT ';'
900 {
901 if (conf_parser_ctx.pass == 2)
902 set_log_level(L_CRIT);
903 } | LOG_LEVEL '=' T_L_ERROR ';'
904 {
905 if (conf_parser_ctx.pass == 2)
906 set_log_level(L_ERROR);
907 } | LOG_LEVEL '=' T_L_WARN ';'
908 {
909 if (conf_parser_ctx.pass == 2)
910 set_log_level(L_WARN);
911 } | LOG_LEVEL '=' T_L_NOTICE ';'
912 {
913 if (conf_parser_ctx.pass == 2)
914 set_log_level(L_NOTICE);
915 } | LOG_LEVEL '=' T_L_TRACE ';'
916 {
917 if (conf_parser_ctx.pass == 2)
918 set_log_level(L_TRACE);
919 } | LOG_LEVEL '=' T_L_INFO ';'
920 {
921 if (conf_parser_ctx.pass == 2)
922 set_log_level(L_INFO);
923 } | LOG_LEVEL '=' T_L_DEBUG ';'
924 {
925 if (conf_parser_ctx.pass == 2)
926 set_log_level(L_DEBUG);
927 };
928
929 logging_use_logging: USE_LOGGING '=' TBOOL ';'
930 {
931 if (conf_parser_ctx.pass == 2)
932 ConfigLoggingEntry.use_logging = yylval.number;
933 };
934
935 /***************************************************************************
936 * section oper
937 ***************************************************************************/
938 oper_entry: OPERATOR
939 {
940 if (conf_parser_ctx.pass == 2)
941 {
942 yy_conf = make_conf_item(OPER_TYPE);
943 yy_aconf = map_to_conf(yy_conf);
944 SetConfEncrypted(yy_aconf); /* Yes, the default is encrypted */
945 }
946 else
947 {
948 MyFree(class_name);
949 class_name = NULL;
950 }
951 } oper_name_b '{' oper_items '}' ';'
952 {
953 if (conf_parser_ctx.pass == 2)
954 {
955 struct CollectItem *yy_tmp;
956 dlink_node *ptr;
957 dlink_node *next_ptr;
958
959 conf_add_class_to_conf(yy_conf, class_name);
960
961 /* Now, make sure there is a copy of the "base" given oper
962 * block in each of the collected copies
963 */
964
965 DLINK_FOREACH_SAFE(ptr, next_ptr, col_conf_list.head)
966 {
967 struct AccessItem *new_aconf;
968 struct ConfItem *new_conf;
969 yy_tmp = ptr->data;
970
971 new_conf = make_conf_item(OPER_TYPE);
972 new_aconf = (struct AccessItem *)map_to_conf(new_conf);
973
974 new_aconf->flags = yy_aconf->flags;
975
976 if (yy_conf->name != NULL)
977 DupString(new_conf->name, yy_conf->name);
978 if (yy_tmp->user != NULL)
979 DupString(new_aconf->user, yy_tmp->user);
980 else
981 DupString(new_aconf->user, "*");
982 if (yy_tmp->host != NULL)
983 DupString(new_aconf->host, yy_tmp->host);
984 else
985 DupString(new_aconf->host, "*");
986 conf_add_class_to_conf(new_conf, class_name);
987 if (yy_aconf->passwd != NULL)
988 DupString(new_aconf->passwd, yy_aconf->passwd);
989
990 new_aconf->port = yy_aconf->port;
991 #ifdef HAVE_LIBCRYPTO
992 if (yy_aconf->rsa_public_key_file != NULL)
993 {
994 BIO *file;
995
996 DupString(new_aconf->rsa_public_key_file,
997 yy_aconf->rsa_public_key_file);
998
999 file = BIO_new_file(yy_aconf->rsa_public_key_file, "r");
1000 new_aconf->rsa_public_key = (RSA *)PEM_read_bio_RSA_PUBKEY(file,
1001 NULL, 0, NULL);
1002 BIO_set_close(file, BIO_CLOSE);
1003 BIO_free(file);
1004 }
1005 #endif
1006
1007 #ifdef HAVE_LIBCRYPTO
1008 if (yy_tmp->name && (yy_tmp->passwd || yy_aconf->rsa_public_key)
1009 && yy_tmp->host)
1010 #else
1011 if (yy_tmp->name && yy_tmp->passwd && yy_tmp->host)
1012 #endif
1013 {
1014 conf_add_class_to_conf(new_conf, class_name);
1015 if (yy_tmp->name != NULL)
1016 DupString(new_conf->name, yy_tmp->name);
1017 }
1018
1019 dlinkDelete(&yy_tmp->node, &col_conf_list);
1020 free_collect_item(yy_tmp);
1021 }
1022
1023 yy_conf = NULL;
1024 yy_aconf = NULL;
1025
1026
1027 MyFree(class_name);
1028 class_name = NULL;
1029 }
1030 };
1031
1032 oper_name_b: | oper_name_t;
1033 oper_items: oper_items oper_item | oper_item;
1034 oper_item: oper_name | oper_user | oper_password | oper_hidden_admin |
1035 oper_hidden_oper | oper_umodes |
1036 oper_class | oper_global_kill | oper_remote |
1037 oper_kline | oper_xline | oper_unkline |
1038 oper_gline | oper_nick_changes | oper_remoteban |
1039 oper_die | oper_rehash | oper_admin | oper_operwall |
1040 oper_encrypted | oper_rsa_public_key_file |
1041 oper_flags | error ';' ;
1042
1043 oper_name: NAME '=' QSTRING ';'
1044 {
1045 if (conf_parser_ctx.pass == 2)
1046 {
1047 if (strlen(yylval.string) > OPERNICKLEN)
1048 yylval.string[OPERNICKLEN] = '\0';
1049
1050 MyFree(yy_conf->name);
1051 DupString(yy_conf->name, yylval.string);
1052 }
1053 };
1054
1055 oper_name_t: QSTRING
1056 {
1057 if (conf_parser_ctx.pass == 2)
1058 {
1059 if (strlen(yylval.string) > OPERNICKLEN)
1060 yylval.string[OPERNICKLEN] = '\0';
1061
1062 MyFree(yy_conf->name);
1063 DupString(yy_conf->name, yylval.string);
1064 }
1065 };
1066
1067 oper_user: USER '=' QSTRING ';'
1068 {
1069 if (conf_parser_ctx.pass == 2)
1070 {
1071 struct split_nuh_item nuh;
1072
1073 nuh.nuhmask = yylval.string;
1074 nuh.nickptr = NULL;
1075 nuh.userptr = userbuf;
1076 nuh.hostptr = hostbuf;
1077
1078 nuh.nicksize = 0;
1079 nuh.usersize = sizeof(userbuf);
1080 nuh.hostsize = sizeof(hostbuf);
1081
1082 split_nuh(&nuh);
1083
1084 if (yy_aconf->user == NULL)
1085 {
1086 DupString(yy_aconf->user, userbuf);
1087 DupString(yy_aconf->host, hostbuf);
1088 }
1089 else
1090 {
1091 struct CollectItem *yy_tmp = MyMalloc(sizeof(struct CollectItem));
1092
1093 DupString(yy_tmp->user, userbuf);
1094 DupString(yy_tmp->host, hostbuf);
1095
1096 dlinkAdd(yy_tmp, &yy_tmp->node, &col_conf_list);
1097 }
1098 }
1099 };
1100
1101 oper_password: PASSWORD '=' QSTRING ';'
1102 {
1103 if (conf_parser_ctx.pass == 2)
1104 {
1105 if (yy_aconf->passwd != NULL)
1106 memset(yy_aconf->passwd, 0, strlen(yy_aconf->passwd));
1107
1108 MyFree(yy_aconf->passwd);
1109 DupString(yy_aconf->passwd, yylval.string);
1110 }
1111 };
1112
1113 oper_encrypted: ENCRYPTED '=' TBOOL ';'
1114 {
1115 if (conf_parser_ctx.pass == 2)
1116 {
1117 if (yylval.number)
1118 SetConfEncrypted(yy_aconf);
1119 else
1120 ClearConfEncrypted(yy_aconf);
1121 }
1122 };
1123
1124 oper_rsa_public_key_file: RSA_PUBLIC_KEY_FILE '=' QSTRING ';'
1125 {
1126 #ifdef HAVE_LIBCRYPTO
1127 if (conf_parser_ctx.pass == 2)
1128 {
1129 BIO *file;
1130
1131 if (yy_aconf->rsa_public_key != NULL)
1132 {
1133 RSA_free(yy_aconf->rsa_public_key);
1134 yy_aconf->rsa_public_key = NULL;
1135 }
1136
1137 if (yy_aconf->rsa_public_key_file != NULL)
1138 {
1139 MyFree(yy_aconf->rsa_public_key_file);
1140 yy_aconf->rsa_public_key_file = NULL;
1141 }
1142
1143 DupString(yy_aconf->rsa_public_key_file, yylval.string);
1144 file = BIO_new_file(yylval.string, "r");
1145
1146 if (file == NULL)
1147 {
1148 yyerror("Ignoring rsa_public_key_file -- file doesn't exist");
1149 break;
1150 }
1151
1152 yy_aconf->rsa_public_key = (RSA *)PEM_read_bio_RSA_PUBKEY(file, NULL, 0, NULL);
1153
1154 if (yy_aconf->rsa_public_key == NULL)
1155 {
1156 yyerror("Ignoring rsa_public_key_file -- Key invalid; check key syntax.");
1157 break;
1158 }
1159
1160 BIO_set_close(file, BIO_CLOSE);
1161 BIO_free(file);
1162 }
1163 #endif /* HAVE_LIBCRYPTO */
1164 };
1165
1166 oper_class: CLASS '=' QSTRING ';'
1167 {
1168 if (conf_parser_ctx.pass == 2)
1169 {
1170 MyFree(class_name);
1171 DupString(class_name, yylval.string);
1172 }
1173 };
1174
1175 oper_umodes: T_UMODES
1176 {
1177 if (conf_parser_ctx.pass == 2)
1178 yy_aconf->modes = 0;
1179 } '=' oper_umodes_items ';' ;
1180
1181 oper_umodes_items: oper_umodes_items ',' oper_umodes_item | oper_umodes_item;
1182 oper_umodes_item: T_BOTS
1183 {
1184 if (conf_parser_ctx.pass == 2)
1185 yy_aconf->modes |= UMODE_BOTS;
1186 } | T_CCONN
1187 {
1188 if (conf_parser_ctx.pass == 2)
1189 yy_aconf->modes |= UMODE_CCONN;
1190 } | T_CCONN_FULL
1191 {
1192 if (conf_parser_ctx.pass == 2)
1193 yy_aconf->modes |= UMODE_CCONN_FULL;
1194 } | T_DEAF
1195 {
1196 if (conf_parser_ctx.pass == 2)
1197 yy_aconf->modes |= UMODE_DEAF;
1198 } | T_DEBUG
1199 {
1200 if (conf_parser_ctx.pass == 2)
1201 yy_aconf->modes |= UMODE_DEBUG;
1202 } | T_FULL
1203 {
1204 if (conf_parser_ctx.pass == 2)
1205 yy_aconf->modes |= UMODE_FULL;
1206 } | T_SKILL
1207 {
1208 if (conf_parser_ctx.pass == 2)
1209 yy_aconf->modes |= UMODE_SKILL;
1210 } | T_NCHANGE
1211 {
1212 if (conf_parser_ctx.pass == 2)
1213 yy_aconf->modes |= UMODE_NCHANGE;
1214 } | T_REJ
1215 {
1216 if (conf_parser_ctx.pass == 2)
1217 yy_aconf->modes |= UMODE_REJ;
1218 } | T_UNAUTH
1219 {
1220 if (conf_parser_ctx.pass == 2)
1221 yy_aconf->modes |= UMODE_UNAUTH;
1222 } | T_SPY
1223 {
1224 if (conf_parser_ctx.pass == 2)
1225 yy_aconf->modes |= UMODE_SPY;
1226 } | T_EXTERNAL
1227 {
1228 if (conf_parser_ctx.pass == 2)
1229 yy_aconf->modes |= UMODE_EXTERNAL;
1230 } | T_OPERWALL
1231 {
1232 if (conf_parser_ctx.pass == 2)
1233 yy_aconf->modes |= UMODE_OPERWALL;
1234 } | T_SERVNOTICE
1235 {
1236 if (conf_parser_ctx.pass == 2)
1237 yy_aconf->modes |= UMODE_SERVNOTICE;
1238 } | T_INVISIBLE
1239 {
1240 if (conf_parser_ctx.pass == 2)
1241 yy_aconf->modes |= UMODE_INVISIBLE;
1242 } | T_WALLOP
1243 {
1244 if (conf_parser_ctx.pass == 2)
1245 yy_aconf->modes |= UMODE_WALLOP;
1246 } | T_SOFTCALLERID
1247 {
1248 if (conf_parser_ctx.pass == 2)
1249 yy_aconf->modes |= UMODE_SOFTCALLERID;
1250 } | T_CALLERID
1251 {
1252 if (conf_parser_ctx.pass == 2)
1253 yy_aconf->modes |= UMODE_CALLERID;
1254 } | T_LOCOPS
1255 {
1256 if (conf_parser_ctx.pass == 2)
1257 yy_aconf->modes |= UMODE_LOCOPS;
1258 };
1259
1260 oper_global_kill: GLOBAL_KILL '=' TBOOL ';'
1261 {
1262 if (conf_parser_ctx.pass == 2)
1263 {
1264 if (yylval.number)
1265 yy_aconf->port |= OPER_FLAG_GLOBAL_KILL;
1266 else
1267 yy_aconf->port &= ~OPER_FLAG_GLOBAL_KILL;
1268 }
1269 };
1270
1271 oper_remote: REMOTE '=' TBOOL ';'
1272 {
1273 if (conf_parser_ctx.pass == 2)
1274 {
1275 if (yylval.number)
1276 yy_aconf->port |= OPER_FLAG_REMOTE;
1277 else
1278 yy_aconf->port &= ~OPER_FLAG_REMOTE;
1279 }
1280 };
1281
1282 oper_remoteban: REMOTEBAN '=' TBOOL ';'
1283 {
1284 if (conf_parser_ctx.pass == 2)
1285 {
1286 if (yylval.number)
1287 yy_aconf->port |= OPER_FLAG_REMOTEBAN;
1288 else
1289 yy_aconf->port &= ~OPER_FLAG_REMOTEBAN;
1290 }
1291 };
1292
1293 oper_kline: KLINE '=' TBOOL ';'
1294 {
1295 if (conf_parser_ctx.pass == 2)
1296 {
1297 if (yylval.number)
1298 yy_aconf->port |= OPER_FLAG_K;
1299 else
1300 yy_aconf->port &= ~OPER_FLAG_K;
1301 }
1302 };
1303
1304 oper_xline: XLINE '=' TBOOL ';'
1305 {
1306 if (conf_parser_ctx.pass == 2)
1307 {
1308 if (yylval.number)
1309 yy_aconf->port |= OPER_FLAG_X;
1310 else
1311 yy_aconf->port &= ~OPER_FLAG_X;
1312 }
1313 };
1314
1315 oper_unkline: UNKLINE '=' TBOOL ';'
1316 {
1317 if (conf_parser_ctx.pass == 2)
1318 {
1319 if (yylval.number)
1320 yy_aconf->port |= OPER_FLAG_UNKLINE;
1321 else
1322 yy_aconf->port &= ~OPER_FLAG_UNKLINE;
1323 }
1324 };
1325
1326 oper_gline: GLINE '=' TBOOL ';'
1327 {
1328 if (conf_parser_ctx.pass == 2)
1329 {
1330 if (yylval.number)
1331 yy_aconf->port |= OPER_FLAG_GLINE;
1332 else
1333 yy_aconf->port &= ~OPER_FLAG_GLINE;
1334 }
1335 };
1336
1337 oper_nick_changes: NICK_CHANGES '=' TBOOL ';'
1338 {
1339 if (conf_parser_ctx.pass == 2)
1340 {
1341 if (yylval.number)
1342 yy_aconf->port |= OPER_FLAG_N;
1343 else
1344 yy_aconf->port &= ~OPER_FLAG_N;
1345 }
1346 };
1347
1348 oper_die: DIE '=' TBOOL ';'
1349 {
1350 if (conf_parser_ctx.pass == 2)
1351 {
1352 if (yylval.number)
1353 yy_aconf->port |= OPER_FLAG_DIE;
1354 else
1355 yy_aconf->port &= ~OPER_FLAG_DIE;
1356 }
1357 };
1358
1359 oper_rehash: REHASH '=' TBOOL ';'
1360 {
1361 if (conf_parser_ctx.pass == 2)
1362 {
1363 if (yylval.number)
1364 yy_aconf->port |= OPER_FLAG_REHASH;
1365 else
1366 yy_aconf->port &= ~OPER_FLAG_REHASH;
1367 }
1368 };
1369
1370 oper_admin: ADMIN '=' TBOOL ';'
1371 {
1372 if (conf_parser_ctx.pass == 2)
1373 {
1374 if (yylval.number)
1375 yy_aconf->port |= OPER_FLAG_ADMIN;
1376 else
1377 yy_aconf->port &= ~OPER_FLAG_ADMIN;
1378 }
1379 };
1380
1381 oper_hidden_admin: HIDDEN_ADMIN '=' TBOOL ';'
1382 {
1383 if (conf_parser_ctx.pass == 2)
1384 {
1385 if (yylval.number)
1386 yy_aconf->port |= OPER_FLAG_HIDDEN_ADMIN;
1387 else
1388 yy_aconf->port &= ~OPER_FLAG_HIDDEN_ADMIN;
1389 }
1390 };
1391
1392 oper_hidden_oper: HIDDEN_OPER '=' TBOOL ';'
1393 {
1394 if (conf_parser_ctx.pass == 2)
1395 {
1396 if (yylval.number)
1397 yy_aconf->port |= OPER_FLAG_HIDDEN_OPER;
1398 else
1399 yy_aconf->port &= ~OPER_FLAG_HIDDEN_OPER;
1400 }
1401 };
1402
1403 oper_operwall: T_OPERWALL '=' TBOOL ';'
1404 {
1405 if (conf_parser_ctx.pass == 2)
1406 {
1407 if (yylval.number)
1408 yy_aconf->port |= OPER_FLAG_OPERWALL;
1409 else
1410 yy_aconf->port &= ~OPER_FLAG_OPERWALL;
1411 }
1412 };
1413
1414 oper_flags: IRCD_FLAGS
1415 {
1416 } '=' oper_flags_items ';';
1417
1418 oper_flags_items: oper_flags_items ',' oper_flags_item | oper_flags_item;
1419 oper_flags_item: NOT { not_atom = 1; } oper_flags_item_atom
1420 | { not_atom = 0; } oper_flags_item_atom;
1421
1422 oper_flags_item_atom: GLOBAL_KILL
1423 {
1424 if (conf_parser_ctx.pass == 2)
1425 {
1426 if (not_atom)yy_aconf->port &= ~OPER_FLAG_GLOBAL_KILL;
1427 else yy_aconf->port |= OPER_FLAG_GLOBAL_KILL;
1428 }
1429 } | REMOTE
1430 {
1431 if (conf_parser_ctx.pass == 2)
1432 {
1433 if (not_atom) yy_aconf->port &= ~OPER_FLAG_REMOTE;
1434 else yy_aconf->port |= OPER_FLAG_REMOTE;
1435 }
1436 } | KLINE
1437 {
1438 if (conf_parser_ctx.pass == 2)
1439 {
1440 if (not_atom) yy_aconf->port &= ~OPER_FLAG_K;
1441 else yy_aconf->port |= OPER_FLAG_K;
1442 }
1443 } | UNKLINE
1444 {
1445 if (conf_parser_ctx.pass == 2)
1446 {
1447 if (not_atom) yy_aconf->port &= ~OPER_FLAG_UNKLINE;
1448 else yy_aconf->port |= OPER_FLAG_UNKLINE;
1449 }
1450 } | XLINE
1451 {
1452 if (conf_parser_ctx.pass == 2)
1453 {
1454 if (not_atom) yy_aconf->port &= ~OPER_FLAG_X;
1455 else yy_aconf->port |= OPER_FLAG_X;
1456 }
1457 } | GLINE
1458 {
1459 if (conf_parser_ctx.pass == 2)
1460 {
1461 if (not_atom) yy_aconf->port &= ~OPER_FLAG_GLINE;
1462 else yy_aconf->port |= OPER_FLAG_GLINE;
1463 }
1464 } | DIE
1465 {
1466 if (conf_parser_ctx.pass == 2)
1467 {
1468 if (not_atom) yy_aconf->port &= ~OPER_FLAG_DIE;
1469 else yy_aconf->port |= OPER_FLAG_DIE;
1470 }
1471 } | REHASH
1472 {
1473 if (conf_parser_ctx.pass == 2)
1474 {
1475 if (not_atom) yy_aconf->port &= ~OPER_FLAG_REHASH;
1476 else yy_aconf->port |= OPER_FLAG_REHASH;
1477 }
1478 } | ADMIN
1479 {
1480 if (conf_parser_ctx.pass == 2)
1481 {
1482 if (not_atom) yy_aconf->port &= ~OPER_FLAG_ADMIN;
1483 else yy_aconf->port |= OPER_FLAG_ADMIN;
1484 }
1485 } | HIDDEN_ADMIN
1486 {
1487 if (conf_parser_ctx.pass == 2)
1488 {
1489 if (not_atom) yy_aconf->port &= ~OPER_FLAG_HIDDEN_ADMIN;
1490 else yy_aconf->port |= OPER_FLAG_HIDDEN_ADMIN;
1491 }
1492 } | NICK_CHANGES
1493 {
1494 if (conf_parser_ctx.pass == 2)
1495 {
1496 if (not_atom) yy_aconf->port &= ~OPER_FLAG_N;
1497 else yy_aconf->port |= OPER_FLAG_N;
1498 }
1499 } | T_OPERWALL
1500 {
1501 if (conf_parser_ctx.pass == 2)
1502 {
1503 if (not_atom) yy_aconf->port &= ~OPER_FLAG_OPERWALL;
1504 else yy_aconf->port |= OPER_FLAG_OPERWALL;
1505 }
1506 } | OPER_SPY_T
1507 {
1508 if (conf_parser_ctx.pass == 2)
1509 {
1510 if (not_atom) yy_aconf->port &= ~OPER_FLAG_OPER_SPY;
1511 else yy_aconf->port |= OPER_FLAG_OPER_SPY;
1512 }
1513 } | HIDDEN_OPER
1514 {
1515 if (conf_parser_ctx.pass == 2)
1516 {
1517 if (not_atom) yy_aconf->port &= ~OPER_FLAG_HIDDEN_OPER;
1518 else yy_aconf->port |= OPER_FLAG_HIDDEN_OPER;
1519 }
1520 } | REMOTEBAN
1521 {
1522 if (conf_parser_ctx.pass == 2)
1523 {
1524 if (not_atom) yy_aconf->port &= ~OPER_FLAG_REMOTEBAN;
1525 else yy_aconf->port |= OPER_FLAG_REMOTEBAN;
1526 }
1527 } | ENCRYPTED
1528 {
1529 if (conf_parser_ctx.pass == 2)
1530 {
1531 if (not_atom) ClearConfEncrypted(yy_aconf);
1532 else SetConfEncrypted(yy_aconf);
1533 }
1534 };
1535
1536
1537 /***************************************************************************
1538 * section class
1539 ***************************************************************************/
1540 class_entry: CLASS
1541 {
1542 if (conf_parser_ctx.pass == 1)
1543 {
1544 yy_conf = make_conf_item(CLASS_TYPE);
1545 yy_class = map_to_conf(yy_conf);
1546 }
1547 } class_name_b '{' class_items '}' ';'
1548 {
1549 if (conf_parser_ctx.pass == 1)
1550 {
1551 struct ConfItem *cconf = NULL;
1552 struct ClassItem *class = NULL;
1553
1554 if (yy_class_name == NULL)
1555 delete_conf_item(yy_conf);
1556 else
1557 {
1558 cconf = find_exact_name_conf(CLASS_TYPE, yy_class_name, NULL, NULL);
1559
1560 if (cconf != NULL) /* The class existed already */
1561 {
1562 int user_count = 0;
1563
1564 rebuild_cidr_class(cconf, yy_class);
1565
1566 class = map_to_conf(cconf);
1567
1568 user_count = class->curr_user_count;
1569 memcpy(class, yy_class, sizeof(*class));
1570 class->curr_user_count = user_count;
1571 class->active = 1;
1572
1573 delete_conf_item(yy_conf);
1574
1575 MyFree(cconf->name); /* Allows case change of class name */
1576 cconf->name = yy_class_name;
1577 }
1578 else /* Brand new class */
1579 {
1580 MyFree(yy_conf->name); /* just in case it was allocated */
1581 yy_conf->name = yy_class_name;
1582 yy_class->active = 1;
1583 }
1584 }
1585
1586 yy_class_name = NULL;
1587 }
1588 };
1589
1590 class_name_b: | class_name_t;
1591
1592 class_items: class_items class_item | class_item;
1593 class_item: class_name |
1594 class_cidr_bitlen_ipv4 | class_cidr_bitlen_ipv6 |
1595 class_ping_time |
1596 class_ping_warning |
1597 class_number_per_cidr |
1598 class_number_per_ip |
1599 class_connectfreq |
1600 class_max_number |
1601 class_max_global |
1602 class_max_local |
1603 class_max_ident |
1604 class_sendq |
1605 error ';' ;
1606
1607 class_name: NAME '=' QSTRING ';'
1608 {
1609 if (conf_parser_ctx.pass == 1)
1610 {
1611 MyFree(yy_class_name);
1612 DupString(yy_class_name, yylval.string);
1613 }
1614 };
1615
1616 class_name_t: QSTRING
1617 {
1618 if (conf_parser_ctx.pass == 1)
1619 {
1620 MyFree(yy_class_name);
1621 DupString(yy_class_name, yylval.string);
1622 }
1623 };
1624
1625 class_ping_time: PING_TIME '=' timespec ';'
1626 {
1627 if (conf_parser_ctx.pass == 1)
1628 PingFreq(yy_class) = $3;
1629 };
1630
1631 class_ping_warning: PING_WARNING '=' timespec ';'
1632 {
1633 if (conf_parser_ctx.pass == 1)
1634 PingWarning(yy_class) = $3;
1635 };
1636
1637 class_number_per_ip: NUMBER_PER_IP '=' NUMBER ';'
1638 {
1639 if (conf_parser_ctx.pass == 1)
1640 MaxPerIp(yy_class) = $3;
1641 };
1642
1643 class_connectfreq: CONNECTFREQ '=' timespec ';'
1644 {
1645 if (conf_parser_ctx.pass == 1)
1646 ConFreq(yy_class) = $3;
1647 };
1648
1649 class_max_number: MAX_NUMBER '=' NUMBER ';'
1650 {
1651 if (conf_parser_ctx.pass == 1)
1652 MaxTotal(yy_class) = $3;
1653 };
1654
1655 class_max_global: MAX_GLOBAL '=' NUMBER ';'
1656 {
1657 if (conf_parser_ctx.pass == 1)
1658 MaxGlobal(yy_class) = $3;
1659 };
1660
1661 class_max_local: MAX_LOCAL '=' NUMBER ';'
1662 {
1663 if (conf_parser_ctx.pass == 1)
1664 MaxLocal(yy_class) = $3;
1665 };
1666
1667 class_max_ident: MAX_IDENT '=' NUMBER ';'
1668 {
1669 if (conf_parser_ctx.pass == 1)
1670 MaxIdent(yy_class) = $3;
1671 };
1672
1673 class_sendq: SENDQ '=' sizespec ';'
1674 {
1675 if (conf_parser_ctx.pass == 1)
1676 MaxSendq(yy_class) = $3;
1677 };
1678
1679 class_cidr_bitlen_ipv4: CIDR_BITLEN_IPV4 '=' NUMBER ';'
1680 {
1681 if (conf_parser_ctx.pass == 1)
1682 CidrBitlenIPV4(yy_class) = $3;
1683 };
1684
1685 class_cidr_bitlen_ipv6: CIDR_BITLEN_IPV6 '=' NUMBER ';'
1686 {
1687 if (conf_parser_ctx.pass == 1)
1688 CidrBitlenIPV6(yy_class) = $3;
1689 };
1690
1691 class_number_per_cidr: NUMBER_PER_CIDR '=' NUMBER ';'
1692 {
1693 if (conf_parser_ctx.pass == 1)
1694 NumberPerCidr(yy_class) = $3;
1695 };
1696
1697 /***************************************************************************
1698 * section listen
1699 ***************************************************************************/
1700 listen_entry: LISTEN
1701 {
1702 if (conf_parser_ctx.pass == 2)
1703 {
1704 listener_address = NULL;
1705 listener_flags = 0;
1706 }
1707 } '{' listen_items '}' ';'
1708 {
1709 if (conf_parser_ctx.pass == 2)
1710 {
1711 MyFree(listener_address);
1712 listener_address = NULL;
1713 }
1714 };
1715
1716 listen_flags: IRCD_FLAGS
1717 {
1718 listener_flags = 0;
1719 } '=' listen_flags_items ';';
1720
1721 listen_flags_items: listen_flags_items ',' listen_flags_item | listen_flags_item;
1722 listen_flags_item: T_SSL
1723 {
1724 if (conf_parser_ctx.pass == 2)
1725 listener_flags |= LISTENER_SSL;
1726 } | HIDDEN
1727 {
1728 if (conf_parser_ctx.pass == 2)
1729 listener_flags |= LISTENER_HIDDEN;
1730 } | T_SERVER
1731 {
1732 if (conf_parser_ctx.pass == 2)
1733 listener_flags |= LISTENER_SERVER;
1734 };
1735
1736
1737
1738 listen_items: listen_items listen_item | listen_item;
1739 listen_item: listen_port | listen_flags | listen_address | listen_host | error ';';
1740
1741 listen_port: PORT '=' port_items { listener_flags = 0; } ';';
1742
1743 port_items: port_items ',' port_item | port_item;
1744
1745 port_item: NUMBER
1746 {
1747 if (conf_parser_ctx.pass == 2)
1748 {
1749 if ((listener_flags & LISTENER_SSL))
1750 #ifdef HAVE_LIBCRYPTO
1751 if (!ServerInfo.server_ctx)
1752 #endif
1753 {
1754 yyerror("SSL not available - port closed");
1755 break;
1756 }
1757 add_listener($1, listener_address, listener_flags);
1758 }
1759 } | NUMBER TWODOTS NUMBER
1760 {
1761 if (conf_parser_ctx.pass == 2)
1762 {
1763 int i;
1764
1765 if ((listener_flags & LISTENER_SSL))
1766 #ifdef HAVE_LIBCRYPTO
1767 if (!ServerInfo.server_ctx)
1768 #endif
1769 {
1770 yyerror("SSL not available - port closed");
1771 break;
1772 }
1773
1774 for (i = $1; i <= $3; ++i)
1775 add_listener(i, listener_address, listener_flags);
1776 }
1777 };
1778
1779 listen_address: IP '=' QSTRING ';'
1780 {
1781 if (conf_parser_ctx.pass == 2)
1782 {
1783 MyFree(listener_address);
1784 DupString(listener_address, yylval.string);
1785 }
1786 };
1787
1788 listen_host: HOST '=' QSTRING ';'
1789 {
1790 if (conf_parser_ctx.pass == 2)
1791 {
1792 MyFree(listener_address);
1793 DupString(listener_address, yylval.string);
1794 }
1795 };
1796
1797 /***************************************************************************
1798 * section auth
1799 ***************************************************************************/
1800 auth_entry: IRCD_AUTH
1801 {
1802 if (conf_parser_ctx.pass == 2)
1803 {
1804 yy_conf = make_conf_item(CLIENT_TYPE);
1805 yy_aconf = map_to_conf(yy_conf);
1806 }
1807 else
1808 {
1809 MyFree(class_name);
1810 class_name = NULL;
1811 }
1812 } '{' auth_items '}' ';'
1813 {
1814 if (conf_parser_ctx.pass == 2)
1815 {
1816 struct CollectItem *yy_tmp = NULL;
1817 dlink_node *ptr = NULL, *next_ptr = NULL;
1818
1819 if (yy_aconf->user && yy_aconf->host)
1820 {
1821 conf_add_class_to_conf(yy_conf, class_name);
1822 add_conf_by_address(CONF_CLIENT, yy_aconf);
1823 }
1824 else
1825 delete_conf_item(yy_conf);
1826
1827 /* copy over settings from first struct */
1828 DLINK_FOREACH_SAFE(ptr, next_ptr, col_conf_list.head)
1829 {
1830 struct AccessItem *new_aconf;
1831 struct ConfItem *new_conf;
1832
1833 new_conf = make_conf_item(CLIENT_TYPE);
1834 new_aconf = map_to_conf(new_conf);
1835
1836 yy_tmp = ptr->data;
1837
1838 assert(yy_tmp->user && yy_tmp->host);
1839
1840 if (yy_aconf->passwd != NULL)
1841 DupString(new_aconf->passwd, yy_aconf->passwd);
1842 if (yy_conf->name != NULL)
1843 DupString(new_conf->name, yy_conf->name);
1844 if (yy_aconf->passwd != NULL)
1845 DupString(new_aconf->passwd, yy_aconf->passwd);
1846
1847 new_aconf->flags = yy_aconf->flags;
1848 new_aconf->port = yy_aconf->port;
1849
1850 DupString(new_aconf->user, yy_tmp->user);
1851 collapse(new_aconf->user);
1852
1853 DupString(new_aconf->host, yy_tmp->host);
1854 collapse(new_aconf->host);
1855
1856 conf_add_class_to_conf(new_conf, class_name);
1857 add_conf_by_address(CONF_CLIENT, new_aconf);
1858 dlinkDelete(&yy_tmp->node, &col_conf_list);
1859 free_collect_item(yy_tmp);
1860 }
1861
1862 MyFree(class_name);
1863 class_name = NULL;
1864 yy_conf = NULL;
1865 yy_aconf = NULL;
1866 }
1867 };
1868
1869 auth_items: auth_items auth_item | auth_item;
1870 auth_item: auth_user | auth_passwd | auth_class | auth_flags |
1871 auth_kline_exempt | auth_need_ident |
1872 auth_exceed_limit | auth_no_tilde | auth_gline_exempt |
1873 auth_spoof | auth_spoof_notice |
1874 auth_redir_serv | auth_redir_port | auth_can_flood |
1875 auth_need_password | auth_encrypted | error ';' ;
1876
1877 auth_user: USER '=' QSTRING ';'
1878 {
1879 if (conf_parser_ctx.pass == 2)
1880 {
1881 struct CollectItem *yy_tmp = NULL;
1882 struct split_nuh_item nuh;
1883
1884 nuh.nuhmask = yylval.string;
1885 nuh.nickptr = NULL;
1886 nuh.userptr = userbuf;
1887 nuh.hostptr = hostbuf;
1888
1889 nuh.nicksize = 0;
1890 nuh.usersize = sizeof(userbuf);
1891 nuh.hostsize = sizeof(hostbuf);
1892
1893 split_nuh(&nuh);
1894
1895 if (yy_aconf->user == NULL)
1896 {
1897 DupString(yy_aconf->user, userbuf);
1898 DupString(yy_aconf->host, hostbuf);
1899 }
1900 else
1901 {
1902 yy_tmp = MyMalloc(sizeof(struct CollectItem));
1903
1904 DupString(yy_tmp->user, userbuf);
1905 DupString(yy_tmp->host, hostbuf);
1906
1907 dlinkAdd(yy_tmp, &yy_tmp->node, &col_conf_list);
1908 }
1909 }
1910 };
1911
1912 /* XXX - IP/IPV6 tags don't exist anymore - put IP/IPV6 into user. */
1913
1914 auth_passwd: PASSWORD '=' QSTRING ';'
1915 {
1916 if (conf_parser_ctx.pass == 2)
1917 {
1918 /* be paranoid */
1919 if (yy_aconf->passwd != NULL)
1920 memset(yy_aconf->passwd, 0, strlen(yy_aconf->passwd));
1921
1922 MyFree(yy_aconf->passwd);
1923 DupString(yy_aconf->passwd, yylval.string);
1924 }
1925 };
1926
1927 auth_spoof_notice: SPOOF_NOTICE '=' TBOOL ';'
1928 {
1929 if (conf_parser_ctx.pass == 2)
1930 {
1931 if (yylval.number)
1932 yy_aconf->flags |= CONF_FLAGS_SPOOF_NOTICE;
1933 else
1934 yy_aconf->flags &= ~CONF_FLAGS_SPOOF_NOTICE;
1935 }
1936 };
1937
1938 auth_class: CLASS '=' QSTRING ';'
1939 {
1940 if (conf_parser_ctx.pass == 2)
1941 {
1942 MyFree(class_name);
1943 DupString(class_name, yylval.string);
1944 }
1945 };
1946
1947 auth_encrypted: ENCRYPTED '=' TBOOL ';'
1948 {
1949 if (conf_parser_ctx.pass == 2)
1950 {
1951 if (yylval.number)
1952 SetConfEncrypted(yy_aconf);
1953 else
1954 ClearConfEncrypted(yy_aconf);
1955 }
1956 };
1957
1958 auth_flags: IRCD_FLAGS
1959 {
1960 } '=' auth_flags_items ';';
1961
1962 auth_flags_items: auth_flags_items ',' auth_flags_item | auth_flags_item;
1963 auth_flags_item: NOT { not_atom = 1; } auth_flags_item_atom
1964 | { not_atom = 0; } auth_flags_item_atom;
1965
1966 auth_flags_item_atom: SPOOF_NOTICE
1967 {
1968 if (conf_parser_ctx.pass == 2)
1969 {
1970 if (not_atom) yy_aconf->flags &= ~CONF_FLAGS_SPOOF_NOTICE;
1971 else yy_aconf->flags |= CONF_FLAGS_SPOOF_NOTICE;
1972 }
1973
1974 } | EXCEED_LIMIT
1975 {
1976 if (conf_parser_ctx.pass == 2)
1977 {
1978 if (not_atom) yy_aconf->flags &= ~CONF_FLAGS_NOLIMIT;
1979 else yy_aconf->flags |= CONF_FLAGS_NOLIMIT;
1980 }
1981 } | KLINE_EXEMPT
1982 {
1983 if (conf_parser_ctx.pass == 2)
1984 {
1985 if (not_atom) yy_aconf->flags &= ~CONF_FLAGS_EXEMPTKLINE;
1986 else yy_aconf->flags |= CONF_FLAGS_EXEMPTKLINE;
1987 }
1988 } | NEED_IDENT
1989 {
1990 if (conf_parser_ctx.pass == 2)
1991 {
1992 if (not_atom) yy_aconf->flags &= ~CONF_FLAGS_NEED_IDENTD;
1993 else yy_aconf->flags |= CONF_FLAGS_NEED_IDENTD;
1994 }
1995 } | CAN_FLOOD
1996 {
1997 if (conf_parser_ctx.pass == 2)
1998 {
1999 if (not_atom) yy_aconf->flags &= ~CONF_FLAGS_CAN_FLOOD;
2000 else yy_aconf->flags |= CONF_FLAGS_CAN_FLOOD;
2001 }
2002 } | CAN_IDLE
2003 {
2004 if (conf_parser_ctx.pass == 2)
2005 {
2006 if (not_atom) yy_aconf->flags &= ~CONF_FLAGS_IDLE_LINED;
2007 else yy_aconf->flags |= CONF_FLAGS_IDLE_LINED;
2008 }
2009 } | NO_TILDE
2010 {
2011 if (conf_parser_ctx.pass == 2)
2012 {
2013 if (not_atom) yy_aconf->flags &= ~CONF_FLAGS_NO_TILDE;
2014 else yy_aconf->flags |= CONF_FLAGS_NO_TILDE;
2015 }
2016 } | GLINE_EXEMPT
2017 {
2018 if (conf_parser_ctx.pass == 2)
2019 {
2020 if (not_atom) yy_aconf->flags &= ~CONF_FLAGS_EXEMPTGLINE;
2021 else yy_aconf->flags |= CONF_FLAGS_EXEMPTGLINE;
2022 }
2023 } | RESV_EXEMPT
2024 {
2025 if (conf_parser_ctx.pass == 2)
2026 {
2027 if (not_atom) yy_aconf->flags &= ~CONF_FLAGS_EXEMPTRESV;
2028 else yy_aconf->flags |= CONF_FLAGS_EXEMPTRESV;
2029 }
2030 } | NEED_PASSWORD
2031 {
2032 if (conf_parser_ctx.pass == 2)
2033 {
2034 if (not_atom) yy_aconf->flags &= ~CONF_FLAGS_NEED_PASSWORD;
2035 else yy_aconf->flags |= CONF_FLAGS_NEED_PASSWORD;
2036 }
2037 };
2038
2039 auth_kline_exempt: KLINE_EXEMPT '=' TBOOL ';'
2040 {
2041 if (conf_parser_ctx.pass == 2)
2042 {
2043 if (yylval.number)
2044 yy_aconf->flags |= CONF_FLAGS_EXEMPTKLINE;
2045 else
2046 yy_aconf->flags &= ~CONF_FLAGS_EXEMPTKLINE;
2047 }
2048 };
2049
2050 auth_need_ident: NEED_IDENT '=' TBOOL ';'
2051 {
2052 if (conf_parser_ctx.pass == 2)
2053 {
2054 if (yylval.number)
2055 yy_aconf->flags |= CONF_FLAGS_NEED_IDENTD;
2056 else
2057 yy_aconf->flags &= ~CONF_FLAGS_NEED_IDENTD;
2058 }
2059 };
2060
2061 auth_exceed_limit: EXCEED_LIMIT '=' TBOOL ';'
2062 {
2063 if (conf_parser_ctx.pass == 2)
2064 {
2065 if (yylval.number)
2066 yy_aconf->flags |= CONF_FLAGS_NOLIMIT;
2067 else
2068 yy_aconf->flags &= ~CONF_FLAGS_NOLIMIT;
2069 }
2070 };
2071
2072 auth_can_flood: CAN_FLOOD '=' TBOOL ';'
2073 {
2074 if (conf_parser_ctx.pass == 2)
2075 {
2076 if (yylval.number)
2077 yy_aconf->flags |= CONF_FLAGS_CAN_FLOOD;
2078 else
2079 yy_aconf->flags &= ~CONF_FLAGS_CAN_FLOOD;
2080 }
2081 };
2082
2083 auth_no_tilde: NO_TILDE '=' TBOOL ';'
2084 {
2085 if (conf_parser_ctx.pass == 2)
2086 {
2087 if (yylval.number)
2088 yy_aconf->flags |= CONF_FLAGS_NO_TILDE;
2089 else
2090 yy_aconf->flags &= ~CONF_FLAGS_NO_TILDE;
2091 }
2092 };
2093
2094 auth_gline_exempt: GLINE_EXEMPT '=' TBOOL ';'
2095 {
2096 if (conf_parser_ctx.pass == 2)
2097 {
2098 if (yylval.number)
2099 yy_aconf->flags |= CONF_FLAGS_EXEMPTGLINE;
2100 else
2101 yy_aconf->flags &= ~CONF_FLAGS_EXEMPTGLINE;
2102 }
2103 };
2104
2105 /* XXX - need check for illegal hostnames here */
2106 auth_spoof: SPOOF '=' QSTRING ';'
2107 {
2108 if (conf_parser_ctx.pass == 2)
2109 {
2110 MyFree(yy_conf->name);
2111
2112 if (strlen(yylval.string) < HOSTLEN)
2113 {
2114 DupString(yy_conf->name, yylval.string);
2115 yy_aconf->flags |= CONF_FLAGS_SPOOF_IP;
2116 }
2117 else
2118 {
2119 ilog(L_ERROR, "Spoofs must be less than %d..ignoring it", HOSTLEN);
2120 yy_conf->name = NULL;
2121 }
2122 }
2123 };
2124
2125 auth_redir_serv: REDIRSERV '=' QSTRING ';'
2126 {
2127 if (conf_parser_ctx.pass == 2)
2128 {
2129 yy_aconf->flags |= CONF_FLAGS_REDIR;
2130 MyFree(yy_conf->name);
2131 DupString(yy_conf->name, yylval.string);
2132 }
2133 };
2134
2135 auth_redir_port: REDIRPORT '=' NUMBER ';'
2136 {
2137 if (conf_parser_ctx.pass == 2)
2138 {
2139 yy_aconf->flags |= CONF_FLAGS_REDIR;
2140 yy_aconf->port = $3;
2141 }
2142 };
2143
2144 auth_need_password: NEED_PASSWORD '=' TBOOL ';'
2145 {
2146 if (conf_parser_ctx.pass == 2)
2147 {
2148 if (yylval.number)
2149 yy_aconf->flags |= CONF_FLAGS_NEED_PASSWORD;
2150 else
2151 yy_aconf->flags &= ~CONF_FLAGS_NEED_PASSWORD;
2152 }
2153 };
2154
2155
2156 /***************************************************************************
2157 * section resv
2158 ***************************************************************************/
2159 resv_entry: RESV
2160 {
2161 if (conf_parser_ctx.pass == 2)
2162 {
2163 MyFree(resv_reason);
2164 resv_reason = NULL;
2165 }
2166 } '{' resv_items '}' ';'
2167 {
2168 if (conf_parser_ctx.pass == 2)
2169 {
2170 MyFree(resv_reason);
2171 resv_reason = NULL;
2172 }
2173 };
2174
2175 resv_items: resv_items resv_item | resv_item;
2176 resv_item: resv_creason | resv_channel | resv_nick | error ';' ;
2177
2178 resv_creason: REASON '=' QSTRING ';'
2179 {
2180 if (conf_parser_ctx.pass == 2)
2181 {
2182 MyFree(resv_reason);
2183 DupString(resv_reason, yylval.string);
2184 }
2185 };
2186
2187 resv_channel: CHANNEL '=' QSTRING ';'
2188 {
2189 if (conf_parser_ctx.pass == 2)
2190 {
2191 if (IsChanPrefix(*yylval.string))
2192 {
2193 char def_reason[] = "No reason";
2194
2195 create_channel_resv(yylval.string, resv_reason != NULL ? resv_reason : def_reason, 1);
2196 }
2197 }
2198 /* ignore it for now.. but we really should make a warning if
2199 * its an erroneous name --fl_ */
2200 };
2201
2202 resv_nick: NICK '=' QSTRING ';'
2203 {
2204 if (conf_parser_ctx.pass == 2)
2205 {
2206 char def_reason[] = "No reason";
2207
2208 create_nick_resv(yylval.string, resv_reason != NULL ? resv_reason : def_reason, 1);
2209 }
2210 };
2211
2212 /***************************************************************************
2213 * section shared, for sharing remote klines etc.
2214 ***************************************************************************/
2215 shared_entry: T_SHARED
2216 {
2217 if (conf_parser_ctx.pass == 2)
2218 {
2219 yy_conf = make_conf_item(ULINE_TYPE);
2220 yy_match_item = map_to_conf(yy_conf);
2221 yy_match_item->action = SHARED_ALL;
2222 }
2223 } '{' shared_items '}' ';'
2224 {
2225 if (conf_parser_ctx.pass == 2)
2226 {
2227 yy_conf = NULL;
2228 }
2229 };
2230
2231 shared_items: shared_items shared_item | shared_item;
2232 shared_item: shared_name | shared_user | shared_type | error ';' ;
2233
2234 shared_name: NAME '=' QSTRING ';'
2235 {
2236 if (conf_parser_ctx.pass == 2)
2237 {
2238 MyFree(yy_conf->name);
2239 DupString(yy_conf->name, yylval.string);
2240 }
2241 };
2242
2243 shared_user: USER '=' QSTRING ';'
2244 {
2245 if (conf_parser_ctx.pass == 2)
2246 {
2247 struct split_nuh_item nuh;
2248
2249 nuh.nuhmask = yylval.string;
2250 nuh.nickptr = NULL;
2251 nuh.userptr = userbuf;
2252 nuh.hostptr = hostbuf;
2253
2254 nuh.nicksize = 0;
2255 nuh.usersize = sizeof(userbuf);
2256 nuh.hostsize = sizeof(hostbuf);
2257
2258 split_nuh(&nuh);
2259
2260 DupString(yy_match_item->user, userbuf);
2261 DupString(yy_match_item->host, hostbuf);
2262 }
2263 };
2264
2265 shared_type: TYPE
2266 {
2267 if (conf_parser_ctx.pass == 2)
2268 yy_match_item->action = 0;
2269 } '=' shared_types ';' ;
2270
2271 shared_types: shared_types ',' shared_type_item | shared_type_item;
2272 shared_type_item: KLINE
2273 {
2274 if (conf_parser_ctx.pass == 2)
2275 yy_match_item->action |= SHARED_KLINE;
2276 } | TKLINE
2277 {
2278 if (conf_parser_ctx.pass == 2)
2279 yy_match_item->action |= SHARED_TKLINE;
2280 } | UNKLINE
2281 {
2282 if (conf_parser_ctx.pass == 2)
2283 yy_match_item->action |= SHARED_UNKLINE;
2284 } | XLINE
2285 {
2286 if (conf_parser_ctx.pass == 2)
2287 yy_match_item->action |= SHARED_XLINE;
2288 } | TXLINE
2289 {
2290 if (conf_parser_ctx.pass == 2)
2291 yy_match_item->action |= SHARED_TXLINE;
2292 } | T_UNXLINE
2293 {
2294 if (conf_parser_ctx.pass == 2)
2295 yy_match_item->action |= SHARED_UNXLINE;
2296 } | RESV
2297 {
2298 if (conf_parser_ctx.pass == 2)
2299 yy_match_item->action |= SHARED_RESV;
2300 } | TRESV
2301 {
2302 if (conf_parser_ctx.pass == 2)
2303 yy_match_item->action |= SHARED_TRESV;
2304 } | T_UNRESV
2305 {
2306 if (conf_parser_ctx.pass == 2)
2307 yy_match_item->action |= SHARED_UNRESV;
2308 } | T_LOCOPS
2309 {
2310 if (conf_parser_ctx.pass == 2)
2311 yy_match_item->action |= SHARED_LOCOPS;
2312 } | T_ALL
2313 {
2314 if (conf_parser_ctx.pass == 2)
2315 yy_match_item->action = SHARED_ALL;
2316 };
2317
2318 /***************************************************************************
2319 * section cluster
2320 ***************************************************************************/
2321 cluster_entry: T_CLUSTER
2322 {
2323 if (conf_parser_ctx.pass == 2)
2324 {
2325 yy_conf = make_conf_item(CLUSTER_TYPE);
2326 yy_conf->flags = SHARED_ALL;
2327 }
2328 } '{' cluster_items '}' ';'
2329 {
2330 if (conf_parser_ctx.pass == 2)
2331 {
2332 if (yy_conf->name == NULL)
2333 DupString(yy_conf->name, "*");
2334 yy_conf = NULL;
2335 }
2336 };
2337
2338 cluster_items: cluster_items cluster_item | cluster_item;
2339 cluster_item: cluster_name | cluster_type | error ';' ;
2340
2341 cluster_name: NAME '=' QSTRING ';'
2342 {
2343 if (conf_parser_ctx.pass == 2)
2344 DupString(yy_conf->name, yylval.string);
2345 };
2346
2347 cluster_type: TYPE
2348 {
2349 if (conf_parser_ctx.pass == 2)
2350 yy_conf->flags = 0;
2351 } '=' cluster_types ';' ;
2352
2353 cluster_types: cluster_types ',' cluster_type_item | cluster_type_item;
2354 cluster_type_item: KLINE
2355 {
2356 if (conf_parser_ctx.pass == 2)
2357 yy_conf->flags |= SHARED_KLINE;
2358 } | TKLINE
2359 {
2360 if (conf_parser_ctx.pass == 2)
2361 yy_conf->flags |= SHARED_TKLINE;
2362 } | UNKLINE
2363 {
2364 if (conf_parser_ctx.pass == 2)
2365 yy_conf->flags |= SHARED_UNKLINE;
2366 } | XLINE
2367 {
2368 if (conf_parser_ctx.pass == 2)
2369 yy_conf->flags |= SHARED_XLINE;
2370 } | TXLINE
2371 {
2372 if (conf_parser_ctx.pass == 2)
2373 yy_conf->flags |= SHARED_TXLINE;
2374 } | T_UNXLINE
2375 {
2376 if (conf_parser_ctx.pass == 2)
2377 yy_conf->flags |= SHARED_UNXLINE;
2378 } | RESV
2379 {
2380 if (conf_parser_ctx.pass == 2)
2381 yy_conf->flags |= SHARED_RESV;
2382 } | TRESV
2383 {
2384 if (conf_parser_ctx.pass == 2)
2385 yy_conf->flags |= SHARED_TRESV;
2386 } | T_UNRESV
2387 {
2388 if (conf_parser_ctx.pass == 2)
2389 yy_conf->flags |= SHARED_UNRESV;
2390 } | T_LOCOPS
2391 {
2392 if (conf_parser_ctx.pass == 2)
2393 yy_conf->flags |= SHARED_LOCOPS;
2394 } | T_ALL
2395 {
2396 if (conf_parser_ctx.pass == 2)
2397 yy_conf->flags = SHARED_ALL;
2398 };
2399
2400 /***************************************************************************
2401 * section connect
2402 ***************************************************************************/
2403 connect_entry: CONNECT
2404 {
2405 if (conf_parser_ctx.pass == 2)
2406 {
2407 yy_conf = make_conf_item(SERVER_TYPE);
2408 yy_aconf = (struct AccessItem *)map_to_conf(yy_conf);
2409 yy_aconf->passwd = NULL;
2410 /* defaults */
2411 yy_aconf->port = PORTNUM;
2412
2413 if (ConfigFileEntry.burst_away)
2414 yy_aconf->flags = CONF_FLAGS_BURST_AWAY;
2415 }
2416 else
2417 {
2418 MyFree(class_name);
2419 class_name = NULL;
2420 }
2421 } connect_name_b '{' connect_items '}' ';'
2422 {
2423 if (conf_parser_ctx.pass == 2)
2424 {
2425 struct CollectItem *yy_hconf=NULL;
2426 struct CollectItem *yy_lconf=NULL;
2427 dlink_node *ptr;
2428 dlink_node *next_ptr;
2429 #ifdef HAVE_LIBCRYPTO
2430 if (yy_aconf->host &&
2431 ((yy_aconf->passwd && yy_aconf->spasswd) ||
2432 (yy_aconf->rsa_public_key && IsConfCryptLink(yy_aconf))))
2433 #else /* !HAVE_LIBCRYPTO */
2434 if (yy_aconf->host && !IsConfCryptLink(yy_aconf) &&
2435 yy_aconf->passwd && yy_aconf->spasswd)
2436 #endif /* !HAVE_LIBCRYPTO */
2437 {
2438 if (conf_add_server(yy_conf, class_name) == -1)
2439 {
2440 delete_conf_item(yy_conf);
2441 yy_conf = NULL;
2442 yy_aconf = NULL;
2443 }
2444 }
2445 else
2446 {
2447 /* Even if yy_conf ->name is NULL
2448 * should still unhook any hub/leaf confs still pending
2449 */
2450 unhook_hub_leaf_confs();
2451
2452 if (yy_conf->name != NULL)
2453 {
2454 #ifndef HAVE_LIBCRYPTO
2455 if (IsConfCryptLink(yy_aconf))
2456 yyerror("Ignoring connect block -- no OpenSSL support");
2457 #else
2458 if (IsConfCryptLink(yy_aconf) && !yy_aconf->rsa_public_key)
2459 yyerror("Ignoring connect block -- missing key");
2460 #endif
2461 if (yy_aconf->host == NULL)
2462 yyerror("Ignoring connect block -- missing host");
2463 else if (!IsConfCryptLink(yy_aconf) &&
2464 (!yy_aconf->passwd || !yy_aconf->spasswd))
2465 yyerror("Ignoring connect block -- missing password");
2466 }
2467
2468
2469 /* XXX
2470 * This fixes a try_connections() core (caused by invalid class_ptr
2471 * pointers) reported by metalrock. That's an ugly fix, but there
2472 * is currently no better way. The entire config subsystem needs an
2473 * rewrite ASAP. make_conf_item() shouldn't really add things onto
2474 * a doubly linked list immediately without any sanity checks! -Michael
2475 */
2476 delete_conf_item(yy_conf);
2477
2478 yy_aconf = NULL;
2479 yy_conf = NULL;
2480 }
2481
2482 /*
2483 * yy_conf is still pointing at the server that is having
2484 * a connect block built for it. This means, y_aconf->name
2485 * points to the actual irc name this server will be known as.
2486 * Now this new server has a set or even just one hub_mask (or leaf_mask)
2487 * given in the link list at yy_hconf. Fill in the HUB confs
2488 * from this link list now.
2489 */
2490 DLINK_FOREACH_SAFE(ptr, next_ptr, hub_conf_list.head)
2491 {
2492 struct ConfItem *new_hub_conf;
2493 struct MatchItem *match_item;
2494
2495 yy_hconf = ptr->data;
2496
2497 /* yy_conf == NULL is a fatal error for this connect block! */
2498 if ((yy_conf != NULL) && (yy_conf->name != NULL))
2499 {
2500 new_hub_conf = make_conf_item(HUB_TYPE);
2501 match_item = (struct MatchItem *)map_to_conf(new_hub_conf);
2502 DupString(new_hub_conf->name, yy_conf->name);
2503 if (yy_hconf->user != NULL)
2504 DupString(match_item->user, yy_hconf->user);
2505 else
2506 DupString(match_item->user, "*");
2507 if (yy_hconf->host != NULL)
2508 DupString(match_item->host, yy_hconf->host);
2509 else
2510 DupString(match_item->host, "*");
2511 }
2512 dlinkDelete(&yy_hconf->node, &hub_conf_list);
2513 free_collect_item(yy_hconf);
2514 }
2515
2516 /* Ditto for the LEAF confs */
2517
2518 DLINK_FOREACH_SAFE(ptr, next_ptr, leaf_conf_list.head)
2519 {
2520 struct ConfItem *new_leaf_conf;
2521 struct MatchItem *match_item;
2522
2523 yy_lconf = ptr->data;
2524
2525 if ((yy_conf != NULL) && (yy_conf->name != NULL))
2526 {
2527 new_leaf_conf = make_conf_item(LEAF_TYPE);
2528 match_item = (struct MatchItem *)map_to_conf(new_leaf_conf);
2529 DupString(new_leaf_conf->name, yy_conf->name);
2530 if (yy_lconf->user != NULL)
2531 DupString(match_item->user, yy_lconf->user);
2532 else
2533 DupString(match_item->user, "*");
2534 if (yy_lconf->host != NULL)
2535 DupString(match_item->host, yy_lconf->host);
2536 else
2537 DupString(match_item->host, "*");
2538 }
2539 dlinkDelete(&yy_lconf->node, &leaf_conf_list);
2540 free_collect_item(yy_lconf);
2541 }
2542 MyFree(class_name);
2543 class_name = NULL;
2544 yy_conf = NULL;
2545 yy_aconf = NULL;
2546 }
2547 };
2548
2549 connect_name_b: | connect_name_t;
2550 connect_items: connect_items connect_item | connect_item;
2551 connect_item: connect_name | connect_host | connect_vhost |
2552 connect_send_password | connect_accept_password |
2553 connect_aftype | connect_port |
2554 connect_fakename | connect_flags | connect_hub_mask |
2555 connect_leaf_mask | connect_class | connect_auto |
2556 connect_encrypted | connect_compressed | connect_cryptlink |
2557 connect_rsa_public_key_file | connect_cipher_preference |
2558 connect_topicburst | error ';' ;
2559
2560 connect_name: NAME '=' QSTRING ';'
2561 {
2562 if (conf_parser_ctx.pass == 2)
2563 {
2564 if (yy_conf->name != NULL)
2565 yyerror("Multiple connect name entry");
2566
2567 MyFree(yy_conf->name);
2568 DupString(yy_conf->name, yylval.string);
2569 }
2570 };
2571
2572 connect_name_t: QSTRING
2573 {
2574 if (conf_parser_ctx.pass == 2)
2575 {
2576 if (yy_conf->name != NULL)
2577 yyerror("Multiple connect name entry");
2578
2579 MyFree(yy_conf->name);
2580 DupString(yy_conf->name, yylval.string);
2581 }
2582 };
2583
2584 connect_host: HOST '=' QSTRING ';'
2585 {
2586 if (conf_parser_ctx.pass == 2)
2587 {
2588 MyFree(yy_aconf->host);
2589 DupString(yy_aconf->host, yylval.string);
2590 }
2591 };
2592
2593 connect_vhost: VHOST '=' QSTRING ';'
2594 {
2595 if (conf_parser_ctx.pass == 2)
2596 {
2597 struct addrinfo hints, *res;
2598
2599 memset(&hints, 0, sizeof(hints));
2600
2601 hints.ai_family = AF_UNSPEC;
2602 hints.ai_socktype = SOCK_STREAM;
2603 hints.ai_flags = AI_PASSIVE | AI_NUMERICHOST;
2604
2605 if (irc_getaddrinfo(yylval.string, NULL, &hints, &res))
2606 ilog(L_ERROR, "Invalid netmask for server vhost(%s)", yylval.string);
2607 else
2608 {
2609 assert(res != NULL);
2610
2611 memcpy(&yy_aconf->my_ipnum, res->ai_addr, res->ai_addrlen);
2612 yy_aconf->my_ipnum.ss.ss_family = res->ai_family;
2613 yy_aconf->my_ipnum.ss_len = res->ai_addrlen;
2614 irc_freeaddrinfo(res);
2615 }
2616 }
2617 };
2618
2619 connect_send_password: SEND_PASSWORD '=' QSTRING ';'
2620 {
2621 if (conf_parser_ctx.pass == 2)
2622 {
2623 if ($3[0] == ':')
2624 yyerror("Server passwords cannot begin with a colon");
2625 else if (strchr($3, ' ') != NULL)
2626 yyerror("Server passwords cannot contain spaces");
2627 else {
2628 if (yy_aconf->spasswd != NULL)
2629 memset(yy_aconf->spasswd, 0, strlen(yy_aconf->spasswd));
2630
2631 MyFree(yy_aconf->spasswd);
2632 DupString(yy_aconf->spasswd, yylval.string);
2633 }
2634 }
2635 };
2636
2637 connect_accept_password: ACCEPT_PASSWORD '=' QSTRING ';'
2638 {
2639 if (conf_parser_ctx.pass == 2)
2640 {
2641 if ($3[0] == ':')
2642 yyerror("Server passwords cannot begin with a colon");
2643 else if (strchr($3, ' ') != NULL)
2644 yyerror("Server passwords cannot contain spaces");
2645 else {
2646 if (yy_aconf->passwd != NULL)
2647 memset(yy_aconf->passwd, 0, strlen(yy_aconf->passwd));
2648
2649 MyFree(yy_aconf->passwd);
2650 DupString(yy_aconf->passwd, yylval.string);
2651 }
2652 }
2653 };
2654
2655 connect_port: PORT '=' NUMBER ';'
2656 {
2657 if (conf_parser_ctx.pass == 2)
2658 yy_aconf->port = $3;
2659 };
2660
2661 connect_aftype: AFTYPE '=' T_IPV4 ';'
2662 {
2663 if (conf_parser_ctx.pass == 2)
2664 yy_aconf->aftype = AF_INET;
2665 } | AFTYPE '=' T_IPV6 ';'
2666 {
2667 #ifdef IPV6
2668 if (conf_parser_ctx.pass == 2)
2669 yy_aconf->aftype = AF_INET6;
2670 #endif
2671 };
2672
2673 connect_fakename: FAKENAME '=' QSTRING ';'
2674 {
2675 if (conf_parser_ctx.pass == 2)
2676 {
2677 MyFree(yy_aconf->fakename);
2678 DupString(yy_aconf->fakename, yylval.string);
2679 }
2680 };
2681
2682 connect_flags: IRCD_FLAGS
2683 {
2684 } '=' connect_flags_items ';';
2685
2686 connect_flags_items: connect_flags_items ',' connect_flags_item | connect_flags_item;
2687 connect_flags_item: NOT { not_atom = 1; } connect_flags_item_atom
2688 | { not_atom = 0; } connect_flags_item_atom;
2689
2690 connect_flags_item_atom: COMPRESSED
2691 {
2692 if (conf_parser_ctx.pass == 2)
2693 #ifndef HAVE_LIBZ
2694 yyerror("Ignoring flags = compressed; -- no zlib support");
2695 #else
2696 {
2697 if (not_atom)ClearConfCompressed(yy_aconf);
2698 else SetConfCompressed(yy_aconf);
2699 }
2700 #endif
2701 } | CRYPTLINK
2702 {
2703 if (conf_parser_ctx.pass == 2)
2704 {
2705 if (not_atom)ClearConfCryptLink(yy_aconf);
2706 else SetConfCryptLink(yy_aconf);
2707 }
2708 } | AUTOCONN
2709 {
2710 if (conf_parser_ctx.pass == 2)
2711 {
2712 if (not_atom)ClearConfAllowAutoConn(yy_aconf);
2713 else SetConfAllowAutoConn(yy_aconf);
2714 }
2715 } | BURST_AWAY
2716 {
2717 if (conf_parser_ctx.pass == 2)
2718 {
2719 if (not_atom)ClearConfAwayBurst(yy_aconf);
2720 else SetConfAwayBurst(yy_aconf);
2721 }
2722 } | TOPICBURST
2723 {
2724 if (conf_parser_ctx.pass == 2)
2725 {
2726 if (not_atom)ClearConfTopicBurst(yy_aconf);
2727 else SetConfTopicBurst(yy_aconf);
2728 }
2729 }
2730 ;
2731
2732 connect_rsa_public_key_file: RSA_PUBLIC_KEY_FILE '=' QSTRING ';'
2733 {
2734 #ifdef HAVE_LIBCRYPTO
2735 if (conf_parser_ctx.pass == 2)
2736 {
2737 BIO *file;
2738
2739 if (yy_aconf->rsa_public_key != NULL)
2740 {
2741 RSA_free(yy_aconf->rsa_public_key);
2742 yy_aconf->rsa_public_key = NULL;
2743 }
2744
2745 if (yy_aconf->rsa_public_key_file != NULL)
2746 {
2747 MyFree(yy_aconf->rsa_public_key_file);
2748 yy_aconf->rsa_public_key_file = NULL;
2749 }
2750
2751 DupString(yy_aconf->rsa_public_key_file, yylval.string);
2752
2753 if ((file = BIO_new_file(yylval.string, "r")) == NULL)
2754 {
2755 yyerror("Ignoring rsa_public_key_file -- file doesn't exist");
2756 break;
2757 }
2758
2759 yy_aconf->rsa_public_key = (RSA *)PEM_read_bio_RSA_PUBKEY(file, NULL, 0, NULL);
2760
2761 if (yy_aconf->rsa_public_key == NULL)
2762 {
2763 yyerror("Ignoring rsa_public_key_file -- Key invalid; check key syntax.");
2764 break;
2765 }
2766
2767 BIO_set_close(file, BIO_CLOSE);
2768 BIO_free(file);
2769 }
2770 #endif /* HAVE_LIBCRYPTO */
2771 };
2772
2773 connect_encrypted: ENCRYPTED '=' TBOOL ';'
2774 {
2775 if (conf_parser_ctx.pass == 2)
2776 {
2777 if (yylval.number)
2778 yy_aconf->flags |= CONF_FLAGS_ENCRYPTED;
2779 else
2780 yy_aconf->flags &= ~CONF_FLAGS_ENCRYPTED;
2781 }
2782 };
2783
2784 connect_cryptlink: CRYPTLINK '=' TBOOL ';'
2785 {
2786 if (conf_parser_ctx.pass == 2)
2787 {
2788 if (yylval.number)
2789 yy_aconf->flags |= CONF_FLAGS_CRYPTLINK;
2790 else
2791 yy_aconf->flags &= ~CONF_FLAGS_CRYPTLINK;
2792 }
2793 };
2794
2795 connect_compressed: COMPRESSED '=' TBOOL ';'
2796 {
2797 if (conf_parser_ctx.pass == 2)
2798 {
2799 if (yylval.number)
2800 #ifndef HAVE_LIBZ
2801 yyerror("Ignoring compressed=yes; -- no zlib support");
2802 #else
2803 yy_aconf->flags |= CONF_FLAGS_COMPRESSED;
2804 #endif
2805 else
2806 yy_aconf->flags &= ~CONF_FLAGS_COMPRESSED;
2807 }
2808 };
2809
2810 connect_auto: AUTOCONN '=' TBOOL ';'
2811 {
2812 if (conf_parser_ctx.pass == 2)
2813 {
2814 if (yylval.number)
2815 yy_aconf->flags |= CONF_FLAGS_ALLOW_AUTO_CONN;
2816 else
2817 yy_aconf->flags &= ~CONF_FLAGS_ALLOW_AUTO_CONN;
2818 }
2819 };
2820
2821 connect_topicburst: TOPICBURST '=' TBOOL ';'
2822 {
2823 if (conf_parser_ctx.pass == 2)
2824 {
2825 if (yylval.number)
2826 SetConfTopicBurst(yy_aconf);
2827 else
2828 ClearConfTopicBurst(yy_aconf);
2829 }
2830 };
2831
2832 connect_hub_mask: HUB_MASK '=' QSTRING ';'
2833 {
2834 if (conf_parser_ctx.pass == 2)
2835 {
2836 struct CollectItem *yy_tmp;
2837
2838 yy_tmp = (struct CollectItem *)MyMalloc(sizeof(struct CollectItem));
2839 DupString(yy_tmp->host, yylval.string);
2840 DupString(yy_tmp->user, "*");
2841 dlinkAdd(yy_tmp, &yy_tmp->node, &hub_conf_list);
2842 }
2843 };
2844
2845 connect_leaf_mask: LEAF_MASK '=' QSTRING ';'
2846 {
2847 if (conf_parser_ctx.pass == 2)
2848 {
2849 struct CollectItem *yy_tmp;
2850
2851 yy_tmp = (struct CollectItem *)MyMalloc(sizeof(struct CollectItem));
2852 DupString(yy_tmp->host, yylval.string);
2853 DupString(yy_tmp->user, "*");
2854 dlinkAdd(yy_tmp, &yy_tmp->node, &leaf_conf_list);
2855 }
2856 };
2857
2858 connect_class: CLASS '=' QSTRING ';'
2859 {
2860 if (conf_parser_ctx.pass == 2)
2861 {
2862 MyFree(class_name);
2863 DupString(class_name, yylval.string);
2864 }
2865 };
2866
2867 connect_cipher_preference: CIPHER_PREFERENCE '=' QSTRING ';'
2868 {
2869 #ifdef HAVE_LIBCRYPTO
2870 if (conf_parser_ctx.pass == 2)
2871 {
2872 struct EncCapability *ecap;
2873 const char *cipher_name;
2874 int found = 0;
2875
2876 yy_aconf->cipher_preference = NULL;
2877 cipher_name = yylval.string;
2878
2879 for (ecap = CipherTable; ecap->name; ecap++)
2880 {
2881 if ((irccmp(ecap->name, cipher_name) == 0) &&
2882 (ecap->cap & CAP_ENC_MASK))
2883 {
2884 yy_aconf->cipher_preference = ecap;
2885 found = 1;
2886 break;
2887 }
2888 }
2889
2890 if (!found)
2891 yyerror("Invalid cipher");
2892 }
2893 #else
2894 if (conf_parser_ctx.pass == 2)
2895 yyerror("Ignoring cipher_preference -- no OpenSSL support");
2896 #endif
2897 };
2898
2899 /***************************************************************************
2900 * section kill
2901 ***************************************************************************/
2902 kill_entry: KILL
2903 {
2904 if (conf_parser_ctx.pass == 2)
2905 {
2906 userbuf[0] = hostbuf[0] = reasonbuf[0] = '\0';
2907 regex_ban = 0;
2908 }
2909 } '{' kill_items '}' ';'
2910 {
2911 if (conf_parser_ctx.pass == 2)
2912 {
2913 if (userbuf[0] && hostbuf[0])
2914 {
2915 if (regex_ban)
2916 {
2917 #ifdef HAVE_LIBPCRE
2918 void *exp_user = NULL;
2919 void *exp_host = NULL;
2920 const char *errptr = NULL;
2921
2922 if (!(exp_user = ircd_pcre_compile(userbuf, &errptr)) ||
2923 !(exp_host = ircd_pcre_compile(hostbuf, &errptr)))
2924 {
2925 ilog(L_ERROR, "Failed to add regular expression based K-Line: %s",
2926 errptr);
2927 break;
2928 }
2929
2930 yy_aconf = map_to_conf(make_conf_item(RKLINE_TYPE));
2931 yy_aconf->regexuser = exp_user;
2932 yy_aconf->regexhost = exp_host;
2933
2934 DupString(yy_aconf->user, userbuf);
2935 DupString(yy_aconf->host, hostbuf);
2936
2937 if (reasonbuf[0])
2938 DupString(yy_aconf->reason, reasonbuf);
2939 else
2940 DupString(yy_aconf->reason, "No reason");
2941 #else
2942 ilog(L_ERROR, "Failed to add regular expression based K-Line: no PCRE support");
2943 break;
2944 #endif
2945 }
2946 else
2947 {
2948 yy_aconf = map_to_conf(make_conf_item(KLINE_TYPE));
2949
2950 DupString(yy_aconf->user, userbuf);
2951 DupString(yy_aconf->host, hostbuf);
2952
2953 if (reasonbuf[0])
2954 DupString(yy_aconf->reason, reasonbuf);
2955 else
2956 DupString(yy_aconf->reason, "No reason");
2957 add_conf_by_address(CONF_KILL, yy_aconf);
2958 }
2959 }
2960
2961 yy_aconf = NULL;
2962 }
2963 };
2964
2965 kill_type: TYPE
2966 {
2967 } '=' kill_type_items ';';
2968
2969 kill_type_items: kill_type_items ',' kill_type_item | kill_type_item;
2970 kill_type_item: REGEX_T
2971 {
2972 if (conf_parser_ctx.pass == 2)
2973 regex_ban = 1;
2974 };
2975
2976 kill_items: kill_items kill_item | kill_item;
2977 kill_item: kill_user | kill_reason | kill_type | error;
2978
2979 kill_user: USER '=' QSTRING ';'
2980 {
2981 if (conf_parser_ctx.pass == 2)
2982 {
2983 struct split_nuh_item nuh;
2984
2985 nuh.nuhmask = yylval.string;
2986 nuh.nickptr = NULL;
2987 nuh.userptr = userbuf;
2988 nuh.hostptr = hostbuf;
2989
2990 nuh.nicksize = 0;
2991 nuh.usersize = sizeof(userbuf);
2992 nuh.hostsize = sizeof(hostbuf);
2993
2994 split_nuh(&nuh);
2995 }
2996 };
2997
2998 kill_reason: REASON '=' QSTRING ';'
2999 {
3000 if (conf_parser_ctx.pass == 2)
3001 strlcpy(reasonbuf, yylval.string, sizeof(reasonbuf));
3002 };
3003
3004 /***************************************************************************
3005 * section deny
3006 ***************************************************************************/
3007 deny_entry: DENY
3008 {
3009 if (conf_parser_ctx.pass == 2)
3010 hostbuf[0] = reasonbuf[0] = '\0';
3011 } '{' deny_items '}' ';'
3012 {
3013 if (conf_parser_ctx.pass == 2)
3014 {
3015 if (hostbuf[0] && parse_netmask(hostbuf, NULL, NULL) != HM_HOST)
3016 {
3017 yy_aconf = map_to_conf(make_conf_item(DLINE_TYPE));
3018 DupString(yy_aconf->host, hostbuf);
3019
3020 if (reasonbuf[0])
3021 DupString(yy_aconf->reason, reasonbuf);
3022 else
3023 DupString(yy_aconf->reason, "No reason");
3024 add_conf_by_address(CONF_DLINE, yy_aconf);
3025 yy_aconf = NULL;
3026 }
3027 }
3028 };
3029
3030 deny_items: deny_items deny_item | deny_item;
3031 deny_item: deny_ip | deny_reason | error;
3032
3033 deny_ip: IP '=' QSTRING ';'
3034 {
3035 if (conf_parser_ctx.pass == 2)
3036 strlcpy(hostbuf, yylval.string, sizeof(hostbuf));
3037 };
3038
3039 deny_reason: REASON '=' QSTRING ';'
3040 {
3041 if (conf_parser_ctx.pass == 2)
3042 strlcpy(reasonbuf, yylval.string, sizeof(reasonbuf));
3043 };
3044
3045 /***************************************************************************
3046 * section exempt
3047 ***************************************************************************/
3048 exempt_entry: EXEMPT '{' exempt_items '}' ';';
3049
3050 exempt_items: exempt_items exempt_item | exempt_item;
3051 exempt_item: exempt_ip | error;
3052
3053 exempt_ip: IP '=' QSTRING ';'
3054 {
3055 if (conf_parser_ctx.pass == 2)
3056 {
3057 if (yylval.string[0] && parse_netmask(yylval.string, NULL, NULL) != HM_HOST)
3058 {
3059 yy_aconf = map_to_conf(make_conf_item(EXEMPTDLINE_TYPE));
3060 DupString(yy_aconf->host, yylval.string);
3061
3062 add_conf_by_address(CONF_EXEMPTDLINE, yy_aconf);
3063 yy_aconf = NULL;
3064 }
3065 }
3066 };
3067
3068 /***************************************************************************
3069 * section gecos
3070 ***************************************************************************/
3071 gecos_entry: GECOS
3072 {
3073 if (conf_parser_ctx.pass == 2)
3074 {
3075 regex_ban = 0;
3076 reasonbuf[0] = gecos_name[0] = '\0';
3077 }
3078 } '{' gecos_items '}' ';'
3079 {
3080 if (conf_parser_ctx.pass == 2)
3081 {
3082 if (gecos_name[0])
3083 {
3084 if (regex_ban)
3085 {
3086 #ifdef HAVE_LIBPCRE
3087 void *exp_p = NULL;
3088 const char *errptr = NULL;
3089
3090 if (!(exp_p = ircd_pcre_compile(gecos_name, &errptr)))
3091 {
3092 ilog(L_ERROR, "Failed to add regular expression based X-Line: %s",
3093 errptr);
3094 break;
3095 }
3096
3097 yy_conf = make_conf_item(RXLINE_TYPE);
3098 yy_conf->regexpname = exp_p;
3099 #else
3100 ilog(L_ERROR, "Failed to add regular expression based X-Line: no PCRE support");
3101 break;
3102 #endif
3103 }
3104 else
3105 yy_conf = make_conf_item(XLINE_TYPE);
3106
3107 yy_match_item = map_to_conf(yy_conf);
3108 DupString(yy_conf->name, gecos_name);
3109
3110 if (reasonbuf[0])
3111 DupString(yy_match_item->reason, reasonbuf);
3112 else
3113 DupString(yy_match_item->reason, "No reason");
3114 }
3115 }
3116 };
3117
3118 gecos_flags: TYPE
3119 {
3120 } '=' gecos_flags_items ';';
3121
3122 gecos_flags_items: gecos_flags_items ',' gecos_flags_item | gecos_flags_item;
3123 gecos_flags_item: REGEX_T
3124 {
3125 if (conf_parser_ctx.pass == 2)
3126 regex_ban = 1;
3127 };
3128
3129 gecos_items: gecos_items gecos_item | gecos_item;
3130 gecos_item: gecos_name | gecos_reason | gecos_flags | error;
3131
3132 gecos_name: NAME '=' QSTRING ';'
3133 {
3134 if (conf_parser_ctx.pass == 2)
3135 strlcpy(gecos_name, yylval.string, sizeof(gecos_name));
3136 };
3137
3138 gecos_reason: REASON '=' QSTRING ';'
3139 {
3140 if (conf_parser_ctx.pass == 2)
3141 strlcpy(reasonbuf, yylval.string, sizeof(reasonbuf));
3142 };
3143
3144 /***************************************************************************
3145 * section general
3146 ***************************************************************************/
3147 general_entry: GENERAL
3148 '{' general_items '}' ';';
3149
3150 general_items: general_items general_item | general_item;
3151 general_item: general_hide_spoof_ips | general_ignore_bogus_ts |
3152 general_failed_oper_notice | general_anti_nick_flood |
3153 general_max_nick_time | general_max_nick_changes |
3154 general_max_accept | general_anti_spam_exit_message_time |
3155 general_ts_warn_delta | general_ts_max_delta |
3156 general_kill_chase_time_limit | general_kline_with_reason |
3157 general_kline_reason | general_invisible_on_connect |
3158 general_warn_no_nline | general_dots_in_ident |
3159 general_stats_o_oper_only | general_stats_k_oper_only |
3160 general_pace_wait | general_stats_i_oper_only |
3161 general_pace_wait_simple | general_stats_P_oper_only |
3162 general_short_motd | general_no_oper_flood |
3163 general_true_no_oper_flood | general_oper_pass_resv |
3164 general_idletime | general_message_locale |
3165 general_oper_only_umodes | general_max_targets |
3166 general_use_egd | general_egdpool_path |
3167 general_oper_umodes | general_caller_id_wait |
3168 general_opers_bypass_callerid | general_default_floodcount |
3169 general_min_nonwildcard | general_min_nonwildcard_simple |
3170 general_servlink_path | general_disable_remote_commands |
3171 general_default_cipher_preference |
3172 general_compression_level | general_client_flood |
3173 general_throttle_time | general_havent_read_conf |
3174 general_dot_in_ip6_addr | general_ping_cookie |
3175 general_disable_auth | general_burst_away |
3176 general_tkline_expire_notices | general_gline_min_cidr |
3177 general_gline_min_cidr6 | general_use_whois_actually |
3178 general_reject_hold_time | general_stats_e_disabled |
3179 general_max_watch |
3180 error;
3181
3182
3183 general_max_watch: MAX_WATCH '=' NUMBER ';'
3184 {
3185 ConfigFileEntry.max_watch = $3;
3186 };
3187
3188 general_gline_min_cidr: GLINE_MIN_CIDR '=' NUMBER ';'
3189 {
3190 ConfigFileEntry.gline_min_cidr = $3;
3191 };
3192
3193 general_gline_min_cidr6: GLINE_MIN_CIDR6 '=' NUMBER ';'
3194 {
3195 ConfigFileEntry.gline_min_cidr6 = $3;
3196 };
3197
3198 general_burst_away: BURST_AWAY '=' TBOOL ';'
3199 {
3200 ConfigFileEntry.burst_away = yylval.number;
3201 };
3202
3203 general_use_whois_actually: USE_WHOIS_ACTUALLY '=' TBOOL ';'
3204 {
3205 ConfigFileEntry.use_whois_actually = yylval.number;
3206 };
3207
3208 general_reject_hold_time: TREJECT_HOLD_TIME '=' timespec ';'
3209 {
3210 GlobalSetOptions.rejecttime = yylval.number;
3211 };
3212
3213 general_tkline_expire_notices: TKLINE_EXPIRE_NOTICES '=' TBOOL ';'
3214 {
3215 ConfigFileEntry.tkline_expire_notices = yylval.number;
3216 };
3217
3218 general_kill_chase_time_limit: KILL_CHASE_TIME_LIMIT '=' NUMBER ';'
3219 {
3220 ConfigFileEntry.kill_chase_time_limit = $3;
3221 };
3222
3223 general_hide_spoof_ips: HIDE_SPOOF_IPS '=' TBOOL ';'
3224 {
3225 ConfigFileEntry.hide_spoof_ips = yylval.number;
3226 };
3227
3228 general_ignore_bogus_ts: IGNORE_BOGUS_TS '=' TBOOL ';'
3229 {
3230 ConfigFileEntry.ignore_bogus_ts = yylval.number;
3231 };
3232
3233 general_disable_remote_commands: DISABLE_REMOTE_COMMANDS '=' TBOOL ';'
3234 {
3235 ConfigFileEntry.disable_remote = yylval.number;
3236 };
3237
3238 general_failed_oper_notice: FAILED_OPER_NOTICE '=' TBOOL ';'
3239 {
3240 ConfigFileEntry.failed_oper_notice = yylval.number;
3241 };
3242
3243 general_anti_nick_flood: ANTI_NICK_FLOOD '=' TBOOL ';'
3244 {
3245 ConfigFileEntry.anti_nick_flood = yylval.number;
3246 };
3247
3248 general_max_nick_time: MAX_NICK_TIME '=' timespec ';'
3249 {
3250 ConfigFileEntry.max_nick_time = $3;
3251 };
3252
3253 general_max_nick_changes: MAX_NICK_CHANGES '=' NUMBER ';'
3254 {
3255 ConfigFileEntry.max_nick_changes = $3;
3256 };
3257
3258 general_max_accept: MAX_ACCEPT '=' NUMBER ';'
3259 {
3260 ConfigFileEntry.max_accept = $3;
3261 };
3262
3263 general_anti_spam_exit_message_time: ANTI_SPAM_EXIT_MESSAGE_TIME '=' timespec ';'
3264 {
3265 ConfigFileEntry.anti_spam_exit_message_time = $3;
3266 };
3267
3268 general_ts_warn_delta: TS_WARN_DELTA '=' timespec ';'
3269 {
3270 ConfigFileEntry.ts_warn_delta = $3;
3271 };
3272
3273 general_ts_max_delta: TS_MAX_DELTA '=' timespec ';'
3274 {
3275 if (conf_parser_ctx.pass == 2)
3276 ConfigFileEntry.ts_max_delta = $3;
3277 };
3278
3279 general_havent_read_conf: HAVENT_READ_CONF '=' NUMBER ';'
3280 {
3281 if (($3 > 0) && conf_parser_ctx.pass == 1)
3282 {
3283 ilog(L_CRIT, "You haven't read your config file properly.");
3284 ilog(L_CRIT, "There is a line in the example conf that will kill your server if not removed.");
3285 ilog(L_CRIT, "Consider actually reading/editing the conf file, and removing this line.");
3286 exit(0);
3287 }
3288 };
3289
3290 general_kline_with_reason: KLINE_WITH_REASON '=' TBOOL ';'
3291 {
3292 ConfigFileEntry.kline_with_reason = yylval.number;
3293 };
3294
3295 general_kline_reason: KLINE_REASON '=' QSTRING ';'
3296 {
3297 if (conf_parser_ctx.pass == 2)
3298 {
3299 MyFree(ConfigFileEntry.kline_reason);
3300 DupString(ConfigFileEntry.kline_reason, yylval.string);
3301 }
3302 };
3303
3304 general_invisible_on_connect: INVISIBLE_ON_CONNECT '=' TBOOL ';'
3305 {
3306 ConfigFileEntry.invisible_on_connect = yylval.number;
3307 };
3308
3309 general_warn_no_nline: WARN_NO_NLINE '=' TBOOL ';'
3310 {
3311 ConfigFileEntry.warn_no_nline = yylval.number;
3312 };
3313
3314 general_stats_e_disabled: STATS_E_DISABLED '=' TBOOL ';'
3315 {
3316 ConfigFileEntry.stats_e_disabled = yylval.number;
3317 };
3318
3319 general_stats_o_oper_only: STATS_O_OPER_ONLY '=' TBOOL ';'
3320 {
3321 ConfigFileEntry.stats_o_oper_only = yylval.number;
3322 };
3323
3324 general_stats_P_oper_only: STATS_P_OPER_ONLY '=' TBOOL ';'
3325 {
3326 ConfigFileEntry.stats_P_oper_only = yylval.number;
3327 };
3328
3329 general_stats_k_oper_only: STATS_K_OPER_ONLY '=' TBOOL ';'
3330 {
3331 ConfigFileEntry.stats_k_oper_only = 2 * yylval.number;
3332 } | STATS_K_OPER_ONLY '=' TMASKED ';'
3333 {
3334 ConfigFileEntry.stats_k_oper_only = 1;
3335 };
3336
3337 general_stats_i_oper_only: STATS_I_OPER_ONLY '=' TBOOL ';'
3338 {
3339 ConfigFileEntry.stats_i_oper_only = 2 * yylval.number;
3340 } | STATS_I_OPER_ONLY '=' TMASKED ';'
3341 {
3342 ConfigFileEntry.stats_i_oper_only = 1;
3343 };
3344
3345 general_pace_wait: PACE_WAIT '=' timespec ';'
3346 {
3347 ConfigFileEntry.pace_wait = $3;
3348 };
3349
3350 general_caller_id_wait: CALLER_ID_WAIT '=' timespec ';'
3351 {
3352 ConfigFileEntry.caller_id_wait = $3;
3353 };
3354
3355 general_opers_bypass_callerid: OPERS_BYPASS_CALLERID '=' TBOOL ';'
3356 {
3357 ConfigFileEntry.opers_bypass_callerid = yylval.number;
3358 };
3359
3360 general_pace_wait_simple: PACE_WAIT_SIMPLE '=' timespec ';'
3361 {
3362 ConfigFileEntry.pace_wait_simple = $3;
3363 };
3364
3365 general_short_motd: SHORT_MOTD '=' TBOOL ';'
3366 {
3367 ConfigFileEntry.short_motd = yylval.number;
3368 };
3369
3370 general_no_oper_flood: NO_OPER_FLOOD '=' TBOOL ';'
3371 {
3372 ConfigFileEntry.no_oper_flood = yylval.number;
3373 };
3374
3375 general_true_no_oper_flood: TRUE_NO_OPER_FLOOD '=' TBOOL ';'
3376 {
3377 ConfigFileEntry.true_no_oper_flood = yylval.number;
3378 };
3379
3380 general_oper_pass_resv: OPER_PASS_RESV '=' TBOOL ';'
3381 {
3382 ConfigFileEntry.oper_pass_resv = yylval.number;
3383 };
3384
3385 general_message_locale: MESSAGE_LOCALE '=' QSTRING ';'
3386 {
3387 if (conf_parser_ctx.pass == 2)
3388 {
3389 if (strlen(yylval.string) > LOCALE_LENGTH-2)
3390 yylval.string[LOCALE_LENGTH-1] = '\0';
3391
3392 set_locale(yylval.string);
3393 }
3394 };
3395
3396 general_idletime: IDLETIME '=' timespec ';'
3397 {
3398 ConfigFileEntry.idletime = $3;
3399 };
3400
3401 general_dots_in_ident: DOTS_IN_IDENT '=' NUMBER ';'
3402 {
3403 ConfigFileEntry.dots_in_ident = $3;
3404 };
3405
3406 general_max_targets: MAX_TARGETS '=' NUMBER ';'
3407 {
3408 ConfigFileEntry.max_targets = $3;
3409 };
3410
3411 general_servlink_path: SERVLINK_PATH '=' QSTRING ';'
3412 {
3413 if (conf_parser_ctx.pass == 2)
3414 {
3415 MyFree(ConfigFileEntry.servlink_path);
3416 DupString(ConfigFileEntry.servlink_path, yylval.string);
3417 }
3418 };
3419
3420 general_default_cipher_preference: DEFAULT_CIPHER_PREFERENCE '=' QSTRING ';'
3421 {
3422 #ifdef HAVE_LIBCRYPTO
3423 if (conf_parser_ctx.pass == 2)
3424 {
3425 struct EncCapability *ecap;
3426 const char *cipher_name;
3427 int found = 0;
3428
3429 ConfigFileEntry.default_cipher_preference = NULL;
3430 cipher_name = yylval.string;
3431
3432 for (ecap = CipherTable; ecap->name; ecap++)
3433 {
3434 if ((irccmp(ecap->name, cipher_name) == 0) &&
3435 (ecap->cap & CAP_ENC_MASK))
3436 {
3437 ConfigFileEntry.default_cipher_preference = ecap;
3438 found = 1;
3439 break;
3440 }
3441 }
3442
3443 if (!found)
3444 yyerror("Invalid cipher");
3445 }
3446 #else
3447 if (conf_parser_ctx.pass == 2)
3448 yyerror("Ignoring default_cipher_preference -- no OpenSSL support");
3449 #endif
3450 };
3451
3452 general_compression_level: COMPRESSION_LEVEL '=' NUMBER ';'
3453 {
3454 if (conf_parser_ctx.pass == 2)
3455 {
3456 ConfigFileEntry.compression_level = $3;
3457 #ifndef HAVE_LIBZ
3458 yyerror("Ignoring compression_level -- no zlib support");
3459 #else
3460 if ((ConfigFileEntry.compression_level < 1) ||
3461 (ConfigFileEntry.compression_level > 9))
3462 {
3463 yyerror("Ignoring invalid compression_level, using default");
3464 ConfigFileEntry.compression_level = 0;
3465 }
3466 #endif
3467 }
3468 };
3469
3470 general_use_egd: USE_EGD '=' TBOOL ';'
3471 {
3472 ConfigFileEntry.use_egd = yylval.number;
3473 };
3474
3475 general_egdpool_path: EGDPOOL_PATH '=' QSTRING ';'
3476 {
3477 if (conf_parser_ctx.pass == 2)
3478 {
3479 MyFree(ConfigFileEntry.egdpool_path);
3480 DupString(ConfigFileEntry.egdpool_path, yylval.string);
3481 }
3482 };
3483
3484 general_ping_cookie: PING_COOKIE '=' TBOOL ';'
3485 {
3486 ConfigFileEntry.ping_cookie = yylval.number;
3487 };
3488
3489 general_disable_auth: DISABLE_AUTH '=' TBOOL ';'
3490 {
3491 ConfigFileEntry.disable_auth = yylval.number;
3492 };
3493
3494 general_throttle_time: THROTTLE_TIME '=' timespec ';'
3495 {
3496 ConfigFileEntry.throttle_time = yylval.number;
3497 };
3498
3499 general_oper_umodes: OPER_UMODES
3500 {
3501 ConfigFileEntry.oper_umodes = 0;
3502 } '=' umode_oitems ';' ;
3503
3504 umode_oitems: umode_oitems ',' umode_oitem | umode_oitem;
3505 umode_oitem: T_BOTS
3506 {
3507 ConfigFileEntry.oper_umodes |= UMODE_BOTS;
3508 } | T_CCONN
3509 {
3510 ConfigFileEntry.oper_umodes |= UMODE_CCONN;
3511 } | T_CCONN_FULL
3512 {
3513 ConfigFileEntry.oper_umodes |= UMODE_CCONN_FULL;
3514 } | T_DEAF
3515 {
3516 ConfigFileEntry.oper_umodes |= UMODE_DEAF;
3517 } | T_DEBUG
3518 {
3519 ConfigFileEntry.oper_umodes |= UMODE_DEBUG;
3520 } | T_FULL
3521 {
3522 ConfigFileEntry.oper_umodes |= UMODE_FULL;
3523 } | T_SKILL
3524 {
3525 ConfigFileEntry.oper_umodes |= UMODE_SKILL;
3526 } | T_NCHANGE
3527 {
3528 ConfigFileEntry.oper_umodes |= UMODE_NCHANGE;
3529 } | T_REJ
3530 {
3531 ConfigFileEntry.oper_umodes |= UMODE_REJ;
3532 } | T_UNAUTH
3533 {
3534 ConfigFileEntry.oper_umodes |= UMODE_UNAUTH;
3535 } | T_SPY
3536 {
3537 ConfigFileEntry.oper_umodes |= UMODE_SPY;
3538 } | T_EXTERNAL
3539 {
3540 ConfigFileEntry.oper_umodes |= UMODE_EXTERNAL;
3541 } | T_OPERWALL
3542 {
3543 ConfigFileEntry.oper_umodes |= UMODE_OPERWALL;
3544 } | T_SERVNOTICE
3545 {
3546 ConfigFileEntry.oper_umodes |= UMODE_SERVNOTICE;
3547 } | T_INVISIBLE
3548 {
3549 ConfigFileEntry.oper_umodes |= UMODE_INVISIBLE;
3550 } | T_WALLOP
3551 {
3552 ConfigFileEntry.oper_umodes |= UMODE_WALLOP;
3553 } | T_SOFTCALLERID
3554 {
3555 ConfigFileEntry.oper_umodes |= UMODE_SOFTCALLERID;
3556 } | T_CALLERID
3557 {
3558 ConfigFileEntry.oper_umodes |= UMODE_CALLERID;
3559 } | T_LOCOPS
3560 {
3561 ConfigFileEntry.oper_umodes |= UMODE_LOCOPS;
3562 };
3563
3564 general_oper_only_umodes: OPER_ONLY_UMODES
3565 {
3566 ConfigFileEntry.oper_only_umodes = 0;
3567 } '=' umode_items ';' ;
3568
3569 umode_items: umode_items ',' umode_item | umode_item;
3570 umode_item: T_BOTS
3571 {
3572 ConfigFileEntry.oper_only_umodes |= UMODE_BOTS;
3573 } | T_CCONN
3574 {
3575 ConfigFileEntry.oper_only_umodes |= UMODE_CCONN;
3576 } | T_CCONN_FULL
3577 {
3578 ConfigFileEntry.oper_only_umodes |= UMODE_CCONN_FULL;
3579 } | T_DEAF
3580 {
3581 ConfigFileEntry.oper_only_umodes |= UMODE_DEAF;
3582 } | T_DEBUG
3583 {
3584 ConfigFileEntry.oper_only_umodes |= UMODE_DEBUG;
3585 } | T_FULL
3586 {
3587 ConfigFileEntry.oper_only_umodes |= UMODE_FULL;
3588 } | T_SKILL
3589 {
3590 ConfigFileEntry.oper_only_umodes |= UMODE_SKILL;
3591 } | T_NCHANGE
3592 {
3593 ConfigFileEntry.oper_only_umodes |= UMODE_NCHANGE;
3594 } | T_REJ
3595 {
3596 ConfigFileEntry.oper_only_umodes |= UMODE_REJ;
3597 } | T_UNAUTH
3598 {
3599 ConfigFileEntry.oper_only_umodes |= UMODE_UNAUTH;
3600 } | T_SPY
3601 {
3602 ConfigFileEntry.oper_only_umodes |= UMODE_SPY;
3603 } | T_EXTERNAL
3604 {
3605 ConfigFileEntry.oper_only_umodes |= UMODE_EXTERNAL;
3606 } | T_OPERWALL
3607 {
3608 ConfigFileEntry.oper_only_umodes |= UMODE_OPERWALL;
3609 } | T_SERVNOTICE
3610 {
3611 ConfigFileEntry.oper_only_umodes |= UMODE_SERVNOTICE;
3612 } | T_INVISIBLE
3613 {
3614 ConfigFileEntry.oper_only_umodes |= UMODE_INVISIBLE;
3615 } | T_WALLOP
3616 {
3617 ConfigFileEntry.oper_only_umodes |= UMODE_WALLOP;
3618 } | T_SOFTCALLERID
3619 {
3620 ConfigFileEntry.oper_only_umodes |= UMODE_SOFTCALLERID;
3621 } | T_CALLERID
3622 {
3623 ConfigFileEntry.oper_only_umodes |= UMODE_CALLERID;
3624 } | T_LOCOPS
3625 {
3626 ConfigFileEntry.oper_only_umodes |= UMODE_LOCOPS;
3627 };
3628
3629 general_min_nonwildcard: MIN_NONWILDCARD '=' NUMBER ';'
3630 {
3631 ConfigFileEntry.min_nonwildcard = $3;
3632 };
3633
3634 general_min_nonwildcard_simple: MIN_NONWILDCARD_SIMPLE '=' NUMBER ';'
3635 {
3636 ConfigFileEntry.min_nonwildcard_simple = $3;
3637 };
3638
3639 general_default_floodcount: DEFAULT_FLOODCOUNT '=' NUMBER ';'
3640 {
3641 ConfigFileEntry.default_floodcount = $3;
3642 };
3643
3644 general_client_flood: T_CLIENT_FLOOD '=' sizespec ';'
3645 {
3646 ConfigFileEntry.client_flood = $3;
3647 };
3648
3649 general_dot_in_ip6_addr: DOT_IN_IP6_ADDR '=' TBOOL ';'
3650 {
3651 ConfigFileEntry.dot_in_ip6_addr = yylval.number;
3652 };
3653
3654 /***************************************************************************
3655 * section glines
3656 ***************************************************************************/
3657 gline_entry: GLINES
3658 {
3659 if (conf_parser_ctx.pass == 2)
3660 {
3661 yy_conf = make_conf_item(GDENY_TYPE);
3662 yy_aconf = map_to_conf(yy_conf);
3663 }
3664 } '{' gline_items '}' ';'
3665 {
3666 if (conf_parser_ctx.pass == 2)
3667 {
3668 /*
3669 * since we re-allocate yy_conf/yy_aconf after the end of action=, at the
3670 * end we will have one extra, so we should free it.
3671 */
3672 if (yy_conf->name == NULL || yy_aconf->user == NULL)
3673 {
3674 delete_conf_item(yy_conf);
3675 yy_conf = NULL;
3676 yy_aconf = NULL;
3677 }
3678 }
3679 };
3680
3681 gline_items: gline_items gline_item | gline_item;
3682 gline_item: gline_enable |
3683 gline_duration |
3684 gline_logging |
3685 gline_user |
3686 gline_server |
3687 gline_action |
3688 error;
3689
3690 gline_enable: ENABLE '=' TBOOL ';'
3691 {
3692 if (conf_parser_ctx.pass == 2)
3693 ConfigFileEntry.glines = yylval.number;
3694 };
3695
3696 gline_duration: DURATION '=' timespec ';'
3697 {
3698 if (conf_parser_ctx.pass == 2)
3699 ConfigFileEntry.gline_time = $3;
3700 };
3701
3702 gline_logging: LOGGING
3703 {
3704 if (conf_parser_ctx.pass == 2)
3705 ConfigFileEntry.gline_logging = 0;
3706 } '=' gline_logging_types ';';
3707 gline_logging_types: gline_logging_types ',' gline_logging_type_item | gline_logging_type_item;
3708 gline_logging_type_item: T_REJECT
3709 {
3710 if (conf_parser_ctx.pass == 2)
3711 ConfigFileEntry.gline_logging |= GDENY_REJECT;
3712 } | T_BLOCK
3713 {
3714 if (conf_parser_ctx.pass == 2)
3715 ConfigFileEntry.gline_logging |= GDENY_BLOCK;
3716 };
3717
3718 gline_user: USER '=' QSTRING ';'
3719 {
3720 if (conf_parser_ctx.pass == 2)
3721 {
3722 struct split_nuh_item nuh;
3723
3724 nuh.nuhmask = yylval.string;
3725 nuh.nickptr = NULL;
3726 nuh.userptr = userbuf;
3727 nuh.hostptr = hostbuf;
3728
3729 nuh.nicksize = 0;
3730 nuh.usersize = sizeof(userbuf);
3731 nuh.hostsize = sizeof(hostbuf);
3732
3733 split_nuh(&nuh);
3734
3735 if (yy_aconf->user == NULL)
3736 {
3737 DupString(yy_aconf->user, userbuf);
3738 DupString(yy_aconf->host, hostbuf);
3739 }
3740 else
3741 {
3742 struct CollectItem *yy_tmp = MyMalloc(sizeof(struct CollectItem));
3743
3744 DupString(yy_tmp->user, userbuf);
3745 DupString(yy_tmp->host, hostbuf);
3746
3747 dlinkAdd(yy_tmp, &yy_tmp->node, &col_conf_list);
3748 }
3749 }
3750 };
3751
3752 gline_server: NAME '=' QSTRING ';'
3753 {
3754 if (conf_parser_ctx.pass == 2)
3755 {
3756 MyFree(yy_conf->name);
3757 DupString(yy_conf->name, yylval.string);
3758 }
3759 };
3760
3761 gline_action: ACTION
3762 {
3763 if (conf_parser_ctx.pass == 2)
3764 yy_aconf->flags = 0;
3765 } '=' gdeny_types ';'
3766 {
3767 if (conf_parser_ctx.pass == 2)
3768 {
3769 struct CollectItem *yy_tmp = NULL;
3770 dlink_node *ptr, *next_ptr;
3771
3772 DLINK_FOREACH_SAFE(ptr, next_ptr, col_conf_list.head)
3773 {
3774 struct AccessItem *new_aconf;
3775 struct ConfItem *new_conf;
3776
3777 yy_tmp = ptr->data;
3778 new_conf = make_conf_item(GDENY_TYPE);
3779 new_aconf = map_to_conf(new_conf);
3780
3781 new_aconf->flags = yy_aconf->flags;
3782
3783 if (yy_conf->name != NULL)
3784 DupString(new_conf->name, yy_conf->name);
3785 else
3786 DupString(new_conf->name, "*");
3787 if (yy_aconf->user != NULL)
3788 DupString(new_aconf->user, yy_tmp->user);
3789 else
3790 DupString(new_aconf->user, "*");
3791 if (yy_aconf->host != NULL)
3792 DupString(new_aconf->host, yy_tmp->host);
3793 else
3794 DupString(new_aconf->host, "*");
3795
3796 dlinkDelete(&yy_tmp->node, &col_conf_list);
3797 }
3798
3799 /*
3800 * In case someone has fed us with more than one action= after user/name
3801 * which would leak memory -Michael
3802 */
3803 if (yy_conf->name == NULL || yy_aconf->user == NULL)
3804 delete_conf_item(yy_conf);
3805
3806 yy_conf = make_conf_item(GDENY_TYPE);
3807 yy_aconf = map_to_conf(yy_conf);
3808 }
3809 };
3810
3811 gdeny_types: gdeny_types ',' gdeny_type_item | gdeny_type_item;
3812 gdeny_type_item: T_REJECT
3813 {
3814 if (conf_parser_ctx.pass == 2)
3815 yy_aconf->flags |= GDENY_REJECT;
3816 } | T_BLOCK
3817 {
3818 if (conf_parser_ctx.pass == 2)
3819 yy_aconf->flags |= GDENY_BLOCK;
3820 };
3821
3822 /***************************************************************************
3823 * section channel
3824 ***************************************************************************/
3825 channel_entry: CHANNEL
3826 '{' channel_items '}' ';';
3827
3828 channel_items: channel_items channel_item | channel_item;
3829 channel_item: channel_disable_local_channels | channel_use_except |
3830 channel_use_invex | channel_use_knock |
3831 channel_max_bans | channel_knock_delay |
3832 channel_knock_delay_channel | channel_max_chans_per_user |
3833 channel_quiet_on_ban | channel_default_split_user_count |
3834 channel_default_split_server_count |
3835 channel_no_create_on_split | channel_restrict_channels |
3836 channel_no_join_on_split | channel_burst_topicwho |
3837 channel_jflood_count | channel_jflood_time |
3838 channel_disable_fake_channels | error;
3839
3840 channel_disable_fake_channels: DISABLE_FAKE_CHANNELS '=' TBOOL ';'
3841 {
3842 ConfigChannel.disable_fake_channels = yylval.number;
3843 };
3844
3845 channel_restrict_channels: RESTRICT_CHANNELS '=' TBOOL ';'
3846 {
3847 ConfigChannel.restrict_channels = yylval.number;
3848 };
3849
3850 channel_disable_local_channels: DISABLE_LOCAL_CHANNELS '=' TBOOL ';'
3851 {
3852 ConfigChannel.disable_local_channels = yylval.number;
3853 };
3854
3855 channel_use_except: USE_EXCEPT '=' TBOOL ';'