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