%{
/**
 * A client-side 802.1x implementation supporting EAP/TLS
 *
 * This code is released under both the GPL version 2 and BSD licenses.
 * Either license may be used.  The respective licenses are found below.
 *
 * Copyright (C) 2002 Bryan D. Payne & Nick L. Petroni Jr.
 * All Rights Reserved
 *
 * --- GPL Version 2 License ---
 * This program is free software; you can redistribute it and/or
 * modify it under the terms of the GNU General Public License
 * as published by the Free Software Foundation; either version 2
 * of the License, or (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program; if not, write to the Free Software
 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
 *
 * --- BSD License ---
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions are met:
 *
 *  - Redistributions of source code must retain the above copyright notice,
 *    this list of conditions and the following disclaimer.
 *  - Redistributions in binary form must reproduce the above copyright
 *    notice, this list of conditions and the following disclaimer in the
 *    documentation and/or other materials provided with the distribution.
 *  - All advertising materials mentioning features or use of this software
 *    must display the following acknowledgement:
 *       This product includes software developed by the University of
 *       Maryland at College Park and its contributors.
 *  - Neither the name of the University nor the names of its contributors
 *    may be used to endorse or promote products derived from this software
 *    without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
 * POSSIBILITY OF SUCH DAMAGE.
 */
/*******************************************************************
 * Grammar for configuration file
 * 
 * File: config_grammar.y
 *
 * Authors: bdpayne@cs.umd.edu, npetroni@cs.umd.edu
 *
 * $Id: config_grammar.y,v 1.33 2004/08/19 02:28:06 chessing Exp $
 * $Date: 2004/08/19 02:28:06 $
 * $Log: config_grammar.y,v $
 * Revision 1.33  2004/08/19 02:28:06  chessing
 * First piece of WPA patch.  (The patch is growing fast, and this commit is to save what is done so far.)
 *
 * Revision 1.32  2004/08/12 01:40:06  chessing
 *
 * Added "association" option to the global configuration file sections.  It can be set to either auto, or manual.  Setting "association" to auto means that XSupplicant will attempt to associate to a network with the lowest value in the "priority" setting.  The default for "association" is auto.  The other option added is "priority" which is a numeric value from 1..256.  A value of 1 is the highest priority, and will be the first network chosen.  (Assuming the network can be found in a scan.)  The default value for "priority" is 0, which means that network will be checked last.   --  Although the options are now in the config file, the actual functionality for auto association/priority is not yet complete.  (So, basically these options don't do anything yet. ;)
 *
 * Revision 1.31  2004/07/19 02:43:16  chessing
 *
 * Changed things to get rid of Linux specific pieces in the interface_data struct. Fixed up EAP-SIM and EAP-AKA to skip AVPs that we don't support.  (We print a mesage, and move on.)  Added the --enable-radiator-test option to configure EAP-AKA to use the test vectors included with Radiator's AKA module.  (To use this mode, no SIM card is required, but the PCSC library is still needed to build.  Also, some errors will be displayed.)
 *
 * Revision 1.30  2004/06/29 01:35:34  chessing
 *
 * Added credit to eapleap.c for Gilbert Goodwill (who gave me the clues I needed to figure out the keying piece for LEAP).  Added patch from Toby Collett to make PEAP work for broken implementations of IAS.  (New option ias_quirk has been added.)
 *
 * Revision 1.29  2004/06/22 20:14:22  chessing
 *
 * Fixed some compile problems where SIM/AKA code was trying to compile even when it wasn't supposed to.
 *
 * Revision 1.28  2004/06/21 05:19:12  chessing
 *
 * Added a few minor fixes to EAP-AKA support.  Added "allmulti" as a global configuration option.  (By default, allmulti is now on!)
 *
 * Revision 1.27  2004/06/15 03:35:19  chessing
 *
 * New updates including fixes to LEAP (keying now works with wireless) and adding EAP-AKA.
 *
 * Revision 1.26  2004/06/15 03:22:17  chessing
 *
 * XSupplicant Release 1.0
 *
 *
 *******************************************************************/  
  
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <stdarg.h>
  
#include "config.h"
#include "xsup_err.h"
#include "xsup_debug.h"
#include "wpa.h"

#ifdef EAP_SIM_ENABLE
#include "winscard.h"
#endif

// there has GOT to be a better way than this...
#include "eap_types/md5/eapmd5.h"
#include "eap_types/tls/eaptls.h"
#include "eap_types/ttls/eapttls.h"
#include "eap_types/mschapv2/eapmschapv2.h"
#include "eap_types/peap/eappeap.h"
#include "eap_types/leap/eapleap.h"
#include "eap_types/sim/eapsim.h"
#include "eap_types/aka/eapaka.h"

#define CLEAN_EXIT cleanup_parse(); return XECONFIGPARSEFAIL

int yylex(void);  
int yyerror(char *err);
extern struct config_data *config_info;

extern int config_parse_debug;

struct config_data *tmp_config = NULL;

struct config_eap_tls *tmp_tls = NULL;
struct config_eap_md5 *tmp_md5 = NULL;
struct config_eap_ttls *tmp_ttls = NULL;
struct config_eap_leap *tmp_leap = NULL;
struct config_eap_mschapv2 *tmp_mschapv2 = NULL;
struct config_eap_peap *tmp_peap = NULL; 
struct config_eap_sim *tmp_sim = NULL;
struct config_eap_aka *tmp_aka = NULL;
struct config_wpa_psk *tmp_wpa_psk = NULL;

struct config_pap *tmp_p2pap =NULL;
struct config_chap *tmp_p2chap = NULL;
struct config_mschap *tmp_p2mschap = NULL;
struct config_mschapv2 *tmp_p2mschapv2 = NULL;

struct config_network *tmp_network = NULL;



void set_current_tls() {
  if (tmp_tls == NULL) 
    initialize_config_eap_tls(&tmp_tls);
} 
void set_current_md5() {
  if (tmp_md5 == NULL) 
    initialize_config_eap_md5(&tmp_md5);
} 
void set_current_ttls() {
  if (tmp_ttls == NULL) 
    initialize_config_eap_ttls(&tmp_ttls);
} 
void set_current_leap() {
  if (tmp_leap == NULL) 
    initialize_config_eap_leap(&tmp_leap);
} 
void set_current_mschapv2() {
  if (tmp_mschapv2 == NULL) 
    initialize_config_eap_mschapv2(&tmp_mschapv2);
} 
void set_current_peap() {
  if (tmp_peap == NULL) 
    initialize_config_eap_peap(&tmp_peap);
} 
void set_current_sim() {
  if (tmp_sim == NULL) 
    initialize_config_eap_sim(&tmp_sim);
} 

void set_current_aka() {
  if (tmp_aka == NULL)
    initialize_config_eap_aka(&tmp_aka);
}

void set_current_wpa_psk() {
  if (tmp_wpa_psk == NULL)
    initialize_config_wpa_psk(&tmp_wpa_psk);
}

void set_current_p2pap() {
  if (tmp_p2pap == NULL)
    initialize_config_pap(&tmp_p2pap);
}
void set_current_p2chap() {
  if (tmp_p2chap == NULL)
    initialize_config_chap(&tmp_p2chap);
}
void set_current_p2mschap() {
  if (tmp_p2mschap == NULL)
    initialize_config_mschap(&tmp_p2mschap);
}
void set_current_p2mschapv2() {
  if (tmp_p2mschapv2 == NULL)
    initialize_config_mschapv2(&tmp_p2mschapv2);
}

void set_current_config() {
  if (tmp_config == NULL) 
    initialize_config_data(&tmp_config);
} 

void set_current_globals() {
  set_current_config();
  if (!tmp_config->globals)
    initialize_config_globals(&(tmp_config->globals));
}   

void set_current_network() {
  if (tmp_network == NULL) 
    initialize_config_network(&tmp_network);
} 


void cleanup_parse()
{
  if (tmp_config)
    delete_config_data(&tmp_config);
  if (tmp_tls)
    delete_config_eap_tls(&tmp_tls);
  if (tmp_md5)
    delete_config_eap_md5(&tmp_md5);
  if (tmp_ttls)
    delete_config_eap_ttls(&tmp_ttls);
  if (tmp_leap)
    delete_config_eap_leap(&tmp_leap);
  if (tmp_mschapv2)
    delete_config_eap_mschapv2(&tmp_mschapv2);
  if (tmp_peap)
    delete_config_eap_peap(&tmp_peap);
  if (tmp_sim)
    delete_config_eap_sim(&tmp_sim);
  if (tmp_aka)
    delete_config_eap_aka(&tmp_aka);
  if (tmp_wpa_psk)
    delete_config_wpa_psk(&tmp_wpa_psk);
  if (tmp_p2pap)
    delete_config_pap(&tmp_p2pap);
  if (tmp_p2chap)
    delete_config_chap(&tmp_p2chap);
  if (tmp_p2mschap)
    delete_config_mschap(&tmp_p2mschap);
  if (tmp_p2mschapv2)
    delete_config_mschapv2(&tmp_p2mschapv2);
  if (tmp_network)
    delete_config_network(&tmp_network);
}



/* function to check if debug is on and if so print the message */
void parameter_debug(char *fmt, ...) {
  va_list ap;
  va_start(ap, fmt);
  if (!config_parse_debug) return;

  vprintf(fmt, ap);
  va_end(ap);
}

%}

