Navigation


source: freeDiameter/freeDiameter/fdd.y @ 24:bd83ce9328ed

Last change on this file since 24:bd83ce9328ed was 24:bd83ce9328ed, checked in by Sebastien Decugis <sdecugis@nict.go.jp>, 11 years ago

Cleanups and completed sctp code (not finished)

File size: 13.6 KB
Line 
1/*********************************************************************************************************
2* Software License Agreement (BSD License)                                                               *
3* Author: Sebastien Decugis <sdecugis@nict.go.jp>                                                        *
4*                                                                                                        *
5* Copyright (c) 2009, WIDE Project and NICT                                                              *
6* All rights reserved.                                                                                   *
7*                                                                                                        *
8* Redistribution and use of this software in source and binary forms, with or without modification, are  *
9* permitted provided that the following conditions are met:                                              *
10*                                                                                                        *
11* * Redistributions of source code must retain the above                                                 *
12*   copyright notice, this list of conditions and the                                                    *
13*   following disclaimer.                                                                                *
14*                                                                                                        *
15* * Redistributions in binary form must reproduce the above                                              *
16*   copyright notice, this list of conditions and the                                                    *
17*   following disclaimer in the documentation and/or other                                               *
18*   materials provided with the distribution.                                                            *
19*                                                                                                        *
20* * Neither the name of the WIDE Project or NICT nor the                                                 *
21*   names of its contributors may be used to endorse or                                                  *
22*   promote products derived from this software without                                                  *
23*   specific prior written permission of WIDE Project and                                                *
24*   NICT.                                                                                                *
25*                                                                                                        *
26* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED *
27* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A *
28* PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR *
29* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT     *
30* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS    *
31* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR *
32* TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF   *
33* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.                                                             *
34*********************************************************************************************************/
35
36/* Yacc configuration parser.
37 *
38 * This file defines the grammar of the configuration file.
39 * Note that each extension has a separate independant configuration file.
40 *
41 * Note : This module is NOT thread-safe. All processing must be done from one thread only.
42 */
43
44/* For development only : */
45%debug
46%error-verbose
47
48%parse-param {struct fd_config * conf}
49
50/* Keep track of location */
51%locations
52%pure-parser
53
54%{
55#include "fD.h"
56#include "fdd.tab.h"    /* bug : bison does not define the YYLTYPE before including this bloc, so... */
57
58/* The Lex parser prototype */
59int fddlex(YYSTYPE *lvalp, YYLTYPE *llocp);
60
61/* Function to report error */
62void yyerror (YYLTYPE *ploc, struct fd_config * conf, char const *s)
63{
64        if (ploc->first_line != ploc->last_line)
65                fprintf(stderr, "%s:%d.%d-%d.%d : %s\n", conf->cnf_file, ploc->first_line, ploc->first_column, ploc->last_line, ploc->last_column, s);
66        else if (ploc->first_column != ploc->last_column)
67                fprintf(stderr, "%s:%d.%d-%d : %s\n", conf->cnf_file, ploc->first_line, ploc->first_column, ploc->last_column, s);
68        else
69                fprintf(stderr, "%s:%d.%d : %s\n", conf->cnf_file, ploc->first_line, ploc->first_column, s);
70}
71
72int got_peer_noip = 0;
73int got_peer_noipv6 = 0;
74int got_peer_notcp = 0;
75int got_peer_nosctp = 0;
76
77struct peer_info fddpi;
78
79%}
80
81/* Values returned by lex for token */
82%union {
83        char             *string;       /* The string is allocated by strdup in lex.*/
84        int               integer;      /* Store integer values */
85}
86
87/* In case of error in the lexical analysis */
88%token          LEX_ERROR
89
90%token <string> QSTRING
91%token <integer> INTEGER
92
93%type <string>  extconf
94
95%token          IDENTITY
96%token          REALM
97%token          PORT
98%token          SECPORT
99%token          NOIP
100%token          NOIP6
101%token          NOTCP
102%token          NOSCTP
103%token          PREFERTCP
104%token          OLDTLS
105%token          NOTLS
106%token          SCTPSTREAMS
107%token          LISTENON
108%token          TCTIMER
109%token          TWTIMER
110%token          NORELAY
111%token          LOADEXT
112%token          CONNPEER
113%token          CONNTO
114%token          TLS_CRED
115%token          TLS_CA
116%token          TLS_CRL
117%token          TLS_PRIO
118%token          TLS_DH_BITS
119
120
121/* -------------------------------------- */
122%%
123
124        /* The grammar definition - Sections blocs. */
125conffile:               /* Empty is OK -- for simplicity here, we reject in daemon later */
126                        | conffile identity
127                        | conffile realm
128                        | conffile tctimer
129                        | conffile twtimer
130                        | conffile port
131                        | conffile secport
132                        | conffile sctpstreams
133                        | conffile listenon
134                        | conffile norelay
135                        | conffile noip
136                        | conffile noip6
137                        | conffile notcp
138                        | conffile nosctp
139                        | conffile prefertcp
140                        | conffile oldtls
141                        | conffile loadext
142                        | conffile connpeer
143                        | conffile tls_cred
144                        | conffile tls_ca
145                        | conffile tls_crl
146                        | conffile tls_prio
147                        | conffile tls_dh
148                        | conffile errors
149                        {
150                                yyerror(&yylloc, conf, "An error occurred while parsing the configuration file");
151                                return EINVAL;
152                        }
153                        ;
154
155                        /* Lexical or syntax error */
156errors:                 LEX_ERROR
157                        | error
158                        ;
159
160identity:               IDENTITY '=' QSTRING ';'
161                        {
162                                conf->cnf_diamid = $3;
163                        }
164                        ;
165
166realm:                  REALM '=' QSTRING ';'
167                        {
168                                conf->cnf_diamrlm = $3;
169                        }
170                        ;
171
172tctimer:                TCTIMER '=' INTEGER ';'
173                        {
174                                CHECK_PARAMS_DO( ($3 > 0),
175                                        { yyerror (&yylloc, conf, "Invalid value"); YYERROR; } );
176                                conf->cnf_timer_tc = (unsigned int)$3;
177                        }
178                        ;
179
180twtimer:                TWTIMER '=' INTEGER ';'
181                        {
182                                CHECK_PARAMS_DO( ($3 > 5),
183                                        { yyerror (&yylloc, conf, "Invalid value"); YYERROR; } );
184                                conf->cnf_timer_tw = (unsigned int)$3;
185                        }
186                        ;
187
188port:                   PORT '=' INTEGER ';'
189                        {
190                                CHECK_PARAMS_DO( ($3 > 0) && ($3 < 1<<16),
191                                        { yyerror (&yylloc, conf, "Invalid value"); YYERROR; } );
192                                conf->cnf_port = (uint16_t)$3;
193                        }
194                        ;
195
196secport:                SECPORT '=' INTEGER ';'
197                        {
198                                CHECK_PARAMS_DO( ($3 > 0) && ($3 < 1<<16),
199                                        { yyerror (&yylloc, conf, "Invalid value"); YYERROR; } );
200                                conf->cnf_port_tls = (uint16_t)$3;
201                        }
202                        ;
203
204sctpstreams:            SCTPSTREAMS '=' INTEGER ';'
205                        {
206                                CHECK_PARAMS_DO( ($3 > 0) && ($3 < 1<<16),
207                                        { yyerror (&yylloc, conf, "Invalid value"); YYERROR; } );
208                                conf->cnf_sctp_str = (uint16_t)$3;
209                        }
210                        ;
211
212listenon:               LISTENON '=' QSTRING ';'
213                        {
214                                struct addrinfo hints, *ai;
215                                int ret;
216                               
217                                memset(&hints, 0, sizeof(hints));
218                                hints.ai_flags = AI_PASSIVE | AI_NUMERICHOST;
219                                ret = getaddrinfo($3, NULL, &hints, &ai);
220                                if (ret) { yyerror (&yylloc, conf, gai_strerror(ret)); YYERROR; }
221                                CHECK_FCT_DO( fd_ep_add_merge( &conf->cnf_endpoints, ai->ai_addr, ai->ai_addrlen, EP_FL_CONF ), YYERROR );
222                                freeaddrinfo(ai);
223                                free($3);
224                        }
225                        ;
226
227norelay:                NORELAY ';'
228                        {
229                                conf->cnf_flags.no_fwd = 1;
230                        }
231                        ;
232
233noip:                   NOIP ';'
234                        {
235                                if (got_peer_noipv6) {
236                                        yyerror (&yylloc, conf, "No_IP conflicts with a ConnectPeer directive No_IPv6.");
237                                        YYERROR;
238                                }
239                                conf->cnf_flags.no_ip4 = 1;
240                        }
241                        ;
242
243noip6:                  NOIP6 ';'
244                        {
245                                if (got_peer_noip) {
246                                        yyerror (&yylloc, conf, "No_IP conflicts with a ConnectPeer directive No_IP.");
247                                        YYERROR;
248                                }
249                                conf->cnf_flags.no_ip6 = 1;
250                        }
251                        ;
252
253notcp:                  NOTCP ';'
254                        {
255                                #ifdef DISABLE_SCTP
256                                yyerror (&yylloc, conf, "No_TCP cannot be specified for daemon compiled with DISABLE_SCTP option.");
257                                YYERROR;
258                                #endif
259                                if (conf->cnf_flags.no_sctp)
260                                {
261                                        yyerror (&yylloc, conf, "No_TCP conflicts with No_SCTP directive." );
262                                        YYERROR;
263                                }
264                                if (got_peer_nosctp) {
265                                        yyerror (&yylloc, conf, "No_TCP conflicts with a ConnectPeer directive No_SCTP.");
266                                        YYERROR;
267                                }
268                                conf->cnf_flags.no_tcp = 1;
269                        }
270                        ;
271
272nosctp:                 NOSCTP ';'
273                        {
274                                if (conf->cnf_flags.no_tcp)
275                                {
276                                        yyerror (&yylloc, conf, "No_SCTP conflicts with No_TCP directive." );
277                                        YYERROR;
278                                }
279                                if (got_peer_notcp) {
280                                        yyerror (&yylloc, conf, "No_SCTP conflicts with a ConnectPeer directive No_TCP.");
281                                        YYERROR;
282                                }
283                                conf->cnf_flags.no_sctp = 1;
284                        }
285                        ;
286
287prefertcp:              PREFERTCP ';'
288                        {
289                                conf->cnf_flags.pr_tcp = 1;
290                        }
291                        ;
292
293oldtls:                 OLDTLS ';'
294                        {
295                                conf->cnf_flags.tls_alg = 1;
296                        }
297                        ;
298
299loadext:                LOADEXT '=' QSTRING extconf ';'
300                        {
301                                CHECK_FCT_DO( fd_ext_add( $3, $4 ),
302                                        { yyerror (&yylloc, conf, "Error adding extension"); YYERROR; } );
303                        }
304                        ;
305                       
306extconf:                /* empty */
307                        {
308                                $$ = NULL;
309                        }
310                        | ':' QSTRING
311                        {
312                                $$ = $2;
313                        }
314                        ;
315                       
316connpeer:               {
317                                memset(&fddpi, 0, sizeof(fddpi));
318                                fd_list_init( &fddpi.pi_endpoints, NULL );
319                                fd_list_init( &fddpi.pi_apps, NULL );
320                        }
321                        CONNPEER '=' QSTRING peerinfo ';'
322                        {
323                                fddpi.pi_diamid = $4;
324                                CHECK_FCT_DO( fd_peer_add ( &fddpi, conf->cnf_file, NULL, NULL ),
325                                        { yyerror (&yylloc, conf, "Error adding ConnectPeer information"); YYERROR; } );
326                                       
327                                /* Now destroy any content in the structure */
328                                free(fddpi.pi_diamid);
329                                free(fddpi.pi_sec_data.priority);
330                                while (!FD_IS_LIST_EMPTY(&fddpi.pi_endpoints)) {
331                                        struct fd_list * li = fddpi.pi_endpoints.next;
332                                        fd_list_unlink(li);
333                                        free(li);
334                                }
335                        }
336                        ;
337                       
338peerinfo:               /* empty */
339                        | '{' peerparams '}'
340                        ;
341                       
342peerparams:             /* empty */
343                        | peerparams NOIP ';'
344                        {
345                                if ((conf->cnf_flags.no_ip6) || (fddpi.pi_flags.pro3 == PI_P3_IP)) {
346                                        yyerror (&yylloc, conf, "No_IP conflicts with a No_IPv6 directive.");
347                                        YYERROR;
348                                }
349                                got_peer_noip++;
350                                fddpi.pi_flags.pro3 = PI_P3_IPv6;
351                        }
352                        | peerparams NOIP6 ';'
353                        {
354                                if ((conf->cnf_flags.no_ip4) || (fddpi.pi_flags.pro3 == PI_P3_IPv6)) {
355                                        yyerror (&yylloc, conf, "No_IPv6 conflicts with a No_IP directive.");
356                                        YYERROR;
357                                }
358                                got_peer_noipv6++;
359                                fddpi.pi_flags.pro3 = PI_P3_IP;
360                        }
361                        | peerparams NOTCP ';'
362                        {
363                                #ifdef DISABLE_SCTP
364                                        yyerror (&yylloc, conf, "No_TCP cannot be specified in daemon compiled with DISABLE_SCTP option.");
365                                        YYERROR;
366                                #endif
367                                if ((conf->cnf_flags.no_sctp) || (fddpi.pi_flags.pro4 == PI_P4_TCP)) {
368                                        yyerror (&yylloc, conf, "No_TCP conflicts with a No_SCTP directive.");
369                                        YYERROR;
370                                }
371                                got_peer_notcp++;
372                                fddpi.pi_flags.pro4 = PI_P4_SCTP;
373                        }
374                        | peerparams NOSCTP ';'
375                        {
376                                if ((conf->cnf_flags.no_tcp) || (fddpi.pi_flags.pro4 == PI_P4_SCTP)) {
377                                        yyerror (&yylloc, conf, "No_SCTP conflicts with a No_TCP directive.");
378                                        YYERROR;
379                                }
380                                got_peer_nosctp++;
381                                fddpi.pi_flags.pro4 = PI_P4_TCP;
382                        }
383                        | peerparams PREFERTCP ';'
384                        {
385                                fddpi.pi_flags.alg = PI_ALGPREF_TCP;
386                        }
387                        | peerparams OLDTLS ';'
388                        {
389                                if (fddpi.pi_flags.sec == PI_SEC_NONE) {
390                                        yyerror (&yylloc, conf, "ConnectPeer: TLS_old_method conflicts with No_TLS.");
391                                        YYERROR;
392                                }
393                                fddpi.pi_flags.sec = PI_SEC_TLS_OLD;
394                        }
395                        | peerparams NOTLS ';'
396                        {
397                                if (fddpi.pi_flags.sec == PI_SEC_TLS_OLD) {
398                                        yyerror (&yylloc, conf, "ConnectPeer: No_TLS conflicts with TLS_old_method.");
399                                        YYERROR;
400                                }
401                                fddpi.pi_flags.sec = PI_SEC_NONE;
402                        }
403                        | peerparams PORT '=' INTEGER ';'
404                        {
405                                CHECK_PARAMS_DO( ($4 > 0) && ($4 < 1<<16),
406                                        { yyerror (&yylloc, conf, "Invalid value"); YYERROR; } );
407                                fddpi.pi_port = (uint16_t)$4;
408                        }
409                        | peerparams TCTIMER '=' INTEGER ';'
410                        {
411                                fddpi.pi_tctimer = $4;
412                        }
413                        | peerparams TLS_PRIO '=' QSTRING ';'
414                        {
415                                fddpi.pi_sec_data.priority = $4;
416                        }
417                        | peerparams TWTIMER '=' INTEGER ';'
418                        {
419                                fddpi.pi_twtimer = $4;
420                        }
421                        | peerparams CONNTO '=' QSTRING ';'
422                        {
423                                struct addrinfo hints, *ai;
424                                int ret;
425                                int disc = 0;
426                               
427                                memset(&hints, 0, sizeof(hints));
428                                hints.ai_flags = AI_ADDRCONFIG | AI_NUMERICHOST;
429                                ret = getaddrinfo($4, NULL, &hints, &ai);
430                                if (ret == EAI_NONAME) {
431                                        /* The name was maybe not numeric, try again */
432                                        disc = EP_FL_DISC;
433                                        hints.ai_flags &= ~ AI_NUMERICHOST;
434                                        ret = getaddrinfo($4, NULL, &hints, &ai);
435                                }
436                                if (ret) { yyerror (&yylloc, conf, gai_strerror(ret)); YYERROR; }
437                               
438                                CHECK_FCT_DO( fd_ep_add_merge( &fddpi.pi_endpoints, ai->ai_addr, ai->ai_addrlen, EP_FL_CONF | disc ), YYERROR );
439                                free($4);
440                                freeaddrinfo(ai);
441                        }
442                        ;
443
444tls_cred:               TLS_CRED '=' QSTRING ',' QSTRING ';'
445                        {
446                                conf->cnf_sec_data.cert_file = $3;
447                                conf->cnf_sec_data.key_file = $5;
448                               
449                                CHECK_GNUTLS_DO( gnutls_certificate_set_x509_key_file(
450                                                        conf->cnf_sec_data.credentials,
451                                                        conf->cnf_sec_data.cert_file,
452                                                        conf->cnf_sec_data.key_file,
453                                                        GNUTLS_X509_FMT_PEM),
454                                                { yyerror (&yylloc, conf, "Error opening certificate or private key file."); YYERROR; } );
455                        }
456                        ;
457
458tls_ca:                 TLS_CA '=' QSTRING ';'
459                        {
460                                conf->cnf_sec_data.ca_file = $3;
461                                CHECK_GNUTLS_DO( gnutls_certificate_set_x509_trust_file(
462                                                        conf->cnf_sec_data.credentials,
463                                                        conf->cnf_sec_data.ca_file,
464                                                        GNUTLS_X509_FMT_PEM),
465                                                { yyerror (&yylloc, conf, "Error setting CA parameters."); YYERROR; } );
466                        }
467                        ;
468                       
469tls_crl:                TLS_CRL '=' QSTRING ';'
470                        {
471                                conf->cnf_sec_data.crl_file = $3;
472                                CHECK_GNUTLS_DO( gnutls_certificate_set_x509_crl_file(
473                                                        conf->cnf_sec_data.credentials,
474                                                        conf->cnf_sec_data.ca_file,
475                                                        GNUTLS_X509_FMT_PEM),
476                                                { yyerror (&yylloc, conf, "Error setting CRL parameters."); YYERROR; } );
477                        }
478                        ;
479                       
480tls_prio:               TLS_PRIO '=' QSTRING ';'
481                        {
482                                const char * err_pos = NULL;
483                                conf->cnf_sec_data.prio_string = $3;
484                                CHECK_GNUTLS_DO( gnutls_priority_init(
485                                                        &conf->cnf_sec_data.prio_cache,
486                                                        conf->cnf_sec_data.prio_string,
487                                                        &err_pos),
488                                                { yyerror (&yylloc, conf, "Error setting Priority parameter.");
489                                                  fprintf(stderr, "Error at position : %s\n", err_pos);
490                                                  YYERROR; } );
491                        }
492                        ;
493                       
494tls_dh:                 TLS_DH_BITS '=' INTEGER ';'
495                        {
496                                conf->cnf_sec_data.dh_bits = $3;
497                                TRACE_DEBUG(FULL, "Generating DH parameters...");
498                                CHECK_GNUTLS_DO( gnutls_dh_params_generate2(
499                                                        conf->cnf_sec_data.dh_cache,
500                                                        conf->cnf_sec_data.dh_bits),
501                                                { yyerror (&yylloc, conf, "Error setting DH Bits parameters.");
502                                                 YYERROR; } );
503                                TRACE_DEBUG(FULL, "DH parameters generated.");
504                        }
505                        ;
Note: See TracBrowser for help on using the repository browser.