blob: e4327191dbb3a4418d240ce894c0306dfe7e545f [file] [log] [blame]
Holger Freyther219518d2009-01-02 22:04:43 +00001/* (C) 2009 by Holger Hans Peter Freyther <zecke@selfish.org>
2 * All Rights Reserved
3 *
4 * This program is free software; you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License as published by
6 * the Free Software Foundation; either version 2 of the License, or
7 * (at your option) any later version.
8 *
9 * This program is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU General Public License for more details.
13 *
14 * You should have received a copy of the GNU General Public License along
15 * with this program; if not, write to the Free Software Foundation, Inc.,
16 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
17 *
18 */
19/*
20 * I'm lazy and will not introduce lemon to this game. Our telnet
21 * interface is matching line based so we can have a pattern that
22 * is matching a line and everyone will be happy.
23 */
24
25%option never-interactive
26%option noyywrap
27%option reentrant
28
29%{
30#include <string.h>
31#include <openbsc/telnet_interface.h>
32
33extern char *strndup(const char *s, size_t n);
34extern void telnet_write_help(int);
35extern void telnet_close_client(struct bsc_fd*);
36extern void telnet_error_client(int fd);
37extern void telnet_page(struct telnet_connection *con, const char *imsi, int page);
38extern void telnet_call(struct telnet_connection *con, const char *imsi,
39 const char* origin);
40extern void telnet_put_channel(struct telnet_connection*, const char *imsi);
41extern void telnet_get_channel(struct telnet_connection*, const char *imsi);
42extern void telnet_send_gsm_48(struct telnet_connection*);
43extern void telnet_send_gsm_11(struct telnet_connection*);
Holger Freytherae61cae2009-01-04 03:46:01 +000044extern void telnet_list_channels(struct telnet_connection*);
Holger Freyther219518d2009-01-02 22:04:43 +000045
46static const int PAGE_LEN = 5; /* "page " */
47static const int CALL_LEN = 5; /* "call " */
48static const int PUT_LEN = 12; /* "put_channel " */
49static const int GET_LEN = 12; /* "get_channel " */
50static const int NET_LEN = 3; /* "48 " "11 " */
Holger Freytherae61cae2009-01-04 03:46:01 +000051static const int SHOW_LEN = 5; /* "show " */
Holger Freyther219518d2009-01-02 22:04:43 +000052
53#define YY_EXTRA_TYPE struct telnet_connection*
54
55/* the string is null terminated */
56static int parse_hex(char *hex)
57{
58 int byte;
59 sscanf(hex, "%x", &byte);
60 return byte;
61}
62
63#define PREPARE_STRING(len) \
64 yytext[yyleng-1] = '\0'; \
65 char *str = yytext + len; \
66 char *pag = strstr(str, "\r"); \
67 if (pag) pag[0] = '\0'; \
68 pag = strstr(str, "\n"); \
69 if (pag) pag[0] = '\0';
70
71%}
72
73CMD_HELP "help"
74CMD_EXIT "exit"
75CMD_CLOSE "close"
76CMD_PAGE "page"
77CMD_GET_CHANNEL "get_channel"
78CMD_PUT_CHANNEL "put_channel"
79CMD_CALL "call"
80CMD_48 "48"
81CMD_11 "11"
Holger Freytherae61cae2009-01-04 03:46:01 +000082CMD_SHOW "show"
Holger Freyther219518d2009-01-02 22:04:43 +000083
84LINE_END \n|\r\n
85HEX [0][x][0-9a-zA-Z][0-9a-zA-Z]
86
87%s READ_HEX_BYTES
88
89%%
90{CMD_HELP}{LINE_END} {telnet_write_help(yyextra->fd.fd); yyterminate();}
91{CMD_EXIT}{LINE_END} {telnet_close_client(&yyextra->fd); yyterminate();}
92{CMD_CLOSE}{LINE_END} {telnet_close_client(&yyextra->fd); yyterminate();}
Holger Freytherae61cae2009-01-04 03:46:01 +000093{CMD_SHOW}{LINE_END} {telnet_list_channels(yyextra); yyterminate();}
Holger Freyther219518d2009-01-02 22:04:43 +000094{CMD_PAGE}[ ][0-9]+{LINE_END} {
95 PREPARE_STRING(PAGE_LEN)
96 telnet_page(yyextra, str, 0);
97 yyterminate();
98 }
99{CMD_PAGE}[ ][0-9]+[ ][0-2]{LINE_END} {
100 PREPARE_STRING(PAGE_LEN)
101 char *sp = strstr(str, " ");
102 sp[0] = '\0';
103 telnet_page(yyextra, str, atoi(sp+1));
104 yyterminate();
105 }
106{CMD_PUT_CHANNEL}[ ][0-9]+{LINE_END} {
107 PREPARE_STRING(PUT_LEN)
108 telnet_put_channel(yyextra, str);
109 yyterminate();
110 }
111{CMD_GET_CHANNEL}[ ][0-9]+{LINE_END} {
112 PREPARE_STRING(GET_LEN)
113 telnet_get_channel(yyextra, str);
114 yyterminate();
115 }
116{CMD_CALL}[ ][0-9]+[ ][0-9]+{LINE_END} {
117 PREPARE_STRING(CALL_LEN)
118 char *sp = strstr(str, " ");
119 sp[0] = '\0';
120 telnet_call(yyextra, str, sp+1);
121 yyterminate();
122 }
123{CMD_CALL}[ ][0-9]+{LINE_END} {
124 PREPARE_STRING(CALL_LEN)
125 telnet_call(yyextra, str, NULL);
126 yyterminate();
127 }
128<READ_HEX_BYTES>{HEX} {
129 if (yyextra->read >= sizeof(yyextra->commands)) {
130 yyterminate();
131 }
132 yytext[yyleng] = '\0';
133 yyextra->commands[yyextra->read++] = parse_hex(yytext+2);
134 }
135<READ_HEX_BYTES>{LINE_END} {
136 if (yyextra->command == TELNET_COMMAND_11) {
137 telnet_send_gsm_11(yyextra);
138 } else if (yyextra->command == TELNET_COMMAND_48) {
139 telnet_send_gsm_48(yyextra);
140 }
141
142 if (yyextra->imsi) {
143 free(yyextra->imsi);
144 yyextra->imsi = NULL;
145 }
146 yyterminate();
147 }
148<INITIAL>{CMD_48}[ ][0-9]+ {
149 BEGIN READ_HEX_BYTES;
150 yyextra->read = 0;
151 yyextra->command = TELNET_COMMAND_48;
152 yytext[yyleng-1] = '\0';
153 yyextra->imsi = strdup(yytext);
154 }
155
156<INITIAL>{CMD_11}[ ][0-9]+ {
157 BEGIN READ_HEX_BYTES;
158 yyextra->read = 0;
159 yyextra->command = TELNET_COMMAND_11;
160 yytext[yyleng-1] = '\0';
161 yyextra->imsi = strdup(yytext);
162 }
163
164
165
166[ \t\r\n] /* Ommit */
167. { telnet_error_client(yyextra->fd.fd); yyterminate(); }
168
169%%
170
171void telnet_parse(struct telnet_connection *conn, char *buf)
172{
173 yyscan_t scanner;
174 yylex_init(&scanner);
175 yyset_extra(conn, scanner);
176 yy_scan_string(buf, scanner);
177 yylex(scanner);
178 yylex_destroy(scanner);
179
180 if (conn->imsi) {
181 free(conn->imsi);
182 conn->imsi = NULL;
183 }
184}
Holger Freytherca362a62009-01-04 21:05:01 +0000185
186__attribute__((unused)) void telnet_unused(void)
187{
188 yyunput(0, 0, 0);
189 input(0);
190}