%union {
        char    *str;
        int     num;
}


%token        TK_NETWORK_LIST
%token        TK_DEFAULT_NETNAME
%token<str>   TK_NETNAME
%token        TK_STARTUP_COMMAND
%token        TK_FIRST_AUTH_COMMAND
%token        TK_REAUTH_COMMAND
%token        TK_LOGFILE
%token        TK_AUTH_PERIOD
%token        TK_HELD_PERIOD
%token        TK_MAX_STARTS
%token        TK_ALLMULTI
%token        TK_ALLOW_INTERFACES
%token        TK_DENY_INTERFACES
%token        TK_ASSOCIATION
%token        TK_AUTO
%token        TK_MANUAL
%token        TK_ALL
%token        TK_TYPE
%token        TK_ALLOW_TYPES
%token        TK_WIRELESS
%token        TK_WIRED
%token        TK_CONTROL_WIRELESS
%token        TK_CRYPT_METHOD
%token        TK_WEP
%token        TK_WPA_TKIP
%token        TK_WPA_CCMP
%token        TK_WPA_ENT
%token        TK_ANY
%token        TK_IDENTITY
%token<str>   TK_IDENTITY_VAL
%token        TK_PRIORITY
%token        TK_DEST_MAC
%token<str>   TK_MACADDRESS
%token        TK_SSID
%token<str>   TK_SSID_VAL
%token        TK_WPA_PSK
%token        TK_WPA_PSK_KEY
%token        TK_WPA_PSK_HEX_KEY
%token        TK_EAP_TLS
%token        TK_USER_CERT
%token        TK_USER_KEY
%token        TK_USER_KEY_PASS
%token        TK_SESSION_RESUME
%token        TK_CNCHECK
%token        TK_CNEXACT
%token        TK_ROOT_CERT
%token        TK_ROOT_DIR
%token        TK_CRL_DIR
%token        TK_CHUNK_SIZE
%token        TK_RANDOM_FILE
%token        TK_EAP_MD5
%token        TK_USERNAME
%token<str>   TK_USERNAME_VAL
%token        TK_PASSWORD
%token        TK_EAP_LEAP
%token        TK_EAP_TTLS
%token        TK_PHASE2_TYPE
%token        TK_PAP
%token        TK_CHAP
%token        TK_MSCHAP
%token        TK_MSCHAPV2
%token        TK_EAP_MSCHAPV2
%token        TK_IAS_QUIRK
%token        TK_EAP_PEAP
%token        TK_EAP_SIM
%token        TK_EAP_AKA
%token        TK_AUTO_REALM
%token        TK_YES
%token        TK_NO
%token        TK_EAP_GTC
%token        TK_EAP_OTP


%token<num>   TK_NUMBER
%token<str>   TK_FNAME
%token<str>   TK_PASS
%token<str>   TK_COMMAND



%%

configfile        : global_section network_section {
		     config_info = tmp_config; 
		     tmp_config = NULL;
                  }
                  | global_section { 
                      debug_printf(DEBUG_NORMAL, "Error: No networks defined.\n"); 
		      CLEAN_EXIT;
		    }
                  | network_section {
		      debug_printf(DEBUG_NORMAL, "Error: No globals defined.\n"); 
		      cleanup_parse();
		      return XECONFIGPARSEFAIL;
                    }
                  | error {
 		      cleanup_parse();
		      return XECONFIGPARSEFAIL; }
                  ;

global_section    : global_section global_statement
                  | global_statement
                  ;

network_section   : network_section  network_entry
                  | network_entry
                  ;

global_statement  : TK_NETWORK_LIST '=' TK_ALL {
                      set_current_globals();
                      parameter_debug("network_list: all\n");
		      // do nothing. leave null
                    } 
                  | TK_NETWORK_LIST '=' network_list {
		    // done below. nothing to do here
  		    }
                  | TK_DEFAULT_NETNAME '=' TK_NETNAME {
 		     set_current_globals();
		     parameter_debug("Default network: \"%s\"\n", $3);
		     if (tmp_config->globals->default_net)
		       free($3);
		     else
		       tmp_config->globals->default_net = $3;
		  }
                  | TK_STARTUP_COMMAND '=' TK_COMMAND {
 		     set_current_globals();
		     parameter_debug("Startup command: \"%s\"\n", $3);
		     if (tmp_config->globals->startup_command)
		       free($3);
		     else
		       tmp_config->globals->startup_command = $3;
		    }
                  | TK_FIRST_AUTH_COMMAND '=' TK_COMMAND {
 		     set_current_globals();
		     parameter_debug("First_Auth command: \"%s\"\n", $3);
		     if (tmp_config->globals->first_auth_command)
		       free($3);
		     else
		       tmp_config->globals->first_auth_command = $3;
		    }
                  | TK_REAUTH_COMMAND '=' TK_COMMAND {
 		     set_current_globals();
		     parameter_debug("Reauth command: \"%s\"\n", $3);
		     if (tmp_config->globals->reauth_command)
		       free($3);
		     else
		       tmp_config->globals->reauth_command = $3;
		    }
                  | TK_LOGFILE '=' TK_NETNAME {
		     set_current_globals();
		     parameter_debug("Logfile: \"%s\"\n", $3);
		     if (tmp_config->globals->logfile)
		       {
			 free($3);
			 tmp_config->globals->logfile = NULL;
		       }
		     else
		       tmp_config->globals->logfile = $3;
		    }
                  | TK_AUTH_PERIOD '=' TK_NUMBER {
		     set_current_globals();
		     if (!TEST_FLAG(tmp_config->globals->flags, CONFIG_GLOBALS_AUTH_PER)) {
		       SET_FLAG(tmp_config->globals->flags, CONFIG_GLOBALS_AUTH_PER);
		       tmp_config->globals->auth_period = $3;
		     }
                    }
                  | TK_HELD_PERIOD '=' TK_NUMBER {
		     set_current_globals();
		     if (!TEST_FLAG(tmp_config->globals->flags, CONFIG_GLOBALS_HELD_PER)) {
		       SET_FLAG(tmp_config->globals->flags, CONFIG_GLOBALS_HELD_PER);
		       tmp_config->globals->held_period = $3;
		     }
                    }
                  | TK_MAX_STARTS '=' TK_NUMBER {
		     set_current_globals();
		     if (!TEST_FLAG(tmp_config->globals->flags, CONFIG_GLOBALS_MAX_STARTS)) {
		       SET_FLAG(tmp_config->globals->flags, CONFIG_GLOBALS_MAX_STARTS);
		       tmp_config->globals->max_starts = $3;
		     }
                    }
                  | TK_ALLMULTI '=' TK_YES {
		     set_current_globals();
		     tmp_config->globals->allmulti = 1;
                    } 
                  | TK_ALLMULTI '=' TK_NO {
		     set_current_globals();
		     tmp_config->globals->allmulti = 0;
                    }
                  | TK_ALLOW_INTERFACES '=' allow_interface_list {
                     // nothing to do here
                    }
                  | TK_DENY_INTERFACES '=' deny_interface_list {
                     // nothing to do here
                    }
                  | TK_ASSOCIATION '=' TK_AUTO {
		     set_current_globals();
		     tmp_config->globals->association = 0;
		    }
                  | TK_ASSOCIATION '=' TK_MANUAL {
		     set_current_globals();
		     tmp_config->globals->association = 1;
		    }
                  ;

