config_parser.y revision 296402
1/*
2 * Copyright (c) 2006 Mellanox Technologies Ltd. All rights reserved.
3 *
4 * This software is available to you under a choice of one of two
5 * licenses.  You may choose to be licensed under the terms of the GNU
6 * General Public License (GPL) Version 2, available from the file
7 * COPYING in the main directory of this source tree, or the
8 * OpenIB.org BSD license below:
9 *
10 *     Redistribution and use in source and binary forms, with or
11 *     without modification, are permitted provided that the following
12 *     conditions are met:
13 *
14 *      - Redistributions of source code must retain the above
15 *        copyright notice, this list of conditions and the following
16 *        disclaimer.
17 *
18 *      - Redistributions in binary form must reproduce the above
19 *        copyright notice, this list of conditions and the following
20 *        disclaimer in the documentation and/or other materials
21 *        provided with the distribution.
22 *
23 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
24 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
25 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
26 * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
27 * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
28 * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
29 * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
30 * SOFTWARE.
31 *
32 * $Id: config_parser.y 1.5 2005/06/29 11:39:27 eitan Exp $
33 */
34
35
36/*
37
38*/
39%{
40
41/* header section */
42#include <stdlib.h>
43#include <stdio.h>
44#include <string.h>
45#include "libsdp.h"
46#include <sys/socket.h>
47#include <netinet/in.h>
48#include <arpa/inet.h>
49
50#define YYERROR_VERBOSE 1
51
52extern int yyerror(char *msg);
53extern int yylex(void);
54static int parse_err = 0;
55
56struct use_family_rule *__sdp_clients_family_rules_head = NULL;
57struct use_family_rule *__sdp_clients_family_rules_tail = NULL;
58struct use_family_rule *__sdp_servers_family_rules_head = NULL;
59struct use_family_rule *__sdp_servers_family_rules_tail = NULL;
60
61/* some globals to store intermidiate parser state */
62static struct use_family_rule __sdp_rule;
63static int current_role = 0;
64
65int __sdp_config_empty(
66                       void
67                       )
68{
69  return ( (__sdp_clients_family_rules_head == NULL) &&
70           (__sdp_servers_family_rules_head == NULL) );
71}
72
73static void __sdp_set_ip_addr(char *addr)
74{
75	int rc;
76	char *addrlen;
77	struct sockaddr_in *addr4 = (struct sockaddr_in *)(&__sdp_rule.ip);
78	struct sockaddr_in6 *addr6 = (struct sockaddr_in6 *)(&__sdp_rule.ip);
79    	int prefixlen = 0;
80
81	addrlen = strrchr(addr, '/');
82	if (addrlen) {
83    		prefixlen = atoi(addrlen + 1);
84		*addrlen = '\0';
85	}
86
87	rc = inet_pton(AF_INET, addr, &addr4->sin_addr);
88	if (rc > 0) {
89		addr4->sin_family = AF_INET;
90		__sdp_rule.prefixlen = prefixlen ?: 32;
91		return;
92	}
93
94	rc = inet_pton(AF_INET6, addr, &addr6->sin6_addr);
95	if (rc > 0) {
96		addr6->sin6_family = AF_INET6;
97		__sdp_rule.prefixlen = prefixlen ?: 128;
98		return;
99	}
100
101    	parse_err = 1;
102    	yyerror("provided address is not legal");
103}
104
105static const char *addr2str(struct sockaddr_storage *src)
106{
107	static char dst[INET6_ADDRSTRLEN];
108	int af = src->ss_family;
109	const struct sockaddr_in *addr4 = (const struct sockaddr_in *)src;
110	const struct sockaddr_in6 *addr6 = (const struct sockaddr_in6 *)src;
111
112	if (af == AF_INET6)
113		return inet_ntop(af, &addr6->sin6_addr, dst, INET6_ADDRSTRLEN);
114
115	return inet_ntop(af, &addr4->sin_addr, dst, INET6_ADDRSTRLEN);
116}
117
118static void __sdp_set_prog_name_expr(char *prog_name_expr)
119{
120  __sdp_rule.prog_name_expr = strdup(prog_name_expr);
121  if (!__sdp_rule.prog_name_expr) {
122    yyerror("fail to allocate program name expression");
123  }
124}
125
126static char *__sdp_get_role_str(int role)
127{
128  if (role == 1) return("server");
129  if (role == 2) return("client");
130  return("unknown role");
131}
132
133extern int __sdp_min_level;
134
135/* dump the current state in readable format */
136static void  __sdp_dump_config_state() {
137  char buf[1024];
138  sprintf(buf, "CONFIG: use %s %s %s",
139          __sdp_get_family_str(__sdp_rule.target_family),
140          __sdp_get_role_str( current_role ),
141          __sdp_rule.prog_name_expr);
142  if (__sdp_rule.match_by_addr) {
143      sprintf(buf+strlen(buf), " %s/%d",
144              addr2str(&__sdp_rule.ip), __sdp_rule.prefixlen);
145  } else {
146    sprintf(buf+strlen(buf), " *");
147  }
148  if (__sdp_rule.match_by_port) {
149    sprintf(buf+strlen(buf), ":%d",__sdp_rule.sport);
150    if (__sdp_rule.eport > __sdp_rule.sport)
151      sprintf(buf+strlen(buf), "-%d",__sdp_rule.eport);
152  }
153  else
154    sprintf(buf+strlen(buf), ":*");
155  sprintf(buf+strlen(buf), "\n");
156  __sdp_log(1, buf);
157}
158
159/* use the above state for making a new rule */
160static void __sdp_add_rule() {
161  struct use_family_rule **p_tail, **p_head, *rule;
162
163  if (__sdp_min_level <= 1) __sdp_dump_config_state();
164  if ( current_role == 1 ) {
165    p_tail = &__sdp_servers_family_rules_tail;
166    p_head = &__sdp_servers_family_rules_head;
167  } else if ( current_role == 2 ) {
168    p_tail = &__sdp_clients_family_rules_tail;
169    p_head = &__sdp_clients_family_rules_head;
170  } else {
171    yyerror("ignoring unknown role");
172    parse_err = 1;
173    return;
174  }
175
176  rule = (struct use_family_rule *)malloc(sizeof(*rule));
177  if (!rule) {
178    yyerror("fail to allocate new rule");
179    parse_err = 1;
180    return;
181  }
182
183  memset(rule, 0, sizeof(*rule));
184  *rule = __sdp_rule;
185  rule->prev = *p_tail;
186  if (!(*p_head)) {
187    *p_head = rule;
188  } else {
189    (*p_tail)->next = rule;
190  } /* if */
191  *p_tail = rule;
192}
193
194%}
195
196
197%union {
198  int        ival;
199  char      *sval;
200}
201%token USE "use"
202%token CLIENT "client or connect"
203%token SERVER "server or listen"
204%token TCP "tcp"
205%token SDP "sdp"
206%token BOTH "both"
207%token INT "integer value"
208%token LOG "log statement"
209%token DEST "destination"
210%token STDERR "stderr"
211%token SYSLOG "syslog"
212%token FILENAME "file"
213%token NAME "a name"
214%token LEVEL "min-level"
215%token LINE "new line"
216%token SUBNET "ip address"
217%type <sval> NAME SUBNET
218%type <ival> INT LOG DEST STDERR SYSLOG FILENAME USE TCP SDP BOTH CLIENT SERVER LEVEL LINE
219%debug
220%error-verbose
221%start config
222
223%{
224  long __sdp_config_line_num;
225%}
226%%
227
228NL:
229    LINE
230  | NL LINE;
231
232ONL:
233  | NL;
234
235config:
236  ONL statements
237  ;
238
239statements:
240  | statements statement
241  ;
242
243statement:
244    log_statement
245  | socket_statement
246  ;
247
248log_statement:
249    LOG log_opts NL
250  ;
251
252log_opts:
253  | log_opts log_dest
254  | log_opts verbosity
255  ;
256
257log_dest:
258    DEST STDERR        { __sdp_log_set_log_stderr(); }
259  | DEST SYSLOG        { __sdp_log_set_log_syslog(); }
260  | DEST FILENAME NAME { __sdp_log_set_log_file($3); }
261  ;
262
263verbosity:
264    LEVEL INT { __sdp_log_set_min_level($2); }
265  ;
266
267socket_statement:
268    USE family role program address ':' ports NL { __sdp_add_rule(); }
269  ;
270
271family:
272    TCP  { __sdp_rule.target_family = USE_TCP; }
273  | SDP  { __sdp_rule.target_family = USE_SDP; }
274  | BOTH { __sdp_rule.target_family = USE_BOTH; }
275  ;
276
277role:
278    SERVER { current_role = 1; }
279  | CLIENT { current_role = 2; }
280  ;
281
282program:
283    NAME { __sdp_set_prog_name_expr($1); }
284  | '*'  { __sdp_set_prog_name_expr("*"); }
285  ;
286
287address:
288    SUBNET       { __sdp_rule.match_by_addr = 1; __sdp_set_ip_addr($1); }
289  | '*'          { __sdp_rule.match_by_addr = 0; __sdp_rule.prefixlen = 32; }
290  ;
291
292ports:
293    INT         { __sdp_rule.match_by_port = 1; __sdp_rule.sport= $1; __sdp_rule.eport= $1; }
294  | INT '-' INT { __sdp_rule.match_by_port = 1; __sdp_rule.sport= $1; __sdp_rule.eport= $3; }
295  | '*'         { __sdp_rule.match_by_port = 0; __sdp_rule.sport= 0 ; __sdp_rule.eport= 0; }
296  ;
297
298%%
299
300int yyerror(char *msg)
301{
302	/* replace the $undefined and $end if exists */
303	char *orig_msg = (char*)malloc(strlen(msg)+25);
304	char *final_msg = (char*)malloc(strlen(msg)+25);
305
306	strcpy(orig_msg, msg);
307
308	char *word = strtok(orig_msg, " ");
309	final_msg[0] = '\0';
310	while (word != NULL) {
311		if (!strncmp(word, "$undefined", 10)) {
312			strcat(final_msg, "unrecognized-token ");
313		} else if (!strncmp(word, "$end",4)) {
314			strcat(final_msg, "end-of-file ");
315		} else {
316			strcat(final_msg, word);
317			strcat(final_msg, " ");
318		}
319		word = strtok(NULL, " ");
320	}
321
322	__sdp_log(9, "Error (line:%ld) : %s\n", __sdp_config_line_num, final_msg);
323	parse_err = 1;
324
325	free(orig_msg);
326	free(final_msg);
327	return 1;
328}
329
330#include <unistd.h>
331#include <errno.h>
332
333/* parse apollo route dump file */
334int __sdp_parse_config (const char *fileName) {
335  extern FILE * libsdp_yyin;
336
337  /* open the file */
338  if (access(fileName, R_OK)) {
339	 printf("libsdp Error: No access to open File:%s %s\n",
340           fileName, strerror(errno));
341	 return(1);
342  }
343
344  libsdp_yyin = fopen(fileName,"r");
345  if (!libsdp_yyin) {
346	 printf("libsdp Error: Fail to open File:%s\n", fileName);
347	 return(1);
348  }
349  parse_err = 0;
350  __sdp_config_line_num = 1;
351
352  /* parse it */
353  yyparse();
354
355  fclose(libsdp_yyin);
356  return(parse_err);
357}
358
359
360