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 range next addrlist { $1->ipn_next = $3; $$ = $1; } 224 | range next { $$ = $1; } 225 | range ',' addrlist { $1->ipn_next = $3; $$ = $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 (set_ipv6_addr) 233 $$->ipe_family = AF_INET6; 234 else 235 $$->ipe_family = AF_INET; 236 bcopy((char *)&($1[0]), 237 (char *)&($$->ipe_addr), 238 sizeof($$->ipe_addr)); 239 bcopy((char *)&($1[1]), 240 (char *)&($$->ipe_mask), 241 sizeof($$->ipe_mask)); 242 set_ipv6_addr = 0; 243 $$->ipe_next = $3; } 244 | groupentry next { $$ = $1; } 245 | addrmask next { $$ = calloc(1, sizeof(iphtent_t)); 246 if (set_ipv6_addr) 247 $$->ipe_family = AF_INET6; 248 else 249 $$->ipe_family = AF_INET; 250 bcopy((char *)&($1[0]), 251 (char *)&($$->ipe_addr), 252 sizeof($$->ipe_addr)); 253 bcopy((char *)&($1[1]), 254 (char *)&($$->ipe_mask), 255 sizeof($$->ipe_mask)); 256 set_ipv6_addr = 0; 257 } 258 ; 259 260 setgrouplist: 261 groupentry next { $$ = $1; } 262 | groupentry next setgrouplist { $1->ipe_next = $3; $$ = $1; } 263 ; 264 265 groupentry: 266 addrmask ',' setgroup { $$ = calloc(1, sizeof(iphtent_t)); 267 if (set_ipv6_addr) 268 $$->ipe_family = AF_INET6; 269 else 270 $$->ipe_family = AF_INET; 271 bcopy((char *)&($1[0]), 272 (char *)&($$->ipe_addr), 273 sizeof($$->ipe_addr)); 274 bcopy((char *)&($1[1]), 275 (char *)&($$->ipe_mask), 276 sizeof($$->ipe_mask)); 277 set_ipv6_addr = 0; 278 strncpy($$->ipe_group, $3, FR_GROUPLEN); 279 free($3); } 280 281 ; 282 283 range: addrmask { $$ = calloc(1, sizeof(*$$)); 284 $$->ipn_info = 0; 285 if (set_ipv6_addr) { 286 $$->ipn_addr.adf_family = AF_INET6; 287 $$->ipn_addr.adf_addr = $1[0]; 288 $$->ipn_mask.adf_addr = $1[1]; 289 290 } else { 291 $$->ipn_addr.adf_family = AF_INET; 292 $$->ipn_addr.adf_addr.in4.s_addr = $1[0].in4.s_addr; 293 $$->ipn_mask.adf_addr.in4.s_addr = $1[1].in4.s_addr; 294 } 295 set_ipv6_addr = 0; 296 } 297 | '!' addrmask { $$ = calloc(1, sizeof(*$$)); 298 $$->ipn_info = 1; 299 if (set_ipv6_addr) { 300 $$->ipn_addr.adf_family = AF_INET6; 301 $$->ipn_addr.adf_addr = $2[0]; 302 $$->ipn_mask.adf_addr = $2[1]; 303 } else { 304 $$->ipn_addr.adf_family = AF_INET; 305 $$->ipn_addr.adf_addr.in4.s_addr = $2[0].in4.s_addr; 306 $$->ipn_mask.adf_addr.in4.s_addr = $2[1].in4.s_addr; 307 } 308 set_ipv6_addr = 0; 309 } 310 311 hashlist: 312 hashentry next { $$ = $1; } 313 | hashentry next hashlist { $1->ipe_next = $3; $$ = $1; } 314 ; 315 316 hashentry: 317 addrmask { $$ = calloc(1, sizeof(iphtent_t)); 318 if (set_ipv6_addr) 319 $$->ipe_family = AF_INET6; 320 else 321 $$->ipe_family = AF_INET; 322 bcopy((char *)&($1[0]), 323 (char *)&($$->ipe_addr), 324 sizeof($$->ipe_addr)); 325 bcopy((char *)&($1[1]), 326 (char *)&($$->ipe_mask), 327 sizeof($$->ipe_mask)); 328 set_ipv6_addr = 0; 329 } 330 ; 331 332 addrmask: 333 ipaddr '/' mask { $$[0] = $1; $$[1] = $3; } 334 | ipaddr { $$[0] = $1; 335 if (set_ipv6_addr) 336 fill6bits(128, (u_32_t *)$$[1].in6.s6_addr); 337 else 338 $$[1].in4.s_addr = 0xffffffff; } 339 ; 340 341 ipaddr: ipv4 { $$ = $1; } 342 | YY_NUMBER { $$.in4.s_addr = htonl($1); } 343 | YY_IPV6 { set_ipv6_addr = 1; 344 bcopy(&$1, &$$, sizeof($$)); 345 yyexpectaddr = 0; } 346 ; 347 348 mask: YY_NUMBER { if (set_ipv6_addr) 349 ntomask(6, $1, (u_32_t *)$$.in6.s6_addr); 350 else 351 ntomask(4, $1, (u_32_t *)&$$.in4.s_addr); 352 } 353 | ipv4 { $$ = $1; } 354 ; 355 356 size: IPT_SIZE '=' YY_NUMBER { ipht.iph_size = $3; } 357 ; 358 359 seed: IPT_SEED '=' YY_NUMBER { ipht.iph_seed = $3; } 360 ; 361 362 ipv4: YY_NUMBER '.' YY_NUMBER '.' YY_NUMBER '.' YY_NUMBER 363 { if ($1 > 255 || $3 > 255 || $5 > 255 || $7 > 255) { 364 yyerror("Invalid octet string for IP address"); 365 return 0; 366 } 367 $$.in4.s_addr = ($1 << 24) | ($3 << 16) | ($5 << 8) | $7; 368 $$.in4.s_addr = htonl($$.in4.s_addr); 369 } 370 ; 371 372 next: ';' { yyexpectaddr = 1; } 373 ; 374 375 376 %% 377 static wordtab_t yywords[] = { 378 { "auth", IPT_AUTH }, 379 { "count", IPT_COUNT }, 380 { "group", IPT_GROUP }, 381 { "group-map", IPT_GROUPMAP }, 382 { "hash", IPT_HASH }, 383 { "in", IPT_IN }, 384 { "ipf", IPT_IPF }, 385 { "name", IPT_NAME }, 386 { "nat", IPT_NAT }, 387 { "number", IPT_NUM }, 388 { "out", IPT_OUT }, 389 { "role", IPT_ROLE }, 390 { "seed", IPT_SEED }, 391 { "size", IPT_SIZE }, 392 { "table", IPT_TABLE }, 393 { "tree", IPT_TREE }, 394 { "type", IPT_TYPE }, 395 { NULL, 0 } 396 }; 397 398 399 int ippool_parsefile(fd, filename, iocfunc) 400 int fd; 401 char *filename; 402 ioctlfunc_t iocfunc; 403 { 404 FILE *fp = NULL; 405 char *s; 406 407 yylineNum = 1; 408 (void) yysettab(yywords); 409 410 s = getenv("YYDEBUG"); 411 if (s) 412 yydebug = atoi(s); 413 else 414 yydebug = 0; 415 416 if (strcmp(filename, "-")) { 417 fp = fopen(filename, "r"); 418 if (!fp) { 419 fprintf(stderr, "fopen(%s) failed: %s\n", filename, 420 STRERROR(errno)); 421 return -1; 422 } 423 } else 424 fp = stdin; 425 426 while (ippool_parsesome(fd, fp, iocfunc) == 1) 427 ; 428 if (fp != NULL) 429 fclose(fp); 430 return 0; 431 } 432 433 434 int ippool_parsesome(fd, fp, iocfunc) 435 int fd; 436 FILE *fp; 437 ioctlfunc_t iocfunc; 438 { 439 char *s; 440 int i; 441 442 poolioctl = iocfunc; 443 444 if (feof(fp)) 445 return 0; 446 i = fgetc(fp); 447 if (i == EOF) 448 return 0; 449 if (ungetc(i, fp) == EOF) 450 return 0; 451 if (feof(fp)) 452 return 0; 453 s = getenv("YYDEBUG"); 454 if (s) 455 yydebug = atoi(s); 456 else 457 yydebug = 0; 458 459 yyin = fp; 460 yyparse(); 461 return 1; 462 } 463