network_list      : network_list ',' TK_NETNAME {
                       parameter_debug("network_list: \"%s\"\n", $3);
		       set_current_globals();
		       if (config_string_list_contains_string(tmp_config->globals->allowed_nets,
							    $3))
			 free($3);
		       else 
			 config_string_list_add_string(&tmp_config->globals->allowed_nets,
						     $3);
                    }
                  | TK_NETNAME { 
                       parameter_debug("network_list: \"%s\"\n", $1);
		       set_current_globals();
		       if (config_string_list_contains_string(tmp_config->globals->allowed_nets,
							    $1))
			 free($1);
		       else 
			 config_string_list_add_string(&tmp_config->globals->allowed_nets,
						     $1);
                    }
                  ;

allow_interface_list      : allow_interface_list ',' TK_NETNAME {
                       parameter_debug("allow_interface_list: \"%s\"\n", $3);
		       set_current_globals();
		       if (config_string_list_contains_string(tmp_config->globals->allow_interfaces,
							      $3))
			 free($3);
		       else if (config_string_list_contains_string(tmp_config->globals->deny_interfaces,
								   $3)) {
			 debug_printf(DEBUG_NORMAL,
				      "Interface \"%s\" both allowed and denied\n", $3);
			 CLEAN_EXIT;
		       }
		       else 
			 config_string_list_add_string(&tmp_config->globals->allow_interfaces,
						     $3);
                    }
                  | TK_NETNAME { 
                       parameter_debug("allow_interface_list: \"%s\"\n", $1);
		       set_current_globals();
		       if (config_string_list_contains_string(tmp_config->globals->allow_interfaces,
							    $1))
			 free($1);
		       else if (config_string_list_contains_string(tmp_config->globals->deny_interfaces,
								   $1)) {
			 debug_printf(DEBUG_NORMAL,
				      "Interface \"%s\" both allowed and denied\n", $1);
			 CLEAN_EXIT;
		       }
		       else 
			 config_string_list_add_string(&tmp_config->globals->allow_interfaces,
						     $1);
                    }
                  ;

deny_interface_list      : deny_interface_list ',' TK_NETNAME {
                       parameter_debug("deny_interface_list: \"%s\"\n", $3);
		       set_current_globals();
		       if (config_string_list_contains_string(tmp_config->globals->deny_interfaces,
							      $3))
			 free($3);
		       else if (config_string_list_contains_string(tmp_config->globals->allow_interfaces,
								   $3)) {
			 debug_printf(DEBUG_NORMAL,
				      "Interface \"%s\" both allowed and denied\n", $3);
			 CLEAN_EXIT;
		       }
		       else 
			 config_string_list_add_string(&tmp_config->globals->deny_interfaces,
						     $3);
                    }
                  | TK_NETNAME { 
                       parameter_debug("deny_interface_list: \"%s\"\n", $1);
		       set_current_globals();
		       if (config_string_list_contains_string(tmp_config->globals->deny_interfaces,
							    $1))
			 free($1);
		       else if (config_string_list_contains_string(tmp_config->globals->allow_interfaces,
								   $1)) {
			 debug_printf(DEBUG_NORMAL,
				      "Interface \"%s\" both allowed and denied\n", $1);
			 CLEAN_EXIT;
		       }
		       else 
			 config_string_list_add_string(&tmp_config->globals->deny_interfaces,
						     $1);
                    }
                  ;

network_entry     : TK_NETNAME '{' network_statements '}' {
                      set_current_config();
		      tmp_network->name = $1;
		      // check if there is a networks field and that 
		      // the current tmp is not already listed
		      if ((!tmp_config->networks ||
			  !config_network_contains_net(tmp_config->networks,
						       tmp_network->name)) &&
			  config_allows_network(tmp_config, tmp_network->name))
		      {
			config_network_add_net(&(tmp_config->networks),
					       tmp_network);
		      }
		      // if we don't need it, delete it
		      else {
			delete_config_network(&tmp_network);
		      }
		      tmp_network = NULL;
                    }
                  ;

network_statements : network_statements network_parameter
                   | network_statements eap_type_statement
                   | network_parameter
                   | eap_type_statement
                   ;


network_parameter  : network_type_parameter
                   | network_encryption_type
                   | network_identity_parameter
                   | network_priority
                   | network_dest_mac_parameter
                   | network_ssid_parameter
                   | network_allow_parameter
                   | network_control_wireless
                   ;

network_type_parameter : TK_TYPE '=' TK_WIRELESS {
                           parameter_debug("Type: Wireless\n");
			   set_current_network();
			   if (tmp_network->type == UNSET)
			     tmp_network->type = WIRELESS;
                         }
                         | TK_TYPE '=' TK_WIRED {
                           parameter_debug("Type: Wired\n");
			   set_current_network();
			   if (tmp_network->type == UNSET)
			     tmp_network->type = WIRED;
                         }
                       ;

network_encryption_type  : TK_CRYPT_METHOD '=' TK_ANY {
                           parameter_debug("Encryption Type : ANY\n");
                           set_current_network();
                           tmp_network->crypt_type = CRYPT_ANY;
                         }
                         | TK_CRYPT_METHOD '=' TK_WEP {
                           parameter_debug("Encryption Type : WEP\n");
                           set_current_network();
                           tmp_network->crypt_type = CRYPT_WEP;
                         }
                         | TK_CRYPT_METHOD '=' TK_WPA_TKIP {
                           parameter_debug("Encryption Type : WPA-TKIP\n");
                           set_current_network();
                           tmp_network->crypt_type = CRYPT_WPA_TKIP;
                         }
                         | TK_CRYPT_METHOD '=' TK_WPA_CCMP {
                           parameter_debug("Encryption Type : WPA-CCMP\n");
                           set_current_network();
                           tmp_network->crypt_type = CRYPT_WPA_CCMP;
                         }
                         | TK_CRYPT_METHOD '=' TK_WPA_ENT {
                           parameter_debug("Encryption Type : WPA-ANY\n");
                           set_current_network();
                           tmp_network->crypt_type = CRYPT_WPA_ANY;
                         }
                       ;

