1 /*
   2  * Copyright (C) 1993-2005  by Darren Reed.
   3  * See the IPFILTER.LICENCE file for details on licencing.
   4  */ 
   5 
   6 %{
   7 #include "ipf.h"
   8 #include <syslog.h>
   9 #undef  OPT_NAT
  10 #undef  OPT_VERBOSE
  11 #include "ipmon_l.h"
  12 #include "ipmon.h"
  13 
  14 #define YYDEBUG 1
  15 
  16 extern  void    yyerror __P((char *));
  17 extern  int     yyparse __P((void));
  18 extern  int     yylex __P((void));
  19 extern  int     yydebug;
  20 extern  FILE    *yyin;
  21 extern  int     yylineNum;
  22 
  23 typedef struct  opt     {
  24         struct  opt     *o_next;
  25         int             o_line;
  26         int             o_type;
  27         int             o_num;
  28         char            *o_str;
  29         struct in_addr  o_ip;
  30 } opt_t;
  31 
  32 static  void    build_action __P((struct opt *));
  33 static  opt_t   *new_opt __P((int));
  34 static  void    free_action __P((ipmon_action_t *));
  35 
  36 static  ipmon_action_t  *alist = NULL;
  37 %}
  38 
  39 %union  {
  40         char    *str;
  41         u_32_t  num;
  42         struct in_addr  addr;
  43         struct opt      *opt;
  44         union   i6addr  ip6;
  45 }
  46 
  47 %token  <num>     YY_NUMBER YY_HEX
  48 %token  <str>     YY_STR
  49 %token  <ip6>     YY_IPV6
  50 %token  YY_COMMENT 
  51 %token  YY_CMP_EQ YY_CMP_NE YY_CMP_LE YY_CMP_GE YY_CMP_LT YY_CMP_GT
  52 %token  YY_RANGE_OUT YY_RANGE_IN
  53 
  54 %token  IPM_MATCH IPM_BODY IPM_COMMENT IPM_DIRECTION IPM_DSTIP IPM_DSTPORT
  55 %token  IPM_EVERY IPM_EXECUTE IPM_GROUP IPM_INTERFACE IPM_IN IPM_NO IPM_OUT
  56 %token  IPM_PACKET IPM_PACKETS IPM_POOL IPM_PROTOCOL IPM_RESULT IPM_RULE
  57 %token  IPM_SECOND IPM_SECONDS IPM_SRCIP IPM_SRCPORT IPM_LOGTAG IPM_WITH
  58 %token  IPM_DO IPM_SAVE IPM_SYSLOG IPM_NOTHING IPM_RAW IPM_TYPE IPM_NAT
  59 %token  IPM_STATE IPM_NATTAG IPM_IPF
  60 %type   <addr> ipv4
  61 %type   <opt> direction dstip dstport every execute group interface
  62 %type   <opt> protocol result rule srcip srcport logtag matching
  63 %type   <opt> matchopt nattag type doopt doing save syslog nothing
  64 %type   <num> saveopts saveopt typeopt
  65 
  66 %%
  67 file:   line
  68         | assign
  69         | file line
  70         | file assign
  71         ;
  72 
  73 line:   IPM_MATCH '{' matching '}' IPM_DO '{' doing '}' ';'
  74                                         { build_action($3); resetlexer(); }
  75         | IPM_COMMENT
  76         | YY_COMMENT
  77         ;
  78 
  79 assign: YY_STR assigning YY_STR ';'             { set_variable($1, $3);
  80                                                   resetlexer();
  81                                                   free($1);
  82                                                   free($3);
  83                                                 } 
  84         ;
  85 
  86 assigning:
  87         '='                                     { yyvarnext = 1; }
  88         ;
  89 
  90 matching:
  91         matchopt                                { $$ = $1; }
  92         | matchopt ',' matching                 { $1->o_next = $3; $$ = $1; }
  93         ;
  94 
  95 matchopt:
  96         direction                               { $$ = $1; }
  97         | dstip                                 { $$ = $1; }
  98         | dstport                               { $$ = $1; }
  99         | every                                 { $$ = $1; }
 100         | group                                 { $$ = $1; }
 101         | interface                             { $$ = $1; }
 102         | protocol                              { $$ = $1; }
 103         | result                                { $$ = $1; }
 104         | rule                                  { $$ = $1; }
 105         | srcip                                 { $$ = $1; }
 106         | srcport                               { $$ = $1; }
 107         | logtag                                { $$ = $1; }
 108         | nattag                                { $$ = $1; }
 109         | type                                  { $$ = $1; }
 110         ;
 111 
 112 doing:
 113         doopt                                   { $$ = $1; }
 114         | doopt ',' doing                       { $1->o_next = $3; $$ = $1; }
 115         ;
 116 
 117 doopt:
 118         execute                                 { $$ = $1; }
 119         | save                                  { $$ = $1; }
 120         | syslog                                { $$ = $1; }
 121         | nothing                               { $$ = $1; }
 122         ;
 123 
 124 direction:
 125         IPM_DIRECTION '=' IPM_IN                { $$ = new_opt(IPM_DIRECTION);
 126                                                   $$->o_num = IPM_IN; }
 127         | IPM_DIRECTION '=' IPM_OUT             { $$ = new_opt(IPM_DIRECTION);
 128                                                   $$->o_num = IPM_OUT; }
 129         ;
 130 
 131 dstip:  IPM_DSTIP '=' ipv4 '/' YY_NUMBER        { $$ = new_opt(IPM_DSTIP);
 132                                                   $$->o_ip = $3;
 133                                                   $$->o_num = $5; }
 134         ;
 135 
 136 dstport:
 137         IPM_DSTPORT '=' YY_NUMBER               { $$ = new_opt(IPM_DSTPORT);
 138                                                   $$->o_num = $3; }
 139         | IPM_DSTPORT '=' YY_STR                { $$ = new_opt(IPM_DSTPORT);
 140                                                   $$->o_str = $3; }
 141         ;
 142 
 143 every:  IPM_EVERY IPM_SECOND                    { $$ = new_opt(IPM_SECOND);
 144                                                   $$->o_num = 1; }
 145         | IPM_EVERY YY_NUMBER IPM_SECONDS       { $$ = new_opt(IPM_SECOND);
 146                                                   $$->o_num = $2; }
 147         | IPM_EVERY IPM_PACKET                  { $$ = new_opt(IPM_PACKET);
 148                                                   $$->o_num = 1; }
 149         | IPM_EVERY YY_NUMBER IPM_PACKETS       { $$ = new_opt(IPM_PACKET);
 150                                                   $$->o_num = $2; }
 151         ;
 152 
 153 group:  IPM_GROUP '=' YY_NUMBER                 { $$ = new_opt(IPM_GROUP);
 154                                                   $$->o_num = $3; }
 155         | IPM_GROUP '=' YY_STR                  { $$ = new_opt(IPM_GROUP);
 156                                                   $$->o_str = $3; }
 157         ;
 158 
 159 interface:
 160         IPM_INTERFACE '=' YY_STR                { $$ = new_opt(IPM_INTERFACE);
 161                                                   $$->o_str = $3; }
 162         ;
 163 
 164 logtag: IPM_LOGTAG '=' YY_NUMBER                { $$ = new_opt(IPM_LOGTAG);
 165                                                   $$->o_num = $3; }
 166         ;
 167 
 168 nattag: IPM_NATTAG '=' YY_STR                   { $$ = new_opt(IPM_NATTAG);
 169                                                   $$->o_str = $3; }
 170         ;
 171 
 172 protocol:
 173         IPM_PROTOCOL '=' YY_NUMBER              { $$ = new_opt(IPM_PROTOCOL);
 174                                                   $$->o_num = $3; }
 175         | IPM_PROTOCOL '=' YY_STR               { $$ = new_opt(IPM_PROTOCOL);
 176                                                   $$->o_num = getproto($3);
 177                                                   free($3);
 178                                                 }
 179         ;
 180 
 181 result: IPM_RESULT '=' YY_STR                   { $$ = new_opt(IPM_RESULT);
 182                                                   $$->o_str = $3; }
 183         ;
 184 
 185 rule:   IPM_RULE '=' YY_NUMBER                  { $$ = new_opt(IPM_RULE);
 186                                                   $$->o_num = YY_NUMBER; }
 187         ;
 188 
 189 srcip:  IPM_SRCIP '=' ipv4 '/' YY_NUMBER        { $$ = new_opt(IPM_SRCIP);
 190                                                   $$->o_ip = $3;
 191                                                   $$->o_num = $5; }
 192         ;
 193 
 194 srcport:
 195         IPM_SRCPORT '=' YY_NUMBER               { $$ = new_opt(IPM_SRCPORT);
 196                                                   $$->o_num = $3; }
 197         | IPM_SRCPORT '=' YY_STR                { $$ = new_opt(IPM_SRCPORT);
 198                                                   $$->o_str = $3; }
 199         ;
 200 
 201 type:   IPM_TYPE '=' typeopt                    { $$ = new_opt(IPM_TYPE);
 202                                                   $$->o_num = $3; }
 203         ;
 204 
 205 typeopt:
 206         IPM_IPF                                 { $$ = IPL_MAGIC; }
 207         | IPM_NAT                               { $$ = IPL_MAGIC_NAT; }
 208         | IPM_STATE                             { $$ = IPL_MAGIC_STATE; }
 209         ;
 210 
 211 execute:
 212         IPM_EXECUTE YY_STR                      { $$ = new_opt(IPM_EXECUTE);
 213                                                   $$->o_str = $2; }
 214         ;
 215 
 216 save:   IPM_SAVE saveopts YY_STR                { $$ = new_opt(IPM_SAVE);
 217                                                   $$->o_num = $2;
 218                                                   $$->o_str = $3; }
 219         ;
 220 
 221 saveopts:                                       { $$ = 0; }
 222         | saveopt                               { $$ = $1; }
 223         | saveopt ',' saveopts                  { $$ = $1 | $3; }
 224         ;
 225 
 226 saveopt:
 227         IPM_RAW                                 { $$ = IPMDO_SAVERAW; }
 228         ;
 229 
 230 syslog: IPM_SYSLOG                              { $$ = new_opt(IPM_SYSLOG); }
 231         ;
 232 
 233 nothing:
 234         IPM_NOTHING                             { $$ = 0; }
 235         ;
 236 
 237 ipv4:   YY_NUMBER '.' YY_NUMBER '.' YY_NUMBER '.' YY_NUMBER
 238                 { if ($1 > 255 || $3 > 255 || $5 > 255 || $7 > 255) {
 239                         yyerror("Invalid octet string for IP address");
 240                         return 0;
 241                   }
 242                   $$.s_addr = ($1 << 24) | ($3 << 16) | ($5 << 8) | $7;
 243                   $$.s_addr = htonl($$.s_addr);
 244                 }
 245 %%
 246 static  struct  wordtab yywords[] = {
 247         { "body",       IPM_BODY },
 248         { "direction",  IPM_DIRECTION },
 249         { "do",         IPM_DO },
 250         { "dstip",      IPM_DSTIP },
 251         { "dstport",    IPM_DSTPORT },
 252         { "every",      IPM_EVERY },
 253         { "execute",    IPM_EXECUTE },
 254         { "group",      IPM_GROUP },
 255         { "in",         IPM_IN },
 256         { "interface",  IPM_INTERFACE },
 257         { "ipf",        IPM_IPF },
 258         { "logtag",     IPM_LOGTAG },
 259         { "match",      IPM_MATCH },
 260         { "nat",        IPM_NAT },
 261         { "nattag",     IPM_NATTAG },
 262         { "no",         IPM_NO },
 263         { "nothing",    IPM_NOTHING },
 264         { "out",        IPM_OUT },
 265         { "packet",     IPM_PACKET },
 266         { "packets",    IPM_PACKETS },
 267         { "protocol",   IPM_PROTOCOL },
 268         { "result",     IPM_RESULT },
 269         { "rule",       IPM_RULE },
 270         { "save",       IPM_SAVE },
 271         { "raw",        IPM_RAW },
 272         { "second",     IPM_SECOND },
 273         { "seconds",    IPM_SECONDS },
 274         { "srcip",      IPM_SRCIP },
 275         { "srcport",    IPM_SRCPORT },
 276         { "state",      IPM_STATE },
 277         { "syslog",     IPM_SYSLOG },
 278         { "with",       IPM_WITH },
 279         { NULL,         0 }
 280 };
 281 
 282 static int macflags[17][2] = {
 283         { IPM_DIRECTION,        IPMAC_DIRECTION },
 284         { IPM_DSTIP,            IPMAC_DSTIP     },
 285         { IPM_DSTPORT,          IPMAC_DSTPORT   },
 286         { IPM_GROUP,            IPMAC_GROUP     },
 287         { IPM_INTERFACE,        IPMAC_INTERFACE },
 288         { IPM_LOGTAG,           IPMAC_LOGTAG    },
 289         { IPM_NATTAG,           IPMAC_NATTAG    },
 290         { IPM_PACKET,           IPMAC_EVERY     },
 291         { IPM_PROTOCOL,         IPMAC_PROTOCOL  },
 292         { IPM_RESULT,           IPMAC_RESULT    },
 293         { IPM_RULE,             IPMAC_RULE      },
 294         { IPM_SECOND,           IPMAC_EVERY     },
 295         { IPM_SRCIP,            IPMAC_SRCIP     },
 296         { IPM_SRCPORT,          IPMAC_SRCPORT   },
 297         { IPM_TYPE,             IPMAC_TYPE      },
 298         { IPM_WITH,             IPMAC_WITH      },
 299         { 0, 0 }
 300 };
 301 
 302 static opt_t *new_opt(type)
 303 int type;
 304 {
 305         opt_t *o;
 306 
 307         o = (opt_t *)malloc(sizeof(*o));
 308         if (o == NULL)
 309                 yyerror("sorry, out of memory");
 310         o->o_type = type;
 311         o->o_line = yylineNum;
 312         o->o_num = 0;
 313         o->o_str = (char *)0;
 314         o->o_next = NULL;
 315         return o;
 316 }
 317 
 318 static void build_action(olist)
 319 opt_t *olist;
 320 {
 321         ipmon_action_t *a;
 322         opt_t *o;
 323         char c;
 324         int i;
 325 
 326         a = (ipmon_action_t *)calloc(1, sizeof(*a));
 327         if (a == NULL)
 328                 return;
 329         while ((o = olist) != NULL) {
 330                 /*
 331                  * Check to see if the same comparator is being used more than
 332                  * once per matching statement.
 333                  */
 334                 for (i = 0; macflags[i][0]; i++)
 335                         if (macflags[i][0] == o->o_type)
 336                                 break;
 337                 if (macflags[i][1] & a->ac_mflag) {
 338                         fprintf(stderr, "%s redfined on line %d\n",
 339                                 yykeytostr(o->o_type), yylineNum);
 340                         if (o->o_str != NULL)
 341                                 free(o->o_str);
 342                         olist = o->o_next;
 343                         free(o);
 344                         continue;
 345                 }
 346 
 347                 a->ac_mflag |= macflags[i][1];
 348 
 349                 switch (o->o_type)
 350                 {
 351                 case IPM_DIRECTION :
 352                         a->ac_direction = o->o_num;
 353                         break;
 354                 case IPM_DSTIP :
 355                         a->ac_dip = o->o_ip.s_addr;
 356                         a->ac_dmsk = htonl(0xffffffff << (32 - o->o_num));
 357                         break;
 358                 case IPM_DSTPORT :
 359                         a->ac_dport = htons(o->o_num);
 360                         break;
 361                 case IPM_EXECUTE :
 362                         a->ac_exec = o->o_str;
 363                         c = *o->o_str;
 364                         if (c== '"'|| c == '\'') {
 365                                 if (o->o_str[strlen(o->o_str) - 1] == c) {
 366                                         a->ac_run = strdup(o->o_str + 1);
 367                                         a->ac_run[strlen(a->ac_run) - 1] ='\0';
 368                                 } else
 369                                         a->ac_run = o->o_str;
 370                         } else
 371                                 a->ac_run = o->o_str;
 372                         o->o_str = NULL;
 373                         break;
 374                 case IPM_INTERFACE :
 375                         a->ac_iface = o->o_str;
 376                         o->o_str = NULL;
 377                         break;
 378                 case IPM_GROUP : 
 379                         if (o->o_str != NULL)
 380                                 strncpy(a->ac_group, o->o_str, FR_GROUPLEN);
 381                         else
 382                                 sprintf(a->ac_group, "%d", o->o_num);
 383                         break;
 384                 case IPM_LOGTAG :
 385                         a->ac_logtag = o->o_num;
 386                         break;
 387                 case IPM_NATTAG :
 388                         strncpy(a->ac_nattag, o->o_str, sizeof(a->ac_nattag));
 389                         break;
 390                 case IPM_PACKET :
 391                         a->ac_packet = o->o_num;
 392                         break;
 393                 case IPM_PROTOCOL :
 394                         a->ac_proto = o->o_num;
 395                         break;
 396                 case IPM_RULE :
 397                         a->ac_rule = o->o_num;
 398                         break;
 399                 case IPM_RESULT :
 400                         if (!strcasecmp(o->o_str, "pass"))
 401                                 a->ac_result = IPMR_PASS;
 402                         else if (!strcasecmp(o->o_str, "block"))
 403                                 a->ac_result = IPMR_BLOCK;
 404                         else if (!strcasecmp(o->o_str, "nomatch"))
 405                                 a->ac_result = IPMR_NOMATCH;
 406                         else if (!strcasecmp(o->o_str, "log"))
 407                                 a->ac_result = IPMR_LOG;
 408                         break;
 409                 case IPM_SECOND :
 410                         a->ac_second = o->o_num;
 411                         break;
 412                 case IPM_SRCIP :
 413                         a->ac_sip = o->o_ip.s_addr;
 414                         a->ac_smsk = htonl(0xffffffff << (32 - o->o_num));
 415                         break;
 416                 case IPM_SRCPORT :
 417                         a->ac_sport = htons(o->o_num);
 418                         break;
 419                 case IPM_SAVE :
 420                         if (a->ac_savefile != NULL) {
 421                                 fprintf(stderr, "%s redfined on line %d\n",
 422                                         yykeytostr(o->o_type), yylineNum);
 423                                 break;
 424                         }
 425                         a->ac_savefile = strdup(o->o_str);
 426                         a->ac_savefp = fopen(o->o_str, "a");
 427                         a->ac_dflag |= o->o_num & IPMDO_SAVERAW;
 428                         break;
 429                 case IPM_SYSLOG :
 430                         if (a->ac_syslog != 0) {
 431                                 fprintf(stderr, "%s redfined on line %d\n",
 432                                         yykeytostr(o->o_type), yylineNum);
 433                                 break;
 434                         }
 435                         a->ac_syslog = 1;
 436                         break;
 437                 case IPM_TYPE :
 438                         a->ac_type = o->o_num;
 439                         break;
 440                 case IPM_WITH :
 441                         break;
 442                 default :
 443                         break;
 444                 }
 445 
 446                 olist = o->o_next;
 447                 if (o->o_str != NULL)
 448                         free(o->o_str);
 449                 free(o);
 450         }
 451         a->ac_next = alist;
 452         alist = a;
 453 }
 454 
 455 
 456 int check_action(buf, log, opts, lvl)
 457 char *buf, *log;
 458 int opts, lvl;
 459 {
 460         ipmon_action_t *a;
 461         struct timeval tv;
 462         ipflog_t *ipf;
 463         tcphdr_t *tcp;
 464         iplog_t *ipl;
 465         int matched;
 466         u_long t1;
 467         ip_t *ip;
 468 
 469         matched = 0;
 470         ipl = (iplog_t *)buf;
 471         ipf = (ipflog_t *)(ipl +1);
 472         ip = (ip_t *)(ipf + 1);
 473         tcp = (tcphdr_t *)((char *)ip + (IP_HL(ip) << 2));
 474 
 475         for (a = alist; a != NULL; a = a->ac_next) {
 476                 if ((a->ac_mflag & IPMAC_DIRECTION) != 0) {
 477                         if (a->ac_direction == IPM_IN) {
 478                                 if ((ipf->fl_flags & FR_INQUE) == 0)
 479                                         continue;
 480                         } else if (a->ac_direction == IPM_OUT) {
 481                                 if ((ipf->fl_flags & FR_OUTQUE) == 0)
 482                                         continue;
 483                         }
 484                 }
 485 
 486                 if ((a->ac_type != 0) && (a->ac_type != ipl->ipl_magic))
 487                         continue;
 488 
 489                 if ((a->ac_mflag & IPMAC_EVERY) != 0) {
 490                         gettimeofday(&tv, NULL);
 491                         t1 = tv.tv_sec - a->ac_lastsec;
 492                         if (tv.tv_usec <= a->ac_lastusec)
 493                                 t1--;
 494                         if (a->ac_second != 0) {
 495                                 if (t1 < a->ac_second)
 496                                         continue;
 497                                 a->ac_lastsec = tv.tv_sec;
 498                                 a->ac_lastusec = tv.tv_usec;
 499                         }
 500 
 501                         if (a->ac_packet != 0) {
 502                                 if (a->ac_pktcnt == 0)
 503                                         a->ac_pktcnt++;
 504                                 else if (a->ac_pktcnt == a->ac_packet) {
 505                                         a->ac_pktcnt = 0;
 506                                         continue;
 507                                 } else {
 508                                         a->ac_pktcnt++;
 509                                         continue;
 510                                 }
 511                         }
 512                 }
 513 
 514                 if ((a->ac_mflag & IPMAC_DSTIP) != 0) {
 515                         if ((ip->ip_dst.s_addr & a->ac_dmsk) != a->ac_dip)
 516                                 continue;
 517                 }
 518 
 519                 if ((a->ac_mflag & IPMAC_DSTPORT) != 0) {
 520                         if (ip->ip_p != IPPROTO_UDP && ip->ip_p != IPPROTO_TCP)
 521                                 continue;
 522                         if (tcp->th_dport != a->ac_dport)
 523                                 continue;
 524                 }
 525 
 526                 if ((a->ac_mflag & IPMAC_GROUP) != 0) {
 527                         if (strncmp(a->ac_group, ipf->fl_group,
 528                                     FR_GROUPLEN) != 0)
 529                                 continue;
 530                 }
 531 
 532                 if ((a->ac_mflag & IPMAC_INTERFACE) != 0) {
 533                         if (strcmp(a->ac_iface, ipf->fl_ifname))
 534                                 continue;
 535                 }
 536 
 537                 if ((a->ac_mflag & IPMAC_PROTOCOL) != 0) {
 538                         if (a->ac_proto != ip->ip_p)
 539                                 continue;
 540                 }
 541 
 542                 if ((a->ac_mflag & IPMAC_RESULT) != 0) {
 543                         if ((ipf->fl_flags & FF_LOGNOMATCH) != 0) {
 544                                 if (a->ac_result != IPMR_NOMATCH)
 545                                         continue;
 546                         } else if (FR_ISPASS(ipf->fl_flags)) {
 547                                 if (a->ac_result != IPMR_PASS)
 548                                         continue;
 549                         } else if (FR_ISBLOCK(ipf->fl_flags)) {
 550                                 if (a->ac_result != IPMR_BLOCK)
 551                                         continue;
 552                         } else {        /* Log only */
 553                                 if (a->ac_result != IPMR_LOG)
 554                                         continue;
 555                         }
 556                 }
 557 
 558                 if ((a->ac_mflag & IPMAC_RULE) != 0) {
 559                         if (a->ac_rule != ipf->fl_rule)
 560                                 continue;
 561                 }
 562 
 563                 if ((a->ac_mflag & IPMAC_SRCIP) != 0) {
 564                         if ((ip->ip_src.s_addr & a->ac_smsk) != a->ac_sip)
 565                                 continue;
 566                 }
 567 
 568                 if ((a->ac_mflag & IPMAC_SRCPORT) != 0) {
 569                         if (ip->ip_p != IPPROTO_UDP && ip->ip_p != IPPROTO_TCP)
 570                                 continue;
 571                         if (tcp->th_sport != a->ac_sport)
 572                                 continue;
 573                 }
 574 
 575                 if ((a->ac_mflag & IPMAC_LOGTAG) != 0) {
 576                         if (a->ac_logtag != ipf->fl_logtag)
 577                                 continue;
 578                 }
 579 
 580                 if ((a->ac_mflag & IPMAC_NATTAG) != 0) {
 581                         if (strncmp(a->ac_nattag, ipf->fl_nattag.ipt_tag,
 582                                     IPFTAG_LEN) != 0)
 583                                 continue;
 584                 }
 585 
 586                 matched = 1;
 587 
 588                 /*
 589                  * It matched so now execute the command
 590                  */
 591                 if (a->ac_syslog != 0) {
 592                         syslog(lvl, "%s", log);
 593                 }
 594 
 595                 if (a->ac_savefp != NULL) {
 596                         if (a->ac_dflag & IPMDO_SAVERAW)
 597                                 fwrite(ipl, 1, ipl->ipl_dsize, a->ac_savefp);
 598                         else
 599                                 fputs(log, a->ac_savefp);
 600                 }
 601 
 602                 if (a->ac_exec != NULL) {
 603                         switch (fork())
 604                         {
 605                         case 0 :
 606                         {
 607                                 FILE *pi;
 608 
 609                                 pi = popen(a->ac_run, "w");
 610                                 if (pi != NULL) {
 611                                         fprintf(pi, "%s\n", log);
 612                                         if ((opts & OPT_HEXHDR) != 0) {
 613                                                 dumphex(pi, 0, buf,
 614                                                         sizeof(*ipl) +
 615                                                         sizeof(*ipf));
 616                                         }
 617                                         if ((opts & OPT_HEXBODY) != 0) {
 618                                                 dumphex(pi, 0, (char *)ip,
 619                                                         ipf->fl_hlen +
 620                                                         ipf->fl_plen);
 621                                         }
 622                                         pclose(pi);
 623                                 }
 624                                 exit(1);
 625                         }
 626                         case -1 :
 627                                 break;
 628                         default :
 629                                 break;
 630                         }
 631                 }
 632         }
 633 
 634         return matched;
 635 }
 636 
 637 
 638 static void free_action(a)
 639 ipmon_action_t *a;
 640 {
 641         if (a->ac_savefile != NULL) {
 642                 free(a->ac_savefile);
 643                 a->ac_savefile = NULL;
 644         }
 645         if (a->ac_savefp != NULL) {
 646                 fclose(a->ac_savefp);
 647                 a->ac_savefp = NULL;
 648         }
 649         if (a->ac_exec != NULL) {
 650                 free(a->ac_exec);
 651                 if (a->ac_run == a->ac_exec)
 652                         a->ac_run = NULL;
 653                 a->ac_exec = NULL;
 654         }
 655         if (a->ac_run != NULL) {
 656                 free(a->ac_run);
 657                 a->ac_run = NULL;
 658         }
 659         if (a->ac_iface != NULL) {
 660                 free(a->ac_iface);
 661                 a->ac_iface = NULL;
 662         }
 663         a->ac_next = NULL;
 664         free(a);
 665 }
 666 
 667 
 668 int load_config(file)
 669 char *file;
 670 {
 671         ipmon_action_t *a;
 672         FILE *fp;
 673         char *s;
 674 
 675         s = getenv("YYDEBUG");
 676         if (s != NULL)
 677                 yydebug = atoi(s);
 678         else
 679                 yydebug = 0;
 680 
 681         while ((a = alist) != NULL) {
 682                 alist = a->ac_next;
 683                 free_action(a);
 684         }
 685 
 686         yylineNum = 1;
 687 
 688         (void) yysettab(yywords);
 689 
 690         fp = fopen(file, "r");
 691         if (!fp) {
 692                 perror("load_config:fopen:");
 693                 return -1;
 694         }
 695         yyin = fp;
 696         while (!feof(fp))
 697                 yyparse();
 698         fclose(fp);
 699         return 0;
 700 }