blob: 8afd779654dfaafaa4ab88d25cfc388f08add385 [file] [log] [blame]
Brian Waters13d96012017-12-08 16:53:31 -06001/*********************************************************************************************************
2* Software License Agreement (BSD License) *
3* Author: Sebastien Decugis <sdecugis@freediameter.net> *
4* *
5* Copyright (c) 2013, 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/* Lex configuration parser for radius_gw extension.
36 *
37 */
38
39%{
40#include "rgw.h"
41#include "rgw_conf.tab.h"
42
43/* Update the column information */
44#define YY_USER_ACTION { \
45 yylloc->first_column = yylloc->last_column + 1; \
46 yylloc->last_column = yylloc->first_column + yyleng - 1; \
47}
48
49/* %option noinput ? */
50#define YY_NO_INPUT
51%}
52
53%option bison-bridge bison-locations
54%option noyywrap
55%option nounput
56
57/* Use the following start condition to parse an URI */
58%x IN_PLG
59%x IN_CLI1
60%x IN_CLI2
61%x EXPECT_IP4
62%x EXPECT_IP6
63%x EXPECT_DECINT
64
65/* Quoted string. Multilines do not match. */
66qstring \"[^\"\n]*\"
67
68/* Used to match IP, IP6, and port */
69IP4 [0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}
70IP6 [[:xdigit:]]*:[[:xdigit:]]*:[[:xdigit:].:]*
71BR_PORT [[][0-9]+[]]
72
73
74%%
75
76 /* All sections */
77<*>\n {
78 /* Update the line count */
79 yylloc->first_line++;
80 yylloc->last_line++;
81 yylloc->last_column=0;
82 }
83
84<*>([[:space:]]{-}[\n])+ ; /* Eat all spaces, not new lines */
85<*>#.*$ ; /* Eat all comments */
86
87<*>{qstring} {
88 /* First copy the string without the quotes for use in the yacc parser */
89 yylval->string = strdup(yytext+1);
90 if (yylval->string == NULL) {
91 fd_log_debug("Unable to allocate memory: %s", strerror(errno));
92 return LEX_ERROR; /* trig an error in yacc parser */
93 }
94
95 yylval->string[yyleng-2] = '\0';
96
97 /* the yacc parser will check the string is valid */
98 return QSTRING;
99 }
100
101
102 /* Extension section */
103(?i:"RGWX") { BEGIN(IN_PLG); return PLG_PREFIX; }
104
105<IN_PLG>(?i:"auth") { return AUTH; }
106<IN_PLG>(?i:"acct") { return ACCT; }
107
108<IN_PLG,IN_CLI2>[[:xdigit:]]+ {
109 /* Convert this to an integer value */
110 int ret = sscanf(yytext, "%x", &yylval->integer);
111 if (ret != 1) {
112 /* No matching: an error occurred */
113 fd_log_debug("Unable to convert the value '%s' to a valid number: %s", yytext, strerror(errno));
114 return LEX_ERROR; /* trig an error in yacc parser */
115 /* Maybe we could REJECT instead of failing here? */
116 }
117 return INTEGER;
118 }
119
120<IN_PLG>[:] { return yytext[0]; }
121
122
123 /* Client section */
124(?i:"nas"|"cli") { BEGIN(IN_CLI1); yylval->integer=RGW_CLI_NAS; return NAS_OR_PXY; }
125(?i:"pxy") { BEGIN(IN_CLI1); yylval->integer=RGW_CLI_PXY; return NAS_OR_PXY; }
126
127 /* Match an IP (4 or 6) and optional port */
128<IN_CLI1>({IP4}|{IP6}){BR_PORT}? {
129 char * work;
130 char * port;
131 unsigned short p = 0;
132
133 work = strdup(yytext);
134 if ( work == NULL ) {
135 fd_log_debug("Unable to allocate memory: %s", strerror(errno));
136 return LEX_ERROR; /* trig an error in yacc parser */
137 }
138
139 if ((port = strchr(work, '[')) != NULL) {
140 *port = '\0';
141 port++;
142 if (sscanf(port, "%hu]", &p) != 1) {
143 fd_log_debug("'%s' is not a valid port: %s", port, strerror(errno));
144 free(work);
145 return LEX_ERROR; /* trig an error in yacc parser */
146 }
147 }
148
149 /* Do we have an IP or IPv6? Let's check if we have ':' char somewhere in the beginning */
150 if (memchr(work, ':', 5) != NULL) {
151 struct sockaddr_in6 * sin6 = NULL;
152
153 sin6 = malloc(sizeof(struct sockaddr_in6));
154 if (sin6 == NULL) {
155 fd_log_debug("Unable to allocate memory: %s", strerror(errno));
156 free(work);
157 return LEX_ERROR; /* trig an error in yacc parser */
158 }
159
160 memset(sin6, 0, sizeof(struct sockaddr_in6));
161 sin6->sin6_family = AF_INET6;
162 if (inet_pton(AF_INET6, work, &sin6->sin6_addr) != 1) {
163 fd_log_debug("'%s' is not a valid IPv6 address: %s", work, strerror(errno));
164 free(work);
165 free(sin6);
166 return LEX_ERROR; /* trig an error in yacc parser */
167 }
168 sin6->sin6_port = htons(p);
169 yylval->ss = (struct sockaddr *)sin6;
170 } else {
171 struct sockaddr_in * sin = NULL;
172
173 sin = malloc(sizeof(struct sockaddr_in));
174 if (sin == NULL) {
175 fd_log_debug("Unable to allocate memory: %s", strerror(errno));
176 free(work);
177 return LEX_ERROR; /* trig an error in yacc parser */
178 }
179
180 memset(sin, 0, sizeof(struct sockaddr_in));
181 sin->sin_family = AF_INET;
182 if (inet_pton(AF_INET, work, &sin->sin_addr) != 1) {
183 fd_log_debug("'%s' is not a valid IP address: %s", work, strerror(errno));
184 free(work);
185 free(sin);
186 return LEX_ERROR; /* trig an error in yacc parser */
187 }
188
189 sin->sin_port = htons(p);
190 yylval->ss = (struct sockaddr *)sin;
191 }
192 free(work);
193 return IP;
194 }
195
196
197<IN_CLI1>"/" { BEGIN(IN_CLI2); return '/'; }
198
199
200 /* Servers section */
201(?i:"auth_server_enable") { BEGIN(EXPECT_DECINT); return AUTH_ENABLE; }
202(?i:"auth_server_port") { BEGIN(EXPECT_DECINT); return AUTH_PORT; }
203(?i:"auth_server_ip4") { BEGIN(EXPECT_IP4); return AUTH_IP4; }
204(?i:"auth_server_ip6") { BEGIN(EXPECT_IP6); return AUTH_IP6; }
205(?i:"acct_server_enable") { BEGIN(EXPECT_DECINT); return ACCT_ENABLE; }
206(?i:"acct_server_port") { BEGIN(EXPECT_DECINT); return ACCT_PORT; }
207(?i:"acct_server_ip4") { BEGIN(EXPECT_IP4); return ACCT_IP4; }
208(?i:"acct_server_ip6") { BEGIN(EXPECT_IP6); return ACCT_IP6; }
209
210<EXPECT_DECINT>[[:digit:]]+ {
211 /* Match an integer (not hexa) */
212 int ret = sscanf(yytext, "%d", &yylval->integer);
213 if (ret != 1) {
214 /* No matching: an error occurred */
215 fd_log_debug("Unable to convert the value '%s' to a valid number: %s", yytext, strerror(errno));
216 return LEX_ERROR; /* trig an error in yacc parser */
217 /* Maybe we could REJECT instead of failing here? */
218 }
219 return INTEGER;
220 }
221
222<EXPECT_IP4,EXPECT_IP6>(?i:"disable") { return DISABLED; }
223
224<EXPECT_IP4>{IP4} {
225 struct sockaddr_in * sin = NULL;
226
227 sin = malloc(sizeof(struct sockaddr_in));
228 if (sin == NULL) {
229 fd_log_debug("Unable to allocate memory: %s", strerror(errno));
230 return LEX_ERROR; /* trig an error in yacc parser */
231 }
232
233 memset(sin, 0, sizeof(struct sockaddr_in));
234 sin->sin_family = AF_INET;
235 if (inet_pton(AF_INET, yytext, &sin->sin_addr) != 1) {
236 fd_log_debug("'%s' is not a valid IP address: %s", yytext, strerror(errno));
237 free(sin);
238 return LEX_ERROR; /* trig an error in yacc parser */
239 }
240 yylval->ss = (struct sockaddr *)sin;
241 return IP;
242 }
243
244<EXPECT_IP6>{IP6} {
245 struct sockaddr_in6 * sin6 = NULL;
246
247 sin6 = malloc(sizeof(struct sockaddr_in6));
248 if (sin6 == NULL) {
249 fd_log_debug("Unable to allocate memory: %s", strerror(errno));
250 return LEX_ERROR; /* trig an error in yacc parser */
251 }
252
253 memset(sin6, 0, sizeof(struct sockaddr_in6));
254 sin6->sin6_family = AF_INET6;
255 if (inet_pton(AF_INET6, yytext, &sin6->sin6_addr) != 1) {
256 fd_log_debug("'%s' is not a valid IPv6 address: %s", yytext, strerror(errno));
257 free(sin6);
258 return LEX_ERROR; /* trig an error in yacc parser */
259 }
260 yylval->ss = (struct sockaddr *)sin6;
261 return IP;
262 }
263
264
265 /* Valid single characters for yyparse in all contexts */
266<*>[=] { return yytext[0]; }
267<*>[;] { BEGIN(INITIAL); return yytext[0]; }
268
269 /* Unrecognized token */
270<*>[[:alnum:]]+ | /* This rule is only useful to print a complete token in error messages */
271 /* Unrecognized character */
272<*>. {
273 fd_log_debug("Unrecognized text on line %d col %d: '%s'.", yylloc->first_line, yylloc->first_column, yytext);
274 return LEX_ERROR;
275 }
276
277%%