network_control_wireless : TK_CONTROL_WIRELESS '=' TK_YES {
                           parameter_debug("Control Wireless = YES\n");
			   set_current_network();
			   if (tmp_network->wireless_ctrl == CTL_UNSET)
			     tmp_network->wireless_ctrl = CTL_YES;
                         }
                         | TK_CONTROL_WIRELESS '=' TK_NO {
			   parameter_debug("Control Wireless = NO\n");
			   set_current_network();
			   if (tmp_network->wireless_ctrl == CTL_UNSET)
			     tmp_network->wireless_ctrl = CTL_NO;
			 }
                       ;

network_identity_parameter : TK_IDENTITY '=' TK_IDENTITY_VAL {
                            parameter_debug("ID: \"%s\"\n", $3);
			    set_current_network();
			    if (!tmp_network->identity)
			      tmp_network->identity = $3;
			    else
			      free($3);
                          }
                        ;

network_priority : TK_PRIORITY '=' TK_NUMBER {
                            parameter_debug("Priority : \"%d\"\n", $3);
                            set_current_network();
                            tmp_network->priority = $3;
                          }
                        ;

network_ssid_parameter : TK_SSID '=' TK_SSID_VAL {
                            parameter_debug("SSID: \"%s\"\n", $3);
			    set_current_network();
			    if (!tmp_network->ssid)
			      tmp_network->ssid = $3;
			    else
			      free($3);
                         }
                       ;

network_dest_mac_parameter: TK_DEST_MAC '=' TK_MACADDRESS {
                            parameter_debug("Dest Mac: %s\n", $3);
			    set_current_network();
			    if (TEST_FLAG(tmp_network->flags, CONFIG_NET_DEST_MAC)) {
			      free($3);
			    }
			    else {
			      int tmp_dst_mac[CONFIG_MAC_LEN];
			      SET_FLAG(tmp_network->flags, CONFIG_NET_DEST_MAC);
			      sscanf($3, "%2x:%2x:%2x:%2x:%2x:%2x", 
				     &tmp_dst_mac[0], 
				     &tmp_dst_mac[1], 
				     &tmp_dst_mac[2], 
				     &tmp_dst_mac[3], 
				     &tmp_dst_mac[4], 
				     &tmp_dst_mac[5]);
			      tmp_network->dest_mac[0] = tmp_dst_mac[0];
			      tmp_network->dest_mac[1] = tmp_dst_mac[1];
			      tmp_network->dest_mac[2] = tmp_dst_mac[2];
			      tmp_network->dest_mac[3] = tmp_dst_mac[3];
			      tmp_network->dest_mac[4] = tmp_dst_mac[4];
			      tmp_network->dest_mac[5] = tmp_dst_mac[5];
			    }
                         }
                       ;

network_allow_parameter: TK_ALLOW_TYPES '=' TK_ALL {
                           parameter_debug("Allow Types: ALL\n");
			   set_current_network();
			   SET_FLAG(tmp_network->flags, CONFIG_NET_ALLOW_ALL);
                       }
                       | TK_ALLOW_TYPES '=' eap_type_list
                       ;

eap_type_statement  : eap_tls_statement {
                       set_current_network(); 
		       if (!config_eap_method_contains_method(tmp_network->methods,
							      EAP_TYPE_TLS)) {
			 add_config_eap_method(&(tmp_network->methods),
					       EAP_TYPE_TLS,
					       tmp_tls);
		       }
		       else 
			 delete_config_eap_tls(&tmp_tls);
		       tmp_tls = NULL;
                      }
                    | eap_md5_statement {
                       set_current_network(); 
		       if (!config_eap_method_contains_method(tmp_network->methods,
							      EAP_TYPE_MD5))
			 add_config_eap_method(&(tmp_network->methods),
					       EAP_TYPE_MD5,
					       tmp_md5);
		       else 
			 delete_config_eap_md5(&tmp_md5);
		       tmp_md5 = NULL;
                      }
                    | eap_ttls_statement {
                       set_current_network(); 
		       if (!config_eap_method_contains_method(tmp_network->methods,
							      EAP_TYPE_TTLS))
			 add_config_eap_method(&(tmp_network->methods),
					       EAP_TYPE_TTLS,
					       tmp_ttls);
		       else 
			 delete_config_eap_ttls(&tmp_ttls);
		       tmp_ttls = NULL;
                      }
                    | eap_leap_statement {
                       set_current_network(); 
		       if (!config_eap_method_contains_method(tmp_network->methods,
							      EAP_TYPE_LEAP))
			 add_config_eap_method(&(tmp_network->methods),
					       EAP_TYPE_LEAP,
					       tmp_leap);
		       else 
			 delete_config_eap_leap(&tmp_leap);
		       tmp_leap = NULL;
                      }
                    | eap_mschapv2_statement {
                       set_current_network(); 
		       if (!config_eap_method_contains_method(tmp_network->methods,
							      EAP_TYPE_MSCHAPV2))
			 add_config_eap_method(&(tmp_network->methods),
					       EAP_TYPE_MSCHAPV2,
					       tmp_mschapv2);
		       else 
			 delete_config_eap_mschapv2(&tmp_mschapv2);
		       tmp_mschapv2 = NULL;
                      }
                    | eap_peap_statement {
                       set_current_network(); 
		       if (!config_eap_method_contains_method(tmp_network->methods,
							      EAP_TYPE_PEAP))
			 add_config_eap_method(&(tmp_network->methods),
					       EAP_TYPE_PEAP,
					       tmp_peap);
		       else 
			 delete_config_eap_peap(&tmp_peap);
		       tmp_peap = NULL;
                      }
                    | eap_sim_statement {
                       set_current_network(); 
		       if (!config_eap_method_contains_method(tmp_network->methods,
							      EAP_TYPE_SIM))
			 add_config_eap_method(&(tmp_network->methods),
					       EAP_TYPE_SIM,
					       tmp_sim);
		       else 
			 delete_config_eap_sim(&tmp_sim);
		       tmp_sim = NULL;
                      }
                    | eap_aka_statement {
		      set_current_network();
		      if (!config_eap_method_contains_method(tmp_network->methods,
							     EAP_TYPE_AKA))
			add_config_eap_method(&(tmp_network->methods),
					      EAP_TYPE_AKA,
					      tmp_aka);
		      else
			delete_config_eap_aka(&tmp_aka);
		      tmp_aka = NULL;
                      }
                    | wpa_psk_statement {
		      set_current_network();
		      if (!config_eap_method_contains_method(tmp_network->methods,
							     WPA_PSK))
			add_config_eap_method(&(tmp_network->methods),
					      WPA_PSK,
					      tmp_wpa_psk);
		      else
			delete_config_wpa_psk(&tmp_wpa_psk);
		      tmp_wpa_psk = NULL;
                      }
                    ;

eap_type_list       : eap_type_list ',' eap_type 
                    | eap_type
                    ;

