blob: 3af0d5818ad4c0c9dd0f5c8d44b6e47a7b628548 [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*);
44
45static const int PAGE_LEN = 5; /* "page " */
46static const int CALL_LEN = 5; /* "call " */
47static const int PUT_LEN = 12; /* "put_channel " */
48static const int GET_LEN = 12; /* "get_channel " */
49static const int NET_LEN = 3; /* "48 " "11 " */
50
51#define YY_EXTRA_TYPE struct telnet_connection*
52
53/* the string is null terminated */
54static int parse_hex(char *hex)
55{
56 int byte;
57 sscanf(hex, "%x", &byte);
58 return byte;
59}
60
61#define PREPARE_STRING(len) \
62 yytext[yyleng-1] = '\0'; \
63 char *str = yytext + len; \
64 char *pag = strstr(str, "\r"); \
65 if (pag) pag[0] = '\0'; \
66 pag = strstr(str, "\n"); \
67 if (pag) pag[0] = '\0';
68
69%}
70
71CMD_HELP "help"
72CMD_EXIT "exit"
73CMD_CLOSE "close"
74CMD_PAGE "page"
75CMD_GET_CHANNEL "get_channel"
76CMD_PUT_CHANNEL "put_channel"
77CMD_CALL "call"
78CMD_48 "48"
79CMD_11 "11"
80
81LINE_END \n|\r\n
82HEX [0][x][0-9a-zA-Z][0-9a-zA-Z]
83
84%s READ_HEX_BYTES
85
86%%
87{CMD_HELP}{LINE_END} {telnet_write_help(yyextra->fd.fd); yyterminate();}
88{CMD_EXIT}{LINE_END} {telnet_close_client(&yyextra->fd); yyterminate();}
89{CMD_CLOSE}{LINE_END} {telnet_close_client(&yyextra->fd); yyterminate();}
90{CMD_PAGE}[ ][0-9]+{LINE_END} {
91 PREPARE_STRING(PAGE_LEN)
92 telnet_page(yyextra, str, 0);
93 yyterminate();
94 }
95{CMD_PAGE}[ ][0-9]+[ ][0-2]{LINE_END} {
96 PREPARE_STRING(PAGE_LEN)
97 char *sp = strstr(str, " ");
98 sp[0] = '\0';
99 telnet_page(yyextra, str, atoi(sp+1));
100 yyterminate();
101 }
102{CMD_PUT_CHANNEL}[ ][0-9]+{LINE_END} {
103 PREPARE_STRING(PUT_LEN)
104 telnet_put_channel(yyextra, str);
105 yyterminate();
106 }
107{CMD_GET_CHANNEL}[ ][0-9]+{LINE_END} {
108 PREPARE_STRING(GET_LEN)
109 telnet_get_channel(yyextra, str);
110 yyterminate();
111 }
112{CMD_CALL}[ ][0-9]+[ ][0-9]+{LINE_END} {
113 PREPARE_STRING(CALL_LEN)
114 char *sp = strstr(str, " ");
115 sp[0] = '\0';
116 telnet_call(yyextra, str, sp+1);
117 yyterminate();
118 }
119{CMD_CALL}[ ][0-9]+{LINE_END} {
120 PREPARE_STRING(CALL_LEN)
121 telnet_call(yyextra, str, NULL);
122 yyterminate();
123 }
124<READ_HEX_BYTES>{HEX} {
125 if (yyextra->read >= sizeof(yyextra->commands)) {
126 yyterminate();
127 }
128 yytext[yyleng] = '\0';
129 yyextra->commands[yyextra->read++] = parse_hex(yytext+2);
130 }
131<READ_HEX_BYTES>{LINE_END} {
132 if (yyextra->command == TELNET_COMMAND_11) {
133 telnet_send_gsm_11(yyextra);
134 } else if (yyextra->command == TELNET_COMMAND_48) {
135 telnet_send_gsm_48(yyextra);
136 }
137
138 if (yyextra->imsi) {
139 free(yyextra->imsi);
140 yyextra->imsi = NULL;
141 }
142 yyterminate();
143 }
144<INITIAL>{CMD_48}[ ][0-9]+ {
145 BEGIN READ_HEX_BYTES;
146 yyextra->read = 0;
147 yyextra->command = TELNET_COMMAND_48;
148 yytext[yyleng-1] = '\0';
149 yyextra->imsi = strdup(yytext);
150 }
151
152<INITIAL>{CMD_11}[ ][0-9]+ {
153 BEGIN READ_HEX_BYTES;
154 yyextra->read = 0;
155 yyextra->command = TELNET_COMMAND_11;
156 yytext[yyleng-1] = '\0';
157 yyextra->imsi = strdup(yytext);
158 }
159
160
161
162[ \t\r\n] /* Ommit */
163. { telnet_error_client(yyextra->fd.fd); yyterminate(); }
164
165%%
166
167void telnet_parse(struct telnet_connection *conn, char *buf)
168{
169 yyscan_t scanner;
170 yylex_init(&scanner);
171 yyset_extra(conn, scanner);
172 yy_scan_string(buf, scanner);
173 yylex(scanner);
174 yylex_destroy(scanner);
175
176 if (conn->imsi) {
177 free(conn->imsi);
178 conn->imsi = NULL;
179 }
180}