1 %{ 2 /* 3 * Copyright (C) 2003 by Darren Reed. 4 * 5 * See the IPFILTER.LICENCE file for details on licencing. 6 * 7 * Copyright 2006 Sun Microsystems, Inc. All rights reserved. 8 * Use is subject to license terms. 9 */ 10 11 #include <sys/types.h> 12 #include <sys/time.h> 13 #include <sys/param.h> 14 #include <sys/socket.h> 15 #if defined(BSD) && (BSD >= 199306) 16 # include <sys/cdefs.h> 17 #endif 18 #include <sys/ioctl.h> 19 20 #include <net/if.h> 21 #if __FreeBSD_version >= 300000 22 # include <net/if_var.h> 23 #endif 24 #include <netinet/in.h> 25 26 #include <arpa/inet.h> 27 28 #include <stdio.h> 29 #include <fcntl.h> 30 #include <stdlib.h> 31 #include <string.h> 32 #include <netdb.h> 33 #include <ctype.h> 34 #include <unistd.h> 35 36 #include "ipf.h" 37 #include "netinet/ip_lookup.h" 38 #include "netinet/ip_pool.h" 39 #include "netinet/ip_htable.h" 40 #include "ippool_l.h" 41 #include "kmem.h" 42 43 #define YYDEBUG 1 44 45 extern int yyparse __P((void)); 46 extern int yydebug; 47 extern FILE *yyin; 48 49 static iphtable_t ipht; 50 static iphtent_t iphte; 51 static ip_pool_t iplo; 52 static ioctlfunc_t poolioctl = NULL; 53 static char poolname[FR_GROUPLEN]; 54 static int set_ipv6_addr = 0; 55 56 %} 57 58 %union { 59 char *str; 60 u_32_t num; 61 struct in_addr addr; 62 struct alist_s *alist; 63 union i6addr adrmsk[2]; 64 iphtent_t *ipe; 65 ip_pool_node_t *ipp; 66 union i6addr ip6; 67 } 68 69 %token <num> YY_NUMBER YY_HEX 70 %token <str> YY_STR 71 %token YY_COMMENT 72 %token YY_CMP_EQ YY_CMP_NE YY_CMP_LE YY_CMP_GE YY_CMP_LT YY_CMP_GT 73 %token YY_RANGE_OUT YY_RANGE_IN 74 %token <ip6> YY_IPV6 75 76 %token IPT_IPF IPT_NAT IPT_COUNT IPT_AUTH IPT_IN IPT_OUT 77 %token IPT_TABLE IPT_GROUPMAP IPT_HASH 78 %token IPT_ROLE IPT_TYPE IPT_TREE 79 %token IPT_GROUP IPT_SIZE IPT_SEED IPT_NUM IPT_NAME 80 %type <num> role table inout 81 %type <ipp> ipftree range addrlist 82 %type <adrmsk> addrmask 83 %type <ipe> ipfgroup ipfhash hashlist hashentry 84 %type <ipe> groupentry setgrouplist grouplist 85 %type <ip6> ipaddr mask ipv4 86 %type <str> number setgroup 87 88 %% 89 file: line 90 | assign 91 | file line 92 | file assign 93 ; 94 95 line: table role ipftree eol { iplo.ipo_unit = $2; 96 iplo.ipo_list = $3; 97 load_pool(&iplo, poolioctl); 98 resetlexer(); 99 } 100 | table role ipfhash eol { ipht.iph_unit = $2; 101 ipht.iph_type = IPHASH_LOOKUP; 102 load_hash(&ipht, $3, poolioctl); 103 resetlexer(); 104 } 105 | groupmap role number ipfgroup eol 106 { ipht.iph_unit = $2; 107 strncpy(ipht.iph_name, $3, 108 sizeof(ipht.iph_name)); 109 ipht.iph_type = IPHASH_GROUPMAP; 110 load_hash(&ipht, $4, poolioctl); 111 resetlexer(); 112 } 113 | YY_COMMENT 114 ; 115 116 eol: ';' 117 ; 118 119 assign: YY_STR assigning YY_STR ';' { set_variable($1, $3); 120 resetlexer(); 121 free($1); 122 free($3); 123 } 124 ; 125 126 assigning: 127 '=' { yyvarnext = 1; } 128 ; 129 130 table: IPT_TABLE { bzero((char *)&ipht, sizeof(ipht)); 131 bzero((char *)&iphte, sizeof(iphte)); 132 bzero((char *)&iplo, sizeof(iplo)); 133 *ipht.iph_name = '\0'; 134 iplo.ipo_flags = IPHASH_ANON; 135 iplo.ipo_name[0] = '\0'; 136 } 137 ; 138 139 groupmap: 140 IPT_GROUPMAP inout { bzero((char *)&ipht, sizeof(ipht)); 141 bzero((char *)&iphte, sizeof(iphte)); 142 *ipht.iph_name = '\0'; 143 ipht.iph_unit = IPHASH_GROUPMAP; 144 ipht.iph_flags = $2; 145 } 146 ; 147 148 inout: IPT_IN { $$ = FR_INQUE; } 149 | IPT_OUT { $$ = FR_OUTQUE; } 150 ; 151 role: 152 IPT_ROLE '=' IPT_IPF { $$ = IPL_LOGIPF; } 153 | IPT_ROLE '=' IPT_NAT { $$ = IPL_LOGNAT; } 154 | IPT_ROLE '=' IPT_AUTH { $$ = IPL_LOGAUTH; } 155 | IPT_ROLE '=' IPT_COUNT { $$ = IPL_LOGCOUNT; } 156 ; 157 158 ipftree: 159 IPT_TYPE '=' IPT_TREE number start addrlist end 160 { strncpy(iplo.ipo_name, $4, 161 sizeof(iplo.ipo_name)); 162 $$ = $6; 163 } 164 ; 165 166 ipfhash: 167 IPT_TYPE '=' IPT_HASH number hashopts start hashlist end 168 { strncpy(ipht.iph_name, $4, 169 sizeof(ipht.iph_name)); 170 $$ = $7; 171 } 172 ; 173 174 ipfgroup: 175 setgroup hashopts start grouplist end 176 { iphtent_t *e; 177 for (e = $4; e != NULL; 178 e = e->ipe_next) 179 if (e->ipe_group[0] == '\0') 180 strncpy(e->ipe_group, 181 $1, 182 FR_GROUPLEN); 183 $$ = $4; 184 } 185 | hashopts start setgrouplist end { $$ = $3; } 186 ; 187 188 number: IPT_NUM '=' YY_NUMBER { snprintf(poolname, FR_GROUPLEN, "%u", $3); 189 $$ = poolname; 190 } 191 | IPT_NAME '=' YY_STR { $$ = $3; } 192 | { $$ = ""; } 193 ; 194 195 setgroup: 196 IPT_GROUP '=' YY_STR { char tmp[FR_GROUPLEN+1]; 197 strncpy(tmp, $3, FR_GROUPLEN); 198 $$ = strdup(tmp); 199 } 200 | IPT_GROUP '=' YY_NUMBER { char tmp[FR_GROUPLEN+1]; 201 snprintf(tmp, FR_GROUPLEN, "%u", $3); 202 $$ = strdup(tmp); 203 } 204 ; 205 206 hashopts: 207 | size 208 | seed 209 | size seed 210 ; 211 212 addrlist: 213 ';' { $$ = NULL; } 214 | range next addrlist { $1->ipn_next = $3; $$ = $1; } 215 | range next { $$ = $1; } 216 | range 217 ; 218 219 grouplist: 220 ';' { $$ = NULL; } 221 | groupentry next grouplist { $$ = $1; $1->ipe_next = $3; } 222 | addrmask next grouplist { $$ = calloc(1, sizeof(iphtent_t)); 223 if ($$ == NULL) 224 yyerror("sorry, out of memory"); 225 if (set_ipv6_addr) 226 $$->ipe_family = AF_INET6; 227 else 228 $$->ipe_family = AF_INET; 229 bcopy((char *)&($1[0]), 230 (char *)&($$->ipe_addr), 231 sizeof($$->ipe_addr)); 232 bcopy((char *)&($1[1]), 233 (char *)&($$->ipe_mask), 234 sizeof($$->ipe_mask)); 235 set_ipv6_addr = 0; 236 $$->ipe_next = $3; 237 } 238 | groupentry next { $$ = $1; } 239 | addrmask next { $$ = calloc(1, sizeof(iphtent_t)); 240 if ($$ == NULL) 241 yyerror("sorry, out of memory"); 242 if (set_ipv6_addr) 243 $$->ipe_family = AF_INET6; 244 else 245 $$->ipe_family = AF_INET; 246 bcopy((char *)&($1[0]), 247 (char *)&($$->ipe_addr), 248 sizeof($$->ipe_addr)); 249 bcopy((char *)&($1[1]), 250 (char *)&($$->ipe_mask), 251 sizeof($$->ipe_mask)); 252 set_ipv6_addr = 0; 253 } 254 ; 255 256 setgrouplist: 257 ';' { $$ = NULL; } 258 | groupentry next { $$ = $1; } 259 | groupentry next setgrouplist { $1->ipe_next = $3; $$ = $1; } 260 ; 261 262 groupentry: 263 addrmask ',' setgroup { $$ = calloc(1, sizeof(iphtent_t)); 264 if ($$ == NULL) 265 yyerror("sorry, out of memory"); 266 if (set_ipv6_addr) 267 $$->ipe_family = AF_INET6; 268 else 269 $$->ipe_family = AF_INET; 270 bcopy((char *)&($1[0]), 271 (char *)&($$->ipe_addr), 272 sizeof($$->ipe_addr)); 273 bcopy((char *)&($1[1]), 274 (char *)&($$->ipe_mask), 275 sizeof($$->ipe_mask)); 276 set_ipv6_addr = 0; 277 strncpy($$->ipe_group, $3, 278 FR_GROUPLEN); 279 free($3); 280 } 281 ; 282 283 range: addrmask { $$ = calloc(1, sizeof(*$$)); 284 if ($$ == NULL) 285 yyerror("sorry, out of memory"); 286 $$->ipn_info = 0; 287 $$->ipn_addr.adf_len = sizeof($$->ipn_addr); 288 $$->ipn_mask.adf_len = sizeof($$->ipn_mask); 289 if (set_ipv6_addr) { 290 $$->ipn_addr.adf_family = AF_INET6; 291 $$->ipn_addr.adf_addr = $1[0]; 292 $$->ipn_mask.adf_addr = $1[1]; 293 294 } else { 295 $$->ipn_addr.adf_family = AF_INET; 296 $$->ipn_addr.adf_addr.in4.s_addr = $1[0].in4.s_addr; 297 $$->ipn_mask.adf_addr.in4.s_addr = $1[1].in4.s_addr; 298 } 299 set_ipv6_addr = 0; 300 } 301 | '!' addrmask { $$ = calloc(1, sizeof(*$$)); 302 if ($$ == NULL) 303 yyerror("sorry, out of memory"); 304 $$->ipn_info = 1; 305 $$->ipn_addr.adf_len = sizeof($$->ipn_addr); 306 $$->ipn_mask.adf_len = sizeof($$->ipn_mask); 307 if (set_ipv6_addr) { 308 $$->ipn_addr.adf_family = AF_INET6; 309 $$->ipn_addr.adf_addr = $2[0]; 310 $$->ipn_mask.adf_addr = $2[1]; 311 } else { 312 $$->ipn_addr.adf_family = AF_INET; 313 $$->ipn_addr.adf_addr.in4.s_addr = $2[0].in4.s_addr; 314 $$->ipn_mask.adf_addr.in4.s_addr = $2[1].in4.s_addr; 315 } 316 set_ipv6_addr = 0; 317 } 318 319 hashlist: 320 ';' { $$ = NULL; } 321 | hashentry next { $$ = $1; } 322 | hashentry next hashlist { $1->ipe_next = $3; $$ = $1; } 323 ; 324 325 hashentry: 326 addrmask { $$ = calloc(1, sizeof(iphtent_t)); 327 if ($$ == NULL) 328 yyerror("sorry, out of memory"); 329 if (set_ipv6_addr) 330 $$->ipe_family = AF_INET6; 331 else 332 $$->ipe_family = AF_INET; 333 bcopy((char *)&($1[0]), 334 (char *)&($$->ipe_addr), 335 sizeof($$->ipe_addr)); 336 bcopy((char *)&($1[1]), 337 (char *)&($$->ipe_mask), 338 sizeof($$->ipe_mask)); 339 } 340 ; 341 342 addrmask: 343 ipaddr '/' mask { $$[0] = $1; $$[1] = $3; 344 yyexpectaddr = 0; 345 } 346 | ipaddr { $$[0] = $1; 347 yyexpectaddr = 0; 348 if (set_ipv6_addr) 349 fill6bits(128, (u_32_t *)$$[1].in6.s6_addr); 350 else 351 $$[1].in4.s_addr = 0xffffffff; 352 } 353 ; 354 355 ipaddr: ipv4 { $$ = $1; } 356 | YY_NUMBER { $$.in4.s_addr = htonl($1); } 357 | YY_IPV6 { set_ipv6_addr = 1; 358 bcopy(&$1, &$$, sizeof($$)); 359 yyexpectaddr = 0; } 360 | YY_STR { if (gethost($1, &$$, 0) == -1) 361 yyerror("Unknown hostname"); 362 } 363 ; 364 365 mask: YY_NUMBER { if (set_ipv6_addr) 366 ntomask(6, $1, (u_32_t *)$$.in6.s6_addr); 367 else 368 ntomask(4, $1, (u_32_t *)&$$.in4.s_addr); } 369 | ipv4 { $$ = $1; } 370 ; 371 372 start: '{' { yyexpectaddr = 1; } 373 ; 374 375 end: '}' { yyexpectaddr = 0; } 376 ; 377 378 next: ',' { yyexpectaddr = 1; } 379 | ';' { yyexpectaddr = 1; } 380 ; 381 382 size: IPT_SIZE '=' YY_NUMBER { ipht.iph_size = $3; } 383 ; 384 385 seed: IPT_SEED '=' YY_NUMBER { ipht.iph_seed = $3; } 386 ; 387 388 ipv4: YY_NUMBER '.' YY_NUMBER '.' YY_NUMBER '.' YY_NUMBER 389 { if ($1 > 255 || $3 > 255 || $5 > 255 || $7 > 255) { 390 yyerror("Invalid octet string for IP address"); 391 return 0; 392 } 393 $$.in4.s_addr = ($1 << 24) | ($3 << 16) | ($5 << 8) | $7; 394 $$.in4.s_addr = htonl($$.in4.s_addr); 395 } 396 ; 397 %% 398 static wordtab_t yywords[] = { 399 { "auth", IPT_AUTH }, 400 { "count", IPT_COUNT }, 401 { "group", IPT_GROUP }, 402 { "group-map", IPT_GROUPMAP }, 403 { "hash", IPT_HASH }, 404 { "in", IPT_IN }, 405 { "ipf", IPT_IPF }, 406 { "name", IPT_NAME }, 407 { "nat", IPT_NAT }, 408 { "number", IPT_NUM }, 409 { "out", IPT_OUT }, 410 { "role", IPT_ROLE }, 411 { "seed", IPT_SEED }, 412 { "size", IPT_SIZE }, 413 { "table", IPT_TABLE }, 414 { "tree", IPT_TREE }, 415 { "type", IPT_TYPE }, 416 { NULL, 0 } 417 }; 418 419 420 int ippool_parsefile(fd, filename, iocfunc) 421 int fd; 422 char *filename; 423 ioctlfunc_t iocfunc; 424 { 425 FILE *fp = NULL; 426 char *s; 427 428 yylineNum = 1; 429 (void) yysettab(yywords); 430 431 s = getenv("YYDEBUG"); 432 if (s) 433 yydebug = atoi(s); 434 else 435 yydebug = 0; 436 437 if (strcmp(filename, "-")) { 438 fp = fopen(filename, "r"); 439 if (!fp) { 440 fprintf(stderr, "fopen(%s) failed: %s\n", filename, 441 STRERROR(errno)); 442 return -1; 443 } 444 } else 445 fp = stdin; 446 447 while (ippool_parsesome(fd, fp, iocfunc) == 1) 448 ; 449 if (fp != NULL) 450 fclose(fp); 451 return 0; 452 } 453 454 455 int ippool_parsesome(fd, fp, iocfunc) 456 int fd; 457 FILE *fp; 458 ioctlfunc_t iocfunc; 459 { 460 char *s; 461 int i; 462 463 poolioctl = iocfunc; 464 465 if (feof(fp)) 466 return 0; 467 i = fgetc(fp); 468 if (i == EOF) 469 return 0; 470 if (ungetc(i, fp) == EOF) 471 return 0; 472 if (feof(fp)) 473 return 0; 474 s = getenv("YYDEBUG"); 475 if (s) 476 yydebug = atoi(s); 477 else 478 yydebug = 0; 479 480 yyin = fp; 481 yyparse(); 482 return 1; 483 } 484