eap_type            : TK_EAP_TLS {
                        parameter_debug("Allow Type: TLS\n");
			set_current_network();
			SET_FLAG(tmp_network->flags, CONFIG_NET_ALLOW_TLS);
                      }
                    | TK_EAP_MD5 {
                        parameter_debug("Allow Type: MD5\n");
			set_current_network();
			SET_FLAG(tmp_network->flags, CONFIG_NET_ALLOW_MD5);
                      }
                    | TK_EAP_TTLS {
                        parameter_debug("Allow Type: TTLS\n");
			set_current_network();
			SET_FLAG(tmp_network->flags, CONFIG_NET_ALLOW_TTLS);
                      }
                    | TK_EAP_LEAP {
                        parameter_debug("Allow Type: LEAP\n");
			set_current_network();
			SET_FLAG(tmp_network->flags, CONFIG_NET_ALLOW_LEAP);
                      }
                    | TK_EAP_MSCHAPV2 {
                        parameter_debug("Allow Type: MSCHAPV2\n");
			set_current_network();
			SET_FLAG(tmp_network->flags, CONFIG_NET_ALLOW_MSCV2);
                      }
                    | TK_EAP_PEAP {
                        parameter_debug("Allow Type: PEAP\n");
			set_current_network();
			SET_FLAG(tmp_network->flags, CONFIG_NET_ALLOW_PEAP);
                      }
                    | TK_EAP_SIM {
                        parameter_debug("Allow Type: SIM\n");
			set_current_network();
			SET_FLAG(tmp_network->flags, CONFIG_NET_ALLOW_SIM);
                      }
                    | TK_EAP_AKA {
		        parameter_debug("Allow Type: AKA\n");
		        set_current_network();
		        SET_FLAG(tmp_network->flags, CONFIG_NET_ALLOW_AKA);
		      }
                    | TK_EAP_GTC {
                        parameter_debug("Allow Type: GTC\n");
			set_current_network();
			SET_FLAG(tmp_network->flags, CONFIG_NET_ALLOW_GTC);
                      }
                    | TK_EAP_OTP {
                        parameter_debug("Allow Type: OTP\n");
			set_current_network();
			SET_FLAG(tmp_network->flags, CONFIG_NET_ALLOW_OTP);
                      }
                    ;

eap_tls_statement   : TK_EAP_TLS '{' eap_tls_params '}'  
                    | TK_EAP_TLS '{' '}' {
                        set_current_tls(); /* define an empty tls struct*/
                      }
                    ;

eap_tls_params      : eap_tls_params eap_tls_param
                    | eap_tls_param
                    ;

eap_tls_param       :  TK_USER_CERT '=' TK_FNAME {
                        parameter_debug("tls user cert: \"%s\"\n", $3);
			set_current_tls();
			if (!tmp_tls->user_cert)
			  tmp_tls->user_cert = $3;
			else
			  free($3);
                      }
                    |  TK_USER_KEY '=' TK_FNAME {
	 	        parameter_debug("tls user key: \"%s\"\n", $3);
			set_current_tls();
			if (!tmp_tls->user_key)
			  tmp_tls->user_key = $3;
			else 
			  free($3);
        	      }
                    |  TK_USER_KEY_PASS '=' TK_PASS {
	 	        parameter_debug("tls user pass: \"%s\"\n", $3);
			set_current_tls();
			if (!tmp_tls->user_key_pass)
			  tmp_tls->user_key_pass = $3;
			else
			  free($3);
        	      }
                    |  TK_SESSION_RESUME '=' TK_YES {
		        parameter_debug("Session Resumption = YES\n");
		        set_current_tls();
		        if (tmp_tls->session_resume == RES_UNSET)
			  tmp_tls->session_resume = RES_YES;
		      }
                    | TK_SESSION_RESUME '=' TK_NO {
			parameter_debug("Session Resumption = NO\n");
			set_current_tls();
			if (tmp_tls->session_resume == RES_UNSET)
			  tmp_tls->session_resume = RES_NO;
		      }
                    |  TK_ROOT_CERT  '=' TK_FNAME {
	 	        parameter_debug("tls root_cert: \"%s\"\n", $3);
			set_current_tls();
			if (!tmp_tls->root_cert)
			  tmp_tls->root_cert = $3;
			else
			  free($3);
        	      }
                    |  TK_ROOT_DIR  '=' TK_FNAME {
	 	        parameter_debug("tls root_dir: \"%s\"\n", $3);
			set_current_tls();
			if (!tmp_tls->root_dir)
			  tmp_tls->root_dir = $3;
			else
			  free($3);
        	      }
                    |  TK_CRL_DIR  '=' TK_FNAME {
	 	        parameter_debug("tls crl_dir: \"%s\"\n", $3);
			set_current_tls();
			if (!tmp_tls->crl_dir)
			  tmp_tls->crl_dir = $3;
			else
			  free($3);
        	      }
                    |  TK_CHUNK_SIZE '=' TK_NUMBER {
 		        parameter_debug("tls chunk: %d\n", $3);
			set_current_tls();
			if (tmp_tls->chunk_size == 0)
			  tmp_tls->chunk_size = $3;
  		      }
                    |  TK_RANDOM_FILE '=' TK_FNAME {
	 	        parameter_debug("tls rand: \"%s\"\n", $3);
			set_current_tls();
			if (!tmp_tls->random_file)
			  tmp_tls->random_file = $3;
			else 
			  free($3);
        	      }
                    ;

eap_md5_statement   : TK_EAP_MD5 '{' eap_md5_params'}' 
                    | TK_EAP_MD5 '{' '}' {
                        set_current_md5(); /* define an empty md5 struct*/
                      }
                    ;

eap_md5_params     : eap_md5_params eap_md5_param
                   | eap_md5_param
                   ;

eap_md5_param      : TK_USERNAME '=' TK_USERNAME_VAL {
                       parameter_debug("md5 username: \"%s\"\n", $3);
		       set_current_md5();
		       if (!tmp_md5->username)
			 tmp_md5->username = $3;
		       else
			 free($3);
                     }
                   | TK_PASSWORD '=' TK_PASS {
		       parameter_debug("md5 password: \"%s\"\n", $3);
		       set_current_md5();
		       if (!tmp_md5->password)
			 tmp_md5->password = $3;
		       else
			 free($3);
		     }
                   ;

eap_ttls_statement   : TK_EAP_TTLS '{' eap_ttls_params '}' 
                    | TK_EAP_TTLS '{' '}' {
                        set_current_ttls(); /* define an empty ttls struct*/
                      }
                    ;

eap_ttls_params      : eap_ttls_params eap_ttls_param
                    | eap_ttls_param
                    ;

