/[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 595 - (show annotations)
Fri May 12 21:17:16 2006 UTC (14 years, 3 months ago) by michael
File size: 90226 byte(s)
- Backported core fix for regexp k-lines

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