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