eap_ttls_param       : TK_USER_CERT '=' TK_FNAME {
                        parameter_debug("ttls user cert: \"%s\"\n", $3);
			set_current_ttls();
			if (!tmp_ttls->user_cert)
			  tmp_ttls->user_cert = $3;
			else
			  free($3);
                      }
                    |  TK_USER_KEY '=' TK_FNAME {
	 	        parameter_debug("ttls user key: \"%s\"\n", $3);
			set_current_ttls();
			if (!tmp_ttls->user_key)
			  tmp_ttls->user_key = $3;
			else 
			  free($3);
        	      }
                    |  TK_USER_KEY_PASS '=' TK_PASS {
	 	        parameter_debug("ttls user pass: \"%s\"\n", $3);
			set_current_ttls();
			if (!tmp_ttls->user_key_pass)
			  tmp_ttls->user_key_pass = $3;
			else
			  free($3);
        	      }
                    |TK_ROOT_CERT  '=' TK_FNAME {
	 	        parameter_debug("ttls root_cert: \"%s\"\n", $3);
			set_current_ttls();
			if (!tmp_ttls->root_cert)
			  tmp_ttls->root_cert = $3;
			else
			  free($3);
        	      }
                    |  TK_ROOT_DIR '=' TK_FNAME {
	 	        parameter_debug("ttls root_dir: \"%s\"\n", $3);
			set_current_ttls();
			if (!tmp_ttls->root_dir)
			  tmp_ttls->root_dir = $3;
			else 
			  free($3);
        	      }
                    |  TK_CRL_DIR '=' TK_FNAME {
	 	        parameter_debug("ttls crl_dir: \"%s\"\n", $3);
			set_current_ttls();
			if (!tmp_ttls->crl_dir)
			  tmp_ttls->crl_dir = $3;
			else 
			  free($3);
        	      }
                    |  TK_CHUNK_SIZE '=' TK_NUMBER {
 		        parameter_debug("ttls chunk: %d\n", $3);
			set_current_ttls();
			if (tmp_ttls->chunk_size == 0)
			  tmp_ttls->chunk_size = $3;
  		      }
                    |  TK_RANDOM_FILE '=' TK_FNAME {
	 	        parameter_debug("ttls rand: \"%s\"\n", $3);
			set_current_ttls();
			if (!tmp_ttls->random_file)
			  tmp_ttls->random_file = $3;
			else 
			  free($3);
        	      }
                    |  TK_SESSION_RESUME '=' TK_YES {
		        parameter_debug("Session Resumption = YES\n");
		        set_current_ttls();
		        if (tmp_ttls->session_resume == RES_UNSET)
			  tmp_ttls->session_resume = RES_YES;
		      }
                    | TK_SESSION_RESUME '=' TK_NO {
			parameter_debug("Session Resumption = NO\n");
			set_current_ttls();
			if (tmp_ttls->session_resume == RES_UNSET)
			  tmp_ttls->session_resume = RES_NO;
		      }
                    |  TK_CNCHECK '=' TK_FNAME {
		        parameter_debug("ttls CN check : \"%s\"\n", $3);
                        set_current_ttls();
                        if (!tmp_ttls->cncheck)
                          tmp_ttls->cncheck = $3;
                        else
                          free($3);
		      }
                    | TK_CNEXACT '=' TK_YES {
  		        parameter_debug("match CN exactly : \"yes\"\n");
		        set_current_ttls();
		        tmp_ttls->cnexact = 1;
		    }
                    | TK_CNEXACT '=' TK_NO {
  		        parameter_debug("match CN exactly : \"no\"\n");
		        set_current_ttls();
		        tmp_ttls->cnexact = 0;
		    }
                    |  TK_PHASE2_TYPE '=' TK_PAP {
	 	        parameter_debug("ttls phase2_type 'pap'\n");
			if (tmp_ttls && 
			    tmp_ttls->phase2_type != TTLS_PHASE2_UNDEFINED) {
			  cleanup_parse();
			  return XECONFIGPARSEFAIL;  
			}
			set_current_ttls();
			tmp_ttls->phase2_type = TTLS_PHASE2_PAP;
        	      }
                    |  TK_PHASE2_TYPE '=' TK_CHAP {
	 	        parameter_debug("ttls phase2_type 'chap'\n");
			if (tmp_ttls && 
			    tmp_ttls->phase2_type != TTLS_PHASE2_UNDEFINED) {
			  cleanup_parse();
			  return XECONFIGPARSEFAIL;  
			}
			set_current_ttls();
			tmp_ttls->phase2_type = TTLS_PHASE2_CHAP;
        	      }
                    |  TK_PHASE2_TYPE '=' TK_MSCHAP {
	 	        parameter_debug("ttls phase2_type 'mschap'\n");
			if (tmp_ttls && 
			    tmp_ttls->phase2_type != TTLS_PHASE2_UNDEFINED) {
			  cleanup_parse();
			  return XECONFIGPARSEFAIL;  
			}
			set_current_ttls();
			tmp_ttls->phase2_type = TTLS_PHASE2_MSCHAP;
        	      }
                    |  TK_PHASE2_TYPE '=' TK_MSCHAPV2 {
	 	        parameter_debug("ttls phase2_type 'mschapv2'\n");
			if (tmp_ttls && 
			    tmp_ttls->phase2_type != TTLS_PHASE2_UNDEFINED) {
			  cleanup_parse();
			  return XECONFIGPARSEFAIL;  
			}
			set_current_ttls();
			tmp_ttls->phase2_type = TTLS_PHASE2_MSCHAPV2;
        	      }
                    | eap_ttls_phase2_statement
                    ;

eap_ttls_phase2_statement  : phase2_pap_statement
                           | phase2_chap_statement
                           | phase2_mschap_statement
                           | phase2_mschapv2_statement
                           ;

phase2_pap_statement   : TK_PAP '{' phase2_pap_params'}' {
                       set_current_ttls(); 
		       if (!config_ttls_phase2_contains_phase2(tmp_ttls->phase2,
							       TTLS_PHASE2_PAP))
			 add_config_ttls_phase2(&(tmp_ttls->phase2), 
						TTLS_PHASE2_PAP,
						tmp_p2pap);
		       else
			 delete_config_pap(&tmp_p2pap);
		       tmp_p2pap = NULL;
                      }
                    ;

phase2_pap_params     : phase2_pap_params phase2_pap_param
                   | phase2_pap_param
                   ;

phase2_pap_param      : TK_USERNAME '=' TK_USERNAME_VAL {
                       parameter_debug("pap username: \"%s\"\n", $3);
		       set_current_p2pap();
		       if (!tmp_p2pap->username)
			 tmp_p2pap->username = $3;
		       else
			 free($3);
                     }
                   | TK_PASSWORD '=' TK_PASS {
		       parameter_debug("pap password: \"%s\"\n", $3);
		       set_current_p2pap();
		       if (!tmp_p2pap->password)
			 tmp_p2pap->password = $3;
		       else
			 free($3);
		     }
                   ;

phase2_chap_statement   : TK_CHAP '{' phase2_chap_params'}' {
                       set_current_ttls(); 
		       if (!config_ttls_phase2_contains_phase2(tmp_ttls->phase2,
							       TTLS_PHASE2_CHAP))
			 add_config_ttls_phase2(&(tmp_ttls->phase2), 
						TTLS_PHASE2_CHAP,
						tmp_p2chap);
		       else
			 delete_config_chap(&tmp_p2chap);
		       tmp_p2chap = NULL;
                      }
                    ;

phase2_chap_params     : phase2_chap_params phase2_chap_param
                   | phase2_chap_param
                   ;

phase2_chap_param      : TK_USERNAME '=' TK_USERNAME_VAL {
                       parameter_debug("chap username: \"%s\"\n", $3);
		       set_current_p2chap();
		       if (!tmp_p2chap->username)
			 tmp_p2chap->username = $3;
		       else
			 free($3);
                     }
                   | TK_PASSWORD '=' TK_PASS {
		       parameter_debug("chap password: \"%s\"\n", $3);
		       set_current_p2chap();
		       if (!tmp_p2chap->password)
			 tmp_p2chap->password = $3;
		       else
			 free($3);
		     }
                   ;

phase2_mschap_statement   : TK_MSCHAP '{' phase2_mschap_params'}' {
                       set_current_ttls(); 
		       if (!config_ttls_phase2_contains_phase2(tmp_ttls->phase2,
							       TTLS_PHASE2_MSCHAP))
			 add_config_ttls_phase2(&(tmp_ttls->phase2), 
						TTLS_PHASE2_MSCHAP,
						tmp_p2mschap);
		       else
			 delete_config_mschap(&tmp_p2mschap);
		       tmp_p2mschap = NULL;
                      }
                    ;

phase2_mschap_params     : phase2_mschap_params phase2_mschap_param
                   | phase2_mschap_param
                   ;

