1%{ 2/* 3 * (C) 2006-2009 by Pablo Neira Ayuso <pablo@netfilter.org> 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., 675 Mass Ave, Cambridge, MA 02139, USA. 18 * 19 * Description: configuration file abstract grammar 20 */ 21 22#include <stdio.h> 23#include <stdlib.h> 24#include <string.h> 25#include <netdb.h> 26#include <errno.h> 27#include <stdarg.h> 28#include "conntrackd.h" 29#include "bitops.h" 30#include "cidr.h" 31#include "helper.h" 32#include "stack.h" 33#include <syslog.h> 34#include <sched.h> 35#include <dlfcn.h> 36#include <libnetfilter_conntrack/libnetfilter_conntrack.h> 37#include <libnetfilter_conntrack/libnetfilter_conntrack_tcp.h> 38 39extern char *yytext; 40extern int yylineno; 41 42struct ct_conf conf; 43 44enum { 45 CTD_CFG_ERROR = 0, 46 CTD_CFG_WARN, 47}; 48 49static void print_err(int err, const char *msg, ...); 50 51static void __kernel_filter_start(void); 52static void __kernel_filter_add_state(int value); 53static void __max_dedicated_links_reached(void); 54 55struct stack symbol_stack; 56 57enum { 58 SYMBOL_HELPER_QUEUE_NUM, 59 SYMBOL_HELPER_QUEUE_LEN, 60 SYMBOL_HELPER_POLICY_EXPECT_ROOT, 61 SYMBOL_HELPER_EXPECT_POLICY_LEAF, 62}; 63 64%} 65 66%union { 67 int val; 68 char *string; 69} 70 71%token T_IPV4_ADDR T_IPV4_IFACE T_PORT T_HASHSIZE T_HASHLIMIT T_MULTICAST 72%token T_PATH T_UNIX T_REFRESH T_IPV6_ADDR T_IPV6_IFACE 73%token T_IGNORE_UDP T_IGNORE_ICMP T_IGNORE_TRAFFIC T_BACKLOG T_GROUP 74%token T_LOG T_UDP T_ICMP T_IGMP T_VRRP T_TCP T_IGNORE_PROTOCOL 75%token T_LOCK T_STRIP_NAT T_BUFFER_SIZE_MAX_GROWN T_EXPIRE T_TIMEOUT 76%token T_GENERAL T_SYNC T_STATS T_RELAX_TRANSITIONS T_BUFFER_SIZE T_DELAY 77%token T_SYNC_MODE T_LISTEN_TO T_FAMILY T_RESEND_BUFFER_SIZE 78%token T_ALARM T_FTFW T_CHECKSUM T_WINDOWSIZE T_ON T_OFF 79%token T_REPLICATE T_FOR T_IFACE T_PURGE T_RESEND_QUEUE_SIZE 80%token T_ESTABLISHED T_SYN_SENT T_SYN_RECV T_FIN_WAIT 81%token T_CLOSE_WAIT T_LAST_ACK T_TIME_WAIT T_CLOSE T_LISTEN 82%token T_SYSLOG T_WRITE_THROUGH T_STAT_BUFFER_SIZE T_DESTROY_TIMEOUT 83%token T_RCVBUFF T_SNDBUFF T_NOTRACK T_POLL_SECS 84%token T_FILTER T_ADDRESS T_PROTOCOL T_STATE T_ACCEPT T_IGNORE 85%token T_FROM T_USERSPACE T_KERNELSPACE T_EVENT_ITER_LIMIT T_DEFAULT 86%token T_NETLINK_OVERRUN_RESYNC T_NICE T_IPV4_DEST_ADDR T_IPV6_DEST_ADDR 87%token T_SCHEDULER T_TYPE T_PRIO T_NETLINK_EVENTS_RELIABLE 88%token T_DISABLE_INTERNAL_CACHE T_DISABLE_EXTERNAL_CACHE T_ERROR_QUEUE_LENGTH 89%token T_OPTIONS T_TCP_WINDOW_TRACKING T_EXPECT_SYNC 90%token T_HELPER T_HELPER_QUEUE_NUM T_HELPER_QUEUE_LEN T_HELPER_POLICY 91%token T_HELPER_EXPECT_TIMEOUT T_HELPER_EXPECT_MAX 92 93%token <string> T_IP T_PATH_VAL 94%token <val> T_NUMBER 95%token <val> T_SIGNED_NUMBER 96%token <string> T_STRING 97 98%% 99 100configfile : 101 | lines 102 ; 103 104lines : line 105 | lines line 106 ; 107 108line : ignore_protocol 109 | ignore_traffic 110 | strip_nat 111 | general 112 | sync 113 | stats 114 | helper 115 ; 116 117logfile_bool : T_LOG T_ON 118{ 119 strncpy(conf.logfile, DEFAULT_LOGFILE, FILENAME_MAXLEN); 120}; 121 122logfile_bool : T_LOG T_OFF 123{ 124}; 125 126logfile_path : T_LOG T_PATH_VAL 127{ 128 strncpy(conf.logfile, $2, FILENAME_MAXLEN); 129}; 130 131syslog_bool : T_SYSLOG T_ON 132{ 133 conf.syslog_facility = DEFAULT_SYSLOG_FACILITY; 134}; 135 136syslog_bool : T_SYSLOG T_OFF 137{ 138 conf.syslog_facility = -1; 139} 140 141syslog_facility : T_SYSLOG T_STRING 142{ 143 if (!strcmp($2, "daemon")) 144 conf.syslog_facility = LOG_DAEMON; 145 else if (!strcmp($2, "local0")) 146 conf.syslog_facility = LOG_LOCAL0; 147 else if (!strcmp($2, "local1")) 148 conf.syslog_facility = LOG_LOCAL1; 149 else if (!strcmp($2, "local2")) 150 conf.syslog_facility = LOG_LOCAL2; 151 else if (!strcmp($2, "local3")) 152 conf.syslog_facility = LOG_LOCAL3; 153 else if (!strcmp($2, "local4")) 154 conf.syslog_facility = LOG_LOCAL4; 155 else if (!strcmp($2, "local5")) 156 conf.syslog_facility = LOG_LOCAL5; 157 else if (!strcmp($2, "local6")) 158 conf.syslog_facility = LOG_LOCAL6; 159 else if (!strcmp($2, "local7")) 160 conf.syslog_facility = LOG_LOCAL7; 161 else { 162 print_err(CTD_CFG_WARN, "'%s' is not a known syslog facility, " 163 "ignoring", $2); 164 break; 165 } 166 167 if (conf.stats.syslog_facility != -1 && 168 conf.syslog_facility != conf.stats.syslog_facility) 169 print_err(CTD_CFG_WARN, "conflicting Syslog facility " 170 "values, defaulting to General"); 171}; 172 173lock : T_LOCK T_PATH_VAL 174{ 175 strncpy(conf.lockfile, $2, FILENAME_MAXLEN); 176}; 177 178strip_nat: T_STRIP_NAT 179{ 180 print_err(CTD_CFG_WARN, "`StripNAT' clause is obsolete, ignoring"); 181}; 182 183refreshtime : T_REFRESH T_NUMBER 184{ 185 conf.refresh = $2; 186}; 187 188expiretime: T_EXPIRE T_NUMBER 189{ 190 conf.cache_timeout = $2; 191}; 192 193timeout: T_TIMEOUT T_NUMBER 194{ 195 conf.commit_timeout = $2; 196}; 197 198purge: T_PURGE T_NUMBER 199{ 200 conf.purge_timeout = $2; 201}; 202 203checksum: T_CHECKSUM T_ON 204{ 205 print_err(CTD_CFG_WARN, "the use of `Checksum' outside the " 206 "`Multicast' clause is ambiguous"); 207 /* 208 * XXX: The use of Checksum outside of the Multicast clause is broken 209 * if we have more than one dedicated links. 210 */ 211 conf.channel[0].u.mcast.checksum = 0; 212}; 213 214checksum: T_CHECKSUM T_OFF 215{ 216 print_err(CTD_CFG_WARN, "the use of `Checksum' outside the " 217 "`Multicast' clause is ambiguous"); 218 /* 219 * XXX: The use of Checksum outside of the Multicast clause is broken 220 * if we have more than one dedicated links. 221 */ 222 conf.channel[0].u.mcast.checksum = 1; 223}; 224 225ignore_traffic : T_IGNORE_TRAFFIC '{' ignore_traffic_options '}' 226{ 227 ct_filter_set_logic(STATE(us_filter), 228 CT_FILTER_ADDRESS, 229 CT_FILTER_NEGATIVE); 230 231 print_err(CTD_CFG_WARN, "the clause `IgnoreTrafficFor' is obsolete. " 232 "Use `Filter' instead"); 233}; 234 235ignore_traffic_options : 236 | ignore_traffic_options ignore_traffic_option; 237 238ignore_traffic_option : T_IPV4_ADDR T_IP 239{ 240 union inet_address ip; 241 242 memset(&ip, 0, sizeof(union inet_address)); 243 244 if (!inet_aton($2, &ip.ipv4)) { 245 print_err(CTD_CFG_WARN, "%s is not a valid IPv4, " 246 "ignoring", $2); 247 break; 248 } 249 250 if (!ct_filter_add_ip(STATE(us_filter), &ip, AF_INET)) { 251 if (errno == EEXIST) 252 print_err(CTD_CFG_WARN, "IP %s is repeated " 253 "in the ignore pool", $2); 254 if (errno == ENOSPC) 255 print_err(CTD_CFG_WARN, "too many IP in the " 256 "ignore pool!"); 257 } 258}; 259 260ignore_traffic_option : T_IPV6_ADDR T_IP 261{ 262 union inet_address ip; 263 264 memset(&ip, 0, sizeof(union inet_address)); 265 266#ifdef HAVE_INET_PTON_IPV6 267 if (inet_pton(AF_INET6, $2, &ip.ipv6) <= 0) { 268 print_err(CTD_CFG_WARN, "%s is not a valid IPv6, ignoring", $2); 269 break; 270 } 271#else 272 print_err(CTD_CFG_WARN, "cannot find inet_pton(), IPv6 unsupported!"); 273#endif 274 275 if (!ct_filter_add_ip(STATE(us_filter), &ip, AF_INET6)) { 276 if (errno == EEXIST) 277 print_err(CTD_CFG_WARN, "IP %s is repeated " 278 "in the ignore pool", $2); 279 if (errno == ENOSPC) 280 print_err(CTD_CFG_WARN, "too many IP in the " 281 "ignore pool!"); 282 } 283 284}; 285 286multicast_line : T_MULTICAST '{' multicast_options '}' 287{ 288 if (conf.channel_type_global != CHANNEL_NONE && 289 conf.channel_type_global != CHANNEL_MCAST) { 290 print_err(CTD_CFG_ERROR, "cannot use `Multicast' with other " 291 "dedicated link protocols!"); 292 exit(EXIT_FAILURE); 293 } 294 conf.channel_type_global = CHANNEL_MCAST; 295 conf.channel[conf.channel_num].channel_type = CHANNEL_MCAST; 296 conf.channel[conf.channel_num].channel_flags = CHANNEL_F_BUFFERED; 297 conf.channel_num++; 298}; 299 300multicast_line : T_MULTICAST T_DEFAULT '{' multicast_options '}' 301{ 302 if (conf.channel_type_global != CHANNEL_NONE && 303 conf.channel_type_global != CHANNEL_MCAST) { 304 print_err(CTD_CFG_ERROR, "cannot use `Multicast' with other " 305 "dedicated link protocols!"); 306 exit(EXIT_FAILURE); 307 } 308 conf.channel_type_global = CHANNEL_MCAST; 309 conf.channel[conf.channel_num].channel_type = CHANNEL_MCAST; 310 conf.channel[conf.channel_num].channel_flags = CHANNEL_F_DEFAULT | 311 CHANNEL_F_BUFFERED; 312 conf.channel_default = conf.channel_num; 313 conf.channel_num++; 314}; 315 316multicast_options : 317 | multicast_options multicast_option; 318 319multicast_option : T_IPV4_ADDR T_IP 320{ 321 __max_dedicated_links_reached(); 322 323 if (!inet_aton($2, &conf.channel[conf.channel_num].u.mcast.in)) { 324 print_err(CTD_CFG_WARN, "%s is not a valid IPv4 address", $2); 325 break; 326 } 327 328 if (conf.channel[conf.channel_num].u.mcast.ipproto == AF_INET6) { 329 print_err(CTD_CFG_WARN, "your multicast address is IPv4 but " 330 "is binded to an IPv6 interface? " 331 "Surely, this is not what you want"); 332 break; 333 } 334 335 conf.channel[conf.channel_num].u.mcast.ipproto = AF_INET; 336}; 337 338multicast_option : T_IPV6_ADDR T_IP 339{ 340 __max_dedicated_links_reached(); 341 342#ifdef HAVE_INET_PTON_IPV6 343 if (inet_pton(AF_INET6, $2, 344 &conf.channel[conf.channel_num].u.mcast.in) <= 0) { 345 print_err(CTD_CFG_WARN, "%s is not a valid IPv6 address", $2); 346 break; 347 } 348#else 349 print_err(CTD_CFG_WARN, "cannot find inet_pton(), IPv6 unsupported!"); 350 break; 351#endif 352 353 if (conf.channel[conf.channel_num].u.mcast.ipproto == AF_INET) { 354 print_err(CTD_CFG_WARN, "your multicast address is IPv6 but " 355 "is binded to an IPv4 interface? " 356 "Surely this is not what you want"); 357 break; 358 } 359 360 conf.channel[conf.channel_num].u.mcast.ipproto = AF_INET6; 361 362 if (conf.channel[conf.channel_num].channel_ifname[0] && 363 !conf.channel[conf.channel_num].u.mcast.ifa.interface_index6) { 364 unsigned int idx; 365 366 idx = if_nametoindex($2); 367 if (!idx) { 368 print_err(CTD_CFG_WARN, 369 "%s is an invalid interface", $2); 370 break; 371 } 372 373 conf.channel[conf.channel_num].u.mcast.ifa.interface_index6 = idx; 374 conf.channel[conf.channel_num].u.mcast.ipproto = AF_INET6; 375 } 376}; 377 378multicast_option : T_IPV4_IFACE T_IP 379{ 380 __max_dedicated_links_reached(); 381 382 if (!inet_aton($2, &conf.channel[conf.channel_num].u.mcast.ifa)) { 383 print_err(CTD_CFG_WARN, "%s is not a valid IPv4 address", $2); 384 break; 385 } 386 387 if (conf.channel[conf.channel_num].u.mcast.ipproto == AF_INET6) { 388 print_err(CTD_CFG_WARN, "your multicast interface is IPv4 but " 389 "is binded to an IPv6 interface? " 390 "Surely, this is not what you want"); 391 break; 392 } 393 394 conf.channel[conf.channel_num].u.mcast.ipproto = AF_INET; 395}; 396 397multicast_option : T_IPV6_IFACE T_IP 398{ 399 print_err(CTD_CFG_WARN, "`IPv6_interface' not required, ignoring"); 400} 401 402multicast_option : T_IFACE T_STRING 403{ 404 unsigned int idx; 405 406 __max_dedicated_links_reached(); 407 408 strncpy(conf.channel[conf.channel_num].channel_ifname, $2, IFNAMSIZ); 409 410 idx = if_nametoindex($2); 411 if (!idx) { 412 print_err(CTD_CFG_WARN, "%s is an invalid interface", $2); 413 break; 414 } 415 416 if (conf.channel[conf.channel_num].u.mcast.ipproto == AF_INET6) { 417 conf.channel[conf.channel_num].u.mcast.ifa.interface_index6 = idx; 418 conf.channel[conf.channel_num].u.mcast.ipproto = AF_INET6; 419 } 420}; 421 422multicast_option : T_BACKLOG T_NUMBER 423{ 424 print_err(CTD_CFG_WARN, "`Backlog' option inside Multicast clause is " 425 "obsolete. Please, remove it from " 426 "conntrackd.conf"); 427}; 428 429multicast_option : T_GROUP T_NUMBER 430{ 431 __max_dedicated_links_reached(); 432 conf.channel[conf.channel_num].u.mcast.port = $2; 433}; 434 435multicast_option: T_SNDBUFF T_NUMBER 436{ 437 __max_dedicated_links_reached(); 438 conf.channel[conf.channel_num].u.mcast.sndbuf = $2; 439}; 440 441multicast_option: T_RCVBUFF T_NUMBER 442{ 443 __max_dedicated_links_reached(); 444 conf.channel[conf.channel_num].u.mcast.rcvbuf = $2; 445}; 446 447multicast_option: T_CHECKSUM T_ON 448{ 449 __max_dedicated_links_reached(); 450 conf.channel[conf.channel_num].u.mcast.checksum = 0; 451}; 452 453multicast_option: T_CHECKSUM T_OFF 454{ 455 __max_dedicated_links_reached(); 456 conf.channel[conf.channel_num].u.mcast.checksum = 1; 457}; 458 459udp_line : T_UDP '{' udp_options '}' 460{ 461 if (conf.channel_type_global != CHANNEL_NONE && 462 conf.channel_type_global != CHANNEL_UDP) { 463 print_err(CTD_CFG_ERROR, "cannot use `UDP' with other " 464 "dedicated link protocols!"); 465 exit(EXIT_FAILURE); 466 } 467 conf.channel_type_global = CHANNEL_UDP; 468 conf.channel[conf.channel_num].channel_type = CHANNEL_UDP; 469 conf.channel[conf.channel_num].channel_flags = CHANNEL_F_BUFFERED; 470 conf.channel_num++; 471}; 472 473udp_line : T_UDP T_DEFAULT '{' udp_options '}' 474{ 475 if (conf.channel_type_global != CHANNEL_NONE && 476 conf.channel_type_global != CHANNEL_UDP) { 477 print_err(CTD_CFG_ERROR, "cannot use `UDP' with other " 478 "dedicated link protocols!"); 479 exit(EXIT_FAILURE); 480 } 481 conf.channel_type_global = CHANNEL_UDP; 482 conf.channel[conf.channel_num].channel_type = CHANNEL_UDP; 483 conf.channel[conf.channel_num].channel_flags = CHANNEL_F_DEFAULT | 484 CHANNEL_F_BUFFERED; 485 conf.channel_default = conf.channel_num; 486 conf.channel_num++; 487}; 488 489udp_options : 490 | udp_options udp_option; 491 492udp_option : T_IPV4_ADDR T_IP 493{ 494 __max_dedicated_links_reached(); 495 496 if (!inet_aton($2, &conf.channel[conf.channel_num].u.udp.server.ipv4)) { 497 print_err(CTD_CFG_WARN, "%s is not a valid IPv4 address", $2); 498 break; 499 } 500 conf.channel[conf.channel_num].u.udp.ipproto = AF_INET; 501}; 502 503udp_option : T_IPV6_ADDR T_IP 504{ 505 __max_dedicated_links_reached(); 506 507#ifdef HAVE_INET_PTON_IPV6 508 if (inet_pton(AF_INET6, $2, 509 &conf.channel[conf.channel_num].u.udp.server.ipv6) <= 0) { 510 print_err(CTD_CFG_WARN, "%s is not a valid IPv6 address", $2); 511 break; 512 } 513#else 514 print_err(CTD_CFG_WARN, "cannot find inet_pton(), IPv6 unsupported!"); 515 break; 516#endif 517 conf.channel[conf.channel_num].u.udp.ipproto = AF_INET6; 518}; 519 520udp_option : T_IPV4_DEST_ADDR T_IP 521{ 522 __max_dedicated_links_reached(); 523 524 if (!inet_aton($2, &conf.channel[conf.channel_num].u.udp.client)) { 525 print_err(CTD_CFG_WARN, "%s is not a valid IPv4 address", $2); 526 break; 527 } 528 conf.channel[conf.channel_num].u.udp.ipproto = AF_INET; 529}; 530 531udp_option : T_IPV6_DEST_ADDR T_IP 532{ 533 __max_dedicated_links_reached(); 534 535#ifdef HAVE_INET_PTON_IPV6 536 if (inet_pton(AF_INET6, $2, 537 &conf.channel[conf.channel_num].u.udp.client) <= 0) { 538 print_err(CTD_CFG_WARN, "%s is not a valid IPv6 address", $2); 539 break; 540 } 541#else 542 print_err(CTD_CFG_WARN, "cannot find inet_pton(), IPv6 unsupported!"); 543 break; 544#endif 545 conf.channel[conf.channel_num].u.udp.ipproto = AF_INET6; 546}; 547 548udp_option : T_IFACE T_STRING 549{ 550 int idx; 551 552 __max_dedicated_links_reached(); 553 strncpy(conf.channel[conf.channel_num].channel_ifname, $2, IFNAMSIZ); 554 555 idx = if_nametoindex($2); 556 if (!idx) { 557 print_err(CTD_CFG_WARN, "%s is an invalid interface", $2); 558 break; 559 } 560 conf.channel[conf.channel_num].u.udp.server.ipv6.scope_id = idx; 561}; 562 563udp_option : T_PORT T_NUMBER 564{ 565 __max_dedicated_links_reached(); 566 conf.channel[conf.channel_num].u.udp.port = $2; 567}; 568 569udp_option: T_SNDBUFF T_NUMBER 570{ 571 __max_dedicated_links_reached(); 572 conf.channel[conf.channel_num].u.udp.sndbuf = $2; 573}; 574 575udp_option: T_RCVBUFF T_NUMBER 576{ 577 __max_dedicated_links_reached(); 578 conf.channel[conf.channel_num].u.udp.rcvbuf = $2; 579}; 580 581udp_option: T_CHECKSUM T_ON 582{ 583 __max_dedicated_links_reached(); 584 conf.channel[conf.channel_num].u.udp.checksum = 0; 585}; 586 587udp_option: T_CHECKSUM T_OFF 588{ 589 __max_dedicated_links_reached(); 590 conf.channel[conf.channel_num].u.udp.checksum = 1; 591}; 592 593tcp_line : T_TCP '{' tcp_options '}' 594{ 595 if (conf.channel_type_global != CHANNEL_NONE && 596 conf.channel_type_global != CHANNEL_TCP) { 597 print_err(CTD_CFG_ERROR, "cannot use `TCP' with other " 598 "dedicated link protocols!"); 599 exit(EXIT_FAILURE); 600 } 601 conf.channel_type_global = CHANNEL_TCP; 602 conf.channel[conf.channel_num].channel_type = CHANNEL_TCP; 603 conf.channel[conf.channel_num].channel_flags = CHANNEL_F_BUFFERED | 604 CHANNEL_F_STREAM | 605 CHANNEL_F_ERRORS; 606 conf.channel_num++; 607}; 608 609tcp_line : T_TCP T_DEFAULT '{' tcp_options '}' 610{ 611 if (conf.channel_type_global != CHANNEL_NONE && 612 conf.channel_type_global != CHANNEL_TCP) { 613 print_err(CTD_CFG_ERROR, "cannot use `TCP' with other " 614 "dedicated link protocols!"); 615 exit(EXIT_FAILURE); 616 } 617 conf.channel_type_global = CHANNEL_TCP; 618 conf.channel[conf.channel_num].channel_type = CHANNEL_TCP; 619 conf.channel[conf.channel_num].channel_flags = CHANNEL_F_DEFAULT | 620 CHANNEL_F_BUFFERED | 621 CHANNEL_F_STREAM | 622 CHANNEL_F_ERRORS; 623 conf.channel_default = conf.channel_num; 624 conf.channel_num++; 625}; 626 627tcp_options : 628 | tcp_options tcp_option; 629 630tcp_option : T_IPV4_ADDR T_IP 631{ 632 __max_dedicated_links_reached(); 633 634 if (!inet_aton($2, &conf.channel[conf.channel_num].u.tcp.server.ipv4)) { 635 print_err(CTD_CFG_WARN, "%s is not a valid IPv4 address", $2); 636 break; 637 } 638 conf.channel[conf.channel_num].u.tcp.ipproto = AF_INET; 639}; 640 641tcp_option : T_IPV6_ADDR T_IP 642{ 643 __max_dedicated_links_reached(); 644 645#ifdef HAVE_INET_PTON_IPV6 646 if (inet_pton(AF_INET6, $2, 647 &conf.channel[conf.channel_num].u.tcp.server.ipv6) <= 0) { 648 print_err(CTD_CFG_WARN, "%s is not a valid IPv6 address", $2); 649 break; 650 } 651#else 652 print_err(CTD_CFG_WARN, "cannot find inet_pton(), IPv6 unsupported!"); 653 break; 654#endif 655 conf.channel[conf.channel_num].u.tcp.ipproto = AF_INET6; 656}; 657 658tcp_option : T_IPV4_DEST_ADDR T_IP 659{ 660 __max_dedicated_links_reached(); 661 662 if (!inet_aton($2, &conf.channel[conf.channel_num].u.tcp.client)) { 663 print_err(CTD_CFG_WARN, "%s is not a valid IPv4 address", $2); 664 break; 665 } 666 conf.channel[conf.channel_num].u.tcp.ipproto = AF_INET; 667}; 668 669tcp_option : T_IPV6_DEST_ADDR T_IP 670{ 671 __max_dedicated_links_reached(); 672 673#ifdef HAVE_INET_PTON_IPV6 674 if (inet_pton(AF_INET6, $2, 675 &conf.channel[conf.channel_num].u.tcp.client) <= 0) { 676 print_err(CTD_CFG_WARN, "%s is not a valid IPv6 address", $2); 677 break; 678 } 679#else 680 print_err(CTD_CFG_WARN, "cannot find inet_pton(), IPv6 unsupported!"); 681 break; 682#endif 683 conf.channel[conf.channel_num].u.tcp.ipproto = AF_INET6; 684}; 685 686tcp_option : T_IFACE T_STRING 687{ 688 int idx; 689 690 __max_dedicated_links_reached(); 691 strncpy(conf.channel[conf.channel_num].channel_ifname, $2, IFNAMSIZ); 692 693 idx = if_nametoindex($2); 694 if (!idx) { 695 print_err(CTD_CFG_WARN, "%s is an invalid interface", $2); 696 break; 697 } 698 conf.channel[conf.channel_num].u.tcp.server.ipv6.scope_id = idx; 699}; 700 701tcp_option : T_PORT T_NUMBER 702{ 703 __max_dedicated_links_reached(); 704 conf.channel[conf.channel_num].u.tcp.port = $2; 705}; 706 707tcp_option: T_SNDBUFF T_NUMBER 708{ 709 __max_dedicated_links_reached(); 710 conf.channel[conf.channel_num].u.tcp.sndbuf = $2; 711}; 712 713tcp_option: T_RCVBUFF T_NUMBER 714{ 715 __max_dedicated_links_reached(); 716 conf.channel[conf.channel_num].u.tcp.rcvbuf = $2; 717}; 718 719tcp_option: T_CHECKSUM T_ON 720{ 721 __max_dedicated_links_reached(); 722 conf.channel[conf.channel_num].u.tcp.checksum = 0; 723}; 724 725tcp_option: T_CHECKSUM T_OFF 726{ 727 __max_dedicated_links_reached(); 728 conf.channel[conf.channel_num].u.tcp.checksum = 1; 729}; 730 731tcp_option: T_ERROR_QUEUE_LENGTH T_NUMBER 732{ 733 __max_dedicated_links_reached(); 734 CONFIG(channelc).error_queue_length = $2; 735}; 736 737hashsize : T_HASHSIZE T_NUMBER 738{ 739 conf.hashsize = $2; 740}; 741 742hashlimit: T_HASHLIMIT T_NUMBER 743{ 744 conf.limit = $2; 745}; 746 747unix_line: T_UNIX '{' unix_options '}'; 748 749unix_options: 750 | unix_options unix_option 751 ; 752 753unix_option : T_PATH T_PATH_VAL 754{ 755 strcpy(conf.local.path, $2); 756}; 757 758unix_option : T_BACKLOG T_NUMBER 759{ 760 conf.local.backlog = $2; 761}; 762 763ignore_protocol: T_IGNORE_PROTOCOL '{' ignore_proto_list '}' 764{ 765 ct_filter_set_logic(STATE(us_filter), 766 CT_FILTER_L4PROTO, 767 CT_FILTER_NEGATIVE); 768 769 print_err(CTD_CFG_WARN, "the clause `IgnoreProtocol' is " 770 "obsolete. Use `Filter' instead"); 771}; 772 773ignore_proto_list: 774 | ignore_proto_list ignore_proto 775 ; 776 777ignore_proto: T_NUMBER 778{ 779 if ($1 < IPPROTO_MAX) 780 ct_filter_add_proto(STATE(us_filter), $1); 781 else 782 print_err(CTD_CFG_WARN, "protocol number `%d' is freak", $1); 783}; 784 785ignore_proto: T_STRING 786{ 787 struct protoent *pent; 788 789 pent = getprotobyname($1); 790 if (pent == NULL) { 791 print_err(CTD_CFG_WARN, "getprotobyname() cannot find " 792 "protocol `%s' in /etc/protocols", $1); 793 break; 794 } 795 ct_filter_add_proto(STATE(us_filter), pent->p_proto); 796}; 797 798sync: T_SYNC '{' sync_list '}' 799{ 800 if (conf.flags & CTD_STATS_MODE) { 801 print_err(CTD_CFG_ERROR, "cannot use both `Stats' and `Sync' " 802 "clauses in conntrackd.conf"); 803 exit(EXIT_FAILURE); 804 } 805 conf.flags |= CTD_SYNC_MODE; 806}; 807 808sync_list: 809 | sync_list sync_line; 810 811sync_line: refreshtime 812 | expiretime 813 | timeout 814 | purge 815 | checksum 816 | multicast_line 817 | udp_line 818 | tcp_line 819 | relax_transitions 820 | delay_destroy_msgs 821 | sync_mode_alarm 822 | sync_mode_ftfw 823 | sync_mode_notrack 824 | listen_to 825 | state_replication 826 | cache_writethrough 827 | destroy_timeout 828 | option_line 829 ; 830 831option_line: T_OPTIONS '{' options '}'; 832 833options: 834 | options option 835 ; 836 837option: T_TCP_WINDOW_TRACKING T_ON 838{ 839 CONFIG(sync).tcp_window_tracking = 1; 840}; 841 842option: T_TCP_WINDOW_TRACKING T_OFF 843{ 844 CONFIG(sync).tcp_window_tracking = 0; 845}; 846 847option: T_EXPECT_SYNC T_ON 848{ 849 CONFIG(flags) |= CTD_EXPECT; 850 CONFIG(netlink).subsys_id = NFNL_SUBSYS_NONE; 851 CONFIG(netlink).groups = NF_NETLINK_CONNTRACK_NEW | 852 NF_NETLINK_CONNTRACK_UPDATE | 853 NF_NETLINK_CONNTRACK_DESTROY | 854 NF_NETLINK_CONNTRACK_EXP_NEW | 855 NF_NETLINK_CONNTRACK_EXP_UPDATE | 856 NF_NETLINK_CONNTRACK_EXP_DESTROY; 857}; 858 859option: T_EXPECT_SYNC T_OFF 860{ 861 CONFIG(netlink).subsys_id = NFNL_SUBSYS_CTNETLINK; 862 CONFIG(netlink).groups = NF_NETLINK_CONNTRACK_NEW | 863 NF_NETLINK_CONNTRACK_UPDATE | 864 NF_NETLINK_CONNTRACK_DESTROY; 865}; 866 867option: T_EXPECT_SYNC '{' expect_list '}' 868{ 869 CONFIG(flags) |= CTD_EXPECT; 870 CONFIG(netlink).subsys_id = NFNL_SUBSYS_NONE; 871 CONFIG(netlink).groups = NF_NETLINK_CONNTRACK_NEW | 872 NF_NETLINK_CONNTRACK_UPDATE | 873 NF_NETLINK_CONNTRACK_DESTROY | 874 NF_NETLINK_CONNTRACK_EXP_NEW | 875 NF_NETLINK_CONNTRACK_EXP_UPDATE | 876 NF_NETLINK_CONNTRACK_EXP_DESTROY; 877}; 878 879expect_list: 880 | expect_list expect_item ; 881 882expect_item: T_STRING 883{ 884 exp_filter_add(STATE(exp_filter), $1); 885} 886 887sync_mode_alarm: T_SYNC_MODE T_ALARM '{' sync_mode_alarm_list '}' 888{ 889 conf.flags |= CTD_SYNC_ALARM; 890}; 891 892sync_mode_ftfw: T_SYNC_MODE T_FTFW '{' sync_mode_ftfw_list '}' 893{ 894 conf.flags |= CTD_SYNC_FTFW; 895}; 896 897sync_mode_notrack: T_SYNC_MODE T_NOTRACK '{' sync_mode_notrack_list '}' 898{ 899 conf.flags |= CTD_SYNC_NOTRACK; 900}; 901 902sync_mode_alarm_list: 903 | sync_mode_alarm_list sync_mode_alarm_line; 904 905sync_mode_alarm_line: refreshtime 906 | expiretime 907 | timeout 908 | purge 909 | relax_transitions 910 | delay_destroy_msgs 911 ; 912 913sync_mode_ftfw_list: 914 | sync_mode_ftfw_list sync_mode_ftfw_line; 915 916sync_mode_ftfw_line: resend_queue_size 917 | resend_buffer_size 918 | timeout 919 | purge 920 | window_size 921 | disable_external_cache 922 ; 923 924sync_mode_notrack_list: 925 | sync_mode_notrack_list sync_mode_notrack_line; 926 927sync_mode_notrack_line: timeout 928 | purge 929 | disable_internal_cache 930 | disable_external_cache 931 ; 932 933disable_internal_cache: T_DISABLE_INTERNAL_CACHE T_ON 934{ 935 conf.sync.internal_cache_disable = 1; 936}; 937 938disable_internal_cache: T_DISABLE_INTERNAL_CACHE T_OFF 939{ 940 conf.sync.internal_cache_disable = 0; 941}; 942 943disable_external_cache: T_DISABLE_EXTERNAL_CACHE T_ON 944{ 945 conf.sync.external_cache_disable = 1; 946}; 947 948disable_external_cache: T_DISABLE_EXTERNAL_CACHE T_OFF 949{ 950 conf.sync.external_cache_disable = 0; 951}; 952 953resend_buffer_size: T_RESEND_BUFFER_SIZE T_NUMBER 954{ 955 print_err(CTD_CFG_WARN, "`ResendBufferSize' is deprecated. " 956 "Use `ResendQueueSize' instead"); 957}; 958 959resend_queue_size: T_RESEND_QUEUE_SIZE T_NUMBER 960{ 961 conf.resend_queue_size = $2; 962}; 963 964window_size: T_WINDOWSIZE T_NUMBER 965{ 966 conf.window_size = $2; 967}; 968 969destroy_timeout: T_DESTROY_TIMEOUT T_NUMBER 970{ 971 print_err(CTD_CFG_WARN, "`DestroyTimeout' is deprecated. Remove it"); 972}; 973 974relax_transitions: T_RELAX_TRANSITIONS 975{ 976 print_err(CTD_CFG_WARN, "`RelaxTransitions' clause is obsolete. " 977 "Please, remove it from conntrackd.conf"); 978}; 979 980delay_destroy_msgs: T_DELAY 981{ 982 print_err(CTD_CFG_WARN, "`DelayDestroyMessages' clause is obsolete. " 983 "Please, remove it from conntrackd.conf"); 984}; 985 986listen_to: T_LISTEN_TO T_IP 987{ 988 print_err(CTD_CFG_WARN, "the clause `ListenTo' is obsolete, ignoring"); 989}; 990 991state_replication: T_REPLICATE states T_FOR state_proto 992{ 993 ct_filter_set_logic(STATE(us_filter), 994 CT_FILTER_STATE, 995 CT_FILTER_POSITIVE); 996 997 print_err(CTD_CFG_WARN, "the clause `Replicate' is obsolete. " 998 "Use `Filter' instead"); 999}; 1000 1001states: 1002 | states state; 1003 1004state_proto: T_STRING 1005{ 1006 if (strncmp($1, "TCP", strlen("TCP")) != 0) { 1007 print_err(CTD_CFG_WARN, "unsupported protocol `%s' in line %d", 1008 $1, yylineno); 1009 } 1010}; 1011state: tcp_state; 1012 1013tcp_states: 1014 | tcp_states tcp_state; 1015 1016tcp_state: T_SYN_SENT 1017{ 1018 ct_filter_add_state(STATE(us_filter), 1019 IPPROTO_TCP, 1020 TCP_CONNTRACK_SYN_SENT); 1021 1022 __kernel_filter_add_state(TCP_CONNTRACK_SYN_SENT); 1023}; 1024tcp_state: T_SYN_RECV 1025{ 1026 ct_filter_add_state(STATE(us_filter), 1027 IPPROTO_TCP, 1028 TCP_CONNTRACK_SYN_RECV); 1029 1030 __kernel_filter_add_state(TCP_CONNTRACK_SYN_RECV); 1031}; 1032tcp_state: T_ESTABLISHED 1033{ 1034 ct_filter_add_state(STATE(us_filter), 1035 IPPROTO_TCP, 1036 TCP_CONNTRACK_ESTABLISHED); 1037 1038 __kernel_filter_add_state(TCP_CONNTRACK_ESTABLISHED); 1039}; 1040tcp_state: T_FIN_WAIT 1041{ 1042 ct_filter_add_state(STATE(us_filter), 1043 IPPROTO_TCP, 1044 TCP_CONNTRACK_FIN_WAIT); 1045 1046 __kernel_filter_add_state(TCP_CONNTRACK_FIN_WAIT); 1047}; 1048tcp_state: T_CLOSE_WAIT 1049{ 1050 ct_filter_add_state(STATE(us_filter), 1051 IPPROTO_TCP, 1052 TCP_CONNTRACK_CLOSE_WAIT); 1053 1054 __kernel_filter_add_state(TCP_CONNTRACK_CLOSE_WAIT); 1055}; 1056tcp_state: T_LAST_ACK 1057{ 1058 ct_filter_add_state(STATE(us_filter), 1059 IPPROTO_TCP, 1060 TCP_CONNTRACK_LAST_ACK); 1061 1062 __kernel_filter_add_state(TCP_CONNTRACK_LAST_ACK); 1063}; 1064tcp_state: T_TIME_WAIT 1065{ 1066 ct_filter_add_state(STATE(us_filter), 1067 IPPROTO_TCP, 1068 TCP_CONNTRACK_TIME_WAIT); 1069 1070 __kernel_filter_add_state(TCP_CONNTRACK_TIME_WAIT); 1071}; 1072tcp_state: T_CLOSE 1073{ 1074 ct_filter_add_state(STATE(us_filter), 1075 IPPROTO_TCP, 1076 TCP_CONNTRACK_CLOSE); 1077 1078 __kernel_filter_add_state(TCP_CONNTRACK_CLOSE); 1079}; 1080tcp_state: T_LISTEN 1081{ 1082 ct_filter_add_state(STATE(us_filter), 1083 IPPROTO_TCP, 1084 TCP_CONNTRACK_LISTEN); 1085 1086 __kernel_filter_add_state(TCP_CONNTRACK_LISTEN); 1087}; 1088 1089cache_writethrough: T_WRITE_THROUGH T_ON 1090{ 1091 print_err(CTD_CFG_WARN, "`CacheWriteThrough' clause is obsolete, " 1092 "ignoring"); 1093}; 1094 1095cache_writethrough: T_WRITE_THROUGH T_OFF 1096{ 1097 print_err(CTD_CFG_WARN, "`CacheWriteThrough' clause is obsolete, " 1098 "ignoring"); 1099}; 1100 1101general: T_GENERAL '{' general_list '}'; 1102 1103general_list: 1104 | general_list general_line 1105 ; 1106 1107general_line: hashsize 1108 | hashlimit 1109 | logfile_bool 1110 | logfile_path 1111 | syslog_facility 1112 | syslog_bool 1113 | lock 1114 | unix_line 1115 | netlink_buffer_size 1116 | netlink_buffer_size_max_grown 1117 | family 1118 | event_iterations_limit 1119 | poll_secs 1120 | filter 1121 | netlink_overrun_resync 1122 | netlink_events_reliable 1123 | nice 1124 | scheduler 1125 ; 1126 1127netlink_buffer_size: T_BUFFER_SIZE T_NUMBER 1128{ 1129 conf.netlink_buffer_size = $2; 1130}; 1131 1132netlink_buffer_size_max_grown : T_BUFFER_SIZE_MAX_GROWN T_NUMBER 1133{ 1134 conf.netlink_buffer_size_max_grown = $2; 1135}; 1136 1137netlink_overrun_resync : T_NETLINK_OVERRUN_RESYNC T_ON 1138{ 1139 conf.nl_overrun_resync = 30; 1140}; 1141 1142netlink_overrun_resync : T_NETLINK_OVERRUN_RESYNC T_OFF 1143{ 1144 conf.nl_overrun_resync = -1; 1145}; 1146 1147netlink_overrun_resync : T_NETLINK_OVERRUN_RESYNC T_NUMBER 1148{ 1149 conf.nl_overrun_resync = $2; 1150}; 1151 1152netlink_events_reliable : T_NETLINK_EVENTS_RELIABLE T_ON 1153{ 1154 conf.netlink.events_reliable = 1; 1155}; 1156 1157netlink_events_reliable : T_NETLINK_EVENTS_RELIABLE T_OFF 1158{ 1159 conf.netlink.events_reliable = 0; 1160}; 1161 1162nice : T_NICE T_SIGNED_NUMBER 1163{ 1164 conf.nice = $2; 1165}; 1166 1167scheduler : T_SCHEDULER '{' scheduler_options '}'; 1168 1169scheduler_options : 1170 | scheduler_options scheduler_line 1171 ; 1172 1173scheduler_line : T_TYPE T_STRING 1174{ 1175 if (strcasecmp($2, "rr") == 0) { 1176 conf.sched.type = SCHED_RR; 1177 } else if (strcasecmp($2, "fifo") == 0) { 1178 conf.sched.type = SCHED_FIFO; 1179 } else { 1180 print_err(CTD_CFG_ERROR, "unknown scheduler `%s'", $2); 1181 exit(EXIT_FAILURE); 1182 } 1183}; 1184 1185scheduler_line : T_PRIO T_NUMBER 1186{ 1187 conf.sched.prio = $2; 1188 if (conf.sched.prio < 0 || conf.sched.prio > 99) { 1189 print_err(CTD_CFG_ERROR, "`Priority' must be [0, 99]\n", $2); 1190 exit(EXIT_FAILURE); 1191 } 1192}; 1193 1194family : T_FAMILY T_STRING 1195{ 1196 if (strncmp($2, "IPv6", strlen("IPv6")) == 0) 1197 conf.family = AF_INET6; 1198 else 1199 conf.family = AF_INET; 1200}; 1201 1202event_iterations_limit : T_EVENT_ITER_LIMIT T_NUMBER 1203{ 1204 CONFIG(event_iterations_limit) = $2; 1205}; 1206 1207poll_secs: T_POLL_SECS T_NUMBER 1208{ 1209 conf.flags |= CTD_POLL; 1210 conf.poll_kernel_secs = $2; 1211 if (conf.poll_kernel_secs == 0) { 1212 print_err(CTD_CFG_ERROR, "`PollSecs' clause must be > 0"); 1213 exit(EXIT_FAILURE); 1214 } 1215}; 1216 1217filter : T_FILTER '{' filter_list '}' 1218{ 1219 CONFIG(filter_from_kernelspace) = 0; 1220}; 1221 1222filter : T_FILTER T_FROM T_USERSPACE '{' filter_list '}' 1223{ 1224 CONFIG(filter_from_kernelspace) = 0; 1225}; 1226 1227filter : T_FILTER T_FROM T_KERNELSPACE '{' filter_list '}' 1228{ 1229 CONFIG(filter_from_kernelspace) = 1; 1230}; 1231 1232filter_list : 1233 | filter_list filter_item; 1234 1235filter_item : T_PROTOCOL T_ACCEPT '{' filter_protocol_list '}' 1236{ 1237 ct_filter_set_logic(STATE(us_filter), 1238 CT_FILTER_L4PROTO, 1239 CT_FILTER_POSITIVE); 1240 1241 __kernel_filter_start(); 1242}; 1243 1244filter_item : T_PROTOCOL T_IGNORE '{' filter_protocol_list '}' 1245{ 1246 ct_filter_set_logic(STATE(us_filter), 1247 CT_FILTER_L4PROTO, 1248 CT_FILTER_NEGATIVE); 1249 1250 __kernel_filter_start(); 1251 1252 nfct_filter_set_logic(STATE(filter), 1253 NFCT_FILTER_L4PROTO, 1254 NFCT_FILTER_LOGIC_NEGATIVE); 1255}; 1256 1257filter_protocol_list : 1258 | filter_protocol_list filter_protocol_item; 1259 1260filter_protocol_item : T_STRING 1261{ 1262 struct protoent *pent; 1263 1264 pent = getprotobyname($1); 1265 if (pent == NULL) { 1266 print_err(CTD_CFG_WARN, "getprotobyname() cannot find " 1267 "protocol `%s' in /etc/protocols", $1); 1268 break; 1269 } 1270 ct_filter_add_proto(STATE(us_filter), pent->p_proto); 1271 1272 __kernel_filter_start(); 1273 1274 nfct_filter_add_attr_u32(STATE(filter), 1275 NFCT_FILTER_L4PROTO, 1276 pent->p_proto); 1277}; 1278 1279filter_protocol_item : T_TCP 1280{ 1281 struct protoent *pent; 1282 1283 pent = getprotobyname("tcp"); 1284 if (pent == NULL) { 1285 print_err(CTD_CFG_WARN, "getprotobyname() cannot find " 1286 "protocol `tcp' in /etc/protocols"); 1287 break; 1288 } 1289 ct_filter_add_proto(STATE(us_filter), pent->p_proto); 1290 1291 __kernel_filter_start(); 1292 1293 nfct_filter_add_attr_u32(STATE(filter), 1294 NFCT_FILTER_L4PROTO, 1295 pent->p_proto); 1296}; 1297 1298filter_protocol_item : T_UDP 1299{ 1300 struct protoent *pent; 1301 1302 pent = getprotobyname("udp"); 1303 if (pent == NULL) { 1304 print_err(CTD_CFG_WARN, "getprotobyname() cannot find " 1305 "protocol `udp' in /etc/protocols"); 1306 break; 1307 } 1308 ct_filter_add_proto(STATE(us_filter), pent->p_proto); 1309 1310 __kernel_filter_start(); 1311 1312 nfct_filter_add_attr_u32(STATE(filter), 1313 NFCT_FILTER_L4PROTO, 1314 pent->p_proto); 1315}; 1316 1317filter_item : T_ADDRESS T_ACCEPT '{' filter_address_list '}' 1318{ 1319 ct_filter_set_logic(STATE(us_filter), 1320 CT_FILTER_ADDRESS, 1321 CT_FILTER_POSITIVE); 1322 1323 __kernel_filter_start(); 1324}; 1325 1326filter_item : T_ADDRESS T_IGNORE '{' filter_address_list '}' 1327{ 1328 ct_filter_set_logic(STATE(us_filter), 1329 CT_FILTER_ADDRESS, 1330 CT_FILTER_NEGATIVE); 1331 1332 __kernel_filter_start(); 1333 1334 nfct_filter_set_logic(STATE(filter), 1335 NFCT_FILTER_SRC_IPV4, 1336 NFCT_FILTER_LOGIC_NEGATIVE); 1337 nfct_filter_set_logic(STATE(filter), 1338 NFCT_FILTER_DST_IPV4, 1339 NFCT_FILTER_LOGIC_NEGATIVE); 1340 nfct_filter_set_logic(STATE(filter), 1341 NFCT_FILTER_SRC_IPV6, 1342 NFCT_FILTER_LOGIC_NEGATIVE); 1343 nfct_filter_set_logic(STATE(filter), 1344 NFCT_FILTER_DST_IPV6, 1345 NFCT_FILTER_LOGIC_NEGATIVE); 1346}; 1347 1348filter_address_list : 1349 | filter_address_list filter_address_item; 1350 1351filter_address_item : T_IPV4_ADDR T_IP 1352{ 1353 union inet_address ip; 1354 char *slash; 1355 unsigned int cidr = 32; 1356 1357 memset(&ip, 0, sizeof(union inet_address)); 1358 1359 slash = strchr($2, '/'); 1360 if (slash) { 1361 *slash = '\0'; 1362 cidr = atoi(slash+1); 1363 if (cidr > 32) { 1364 print_err(CTD_CFG_WARN, "%s/%d is not a valid network, " 1365 "ignoring", $2, cidr); 1366 break; 1367 } 1368 } 1369 1370 if (!inet_aton($2, &ip.ipv4)) { 1371 print_err(CTD_CFG_WARN, "%s is not a valid IPv4, ignoring", $2); 1372 break; 1373 } 1374 1375 if (slash && cidr < 32) { 1376 /* network byte order */ 1377 struct ct_filter_netmask_ipv4 tmp = { 1378 .ip = ip.ipv4, 1379 .mask = ipv4_cidr2mask_net(cidr) 1380 }; 1381 1382 if (!ct_filter_add_netmask(STATE(us_filter), &tmp, AF_INET)) { 1383 if (errno == EEXIST) 1384 print_err(CTD_CFG_WARN, "netmask %s is " 1385 "repeated in the " 1386 "ignore pool", $2); 1387 } 1388 } else { 1389 if (!ct_filter_add_ip(STATE(us_filter), &ip, AF_INET)) { 1390 if (errno == EEXIST) 1391 print_err(CTD_CFG_WARN, "IP %s is repeated in " 1392 "the ignore pool", $2); 1393 if (errno == ENOSPC) 1394 print_err(CTD_CFG_WARN, "too many IP in the " 1395 "ignore pool!"); 1396 } 1397 } 1398 __kernel_filter_start(); 1399 1400 /* host byte order */ 1401 struct nfct_filter_ipv4 filter_ipv4 = { 1402 .addr = ntohl(ip.ipv4), 1403 .mask = ipv4_cidr2mask_host(cidr), 1404 }; 1405 1406 nfct_filter_add_attr(STATE(filter), NFCT_FILTER_SRC_IPV4, &filter_ipv4); 1407 nfct_filter_add_attr(STATE(filter), NFCT_FILTER_DST_IPV4, &filter_ipv4); 1408}; 1409 1410filter_address_item : T_IPV6_ADDR T_IP 1411{ 1412 union inet_address ip; 1413 char *slash; 1414 int cidr = 128; 1415 struct nfct_filter_ipv6 filter_ipv6; 1416 1417 memset(&ip, 0, sizeof(union inet_address)); 1418 1419 slash = strchr($2, '/'); 1420 if (slash) { 1421 *slash = '\0'; 1422 cidr = atoi(slash+1); 1423 if (cidr > 128) { 1424 print_err(CTD_CFG_WARN, "%s/%d is not a valid network, " 1425 "ignoring", $2, cidr); 1426 break; 1427 } 1428 } 1429 1430#ifdef HAVE_INET_PTON_IPV6 1431 if (inet_pton(AF_INET6, $2, &ip.ipv6) <= 0) { 1432 print_err(CTD_CFG_WARN, "%s is not a valid IPv6, ignoring", $2); 1433 break; 1434 } 1435#else 1436 print_err(CTD_CFG_WARN, "cannot find inet_pton(), IPv6 unsupported!"); 1437 break; 1438#endif 1439 if (slash && cidr < 128) { 1440 struct ct_filter_netmask_ipv6 tmp; 1441 1442 memcpy(tmp.ip, ip.ipv6, sizeof(uint32_t)*4); 1443 ipv6_cidr2mask_net(cidr, tmp.mask); 1444 if (!ct_filter_add_netmask(STATE(us_filter), &tmp, AF_INET6)) { 1445 if (errno == EEXIST) 1446 print_err(CTD_CFG_WARN, "netmask %s is " 1447 "repeated in the " 1448 "ignore pool", $2); 1449 } 1450 } else { 1451 if (!ct_filter_add_ip(STATE(us_filter), &ip, AF_INET6)) { 1452 if (errno == EEXIST) 1453 print_err(CTD_CFG_WARN, "IP %s is repeated in " 1454 "the ignore pool", $2); 1455 if (errno == ENOSPC) 1456 print_err(CTD_CFG_WARN, "too many IP in the " 1457 "ignore pool!"); 1458 } 1459 } 1460 __kernel_filter_start(); 1461 1462 /* host byte order */ 1463 ipv6_addr2addr_host(ip.ipv6, filter_ipv6.addr); 1464 ipv6_cidr2mask_host(cidr, filter_ipv6.mask); 1465 1466 nfct_filter_add_attr(STATE(filter), NFCT_FILTER_SRC_IPV6, &filter_ipv6); 1467 nfct_filter_add_attr(STATE(filter), NFCT_FILTER_DST_IPV6, &filter_ipv6); 1468}; 1469 1470filter_item : T_STATE T_ACCEPT '{' filter_state_list '}' 1471{ 1472 ct_filter_set_logic(STATE(us_filter), 1473 CT_FILTER_STATE, 1474 CT_FILTER_POSITIVE); 1475 1476 __kernel_filter_start(); 1477}; 1478 1479filter_item : T_STATE T_IGNORE '{' filter_state_list '}' 1480{ 1481 ct_filter_set_logic(STATE(us_filter), 1482 CT_FILTER_STATE, 1483 CT_FILTER_NEGATIVE); 1484 1485 1486 __kernel_filter_start(); 1487 1488 nfct_filter_set_logic(STATE(filter), 1489 NFCT_FILTER_L4PROTO_STATE, 1490 NFCT_FILTER_LOGIC_NEGATIVE); 1491}; 1492 1493filter_state_list : 1494 | filter_state_list filter_state_item; 1495 1496filter_state_item : tcp_states T_FOR T_TCP; 1497 1498stats: T_STATS '{' stats_list '}' 1499{ 1500 if (conf.flags & CTD_SYNC_MODE) { 1501 print_err(CTD_CFG_ERROR, "cannot use both `Stats' and `Sync' " 1502 "clauses in conntrackd.conf"); 1503 exit(EXIT_FAILURE); 1504 } 1505 conf.flags |= CTD_STATS_MODE; 1506}; 1507 1508stats_list: 1509 | stats_list stat_line 1510 ; 1511 1512stat_line: stat_logfile_bool 1513 | stat_logfile_path 1514 | stat_syslog_bool 1515 | stat_syslog_facility 1516 | buffer_size 1517 ; 1518 1519stat_logfile_bool : T_LOG T_ON 1520{ 1521 strncpy(conf.stats.logfile, DEFAULT_STATS_LOGFILE, FILENAME_MAXLEN); 1522}; 1523 1524stat_logfile_bool : T_LOG T_OFF 1525{ 1526}; 1527 1528stat_logfile_path : T_LOG T_PATH_VAL 1529{ 1530 strncpy(conf.stats.logfile, $2, FILENAME_MAXLEN); 1531}; 1532 1533stat_syslog_bool : T_SYSLOG T_ON 1534{ 1535 conf.stats.syslog_facility = DEFAULT_SYSLOG_FACILITY; 1536}; 1537 1538stat_syslog_bool : T_SYSLOG T_OFF 1539{ 1540 conf.stats.syslog_facility = -1; 1541} 1542 1543stat_syslog_facility : T_SYSLOG T_STRING 1544{ 1545 if (!strcmp($2, "daemon")) 1546 conf.stats.syslog_facility = LOG_DAEMON; 1547 else if (!strcmp($2, "local0")) 1548 conf.stats.syslog_facility = LOG_LOCAL0; 1549 else if (!strcmp($2, "local1")) 1550 conf.stats.syslog_facility = LOG_LOCAL1; 1551 else if (!strcmp($2, "local2")) 1552 conf.stats.syslog_facility = LOG_LOCAL2; 1553 else if (!strcmp($2, "local3")) 1554 conf.stats.syslog_facility = LOG_LOCAL3; 1555 else if (!strcmp($2, "local4")) 1556 conf.stats.syslog_facility = LOG_LOCAL4; 1557 else if (!strcmp($2, "local5")) 1558 conf.stats.syslog_facility = LOG_LOCAL5; 1559 else if (!strcmp($2, "local6")) 1560 conf.stats.syslog_facility = LOG_LOCAL6; 1561 else if (!strcmp($2, "local7")) 1562 conf.stats.syslog_facility = LOG_LOCAL7; 1563 else { 1564 print_err(CTD_CFG_WARN, "'%s' is not a known syslog facility, " 1565 "ignoring.", $2); 1566 break; 1567 } 1568 1569 if (conf.syslog_facility != -1 && 1570 conf.stats.syslog_facility != conf.syslog_facility) 1571 print_err(CTD_CFG_WARN, "conflicting Syslog facility " 1572 "values, defaulting to General"); 1573}; 1574 1575buffer_size: T_STAT_BUFFER_SIZE T_NUMBER 1576{ 1577 print_err(CTD_CFG_WARN, "`LogFileBufferSize' is deprecated"); 1578}; 1579 1580helper: T_HELPER '{' helper_list '}' 1581{ 1582 conf.flags |= CTD_HELPER; 1583}; 1584 1585helper_list: 1586 | helper_list helper_line 1587 ; 1588 1589helper_line: helper_type 1590 ; 1591 1592helper_type: T_TYPE T_STRING T_STRING T_STRING '{' helper_type_list '}' 1593{ 1594 struct ctd_helper_instance *helper_inst; 1595 struct ctd_helper *helper; 1596 struct stack_item *e; 1597 uint16_t l3proto; 1598 uint8_t l4proto; 1599 1600 if (strcmp($3, "inet") == 0) 1601 l3proto = AF_INET; 1602 else if (strcmp($3, "inet6") == 0) 1603 l3proto = AF_INET6; 1604 else { 1605 print_err(CTD_CFG_ERROR, "unknown layer 3 protocol"); 1606 exit(EXIT_FAILURE); 1607 } 1608 1609 if (strcmp($4, "tcp") == 0) 1610 l4proto = IPPROTO_TCP; 1611 else if (strcmp($4, "udp") == 0) 1612 l4proto = IPPROTO_UDP; 1613 else { 1614 print_err(CTD_CFG_ERROR, "unknown layer 4 protocol"); 1615 exit(EXIT_FAILURE); 1616 } 1617 1618 /* XXX use configure.ac definitions. */ 1619 helper = helper_find("/usr/lib/conntrack-tools", $2, l4proto, RTLD_NOW); 1620 if (helper == NULL) { 1621 print_err(CTD_CFG_ERROR, "Unknown `%s' helper", $2); 1622 exit(EXIT_FAILURE); 1623 } 1624 1625 helper_inst = calloc(1, sizeof(struct ctd_helper_instance)); 1626 if (helper_inst == NULL) 1627 break; 1628 1629 helper_inst->l3proto = l3proto; 1630 helper_inst->l4proto = l4proto; 1631 helper_inst->helper = helper; 1632 1633 while ((e = stack_item_pop(&symbol_stack, -1)) != NULL) { 1634 1635 switch(e->type) { 1636 case SYMBOL_HELPER_QUEUE_NUM: { 1637 int *qnum = (int *) &e->data; 1638 1639 helper_inst->queue_num = *qnum; 1640 stack_item_free(e); 1641 break; 1642 } 1643 case SYMBOL_HELPER_QUEUE_LEN: { 1644 int *qlen = (int *) &e->data; 1645 1646 helper_inst->queue_len = *qlen; 1647 stack_item_free(e); 1648 break; 1649 } 1650 case SYMBOL_HELPER_POLICY_EXPECT_ROOT: { 1651 struct ctd_helper_policy *pol = 1652 (struct ctd_helper_policy *) &e->data; 1653 struct ctd_helper_policy *matching = NULL; 1654 int i; 1655 1656 for (i=0; i<CTD_HELPER_POLICY_MAX; i++) { 1657 if (strcmp(helper->policy[i].name, 1658 pol->name) != 0) 1659 continue; 1660 1661 matching = pol; 1662 break; 1663 } 1664 if (matching == NULL) { 1665 print_err(CTD_CFG_ERROR, 1666 "Unknown policy `%s' in helper " 1667 "configuration", pol->name); 1668 exit(EXIT_FAILURE); 1669 } 1670 /* FIXME: First set default policy, then change only 1671 * tuned fields, not everything. 1672 */ 1673 memcpy(&helper->policy[i], pol, 1674 sizeof(struct ctd_helper_policy)); 1675 1676 stack_item_free(e); 1677 break; 1678 } 1679 default: 1680 print_err(CTD_CFG_ERROR, 1681 "Unexpected symbol parsing helper policy"); 1682 exit(EXIT_FAILURE); 1683 break; 1684 } 1685 } 1686 list_add(&helper_inst->head, &CONFIG(cthelper).list); 1687}; 1688 1689helper_type_list: 1690 | helper_type_list helper_type_line 1691 ; 1692 1693helper_type_line: helper_type 1694 ; 1695 1696helper_type: T_HELPER_QUEUE_NUM T_NUMBER 1697{ 1698 int *qnum; 1699 struct stack_item *e; 1700 1701 e = stack_item_alloc(SYMBOL_HELPER_QUEUE_NUM, sizeof(int)); 1702 qnum = (int *) e->data; 1703 *qnum = $2; 1704 stack_item_push(&symbol_stack, e); 1705}; 1706 1707helper_type: T_HELPER_QUEUE_LEN T_NUMBER 1708{ 1709 int *qlen; 1710 struct stack_item *e; 1711 1712 e = stack_item_alloc(SYMBOL_HELPER_QUEUE_LEN, sizeof(int)); 1713 qlen = (int *) e->data; 1714 *qlen = $2; 1715 stack_item_push(&symbol_stack, e); 1716}; 1717 1718helper_type: T_HELPER_POLICY T_STRING '{' helper_policy_list '}' 1719{ 1720 struct stack_item *e; 1721 struct ctd_helper_policy *policy; 1722 1723 e = stack_item_pop(&symbol_stack, SYMBOL_HELPER_EXPECT_POLICY_LEAF); 1724 if (e == NULL) { 1725 print_err(CTD_CFG_ERROR, 1726 "Helper policy configuration empty, fix your " 1727 "configuration file, please"); 1728 exit(EXIT_FAILURE); 1729 break; 1730 } 1731 1732 policy = (struct ctd_helper_policy *) &e->data; 1733 strncpy(policy->name, $2, CTD_HELPER_NAME_LEN); 1734 policy->name[CTD_HELPER_NAME_LEN-1] = '\0'; 1735 /* Now object is complete. */ 1736 e->type = SYMBOL_HELPER_POLICY_EXPECT_ROOT; 1737 stack_item_push(&symbol_stack, e); 1738}; 1739 1740helper_policy_list: 1741 | helper_policy_list helper_policy_line 1742 ; 1743 1744helper_policy_line: helper_policy_expect_max 1745 | helper_policy_expect_timeout 1746 ; 1747 1748helper_policy_expect_max: T_HELPER_EXPECT_MAX T_NUMBER 1749{ 1750 struct stack_item *e; 1751 struct ctd_helper_policy *policy; 1752 1753 e = stack_item_pop(&symbol_stack, SYMBOL_HELPER_EXPECT_POLICY_LEAF); 1754 if (e == NULL) { 1755 e = stack_item_alloc(SYMBOL_HELPER_EXPECT_POLICY_LEAF, 1756 sizeof(struct ctd_helper_policy)); 1757 } 1758 policy = (struct ctd_helper_policy *) &e->data; 1759 policy->expect_max = $2; 1760 stack_item_push(&symbol_stack, e); 1761}; 1762 1763helper_policy_expect_timeout: T_HELPER_EXPECT_TIMEOUT T_NUMBER 1764{ 1765 struct stack_item *e; 1766 struct ctd_helper_policy *policy; 1767 1768 e = stack_item_pop(&symbol_stack, SYMBOL_HELPER_EXPECT_POLICY_LEAF); 1769 if (e == NULL) { 1770 e = stack_item_alloc(SYMBOL_HELPER_EXPECT_POLICY_LEAF, 1771 sizeof(struct ctd_helper_policy)); 1772 } 1773 policy = (struct ctd_helper_policy *) &e->data; 1774 policy->expect_timeout = $2; 1775 stack_item_push(&symbol_stack, e); 1776}; 1777 1778%% 1779 1780int __attribute__((noreturn)) 1781yyerror(char *msg) 1782{ 1783 print_err(CTD_CFG_ERROR, "parsing config file in " 1784 "line (%d), symbol '%s': %s", 1785 yylineno, yytext, msg); 1786 exit(EXIT_FAILURE); 1787} 1788 1789static void print_err(int type, const char *msg, ...) 1790{ 1791 va_list args; 1792 1793 va_start(args, msg); 1794 switch(type) { 1795 case CTD_CFG_ERROR: 1796 fprintf(stderr, "ERROR: "); 1797 break; 1798 case CTD_CFG_WARN: 1799 fprintf(stderr, "WARNING: "); 1800 break; 1801 default: 1802 fprintf(stderr, "?: "); 1803 } 1804 vfprintf(stderr, msg, args); 1805 va_end(args); 1806 fprintf(stderr,"\n"); 1807} 1808 1809static void __kernel_filter_start(void) 1810{ 1811 if (!STATE(filter)) { 1812 STATE(filter) = nfct_filter_create(); 1813 if (!STATE(filter)) { 1814 print_err(CTD_CFG_ERROR, "cannot create ignore pool!"); 1815 exit(EXIT_FAILURE); 1816 } 1817 } 1818} 1819 1820static void __kernel_filter_add_state(int value) 1821{ 1822 __kernel_filter_start(); 1823 1824 struct nfct_filter_proto filter_proto = { 1825 .proto = IPPROTO_TCP, 1826 .state = value 1827 }; 1828 nfct_filter_add_attr(STATE(filter), 1829 NFCT_FILTER_L4PROTO_STATE, 1830 &filter_proto); 1831} 1832 1833static void __max_dedicated_links_reached(void) 1834{ 1835 if (conf.channel_num >= MULTICHANNEL_MAX) { 1836 print_err(CTD_CFG_ERROR, "too many dedicated links in " 1837 "the configuration file " 1838 "(Maximum: %d)", MULTICHANNEL_MAX); 1839 exit(EXIT_FAILURE); 1840 } 1841} 1842 1843int 1844init_config(char *filename) 1845{ 1846 FILE *fp; 1847 1848 fp = fopen(filename, "r"); 1849 if (!fp) 1850 return -1; 1851 1852 /* Zero may be a valid facility */ 1853 CONFIG(syslog_facility) = -1; 1854 CONFIG(stats).syslog_facility = -1; 1855 CONFIG(netlink).subsys_id = -1; 1856 1857 /* Initialize list of user-space helpers */ 1858 INIT_LIST_HEAD(&CONFIG(cthelper).list); 1859 1860 stack_init(&symbol_stack); 1861 1862 yyrestart(fp); 1863 yyparse(); 1864 fclose(fp); 1865 1866 /* default to IPv4 */ 1867 if (CONFIG(family) == 0) 1868 CONFIG(family) = AF_INET; 1869 1870 /* set to default is not specified */ 1871 if (strcmp(CONFIG(lockfile), "") == 0) 1872 strncpy(CONFIG(lockfile), DEFAULT_LOCKFILE, FILENAME_MAXLEN); 1873 1874 /* default to 180 seconds of expiration time: cache entries */ 1875 if (CONFIG(cache_timeout) == 0) 1876 CONFIG(cache_timeout) = 180; 1877 1878 /* default to 60 seconds: purge kernel entries */ 1879 if (CONFIG(purge_timeout) == 0) 1880 CONFIG(purge_timeout) = 60; 1881 1882 /* default to 60 seconds of refresh time */ 1883 if (CONFIG(refresh) == 0) 1884 CONFIG(refresh) = 60; 1885 1886 if (CONFIG(resend_queue_size) == 0) 1887 CONFIG(resend_queue_size) = 131072; 1888 1889 /* default to a window size of 300 packets */ 1890 if (CONFIG(window_size) == 0) 1891 CONFIG(window_size) = 300; 1892 1893 if (CONFIG(event_iterations_limit) == 0) 1894 CONFIG(event_iterations_limit) = 100; 1895 1896 /* default number of bucket of the hashtable that are committed in 1897 one run loop. XXX: no option available to tune this value yet. */ 1898 if (CONFIG(general).commit_steps == 0) 1899 CONFIG(general).commit_steps = 8192; 1900 1901 /* if overrun, automatically resync with kernel after 30 seconds */ 1902 if (CONFIG(nl_overrun_resync) == 0) 1903 CONFIG(nl_overrun_resync) = 30; 1904 1905 /* default to 128 elements in the channel error queue */ 1906 if (CONFIG(channelc).error_queue_length == 0) 1907 CONFIG(channelc).error_queue_length = 128; 1908 1909 if (CONFIG(netlink).subsys_id == -1) { 1910 CONFIG(netlink).subsys_id = NFNL_SUBSYS_CTNETLINK; 1911 CONFIG(netlink).groups = NF_NETLINK_CONNTRACK_NEW | 1912 NF_NETLINK_CONNTRACK_UPDATE | 1913 NF_NETLINK_CONNTRACK_DESTROY; 1914 } 1915 1916 return 0; 1917} 1918