1 |
/* |
2 |
* Copyright (c) 2002-2003 Erik Fears |
3 |
* Copyright (c) 2014-2017 ircd-hybrid development team |
4 |
* |
5 |
* This program is free software; you can redistribute it and/or modify |
6 |
* it under the terms of the GNU General Public License as published by |
7 |
* the Free Software Foundation; either version 2 of the License, or |
8 |
* (at your option) any later version. |
9 |
* |
10 |
* This program is distributed in the hope that it will be useful, |
11 |
* but WITHOUT ANY WARRANTY; without even the implied warranty of |
12 |
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
13 |
* GNU General Public License for more details. |
14 |
* |
15 |
* You should have received a copy of the GNU General Public License |
16 |
* along with this program; if not, write to the Free Software |
17 |
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 |
18 |
* USA |
19 |
*/ |
20 |
|
21 |
%{ |
22 |
#include <string.h> |
23 |
|
24 |
#include "memory.h" |
25 |
#include "config.h" |
26 |
|
27 |
int yylex(void); |
28 |
|
29 |
static void *tmp; /* Variable to temporarily hold nodes before insertion to list */ |
30 |
|
31 |
%} |
32 |
|
33 |
%token ADDRESS_FAMILY |
34 |
%token AWAY |
35 |
%token BAN_UNKNOWN |
36 |
%token BLACKLIST |
37 |
%token BYTES KBYTES MBYTES |
38 |
%token CHANNEL |
39 |
%token COMMAND_INTERVAL |
40 |
%token COMMAND_QUEUE_SIZE |
41 |
%token COMMAND_TIMEOUT |
42 |
%token CONNREGEX |
43 |
%token DNS_FDLIMIT |
44 |
%token DNS_TIMEOUT |
45 |
%token DNSBL_FROM |
46 |
%token DNSBL_TO |
47 |
%token EXEMPT |
48 |
%token FD |
49 |
%token INVITE |
50 |
%token IPV4 |
51 |
%token IPV6 |
52 |
%token IRC |
53 |
%token KLINE |
54 |
%token KEY |
55 |
%token MASK |
56 |
%token MAX_READ |
57 |
%token MODE |
58 |
%token NAME |
59 |
%token NEGCACHE |
60 |
%token NEGCACHE_REBUILD |
61 |
%token NICK |
62 |
%token NICKSERV |
63 |
%token NOTICE |
64 |
%token OPER |
65 |
%token OPM |
66 |
%token OPTIONS |
67 |
%token PASSWORD |
68 |
%token PERFORM |
69 |
%token PIDFILE |
70 |
%token PORT |
71 |
%token PROTOCOL |
72 |
%token READTIMEOUT |
73 |
%token REALNAME |
74 |
%token RECONNECTINTERVAL |
75 |
%token REPLY |
76 |
%token SCANLOG |
77 |
%token SCANNER |
78 |
%token SECONDS MINUTES HOURS DAYS WEEKS MONTHS YEARS |
79 |
%token SENDMAIL |
80 |
%token SERVER |
81 |
%token TARGET_IP |
82 |
%token TARGET_PORT |
83 |
%token TARGET_STRING |
84 |
%token TIMEOUT |
85 |
%token TYPE |
86 |
%token USERNAME |
87 |
%token USER |
88 |
%token VHOST |
89 |
|
90 |
%union |
91 |
{ |
92 |
int number; |
93 |
char *string; |
94 |
} |
95 |
|
96 |
%token <number> NUMBER |
97 |
%token <string> STRING |
98 |
%token <number> PROTOCOLTYPE |
99 |
%type <number> timespec |
100 |
%type <number> timespec_ |
101 |
%type <number> sizespec |
102 |
%type <number> sizespec_ |
103 |
|
104 |
%% |
105 |
|
106 |
config: |
107 |
| config config_items |
108 |
; |
109 |
|
110 |
config_items: irc_entry | |
111 |
options_entry | |
112 |
opm_entry | |
113 |
user_entry | |
114 |
scanner_entry | |
115 |
exempt_entry; |
116 |
|
117 |
timespec_: { $$ = 0; } | timespec; |
118 |
timespec: NUMBER timespec_ { $$ = $1 + $2; } | |
119 |
NUMBER SECONDS timespec_ { $$ = $1 + $3; } | |
120 |
NUMBER MINUTES timespec_ { $$ = $1 * 60 + $3; } | |
121 |
NUMBER HOURS timespec_ { $$ = $1 * 60 * 60 + $3; } | |
122 |
NUMBER DAYS timespec_ { $$ = $1 * 60 * 60 * 24 + $3; } | |
123 |
NUMBER WEEKS timespec_ { $$ = $1 * 60 * 60 * 24 * 7 + $3; } | |
124 |
NUMBER MONTHS timespec_ { $$ = $1 * 60 * 60 * 24 * 7 * 4 + $3; } | |
125 |
NUMBER YEARS timespec_ { $$ = $1 * 60 * 60 * 24 * 365 + $3; } |
126 |
; |
127 |
|
128 |
sizespec_: { $$ = 0; } | sizespec; |
129 |
sizespec: NUMBER sizespec_ { $$ = $1 + $2; } | |
130 |
NUMBER BYTES sizespec_ { $$ = $1 + $3; } | |
131 |
NUMBER KBYTES sizespec_ { $$ = $1 * 1024 + $3; } | |
132 |
NUMBER MBYTES sizespec_ { $$ = $1 * 1024 * 1024 + $3; } |
133 |
; |
134 |
|
135 |
|
136 |
/*************************** OPTIONS BLOCK ***********************/ |
137 |
options_entry: OPTIONS '{' options_items '}' ';'; |
138 |
|
139 |
options_items: options_items options_item | |
140 |
options_item; |
141 |
|
142 |
options_item: options_negcache | |
143 |
options_negcache_rebuild | |
144 |
options_pidfile | |
145 |
options_dns_fdlimit | |
146 |
options_dns_timeout | |
147 |
options_scanlog | |
148 |
options_command_queue_size | |
149 |
options_command_interval | |
150 |
options_command_timeout | |
151 |
error; |
152 |
|
153 |
options_negcache: NEGCACHE '=' timespec ';' |
154 |
{ |
155 |
OptionsItem->negcache = $3; |
156 |
}; |
157 |
|
158 |
options_negcache_rebuild: NEGCACHE_REBUILD '=' timespec ';' |
159 |
{ |
160 |
OptionsItem->negcache_rebuild = $3; |
161 |
}; |
162 |
|
163 |
options_pidfile: PIDFILE '=' STRING ';' |
164 |
{ |
165 |
xfree(OptionsItem->pidfile); |
166 |
OptionsItem->pidfile = xstrdup($3); |
167 |
}; |
168 |
|
169 |
options_dns_fdlimit: DNS_FDLIMIT '=' NUMBER ';' |
170 |
{ |
171 |
OptionsItem->dns_fdlimit = $3; |
172 |
}; |
173 |
|
174 |
options_dns_timeout: DNS_TIMEOUT '=' timespec ';' |
175 |
{ |
176 |
OptionsItem->dns_timeout = $3; |
177 |
}; |
178 |
|
179 |
options_scanlog: SCANLOG '=' STRING ';' |
180 |
{ |
181 |
xfree(OptionsItem->scanlog); |
182 |
OptionsItem->scanlog = xstrdup($3); |
183 |
}; |
184 |
|
185 |
options_command_queue_size: COMMAND_QUEUE_SIZE '=' NUMBER ';' |
186 |
{ |
187 |
OptionsItem->command_queue_size = $3; |
188 |
}; |
189 |
|
190 |
options_command_interval: COMMAND_INTERVAL '=' timespec ';' |
191 |
{ |
192 |
OptionsItem->command_interval = $3; |
193 |
}; |
194 |
|
195 |
options_command_timeout: COMMAND_TIMEOUT '=' timespec ';' |
196 |
{ |
197 |
OptionsItem->command_timeout = $3; |
198 |
}; |
199 |
|
200 |
|
201 |
/*************************** IRC BLOCK ***************************/ |
202 |
irc_entry: IRC '{' irc_items '}' ';'; |
203 |
|
204 |
irc_items: irc_items irc_item | |
205 |
irc_item; |
206 |
|
207 |
irc_item: irc_away | |
208 |
irc_connregex | |
209 |
irc_kline | |
210 |
irc_nick | |
211 |
irc_nickserv | |
212 |
irc_mode | |
213 |
irc_oper | |
214 |
irc_password | |
215 |
irc_port | |
216 |
irc_readtimeout | |
217 |
irc_reconnectinterval | |
218 |
irc_realname | |
219 |
irc_server | |
220 |
irc_username | |
221 |
irc_vhost | |
222 |
irc_perform | |
223 |
irc_notice | |
224 |
channel_entry | |
225 |
error; |
226 |
|
227 |
irc_away: AWAY '=' STRING ';' |
228 |
{ |
229 |
xfree(IRCItem->away); |
230 |
IRCItem->away = xstrdup($3); |
231 |
}; |
232 |
|
233 |
irc_kline: KLINE '=' STRING ';' |
234 |
{ |
235 |
xfree(IRCItem->kline); |
236 |
IRCItem->kline = xstrdup($3); |
237 |
}; |
238 |
|
239 |
irc_mode: MODE '=' STRING ';' |
240 |
{ |
241 |
xfree(IRCItem->mode); |
242 |
IRCItem->mode = xstrdup($3); |
243 |
}; |
244 |
|
245 |
irc_nick: NICK '=' STRING ';' |
246 |
{ |
247 |
xfree(IRCItem->nick); |
248 |
IRCItem->nick = xstrdup($3); |
249 |
}; |
250 |
|
251 |
irc_nickserv: NICKSERV '=' STRING ';' |
252 |
{ |
253 |
xfree(IRCItem->nickserv); |
254 |
IRCItem->nickserv = xstrdup($3); |
255 |
}; |
256 |
|
257 |
irc_oper: OPER '=' STRING ';' |
258 |
{ |
259 |
xfree(IRCItem->oper); |
260 |
IRCItem->oper = xstrdup($3); |
261 |
}; |
262 |
|
263 |
irc_password: PASSWORD '=' STRING ';' |
264 |
{ |
265 |
xfree(IRCItem->password); |
266 |
IRCItem->password = xstrdup($3); |
267 |
}; |
268 |
|
269 |
irc_perform: PERFORM '=' STRING ';' |
270 |
{ |
271 |
node_t *node; |
272 |
|
273 |
node = node_create(xstrdup($3)); |
274 |
list_add(IRCItem->performs, node); |
275 |
}; |
276 |
|
277 |
irc_notice: NOTICE '=' STRING ';' |
278 |
{ |
279 |
node_t *node; |
280 |
|
281 |
node = node_create(xstrdup($3)); |
282 |
list_add(IRCItem->notices, node); |
283 |
}; |
284 |
|
285 |
irc_port: PORT '=' NUMBER ';' |
286 |
{ |
287 |
IRCItem->port = $3; |
288 |
}; |
289 |
|
290 |
irc_readtimeout: READTIMEOUT '=' timespec ';' |
291 |
{ |
292 |
IRCItem->readtimeout = $3; |
293 |
}; |
294 |
|
295 |
irc_reconnectinterval: RECONNECTINTERVAL '=' timespec ';' |
296 |
{ |
297 |
IRCItem->reconnectinterval = $3; |
298 |
}; |
299 |
|
300 |
irc_realname: REALNAME '=' STRING ';' |
301 |
{ |
302 |
xfree(IRCItem->realname); |
303 |
IRCItem->realname = xstrdup($3); |
304 |
}; |
305 |
|
306 |
irc_server: SERVER '=' STRING ';' |
307 |
{ |
308 |
xfree(IRCItem->server); |
309 |
IRCItem->server = xstrdup($3); |
310 |
}; |
311 |
|
312 |
irc_username: USERNAME '=' STRING ';' |
313 |
{ |
314 |
xfree(IRCItem->username); |
315 |
IRCItem->username = xstrdup($3); |
316 |
}; |
317 |
|
318 |
irc_vhost: VHOST '=' STRING ';' |
319 |
{ |
320 |
xfree(IRCItem->vhost); |
321 |
IRCItem->vhost = xstrdup($3); |
322 |
}; |
323 |
|
324 |
irc_connregex: CONNREGEX '=' STRING ';' |
325 |
{ |
326 |
xfree(IRCItem->connregex); |
327 |
IRCItem->connregex = xstrdup($3); |
328 |
}; |
329 |
|
330 |
|
331 |
/************************** CHANNEL BLOCK *************************/ |
332 |
channel_entry: |
333 |
{ |
334 |
node_t *node; |
335 |
struct ChannelConf *item; |
336 |
|
337 |
item = xcalloc(sizeof(*item)); |
338 |
item->name = xstrdup(""); |
339 |
item->key = xstrdup(""); |
340 |
item->invite = xstrdup(""); |
341 |
|
342 |
node = node_create(item); |
343 |
|
344 |
list_add(IRCItem->channels, node); |
345 |
tmp = item; |
346 |
} |
347 |
CHANNEL '{' channel_items '}' ';'; |
348 |
|
349 |
channel_items: channel_items channel_item | |
350 |
channel_item; |
351 |
|
352 |
channel_item: channel_name | |
353 |
channel_key | |
354 |
channel_invite; |
355 |
|
356 |
channel_name: NAME '=' STRING ';' |
357 |
{ |
358 |
struct ChannelConf *item = tmp; |
359 |
|
360 |
xfree(item->name); |
361 |
item->name = xstrdup($3); |
362 |
}; |
363 |
|
364 |
channel_key: KEY '=' STRING ';' |
365 |
{ |
366 |
struct ChannelConf *item = tmp; |
367 |
|
368 |
xfree(item->key); |
369 |
item->key = xstrdup($3); |
370 |
}; |
371 |
|
372 |
channel_invite: INVITE '=' STRING ';' |
373 |
{ |
374 |
struct ChannelConf *item = tmp; |
375 |
|
376 |
xfree(item->invite); |
377 |
item->invite = xstrdup($3); |
378 |
}; |
379 |
|
380 |
|
381 |
/*************************** USER BLOCK ***************************/ |
382 |
user_entry: |
383 |
{ |
384 |
node_t *node; |
385 |
struct UserConf *item; |
386 |
|
387 |
item = xcalloc(sizeof(*item)); |
388 |
item->masks = list_create(); |
389 |
item->scanners = list_create(); |
390 |
|
391 |
node = node_create(item); |
392 |
|
393 |
list_add(UserItemList, node); |
394 |
tmp = item; |
395 |
} |
396 |
USER '{' user_items '}' ';' ; |
397 |
|
398 |
user_items: user_items user_item | |
399 |
user_item; |
400 |
|
401 |
user_item: user_mask | |
402 |
user_scanner | |
403 |
error; |
404 |
|
405 |
user_mask: MASK '=' STRING ';' |
406 |
{ |
407 |
struct UserConf *item = tmp; |
408 |
node_t *node; |
409 |
|
410 |
node = node_create(xstrdup($3)); |
411 |
|
412 |
list_add(item->masks, node); |
413 |
}; |
414 |
|
415 |
user_scanner: SCANNER '=' STRING ';' |
416 |
{ |
417 |
struct UserConf *item = tmp; |
418 |
node_t *node; |
419 |
|
420 |
node = node_create(xstrdup($3)); |
421 |
|
422 |
list_add(item->scanners, node); |
423 |
}; |
424 |
|
425 |
|
426 |
/*************************** SCANNER BLOCK ***************************/ |
427 |
scanner_entry: |
428 |
{ |
429 |
node_t *node; |
430 |
struct ScannerConf *item, *olditem; |
431 |
|
432 |
item = xcalloc(sizeof(*item)); |
433 |
|
434 |
/* Setup ScannerConf defaults */ |
435 |
item->name = xstrdup("undefined"); |
436 |
|
437 |
if (LIST_SIZE(ScannerItemList) > 0) |
438 |
{ |
439 |
olditem = ScannerItemList->tail->data; |
440 |
|
441 |
item->vhost = xstrdup(olditem->vhost); |
442 |
item->fd = olditem->fd; |
443 |
item->target_ip = xstrdup(olditem->target_ip); |
444 |
item->target_port = olditem->target_port; |
445 |
item->timeout = olditem->timeout; |
446 |
item->max_read = olditem->max_read; |
447 |
item->target_string = olditem->target_string; |
448 |
item->target_string_created = 0; |
449 |
} |
450 |
else |
451 |
{ |
452 |
item->vhost = xstrdup("0.0.0.0"); |
453 |
item->fd = 512; |
454 |
item->target_ip = xstrdup("127.0.0.1"); |
455 |
item->target_port = 6667; |
456 |
item->timeout = 30; |
457 |
item->max_read = 4096; |
458 |
item->target_string = list_create(); |
459 |
item->target_string_created = 1; |
460 |
} |
461 |
|
462 |
item->protocols = list_create(); |
463 |
|
464 |
node = node_create(item); |
465 |
|
466 |
list_add(ScannerItemList, node); |
467 |
tmp = item; |
468 |
} |
469 |
SCANNER '{' scanner_items '}' ';' ; |
470 |
|
471 |
scanner_items: scanner_items scanner_item | |
472 |
scanner_item; |
473 |
|
474 |
scanner_item: scanner_name | |
475 |
scanner_vhost | |
476 |
scanner_fd | |
477 |
scanner_target_ip | |
478 |
scanner_target_port | |
479 |
scanner_target_string | |
480 |
scanner_protocol | |
481 |
scanner_timeout | |
482 |
scanner_max_read | |
483 |
error; |
484 |
|
485 |
scanner_name: NAME '=' STRING ';' |
486 |
{ |
487 |
struct ScannerConf *item = tmp; |
488 |
|
489 |
xfree(item->name); |
490 |
item->name = xstrdup($3); |
491 |
}; |
492 |
|
493 |
scanner_vhost: VHOST '=' STRING ';' |
494 |
{ |
495 |
struct ScannerConf *item = tmp; |
496 |
|
497 |
xfree(item->vhost); |
498 |
item->vhost = xstrdup($3); |
499 |
}; |
500 |
|
501 |
scanner_target_ip: TARGET_IP '=' STRING ';' |
502 |
{ |
503 |
struct ScannerConf *item = tmp; |
504 |
|
505 |
xfree(item->target_ip); |
506 |
item->target_ip = xstrdup($3); |
507 |
}; |
508 |
|
509 |
scanner_target_string: TARGET_STRING '=' STRING ';' |
510 |
{ |
511 |
struct ScannerConf *item = tmp; |
512 |
node_t *node; |
513 |
|
514 |
node = node_create(xstrdup($3)); |
515 |
|
516 |
if (item->target_string_created == 0) |
517 |
{ |
518 |
item->target_string = list_create(); |
519 |
item->target_string_created = 1; |
520 |
} |
521 |
|
522 |
list_add(item->target_string, node); |
523 |
}; |
524 |
|
525 |
scanner_fd: FD '=' NUMBER ';' |
526 |
{ |
527 |
struct ScannerConf *item = tmp; |
528 |
|
529 |
item->fd = $3; |
530 |
}; |
531 |
|
532 |
scanner_target_port: TARGET_PORT '=' NUMBER ';' |
533 |
{ |
534 |
struct ScannerConf *item = tmp; |
535 |
|
536 |
item->target_port = $3; |
537 |
}; |
538 |
|
539 |
scanner_timeout: TIMEOUT '=' timespec ';' |
540 |
{ |
541 |
struct ScannerConf *item = tmp; |
542 |
|
543 |
item->timeout = $3; |
544 |
}; |
545 |
|
546 |
scanner_max_read: MAX_READ '=' sizespec ';' |
547 |
{ |
548 |
struct ScannerConf *item = tmp; |
549 |
|
550 |
item->max_read = $3; |
551 |
}; |
552 |
|
553 |
scanner_protocol: PROTOCOL '=' PROTOCOLTYPE ':' NUMBER ';' |
554 |
{ |
555 |
struct ProtocolConf *item; |
556 |
struct ScannerConf *item2; |
557 |
node_t *node; |
558 |
|
559 |
item = xcalloc(sizeof(*item)); |
560 |
item->type = $3; |
561 |
item->port = $5; |
562 |
|
563 |
item2 = tmp; |
564 |
|
565 |
node = node_create(item); |
566 |
list_add(item2->protocols, node); |
567 |
}; |
568 |
|
569 |
|
570 |
/*************************** OPM BLOCK ***************************/ |
571 |
opm_entry: OPM '{' opm_items '}' ';' ; |
572 |
|
573 |
opm_items: opm_items opm_item | |
574 |
opm_item; |
575 |
|
576 |
opm_item: opm_dnsbl_from | |
577 |
opm_dnsbl_to | |
578 |
opm_sendmail | |
579 |
opm_blacklist_entry | |
580 |
error; |
581 |
|
582 |
opm_dnsbl_from: DNSBL_FROM '=' STRING ';' |
583 |
{ |
584 |
xfree(OpmItem->dnsbl_from); |
585 |
OpmItem->dnsbl_from = xstrdup($3); |
586 |
}; |
587 |
|
588 |
opm_dnsbl_to: DNSBL_TO '=' STRING ';' |
589 |
{ |
590 |
xfree(OpmItem->dnsbl_to); |
591 |
OpmItem->dnsbl_to = xstrdup($3); |
592 |
}; |
593 |
|
594 |
opm_sendmail: SENDMAIL '=' STRING ';' |
595 |
{ |
596 |
xfree(OpmItem->sendmail); |
597 |
OpmItem->sendmail = xstrdup($3); |
598 |
}; |
599 |
|
600 |
|
601 |
/************************** BLACKLIST BLOCK *************************/ |
602 |
opm_blacklist_entry: |
603 |
{ |
604 |
node_t *node; |
605 |
struct BlacklistConf *item; |
606 |
|
607 |
item = xcalloc(sizeof(*item)); |
608 |
item->name = xstrdup(""); |
609 |
item->kline = xstrdup(""); |
610 |
item->ipv4 = 1; |
611 |
item->ban_unknown = 0; |
612 |
item->type = A_BITMASK; |
613 |
item->reply = list_create(); |
614 |
|
615 |
node = node_create(item); |
616 |
list_add(OpmItem->blacklists, node); |
617 |
|
618 |
tmp = item; |
619 |
} |
620 |
BLACKLIST '{' blacklist_items '}' ';'; |
621 |
|
622 |
blacklist_items: blacklist_items blacklist_item | |
623 |
blacklist_item; |
624 |
|
625 |
blacklist_item: blacklist_name | |
626 |
blacklist_address_family | |
627 |
blacklist_type | |
628 |
blacklist_kline | |
629 |
blacklist_ban_unknown | |
630 |
blacklist_reply | |
631 |
error; |
632 |
|
633 |
blacklist_name: NAME '=' STRING ';' |
634 |
{ |
635 |
struct BlacklistConf *item = tmp; |
636 |
|
637 |
xfree(item->name); |
638 |
item->name = xstrdup($3); |
639 |
}; |
640 |
|
641 |
blacklist_address_family: ADDRESS_FAMILY |
642 |
{ |
643 |
struct BlacklistConf *item = tmp; |
644 |
|
645 |
item->ipv4 = 0; |
646 |
item->ipv6 = 0; |
647 |
} '=' blacklist_address_family_items ';' ; |
648 |
|
649 |
blacklist_address_family_items: blacklist_address_family_items ',' blacklist_address_family_item | blacklist_address_family_item; |
650 |
blacklist_address_family_item: IPV4 |
651 |
{ |
652 |
struct BlacklistConf *item = tmp; |
653 |
|
654 |
item->ipv4 = 1; |
655 |
} | IPV6 |
656 |
{ |
657 |
struct BlacklistConf *item = tmp; |
658 |
|
659 |
item->ipv6 = 1; |
660 |
}; |
661 |
|
662 |
blacklist_kline: KLINE '=' STRING ';' |
663 |
{ |
664 |
struct BlacklistConf *item = tmp; |
665 |
|
666 |
xfree(item->kline); |
667 |
item->kline = xstrdup($3); |
668 |
}; |
669 |
|
670 |
blacklist_type: TYPE '=' STRING ';' |
671 |
{ |
672 |
struct BlacklistConf *item = tmp; |
673 |
|
674 |
if (strcmp("A record bitmask", $3) == 0) |
675 |
item->type = A_BITMASK; |
676 |
else if (strcmp("A record reply", $3) == 0) |
677 |
item->type = A_REPLY; |
678 |
else |
679 |
yyerror("Unknown blacklist type defined"); |
680 |
}; |
681 |
|
682 |
blacklist_ban_unknown: BAN_UNKNOWN '=' NUMBER ';' |
683 |
{ |
684 |
struct BlacklistConf *item = tmp; |
685 |
|
686 |
item->ban_unknown = $3; |
687 |
}; |
688 |
|
689 |
blacklist_reply: REPLY '{' blacklist_reply_items '}' ';'; |
690 |
|
691 |
blacklist_reply_items: blacklist_reply_items blacklist_reply_item | |
692 |
blacklist_reply_item; |
693 |
|
694 |
blacklist_reply_item: NUMBER '=' STRING ';' |
695 |
{ |
696 |
struct BlacklistReplyConf *item; |
697 |
struct BlacklistConf *blacklist = tmp; |
698 |
node_t *node; |
699 |
|
700 |
item = xcalloc(sizeof(*item)); |
701 |
item->number = $1; |
702 |
item->type = xstrdup($3); |
703 |
|
704 |
node = node_create(item); |
705 |
list_add(blacklist->reply, node); |
706 |
}; |
707 |
|
708 |
|
709 |
/*************************** EXEMPT BLOCK ***************************/ |
710 |
exempt_entry: EXEMPT '{' exempt_items '}' ';' ; |
711 |
|
712 |
exempt_items: exempt_items exempt_item | |
713 |
exempt_item; |
714 |
|
715 |
exempt_item: exempt_mask | |
716 |
error; |
717 |
|
718 |
exempt_mask: MASK '=' STRING ';' |
719 |
{ |
720 |
node_t *node; |
721 |
node = node_create(xstrdup($3)); |
722 |
|
723 |
list_add(ExemptItem->masks, node); |
724 |
}; |
725 |
|
726 |
%% |