phase2_mschap_param      : TK_USERNAME '=' TK_USERNAME_VAL {
                       parameter_debug("mschap username: \"%s\"\n", $3);
		       set_current_p2mschap();
		       if (!tmp_p2mschap->username)
			 tmp_p2mschap->username = $3;
		       else
			 free($3);
                     }
                   | TK_PASSWORD '=' TK_PASS {
		       parameter_debug("mschap password: \"%s\"\n", $3);
		       set_current_p2mschap();
		       if (!tmp_p2mschap->password)
			 tmp_p2mschap->password = $3;
		       else
			 free($3);
		     }
                   ;


phase2_mschapv2_statement   : TK_MSCHAPV2 '{' phase2_mschapv2_params'}' {
                       set_current_ttls(); 
		       if (!config_ttls_phase2_contains_phase2(tmp_ttls->phase2,
							       TTLS_PHASE2_MSCHAPV2))
			 add_config_ttls_phase2(&(tmp_ttls->phase2), 
						TTLS_PHASE2_MSCHAPV2,
						tmp_p2mschapv2);
		       else
			 delete_config_mschapv2(&tmp_p2mschapv2);
		       tmp_p2mschapv2 = NULL;
                      }
                    ;

phase2_mschapv2_params     : phase2_mschapv2_params phase2_mschapv2_param
                   | phase2_mschapv2_param
                   ;

phase2_mschapv2_param      : TK_USERNAME '=' TK_USERNAME_VAL {
                       parameter_debug("mschapv2 username: \"%s\"\n", $3);
		       set_current_p2mschapv2();
		       if (!tmp_p2mschapv2->username)
			 tmp_p2mschapv2->username = $3;
		       else
			 free($3);
                     }
                   | TK_PASSWORD '=' TK_PASS {
		       parameter_debug("mschapv2 password: \"%s\"\n", $3);
		       set_current_p2mschapv2();
		       if (!tmp_p2mschapv2->password)
			 tmp_p2mschapv2->password = $3;
		       else
			 free($3);
		     }
                   ;

eap_leap_statement   : TK_EAP_LEAP '{' eap_leap_params'}' 
                    | TK_EAP_LEAP '{' '}' {
                        set_current_leap(); /* define an empty leap struct*/
                      }
                    ;

eap_leap_params     : eap_leap_params eap_leap_param
                   | eap_leap_param
                   ;

eap_leap_param      : TK_USERNAME '=' TK_USERNAME_VAL {
                       parameter_debug("leap username: \"%s\"\n", $3);
		       set_current_leap();
		       if (!tmp_leap->username)
			 tmp_leap->username = $3;
		       else
			 free($3);
                     }
                   | TK_PASSWORD '=' TK_PASS {
		       parameter_debug("leap password: \"%s\"\n", $3);
		       set_current_leap();
		       if (!tmp_leap->password)
			 tmp_leap->password = $3;
		       else
			 free($3);
		     }
                   ;

eap_mschapv2_statement   : TK_EAP_MSCHAPV2 '{' eap_mschapv2_params'}'
                    | TK_EAP_MSCHAPV2 '{' '}' {
                        set_current_mschapv2(); /* define an empty mschapv2 struct*/
                      }
                         ;

eap_mschapv2_params     : eap_mschapv2_params eap_mschapv2_param
                   | eap_mschapv2_param
                   ;

eap_mschapv2_param      : TK_USERNAME '=' TK_USERNAME_VAL {
                       parameter_debug("mschapv2 username: \"%s\"\n", $3);
		       set_current_mschapv2();
		       if (!tmp_mschapv2->username)
			 tmp_mschapv2->username = $3;
		       else
			 free($3);
                     }
                   | TK_PASSWORD '=' TK_PASS {
		       parameter_debug("mschapv2 password: \"%s\"\n", $3);
		       set_current_mschapv2();
		       if (!tmp_mschapv2->password)
			 tmp_mschapv2->password = $3;
		       else
			 free($3);
		     }
                   ;

eap_peap_statement   : TK_EAP_PEAP '{' eap_peap_params '}'
                    | TK_EAP_PEAP '{' '}' {
                        set_current_peap(); /* define an empty peap struct*/
                      }
                    ;

eap_peap_params      : eap_peap_params eap_peap_param
                    | eap_peap_param
                    ;

eap_peap_param       : TK_IDENTITY '=' TK_IDENTITY_VAL {
                            parameter_debug("ID: \"%s\"\n", $3);
			    set_current_peap();
			    if (!tmp_peap->identity)
			      tmp_peap->identity = $3;
			    else
			      free($3);
                          }
                    |   TK_USER_CERT '=' TK_FNAME {
                        parameter_debug("peap user cert: \"%s\"\n", $3);
			set_current_peap();
			if (!tmp_peap->user_cert)
			  tmp_peap->user_cert = $3;
			else
			  free($3);
                      }
                    |  TK_USER_KEY '=' TK_FNAME {
	 	        parameter_debug("peap user key: \"%s\"\n", $3);
			set_current_peap();
			if (!tmp_peap->user_key)
			  tmp_peap->user_key = $3;
			else 
			  free($3);
        	      }
                    |  TK_USER_KEY_PASS '=' TK_PASS {
	 	        parameter_debug("peap user pass: \"%s\"\n", $3);
			set_current_peap();
			if (!tmp_peap->user_key_pass)
			  tmp_peap->user_key_pass = $3;
			else
			  free($3);
        	      }
                    |TK_ROOT_CERT  '=' TK_FNAME {
	 	        parameter_debug("peap root_cert: \"%s\"\n", $3);
			set_current_peap();
			if (!tmp_peap->root_cert)
			  tmp_peap->root_cert = $3;
			else
			  free($3);
        	      }
                    |  TK_ROOT_DIR '=' TK_FNAME {
	 	        parameter_debug("peap root_dir: \"%s\"\n", $3);
			set_current_peap();
			if (!tmp_peap->root_dir)
			  tmp_peap->root_dir = $3;
			else 
			  free($3);
        	      }
                    |  TK_CRL_DIR '=' TK_FNAME {
	 	        parameter_debug("peap crl_dir: \"%s\"\n", $3);
			set_current_peap();
			if (!tmp_peap->crl_dir)
			  tmp_peap->crl_dir = $3;
			else 
			  free($3);
        	      }
                    |  TK_SESSION_RESUME '=' TK_YES {
		        parameter_debug("Session Resumption = YES\n");
		        set_current_peap();
		        if (tmp_peap->session_resume == RES_UNSET)
			  tmp_peap->session_resume = RES_YES;
		      }
                    | TK_SESSION_RESUME '=' TK_NO {
			parameter_debug("Session Resumption = NO\n");
			set_current_peap();
			if (tmp_peap->session_resume == RES_UNSET)
			  tmp_peap->session_resume = RES_NO;
		      }
                    |  TK_CHUNK_SIZE '=' TK_NUMBER {
 		        parameter_debug("peap chunk: %d\n", $3);
			set_current_peap();
			if (tmp_peap->chunk_size == 0)
			  tmp_peap->chunk_size = $3;
  		      }
                    |  TK_CNCHECK '=' TK_FNAME {
		        parameter_debug("peap CN check : \"%s\"\n", $3);
                        set_current_peap();
                        if (!tmp_peap->cncheck)
                          tmp_peap->cncheck = $3;
                        else
                          free($3);
		      }
                    | TK_CNEXACT '=' TK_YES {
  		        parameter_debug("match CN exactly : \"yes\"\n");
		        set_current_peap();
		        tmp_peap->cnexact = 1;
		    }
                    | TK_CNEXACT '=' TK_NO {
  		        parameter_debug("match CN exactly : \"no\"\n");
		        set_current_peap();
		        tmp_peap->cnexact = 0;
       		    }
                    |  TK_RANDOM_FILE '=' TK_FNAME {
	 	        parameter_debug("peap rand: \"%s\"\n", $3);
			set_current_peap();
			if (!tmp_peap->random_file)
			  tmp_peap->random_file = $3;
			else 
			  free($3);
        	      }
                   | TK_IAS_QUIRK '=' TK_YES {
		       parameter_debug("peap ias quirk: YES\n");
		       printf("ias quirk yes\n");
		       set_current_peap();
		       tmp_peap->ias_quirk=1;
		     }
                   | TK_IAS_QUIRK '=' TK_NO {
		       parameter_debug("peap ias quirk: NO\n");
		       printf("ias quirk no\n");
		       set_current_peap();
		       tmp_peap->ias_quirk=0;
		     }
                    | eap_peap_allow_parameter {}
                    | eap_peap_phase2_statement {}
                    ;

