Initial commit
Change-Id: I6a4444e3c193dae437cd7929f4c39aba7b749efa
diff --git a/libfdcore/fdd.y b/libfdcore/fdd.y
new file mode 100644
index 0000000..07707c9
--- /dev/null
+++ b/libfdcore/fdd.y
@@ -0,0 +1,667 @@
+/*********************************************************************************************************
+* Software License Agreement (BSD License) *
+* Author: Sebastien Decugis <sdecugis@freediameter.net> *
+* *
+* Copyright (c) 2015, WIDE Project and NICT *
+* All rights reserved. *
+* *
+* Redistribution and use of this software 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. *
+* *
+* * Neither the name of the WIDE Project or NICT nor the *
+* names of its contributors may be used to endorse or *
+* promote products derived from this software without *
+* specific prior written permission of WIDE Project and *
+* NICT. *
+* *
+* 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. *
+*********************************************************************************************************/
+
+/* Yacc configuration parser.
+ *
+ * This file defines the grammar of the configuration file.
+ * Note that each extension has a separate independant configuration file.
+ *
+ * Note : This module is NOT thread-safe. All processing must be done from one thread only.
+ */
+
+/* For development only : */
+%debug
+%error-verbose
+
+%parse-param {struct fd_config * conf}
+
+/* Keep track of location */
+%locations
+%pure-parser
+
+%{
+#include "fdcore-internal.h"
+#include "fdd.tab.h" /* bug : bison does not define the YYLTYPE before including this bloc, so... */
+
+/* The Lex parser prototype */
+int fddlex(YYSTYPE *lvalp, YYLTYPE *llocp);
+
+/* Function to report error */
+void yyerror (YYLTYPE *ploc, struct fd_config * conf, char const *s)
+{
+ if (ploc->first_line != ploc->last_line) {
+ TRACE_ERROR("%s:%d.%d-%d.%d : %s", conf->cnf_file, ploc->first_line, ploc->first_column, ploc->last_line, ploc->last_column, s);
+ } else if (ploc->first_column != ploc->last_column) {
+ TRACE_ERROR("%s:%d.%d-%d : %s", conf->cnf_file, ploc->first_line, ploc->first_column, ploc->last_column, s);
+ } else {
+ TRACE_ERROR("%s:%d.%d : %s", conf->cnf_file, ploc->first_line, ploc->first_column, s);
+ }
+}
+
+int got_peer_noip = 0;
+int got_peer_noipv6 = 0;
+int got_peer_notcp = 0;
+int got_peer_nosctp = 0;
+
+struct peer_info fddpi;
+
+%}
+
+/* Values returned by lex for token */
+%union {
+ char *string; /* The string is allocated by strdup in lex.*/
+ int integer; /* Store integer values */
+}
+
+/* In case of error in the lexical analysis */
+%token LEX_ERROR
+
+%token <string> QSTRING
+%token <integer> INTEGER
+
+%type <string> extconf
+
+%token IDENTITY
+%token REALM
+%token PORT
+%token SECPORT
+%token SEC3436
+%token NOIP
+%token NOIP6
+%token NOTCP
+%token NOSCTP
+%token PREFERTCP
+%token OLDTLS
+%token NOTLS
+%token SCTPSTREAMS
+%token APPSERVTHREADS
+%token LISTENON
+%token THRPERSRV
+%token TCTIMER
+%token TWTIMER
+%token NORELAY
+%token LOADEXT
+%token CONNPEER
+%token CONNTO
+%token TLS_CRED
+%token TLS_CA
+%token TLS_CRL
+%token TLS_PRIO
+%token TLS_DH_BITS
+%token TLS_DH_FILE
+
+
+/* -------------------------------------- */
+%%
+
+ /* The grammar definition - Sections blocs. */
+conffile: /* Empty is OK -- for simplicity here, we reject in daemon later */
+ | conffile identity
+ | conffile realm
+ | conffile tctimer
+ | conffile twtimer
+ | conffile port
+ | conffile secport
+ | conffile sec3436
+ | conffile sctpstreams
+ | conffile listenon
+ | conffile thrpersrv
+ | conffile norelay
+ | conffile appservthreads
+ | conffile noip
+ | conffile noip6
+ | conffile notcp
+ | conffile nosctp
+ | conffile prefertcp
+ | conffile oldtls
+ | conffile loadext
+ | conffile connpeer
+ | conffile tls_cred
+ | conffile tls_ca
+ | conffile tls_crl
+ | conffile tls_prio
+ | conffile tls_dh
+ | conffile errors
+ {
+ yyerror(&yylloc, conf, "An error occurred while parsing the configuration file");
+ return EINVAL;
+ }
+ ;
+
+ /* Lexical or syntax error */
+errors: LEX_ERROR
+ | error
+ ;
+
+identity: IDENTITY '=' QSTRING ';'
+ {
+ conf->cnf_diamid = $3;
+ }
+ ;
+
+realm: REALM '=' QSTRING ';'
+ {
+ conf->cnf_diamrlm = $3;
+ }
+ ;
+
+tctimer: TCTIMER '=' INTEGER ';'
+ {
+ CHECK_PARAMS_DO( ($3 > 0),
+ { yyerror (&yylloc, conf, "Invalid value"); YYERROR; } );
+ conf->cnf_timer_tc = (unsigned int)$3;
+ }
+ ;
+
+twtimer: TWTIMER '=' INTEGER ';'
+ {
+ CHECK_PARAMS_DO( ($3 > 5),
+ { yyerror (&yylloc, conf, "Invalid value"); YYERROR; } );
+ conf->cnf_timer_tw = (unsigned int)$3;
+ }
+ ;
+
+port: PORT '=' INTEGER ';'
+ {
+ CHECK_PARAMS_DO( ($3 >= 0) && ($3 < 1<<16),
+ { yyerror (&yylloc, conf, "Invalid value"); YYERROR; } );
+ conf->cnf_port = (uint16_t)$3;
+ }
+ ;
+
+secport: SECPORT '=' INTEGER ';'
+ {
+ CHECK_PARAMS_DO( ($3 >= 0) && ($3 < 1<<16),
+ { yyerror (&yylloc, conf, "Invalid value"); YYERROR; } );
+ conf->cnf_port_tls = (uint16_t)$3;
+ }
+ ;
+
+sec3436: SEC3436 '=' INTEGER ';'
+ {
+ CHECK_PARAMS_DO( ($3 >= 0) && ($3 < 1<<16),
+ { yyerror (&yylloc, conf, "Invalid value"); YYERROR; } );
+ conf->cnf_port_3436 = (uint16_t)$3;
+ }
+ ;
+
+sctpstreams: SCTPSTREAMS '=' INTEGER ';'
+ {
+ CHECK_PARAMS_DO( ($3 > 0) && ($3 < 1<<16),
+ { yyerror (&yylloc, conf, "Invalid value"); YYERROR; } );
+ conf->cnf_sctp_str = (uint16_t)$3;
+ }
+ ;
+
+listenon: LISTENON '=' QSTRING ';'
+ {
+ struct addrinfo hints, *ai;
+ int ret;
+
+ memset(&hints, 0, sizeof(hints));
+ hints.ai_flags = AI_PASSIVE | AI_NUMERICHOST;
+ ret = getaddrinfo($3, NULL, &hints, &ai);
+ if (ret) { yyerror (&yylloc, conf, gai_strerror(ret)); YYERROR; }
+ CHECK_FCT_DO( fd_ep_add_merge( &conf->cnf_endpoints, ai->ai_addr, ai->ai_addrlen, EP_FL_CONF ), YYERROR );
+ freeaddrinfo(ai);
+ free($3);
+ }
+ ;
+
+thrpersrv: THRPERSRV '=' INTEGER ';'
+ {
+ CHECK_PARAMS_DO( ($3 > 0),
+ { yyerror (&yylloc, conf, "Invalid value"); YYERROR; } );
+ conf->cnf_thr_srv = $3;
+ }
+ ;
+
+norelay: NORELAY ';'
+ {
+ conf->cnf_flags.no_fwd = 1;
+ }
+ ;
+
+appservthreads: APPSERVTHREADS '=' INTEGER ';'
+ {
+ CHECK_PARAMS_DO( ($3 > 0) && ($3 < 256),
+ { yyerror (&yylloc, conf, "Invalid value"); YYERROR; } );
+ conf->cnf_dispthr = (uint16_t)$3;
+ }
+ ;
+
+noip: NOIP ';'
+ {
+ if (got_peer_noipv6) {
+ yyerror (&yylloc, conf, "No_IP conflicts with a ConnectPeer directive No_IPv6.");
+ YYERROR;
+ }
+ conf->cnf_flags.no_ip4 = 1;
+ }
+ ;
+
+noip6: NOIP6 ';'
+ {
+ if (got_peer_noip) {
+ yyerror (&yylloc, conf, "No_IP conflicts with a ConnectPeer directive No_IP.");
+ YYERROR;
+ }
+ conf->cnf_flags.no_ip6 = 1;
+ }
+ ;
+
+notcp: NOTCP ';'
+ {
+ #ifdef DISABLE_SCTP
+ yyerror (&yylloc, conf, "No_TCP cannot be specified for daemon compiled with DISABLE_SCTP option.");
+ YYERROR;
+ #endif
+ if (conf->cnf_flags.no_sctp)
+ {
+ yyerror (&yylloc, conf, "No_TCP conflicts with No_SCTP directive." );
+ YYERROR;
+ }
+ if (got_peer_nosctp) {
+ yyerror (&yylloc, conf, "No_TCP conflicts with a ConnectPeer directive No_SCTP.");
+ YYERROR;
+ }
+ conf->cnf_flags.no_tcp = 1;
+ }
+ ;
+
+nosctp: NOSCTP ';'
+ {
+ if (conf->cnf_flags.no_tcp)
+ {
+ yyerror (&yylloc, conf, "No_SCTP conflicts with No_TCP directive." );
+ YYERROR;
+ }
+ if (got_peer_notcp) {
+ yyerror (&yylloc, conf, "No_SCTP conflicts with a ConnectPeer directive No_TCP.");
+ YYERROR;
+ }
+ conf->cnf_flags.no_sctp = 1;
+ }
+ ;
+
+prefertcp: PREFERTCP ';'
+ {
+ conf->cnf_flags.pr_tcp = 1;
+ }
+ ;
+
+oldtls: OLDTLS ';'
+ {
+ conf->cnf_flags.tls_alg = 1;
+ }
+ ;
+
+loadext: LOADEXT '=' QSTRING extconf ';'
+ {
+ char * fname;
+ char * cfname;
+ FILE * fd;
+
+ /* Try and open the extension file */
+ fname = $3;
+ fd = fopen(fname, "r");
+ if ((fd == NULL) && (*fname != '/')) {
+ char * bkp = fname;
+ CHECK_MALLOC_DO( fname = malloc( strlen(bkp) + strlen(DEFAULT_EXTENSIONS_PATH) + 2 ),
+ { yyerror (&yylloc, conf, "Not enough memory"); YYERROR; } );
+ sprintf(fname, DEFAULT_EXTENSIONS_PATH "/%s", bkp);
+ fd = fopen(fname, "r");
+ if (fd == NULL) {
+ free(fname);
+ fname = bkp;
+ } else {
+ free(bkp);
+ }
+ }
+ if (fd != NULL) {
+ fclose(fd);
+ } /* otherwise, LD_LIBRARY_PATH will be tested by dl_open.
+ This should not give any security issue, otherwise we can add an "else fail" here. */
+
+ /* Try and open the configuration file (optional) */
+ cfname = $4;
+ if (cfname) {
+ fd = fopen(cfname, "r");
+ if ((fd == NULL) && (*cfname != '/')) {
+ char * test;
+ CHECK_MALLOC_DO( test = malloc( strlen(cfname) + strlen(DEFAULT_CONF_PATH) + 2 ),
+ { yyerror (&yylloc, conf, "Not enough memory"); YYERROR; } );
+ sprintf(test, DEFAULT_CONF_PATH "/%s", cfname);
+ fd = fopen(test, "r");
+ if (fd) {
+ free(cfname);
+ cfname=test;
+ } else {
+ /* This is not an error, we allow an extension to wait for something else than a real conf file. */
+ free(test);
+ }
+ }
+ if (fd)
+ fclose(fd);
+ }
+
+ CHECK_FCT_DO( fd_ext_add( fname, cfname ),
+ { yyerror (&yylloc, conf, "Error adding extension"); YYERROR; } );
+ }
+ ;
+
+extconf: /* empty */
+ {
+ $$ = NULL;
+ }
+ | ':' QSTRING
+ {
+ $$ = $2;
+ }
+ ;
+
+connpeer: {
+ memset(&fddpi, 0, sizeof(fddpi));
+ fddpi.config.pic_flags.persist = PI_PRST_ALWAYS;
+ fd_list_init( &fddpi.pi_endpoints, NULL );
+ }
+ CONNPEER '=' QSTRING peerinfo ';'
+ {
+ fddpi.pi_diamid = $4;
+ CHECK_FCT_DO( fd_peer_add ( &fddpi, conf->cnf_file, NULL, NULL ),
+ { yyerror (&yylloc, conf, "Error adding ConnectPeer information"); YYERROR; } );
+
+ /* Now destroy any content in the structure */
+ free(fddpi.pi_diamid);
+ free(fddpi.config.pic_realm);
+ free(fddpi.config.pic_priority);
+ while (!FD_IS_LIST_EMPTY(&fddpi.pi_endpoints)) {
+ struct fd_list * li = fddpi.pi_endpoints.next;
+ fd_list_unlink(li);
+ free(li);
+ }
+ }
+ ;
+
+peerinfo: /* empty */
+ | '{' peerparams '}'
+ ;
+
+peerparams: /* empty */
+ | peerparams NOIP ';'
+ {
+ if ((conf->cnf_flags.no_ip6) || (fddpi.config.pic_flags.pro3 == PI_P3_IP)) {
+ yyerror (&yylloc, conf, "No_IP conflicts with a No_IPv6 directive.");
+ YYERROR;
+ }
+ got_peer_noip++;
+ fddpi.config.pic_flags.pro3 = PI_P3_IPv6;
+ }
+ | peerparams NOIP6 ';'
+ {
+ if ((conf->cnf_flags.no_ip4) || (fddpi.config.pic_flags.pro3 == PI_P3_IPv6)) {
+ yyerror (&yylloc, conf, "No_IPv6 conflicts with a No_IP directive.");
+ YYERROR;
+ }
+ got_peer_noipv6++;
+ fddpi.config.pic_flags.pro3 = PI_P3_IP;
+ }
+ | peerparams NOTCP ';'
+ {
+ #ifdef DISABLE_SCTP
+ yyerror (&yylloc, conf, "No_TCP cannot be specified in daemon compiled with DISABLE_SCTP option.");
+ YYERROR;
+ #endif
+ if ((conf->cnf_flags.no_sctp) || (fddpi.config.pic_flags.pro4 == PI_P4_TCP)) {
+ yyerror (&yylloc, conf, "No_TCP conflicts with a No_SCTP directive.");
+ YYERROR;
+ }
+ got_peer_notcp++;
+ fddpi.config.pic_flags.pro4 = PI_P4_SCTP;
+ }
+ | peerparams NOSCTP ';'
+ {
+ if ((conf->cnf_flags.no_tcp) || (fddpi.config.pic_flags.pro4 == PI_P4_SCTP)) {
+ yyerror (&yylloc, conf, "No_SCTP conflicts with a No_TCP directive.");
+ YYERROR;
+ }
+ got_peer_nosctp++;
+ fddpi.config.pic_flags.pro4 = PI_P4_TCP;
+ }
+ | peerparams PREFERTCP ';'
+ {
+ fddpi.config.pic_flags.alg = PI_ALGPREF_TCP;
+ }
+ | peerparams OLDTLS ';'
+ {
+ fddpi.config.pic_flags.sec |= PI_SEC_TLS_OLD;
+ }
+ | peerparams NOTLS ';'
+ {
+ fddpi.config.pic_flags.sec |= PI_SEC_NONE;
+ }
+ | peerparams SEC3436 ';'
+ {
+ fddpi.config.pic_flags.sctpsec |= PI_SCTPSEC_3436;
+ }
+ | peerparams REALM '=' QSTRING ';'
+ {
+ fddpi.config.pic_realm = $4;
+ }
+ | peerparams PORT '=' INTEGER ';'
+ {
+ CHECK_PARAMS_DO( ($4 > 0) && ($4 < 1<<16),
+ { yyerror (&yylloc, conf, "Invalid port value"); YYERROR; } );
+ fddpi.config.pic_port = (uint16_t)$4;
+ }
+ | peerparams TCTIMER '=' INTEGER ';'
+ {
+ fddpi.config.pic_tctimer = $4;
+ }
+ | peerparams TWTIMER '=' INTEGER ';'
+ {
+ fddpi.config.pic_twtimer = $4;
+ }
+ | peerparams TLS_PRIO '=' QSTRING ';'
+ {
+ fddpi.config.pic_priority = $4;
+ }
+ | peerparams CONNTO '=' QSTRING ';'
+ {
+ struct addrinfo hints, *ai;
+ int ret;
+ int disc = 0;
+
+ memset(&hints, 0, sizeof(hints));
+ hints.ai_flags = AI_ADDRCONFIG | AI_NUMERICHOST;
+ ret = getaddrinfo($4, NULL, &hints, &ai);
+ if (ret == EAI_NONAME) {
+ /* The name was maybe not numeric, try again */
+ disc = EP_FL_DISC;
+ hints.ai_flags &= ~ AI_NUMERICHOST;
+ ret = getaddrinfo($4, NULL, &hints, &ai);
+ }
+ if (ret) { yyerror (&yylloc, conf, gai_strerror(ret)); YYERROR; }
+
+ CHECK_FCT_DO( fd_ep_add_merge( &fddpi.pi_endpoints, ai->ai_addr, ai->ai_addrlen, EP_FL_CONF | (disc ?: EP_ACCEPTALL) ), YYERROR );
+ free($4);
+ freeaddrinfo(ai);
+ }
+ ;
+
+tls_cred: TLS_CRED '=' QSTRING ',' QSTRING ';'
+ {
+ FILE * fd;
+ fd = fopen($3, "r");
+ if (fd == NULL) {
+ int ret = errno;
+ TRACE_ERROR("Unable to open certificate file %s for reading: %s", $3, strerror(ret));
+ yyerror (&yylloc, conf, "Error on file name");
+ YYERROR;
+ }
+ fclose(fd);
+ fd = fopen($5, "r");
+ if (fd == NULL) {
+ int ret = errno;
+ TRACE_ERROR("Unable to open private key file %s for reading: %s", $5, strerror(ret));
+ yyerror (&yylloc, conf, "Error on file name");
+ YYERROR;
+ }
+ fclose(fd);
+ conf->cnf_sec_data.cert_file = $3;
+ conf->cnf_sec_data.key_file = $5;
+
+ CHECK_GNUTLS_DO( gnutls_certificate_set_x509_key_file(
+ conf->cnf_sec_data.credentials,
+ conf->cnf_sec_data.cert_file,
+ conf->cnf_sec_data.key_file,
+ GNUTLS_X509_FMT_PEM),
+ { yyerror (&yylloc, conf, "Error opening certificate or private key file."); YYERROR; } );
+ }
+ ;
+
+tls_ca: TLS_CA '=' QSTRING ';'
+ {
+ FILE * fd;
+ fd = fopen($3, "rb");
+ if (fd == NULL) {
+ int ret = errno;
+ TRACE_ERROR("Unable to open CA file %s for reading: %s", $3, strerror(ret));
+ yyerror (&yylloc, conf, "Error on file name");
+ YYERROR;
+ }
+ #ifdef GNUTLS_VERSION_300
+ {
+ /* We import these CA in the trust list */
+ gnutls_x509_crt_t * calist;
+ unsigned int cacount;
+ gnutls_datum_t cafile;
+
+ CHECK_FCT_DO( fd_conf_stream_to_gnutls_datum(fd, &cafile),
+ { yyerror (&yylloc, conf, "Error reading CA file."); YYERROR; } );
+
+ CHECK_GNUTLS_DO( gnutls_x509_crt_list_import2(&calist, &cacount, &cafile, GNUTLS_X509_FMT_PEM,
+ GNUTLS_X509_CRT_LIST_FAIL_IF_UNSORTED),
+ { yyerror (&yylloc, conf, "Error importing CA file."); YYERROR; } );
+ free(cafile.data);
+
+ CHECK_GNUTLS_DO( gnutls_x509_trust_list_add_cas (fd_g_config->cnf_sec_data.trustlist, calist, cacount, 0),
+ { yyerror (&yylloc, conf, "Error saving CA in trust list."); YYERROR; } );
+ }
+ #endif /* GNUTLS_VERSION_300 */
+ fclose(fd);
+ conf->cnf_sec_data.ca_file = $3;
+ CHECK_GNUTLS_DO( conf->cnf_sec_data.ca_file_nr += gnutls_certificate_set_x509_trust_file(
+ conf->cnf_sec_data.credentials,
+ conf->cnf_sec_data.ca_file,
+ GNUTLS_X509_FMT_PEM),
+ { yyerror (&yylloc, conf, "Error setting CA parameters."); YYERROR; } );
+
+ }
+ ;
+
+tls_crl: TLS_CRL '=' QSTRING ';'
+ {
+ FILE * fd;
+ fd = fopen($3, "rb");
+ if (fd == NULL) {
+ int ret = errno;
+ TRACE_ERROR("Unable to open CRL file %s for reading: %s", $3, strerror(ret));
+ yyerror (&yylloc, conf, "Error on file name");
+ YYERROR;
+ }
+ #ifdef GNUTLS_VERSION_300
+ {
+ /* We import these CRL in the trust list */
+ gnutls_x509_crl_t * crllist;
+ unsigned int crlcount;
+ gnutls_datum_t crlfile;
+
+ CHECK_FCT_DO( fd_conf_stream_to_gnutls_datum(fd, &crlfile),
+ { yyerror (&yylloc, conf, "Error reading CRL file."); YYERROR; } );
+
+ CHECK_GNUTLS_DO( gnutls_x509_crl_list_import2(&crllist, &crlcount, &crlfile, GNUTLS_X509_FMT_PEM, 0),
+ { yyerror (&yylloc, conf, "Error importing CRL file."); YYERROR; } );
+ free(crlfile.data);
+
+ CHECK_GNUTLS_DO( gnutls_x509_trust_list_add_crls (fd_g_config->cnf_sec_data.trustlist, crllist, crlcount,
+ GNUTLS_TL_VERIFY_CRL,
+ 0),
+ { yyerror (&yylloc, conf, "Error importing CRL in trust list."); YYERROR; } );
+ }
+ #endif /* GNUTLS_VERSION_300 */
+ fclose(fd);
+ conf->cnf_sec_data.crl_file = $3;
+ CHECK_GNUTLS_DO( gnutls_certificate_set_x509_crl_file(
+ conf->cnf_sec_data.credentials,
+ conf->cnf_sec_data.crl_file,
+ GNUTLS_X509_FMT_PEM),
+ { yyerror (&yylloc, conf, "Error setting CRL parameters."); YYERROR; } );
+ }
+ ;
+
+tls_prio: TLS_PRIO '=' QSTRING ';'
+ {
+ const char * err_pos = NULL;
+ conf->cnf_sec_data.prio_string = $3;
+ CHECK_GNUTLS_DO( gnutls_priority_init(
+ &conf->cnf_sec_data.prio_cache,
+ conf->cnf_sec_data.prio_string,
+ &err_pos),
+ { yyerror (&yylloc, conf, "Error setting Priority parameter.");
+ TRACE_ERROR("Error at position : %s", err_pos);
+ YYERROR; } );
+ }
+ ;
+
+tls_dh: TLS_DH_BITS '=' INTEGER ';'
+ {
+ conf->cnf_sec_data.dh_bits = $3;
+ }
+ | TLS_DH_FILE '=' QSTRING ';'
+ {
+ FILE * fd;
+ free(conf->cnf_sec_data.dh_file);
+ conf->cnf_sec_data.dh_file = $3;
+ fd = fopen($3, "r");
+ if (fd == NULL) {
+ int ret = errno;
+ TRACE_ERROR("Unable to open DH file %s for reading: %s", $3, strerror(ret));
+ yyerror (&yylloc, conf, "Error on file name");
+ YYERROR;
+ }
+ fclose(fd);
+ }
+ ;