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