eap_peap_allow_parameter: TK_ALLOW_TYPES '=' TK_ALL {
                           parameter_debug("PEAP Allow Types: ALL\n");
			   set_current_peap();
			   SET_FLAG(tmp_peap->flags, CONFIG_PEAP_ALLOW_ALL);
                       }
                       | TK_ALLOW_TYPES '=' eap_peap_phase2_type_list
                       ;

eap_peap_phase2_type_list  : eap_peap_phase2_type_list ',' eap_peap_phase2_type 
                           | eap_peap_phase2_type
                           ;

eap_peap_phase2_type  : TK_EAP_MSCHAPV2 {
                          parameter_debug("PEAP Allow Type: MSCHAPV2\n");
	  	  	  set_current_peap();
			  SET_FLAG(tmp_peap->flags, CONFIG_PEAP_ALLOW_MSCV2);
                        }
                      | TK_EAP_MD5 {
                          parameter_debug("PEAP Allow Type: MD5\n");
	  	  	  set_current_peap();
			  SET_FLAG(tmp_peap->flags, CONFIG_PEAP_ALLOW_MD5);
                        }
                      | TK_EAP_SIM {
                          parameter_debug("PEAP Allow Type: SIM\n");
	  	  	  set_current_peap();
			  SET_FLAG(tmp_peap->flags, CONFIG_PEAP_ALLOW_SIM);
                        }
                      | TK_EAP_OTP {
                          parameter_debug("PEAP Allow Type: OTP\n");
	  	  	  set_current_peap();
			  SET_FLAG(tmp_peap->flags, CONFIG_PEAP_ALLOW_OTP);
                        }
                      | TK_EAP_GTC {
                          parameter_debug("PEAP Allow Type: GTC\n");
	  	  	  set_current_peap();
			  SET_FLAG(tmp_peap->flags, CONFIG_PEAP_ALLOW_GTC);
                        }
                       ;


eap_peap_phase2_statement : eap_mschapv2_statement {
                             set_current_peap(); 
	   	             if (!config_eap_method_contains_method(tmp_peap->phase2,
								    EAP_TYPE_MSCHAPV2))
			       add_config_eap_method(&(tmp_peap->phase2),
						     EAP_TYPE_MSCHAPV2,
						     tmp_mschapv2);
			     else
			       delete_config_eap_mschapv2(&tmp_mschapv2);
			     tmp_mschapv2 = NULL;
                            }
                          | eap_md5_statement {
                             set_current_peap(); 
	   	             if (!config_eap_method_contains_method(tmp_peap->phase2,
								    EAP_TYPE_MD5))
			       add_config_eap_method(&(tmp_peap->phase2),
						     EAP_TYPE_MD5,
						     tmp_md5);
			     else
			       delete_config_eap_md5(&tmp_md5);
			     tmp_md5 = NULL;
                            }
                          | eap_sim_statement {
                             set_current_peap(); 
	   	             if (!config_eap_method_contains_method(tmp_peap->phase2,
								    EAP_TYPE_SIM))
			       add_config_eap_method(&(tmp_peap->phase2),
						     EAP_TYPE_SIM,
						     tmp_sim);
			     else
			       delete_config_eap_sim(&tmp_sim);
			     tmp_sim = NULL;
                            }
                          ;

eap_sim_statement   : TK_EAP_SIM '{' eap_sim_params'}' 
                    | TK_EAP_SIM '{' '}' {
                        set_current_sim(); /* define an empty sim struct*/
                      }
                    ;

eap_sim_params     : eap_sim_params eap_sim_param
                   | eap_sim_param
                   ;

eap_sim_param      : TK_USERNAME '=' TK_USERNAME_VAL {
                       parameter_debug("sim username: \"%s\"\n", $3);
		       set_current_sim();
		       if (!tmp_sim->username)
			 tmp_sim->username = $3;
		       else
			 free($3);
                     }
                   | TK_PASSWORD '=' TK_PASS {
		       parameter_debug("sim password: \"%s\"\n", $3);
		       set_current_sim();
		       if (!tmp_sim->password)
			 tmp_sim->password = $3;
		       else
			 free($3);
		     }
                   | TK_AUTO_REALM '=' TK_YES {
  		       parameter_debug("sim auto_realm: \"yes\"\n");
		       set_current_sim();
		       tmp_sim->auto_realm = 1;
		   }
                   | TK_AUTO_REALM '=' TK_NO {
  		       parameter_debug("sim auto_realm: \"no\"\n");
		       set_current_sim();
		       tmp_sim->auto_realm = 0;
		   }
                   ;
eap_aka_statement   : TK_EAP_AKA '{' eap_aka_params'}' 
                    | TK_EAP_AKA '{' '}' {
                        set_current_aka(); /* define an empty aka struct*/
                      }
                    ;

eap_aka_params     : eap_aka_params eap_aka_param
                   | eap_aka_param
                   ;

eap_aka_param      : TK_USERNAME '=' TK_USERNAME_VAL {
                       parameter_debug("aka username: \"%s\"\n", $3);
		       set_current_aka();
		       if (!tmp_aka->username)
			 tmp_aka->username = $3;
		       else
			 free($3);
                     }
                   | TK_PASSWORD '=' TK_PASS {
		       parameter_debug("aka password: \"%s\"\n", $3);
		       set_current_aka();
		       if (!tmp_aka->password)
			 tmp_aka->password = $3;
		       else
			 free($3);
		     }
                   | TK_AUTO_REALM '=' TK_YES {
  		       parameter_debug("aka auto_realm: \"yes\"\n");
		       set_current_aka();
		       tmp_aka->auto_realm = 1;
		   }
                   | TK_AUTO_REALM '=' TK_NO {
  		       parameter_debug("aka auto_realm: \"no\"\n");
		       set_current_aka();
		       tmp_aka->auto_realm = 0;
		   }
                   ;
wpa_psk_statement   : TK_WPA_PSK '{' wpa_psk_params'}'
                   | TK_WPA_PSK '{' '}' {
                       set_current_wpa_psk(); /* define an empty wpa psk struct*/
                   }
                   ;

wpa_psk_params     : wpa_psk_params wpa_psk_param
                   | wpa_psk_param
                   ;

wpa_psk_param      : TK_WPA_PSK_KEY '=' TK_FNAME {
                       parameter_debug("ascii key : \"%s\"\n", $3);
                       set_current_wpa_psk();
		       if (!tmp_wpa_psk->key)
			 tmp_wpa_psk->key = $3;
		       else
			 free($3);
                   }
                   | TK_WPA_PSK_HEX_KEY '=' TK_FNAME {
                       parameter_debug("hex key : \"%s\"\n", $3);
                       set_current_wpa_psk();
                       if (!tmp_wpa_psk->hex_key)
                         tmp_wpa_psk->hex_key = $3;
                       else
                         free($3);
                   }
                   ;
%%
