Support for recent GCC compiler
[samplevnf.git] / VNFs / DPPD-PROX / prox_lua.c
1 /*
2 // Copyright (c) 2010-2017 Intel Corporation
3 //
4 // Licensed under the Apache License, Version 2.0 (the "License");
5 // you may not use this file except in compliance with the License.
6 // You may obtain a copy of the License at
7 //
8 //     http://www.apache.org/licenses/LICENSE-2.0
9 //
10 // Unless required by applicable law or agreed to in writing, software
11 // distributed under the License is distributed on an "AS IS" BASIS,
12 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 // See the License for the specific language governing permissions and
14 // limitations under the License.
15 */
16
17 #include <string.h>
18 #include <stdlib.h>
19
20 #include "prox_lua.h"
21 #include "lua_compat.h"
22 #include "parse_utils.h"
23 #include "prox_compat.h"
24
25 static struct lua_State *lua_instance;
26
27 static int l_mask(lua_State *L)
28 {
29         uint32_t val, mask;
30
31         if (lua_gettop(L) != 2) {
32                 return luaL_error(L, "Expecting 2 argument and got %d\n", lua_gettop(L));
33         }
34         if (!lua_isnumber(L, -1) || !lua_isnumber(L, -2)) {
35                 return luaL_error(L, "Expecting (integer, integer) as arguments\n");
36         }
37         val = lua_tonumber(L, -1);
38         mask = lua_tonumber(L, -2);
39
40         lua_pushinteger(L, val & mask);
41
42         return 1;
43 }
44
45 static int l_server_content(lua_State *L)
46 {
47         uint32_t beg, len;
48
49         if (lua_gettop(L) != 2) {
50                 return luaL_error(L, "Expecting 2 argument and got %d\n", lua_gettop(L));
51         }
52         if (!lua_isnumber(L, -1) || !lua_isnumber(L, -2)) {
53                 return luaL_error(L, "Expecting (integer, integer) as arguments\n");
54         }
55         len = lua_tonumber(L, -1);
56         beg = lua_tonumber(L, -2);
57
58         lua_createtable(L, 0, 3);
59
60         lua_pushinteger(L, beg);
61         lua_setfield(L, -2, "beg");
62         lua_pushinteger(L, len);
63         lua_setfield(L, -2, "len");
64         lua_pushinteger(L, 0);
65         lua_setfield(L, -2, "peer");
66
67         return 1;
68 }
69
70 static int l_client_content(lua_State *L)
71 {
72         uint32_t beg, len;
73
74         if (lua_gettop(L) != 2) {
75                 return luaL_error(L, "Expecting 2 argument and got %d\n", lua_gettop(L));
76         }
77         if (!lua_isnumber(L, -1) || !lua_isnumber(L, -2)) {
78                 return luaL_error(L, "Expecting (integer, integer) as arguments\n");
79         }
80         len = lua_tonumber(L, -1);
81         beg = lua_tonumber(L, -2);
82
83         lua_createtable(L, 0, 3);
84
85         lua_pushinteger(L, beg);
86         lua_setfield(L, -2, "beg");
87         lua_pushinteger(L, len);
88         lua_setfield(L, -2, "len");
89         lua_pushinteger(L, 1);
90         lua_setfield(L, -2, "peer");
91
92         return 1;
93 }
94
95 static int l_bin_read(lua_State *L)
96 {
97         const char *file_name = lua_tostring(L, -1);
98         int beg = lua_tonumber(L, -2);
99         int len = lua_gettop(L) == 3? lua_tonumber(L, -3) : -1;
100
101         if (lua_gettop(L) == 2) {
102                 if (!lua_isnumber(L, -1) || !lua_isstring(L, -2)) {
103                         return luaL_error(L, "Expecting (string, integer) as arguments\n");
104                 }
105
106                 file_name = lua_tostring(L, -2);
107                 beg = lua_tonumber(L, -1);
108                 len = -1;
109         }
110         else if (lua_gettop(L) == 3) {
111                 if (!lua_isnumber(L, -1) || !lua_isnumber(L, -2) || !lua_isstring(L, 3)) {
112                         return luaL_error(L, "Expecting (string, integer, integer) as arguments\n");
113                 }
114
115                 file_name = lua_tostring(L, -3);
116                 beg = lua_tonumber(L, -2);
117                 len = lua_tonumber(L, -1);
118         }
119         else
120                 return luaL_error(L, "Expecting 2 or 3 arguments\n");
121
122         lua_createtable(L, 0, 3);
123
124         lua_pushstring(L, file_name);
125         lua_setfield(L, -2, "file_name");
126         lua_pushinteger(L, beg);
127         lua_setfield(L, -2, "beg");
128         lua_pushinteger(L, len);
129         lua_setfield(L, -2, "len");
130
131         return 1;
132 }
133
134 static int l_mac(lua_State *L)
135 {
136         int mac[6];
137
138         if (lua_isstring(L, -1)) {
139                 const char *arg = lua_tostring(L, -1);
140                 char arg2[128];
141                 prox_strncpy(arg2, arg, sizeof(arg2));
142
143                 char *p = arg2;
144                 int count = 0;
145
146                 while ((p = strchr(p, ':'))) {
147                         count++;
148                         p++;
149                 }
150                 p = arg2;
151                 if (count != 5)
152                         return luaL_error(L, "Invalid MAC format\n");
153
154                 lua_createtable(L, 6, 0);
155                 for (size_t i = 0; i < 6; ++i) {
156                         char *n = strchr(p, ':');
157                         if (n)
158                                 *n = 0;
159                         if (strlen(p) != 2) {
160                                 return luaL_error(L, "Invalid MAC format\n");
161                         }
162
163                         lua_pushinteger(L, strtol(p, NULL, 16));
164                         lua_rawseti(L, -2, i + 1);
165                         p = n + 1;
166                 }
167                 return 1;
168         }
169
170         return luaL_error(L, "Invalid argument\n");
171 }
172
173 static int l_ip(lua_State *L)
174 {
175         int ip[4];
176         if (lua_isnumber(L, -1)) {
177                 uint32_t arg = lua_tointeger(L, -1);
178
179                 ip[0] = arg >> 24 & 0xff;
180                 ip[1] = arg >> 16 & 0xff;
181                 ip[2] = arg >>  8 & 0xff;
182                 ip[3] = arg >>  0 & 0xff;
183
184                 lua_createtable(L, 4, 0);
185                 for (size_t i = 0; i < 4; ++i) {
186                         lua_pushinteger(L, ip[i]);
187                         lua_rawseti(L, -2, i + 1);
188                 }
189
190                 return 1;
191         }
192         if (lua_isstring(L, -1)) {
193                 const char *arg = lua_tostring(L, -1);
194
195                 if (sscanf(arg, "%d.%d.%d.%d", &ip[0], &ip[1], &ip[2], &ip[3]) != 4) {
196                         return luaL_error(L, "Invalid IP address format\n");
197                 }
198
199                 lua_createtable(L, 4, 0);
200                 for (size_t i = 0; i < 4; ++i) {
201                         lua_pushinteger(L, ip[i]);
202                         lua_rawseti(L, -2, i + 1);
203                 }
204
205                 return 1;
206         }
207
208         return luaL_error(L, "Invalid argument\n");
209 }
210
211 static int l_ip6(lua_State *L)
212 {
213         int ip[16];
214
215         if (!lua_isstring(L, -1)) {
216                 return luaL_error(L, "Invalid argument type\n");
217         }
218
219         const char *arg = lua_tostring(L, -1);
220         char arg2[64];
221         char *addr_parts[8];
222         int n_parts = 0;
223         size_t str_len = strlen(arg);
224         int next_str = 1;
225         int ret;
226
227         prox_strncpy(arg2, arg, sizeof(arg2));
228
229         for (size_t i = 0; i < str_len; ++i) {
230                 if (next_str) {
231                         if (n_parts == 8)
232                                 return luaL_error(L, "IPv6 address can't be longer than 16 bytes\n");
233                         addr_parts[n_parts++] = &arg2[i];
234                         next_str = 0;
235
236                 }
237                 if (arg2[i] == ':') {
238                         arg2[i] = 0;
239                         next_str = 1;
240                 }
241         }
242
243         int omitted = 0;
244
245         for (int i = 0, j = 0; i < n_parts; ++i) {
246                 if (*addr_parts[i] == 0) {
247                         if (omitted == 0) {
248                                 return luaL_error(L, "Can omit zeros only once\n");
249                         }
250                         omitted = 1;
251                         j += 8 - n_parts;
252                 }
253                 else {
254                         uint16_t w = strtoll(addr_parts[i], NULL, 16);
255                         ip[j++] = (w >> 8) & 0xff;
256                         ip[j++] = w & 0xff;
257                 }
258         }
259
260         lua_createtable(L, 16, 0);
261         for (size_t i = 0; i < 16; ++i) {
262                 lua_pushinteger(L, ip[i]);
263                 lua_rawseti(L, -2, i + 1);
264         }
265
266         return 1;
267 }
268
269 static int l_cidr(lua_State *L)
270 {
271         const char *arg = lua_tostring(L, -1);
272
273         char tmp[128];
274         prox_strncpy(tmp, arg, sizeof(tmp));
275
276         char *slash = strchr(tmp, '/');
277         *slash = 0;
278         slash++;
279
280         lua_createtable(L, 0, 2);
281         lua_pushstring(L, "ip");
282
283         lua_pushstring(L, tmp);
284         l_ip(L);
285         lua_remove(L, -2);
286
287         lua_settable(L, -3);
288
289         lua_pushstring(L, "depth");
290         lua_pushinteger(L, atoi(slash));
291         lua_settable(L, -3);
292         return 1;
293 }
294
295 static int l_cidr6(lua_State *L)
296 {
297         const char *arg = lua_tostring(L, -1);
298
299         char tmp[128];
300         prox_strncpy(tmp, arg, sizeof(tmp));
301
302         char *slash = strchr(tmp, '/');
303         *slash = 0;
304         slash++;
305
306         lua_createtable(L, 0, 2);
307         lua_pushstring(L, "ip6");
308
309         lua_pushstring(L, tmp);
310         l_ip6(L);
311         lua_remove(L, -2);
312
313         lua_settable(L, -3);
314
315         lua_pushstring(L, "depth");
316         lua_pushinteger(L, atoi(slash));
317         lua_settable(L, -3);
318         return 1;
319 }
320
321 static int l_val_mask(lua_State *L)
322 {
323         if (!lua_isinteger(L, -2))
324                 return luaL_error(L, "Argument 1 is not an integer\n");
325         if (!lua_isinteger(L, -1))
326                 return luaL_error(L, "Argument 2 is not an integer\n");
327
328         uint32_t val = lua_tointeger(L, -2);
329         uint32_t mask = lua_tointeger(L, -1);
330
331         lua_createtable(L, 0, 2);
332         lua_pushstring(L, "val");
333         lua_pushinteger(L, val);
334         lua_settable(L, -3);
335
336         lua_pushstring(L, "mask");
337         lua_pushinteger(L, mask);
338         lua_settable(L, -3);
339
340         return 1;
341 }
342
343 static int l_val_range(lua_State *L)
344 {
345         if (!lua_isinteger(L, -2))
346                 return luaL_error(L, "Argument 1 is not an integer\n");
347         if (!lua_isinteger(L, -1))
348                 return luaL_error(L, "Argument 2 is not an integer\n");
349
350         uint32_t beg = lua_tointeger(L, -2);
351         uint32_t end = lua_tointeger(L, -1);
352
353         lua_createtable(L, 0, 2);
354         lua_pushstring(L, "beg");
355         lua_pushinteger(L, beg);
356         lua_settable(L, -3);
357
358         lua_pushstring(L, "end");
359         lua_pushinteger(L, end);
360         lua_settable(L, -3);
361
362         return 1;
363 }
364
365 static int l_task_count(lua_State *L)
366 {
367         struct core_task_set cts;
368         const char *str;
369
370         if (!lua_isstring(L, -1))
371                 return luaL_error(L, "Argument 1 is not an string\n");
372         str = lua_tostring(L, -1);
373         if (parse_task_set(&cts, str))
374                 return luaL_error(L, "Invalid core task set syntax\n");
375         lua_pushinteger(L, cts.n_elems);
376         return 1;
377 }
378
379 struct lua_State *prox_lua(void)
380 {
381         if (!lua_instance) {
382                 lua_instance = luaL_newstate();
383
384                 luaL_openlibs(lua_instance);
385
386                 lua_pushcfunction(lua_instance, l_ip);
387                 lua_setglobal(lua_instance, "ip");
388                 lua_pushcfunction(lua_instance, l_ip6);
389                 lua_setglobal(lua_instance, "ip6");
390                 lua_pushcfunction(lua_instance, l_cidr);
391                 lua_setglobal(lua_instance, "cidr");
392                 lua_pushcfunction(lua_instance, l_cidr6);
393                 lua_setglobal(lua_instance, "cidr6");
394                 lua_pushcfunction(lua_instance, l_mac);
395                 lua_setglobal(lua_instance, "mac");
396                 lua_pushcfunction(lua_instance, l_mask);
397                 lua_setglobal(lua_instance, "mask");
398                 lua_pushcfunction(lua_instance, l_val_mask);
399                 lua_setglobal(lua_instance, "val_mask");
400                 lua_pushcfunction(lua_instance, l_val_range);
401                 lua_setglobal(lua_instance, "val_range");
402                 lua_pushcfunction(lua_instance, l_bin_read);
403                 lua_setglobal(lua_instance, "bin_read");
404                 lua_pushcfunction(lua_instance, l_client_content);
405                 lua_setglobal(lua_instance, "client_content");
406                 lua_pushcfunction(lua_instance, l_server_content);
407                 lua_setglobal(lua_instance, "server_content");
408                 lua_pushcfunction(lua_instance, l_task_count);
409                 lua_setglobal(lua_instance, "task_count");
410         }
411         return lua_instance;
412 }