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